├── .babelrc ├── .npmignore ├── .editorconfig ├── .eslintrc.json ├── .gitignore ├── index.html ├── .github └── workflows │ └── npmpublish.yml ├── rollup.config.js ├── LICENSE ├── README.md ├── package.json ├── src └── Vimeo.js └── dist ├── videojs-vimeo.esm.js ├── videojs-vimeo.cjs.js └── videojs-vimeo.umd.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["es2015", {"loose": true}]], 3 | "plugins": ["transform-object-assign"] 4 | } 5 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Intentionally left blank, so that npm does not ignore anything by default, 2 | # but relies on the package.json "files" array to explicitly define what ends 3 | # up in the package. 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | indent_style = space 8 | indent_size = 2 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es6": true 5 | }, 6 | "extends": "videojs", 7 | "globals": { 8 | "Atomics": "readonly", 9 | "SharedArrayBuffer": "readonly" 10 | }, 11 | "parserOptions": { 12 | "ecmaVersion": 2018, 13 | "sourceType": "module" 14 | }, 15 | "rules": { 16 | "require-jsdoc": 0, 17 | "no-console": 0 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS 2 | Thumbs.db 3 | ehthumbs.db 4 | Desktop.ini 5 | .DS_Store 6 | ._* 7 | 8 | # Editors 9 | *~ 10 | *.swp 11 | *.tmproj 12 | *.tmproject 13 | *.sublime-* 14 | .idea/ 15 | .project/ 16 | .settings/ 17 | .vscode/ 18 | 19 | # Logs 20 | logs 21 | *.log 22 | npm-debug.log* 23 | 24 | # Dependency directories 25 | bower_components/ 26 | node_modules/ 27 | 28 | # Yeoman meta-data 29 | .yo-rc.json 30 | 31 | # Build-related directories 32 | docs/api/ 33 | es5/ 34 | test/dist/ 35 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | videojs-vimeo Demo 7 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /.github/workflows/npmpublish.yml: -------------------------------------------------------------------------------- 1 | name: Library - Build and Deploy to NPM 2 | 3 | on: 4 | release: 5 | types: [created] 6 | 7 | jobs: 8 | build-and-deploy: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | - uses: actions/setup-node@v1 13 | with: 14 | node-version: "12.x" 15 | registry-url: "https://registry.npmjs.org" 16 | scope: "@devmobiliza" 17 | - run: yarn install 18 | - run: yarn build:lib 19 | - run: npm publish --access public 20 | env: 21 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 22 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from '@rollup/plugin-node-resolve'; 2 | import commonjs from '@rollup/plugin-commonjs'; 3 | import pkg from './package.json'; 4 | 5 | export default [ 6 | // browser-friendly UMD build 7 | { 8 | input: 'src/Vimeo.js', 9 | output: { 10 | name: 'videojs-vimeo', 11 | file: pkg.browser, 12 | format: 'umd' 13 | }, 14 | plugins: [ 15 | resolve(), 16 | commonjs() 17 | ] 18 | }, 19 | 20 | // CommonJS (for Node) and ES module (for bundlers) build. 21 | // (We could have three entries in the configuration array 22 | // instead of two, but it's quicker to generate multiple 23 | // builds from a single configuration where possible, using 24 | // an array for the `output` option, where we can specify 25 | // `file` and `format` for each target) 26 | { 27 | input: 'src/Vimeo.js', 28 | external: ['ms'], 29 | output: [ 30 | { file: pkg.main, format: 'cjs' }, 31 | { file: pkg.module, format: 'es' } 32 | ] 33 | } 34 | ]; 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020 Kevin Aguiar and videojs-vimeo contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Videojs Vimeo plugin hard fork 2 | 3 | #### videojs-vimeo official plugin fork for supporting videojs v7.6.6 onwards. 4 | 5 | This project is a hard fork of the currently unmaintained official videojs-vimeo plugin: https://github.com/videojs/videojs-vimeo 6 | 7 | This fork has some significant changes in project structure: 8 | 9 | - Build now uses rollup; 10 | 11 | - Project linting now uses eslint + videojs styleguide; 12 | 13 | - Project folder structure reworked; 14 | 15 | - Lib version reseted relative to the official plugin. 16 | 17 | ## Installation 18 | 19 | ```bash 20 | npm i @devmobiliza/videojs-vimeo 21 | // OR 22 | yarn add @devmobiliza/videojs-vimeo 23 | ``` 24 | 25 | ## Usage 26 | 27 | - CommonJS: 28 | 29 | ```js 30 | import videojs from 'video.js'; 31 | import '@devmobiliza/videojs-vimeo/dist/videojs-vimeo.cjs'; 32 | ``` 33 | 34 | - Module: 35 | 36 | ```js 37 | import videojs from 'video.js'; 38 | import '@devmobiliza/videojs-vimeo/dist/videojs-vimeo.esm'; 39 | ``` 40 | 41 | - Browser: 42 | 43 | See [index.html](https://github.com/Mobiliza/videojs-vimeo/blob/master/index.html) 44 | 45 | ## Events / Vimeo Options 46 | 47 | Events, like `on('play')`, `one('play')` work as per the video.js API: https://docs.videojs.com/ 48 | 49 | For setting the time of the player the `videojs.currentTime(TIME_SECONDS)` function can be used. 50 | 51 | Vimeo options are available here (must be used with the `vimeo` key in the options object of the video.js): https://vimeo.zendesk.com/hc/pt/articles/360001494447-Usando-os-par%C3%A2metros-do-player 52 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@devmobiliza/videojs-vimeo", 3 | "version": "0.6.0", 4 | "description": "Videojs Vimeo official plugin fork for working with video.js v7.6.6 onwards.", 5 | "main": "dist/videojs-vimeo.cjs.js", 6 | "module": "dist/videojs-vimeo.esm.js", 7 | "browser": "dist/videojs-vimeo.umd.js", 8 | "scripts": { 9 | "build:lib": "rollup -c", 10 | "dev": "rollup -c -w" 11 | }, 12 | "keywords": [ 13 | "videojs", 14 | "videojs-plugin", 15 | "vimeo", 16 | "mobiliza" 17 | ], 18 | "author": "Kevin Aguiar ", 19 | "license": "MIT", 20 | "files": [ 21 | "dist/", 22 | "index.html", 23 | "src/" 24 | ], 25 | "dependencies": { 26 | "@vimeo/player": "^2.10.0", 27 | "video.js": "^7.6.6" 28 | }, 29 | "devDependencies": { 30 | "@rollup/plugin-commonjs": "^11.0.2", 31 | "@rollup/plugin-node-resolve": "^7.1.1", 32 | "babel-cli": "^6.26.0", 33 | "babel-plugin-transform-object-assign": "^6.22.0", 34 | "babel-preset-es2015": "^6.24.1", 35 | "eslint": "^6.8.0", 36 | "eslint-config-standard": "^14.1.0", 37 | "eslint-config-videojs": "^5.0.2", 38 | "eslint-plugin-import": "^2.20.1", 39 | "eslint-plugin-jsdoc": "^21.0.0", 40 | "eslint-plugin-json-light": "^1.0.3", 41 | "eslint-plugin-markdown": "^1.0.2", 42 | "eslint-plugin-node": "^11.0.0", 43 | "eslint-plugin-promise": "^4.2.1", 44 | "eslint-plugin-standard": "^4.0.1", 45 | "ghooks": "^2.0.4", 46 | "rollup": "^1.32.0" 47 | }, 48 | "repository": { 49 | "type": "git", 50 | "url": "git+https://github.com/Mobiliza/videojs-vimeo.git" 51 | }, 52 | "bugs": { 53 | "url": "https://github.com/Mobiliza/videojs-vimeo/issues" 54 | }, 55 | "homepage": "https://github.com/Mobiliza/videojs-vimeo/#readme" 56 | } 57 | -------------------------------------------------------------------------------- /src/Vimeo.js: -------------------------------------------------------------------------------- 1 | import videojs from 'video.js'; 2 | import VimeoPlayer from '@vimeo/player'; 3 | 4 | let cssInjected = false; 5 | 6 | // Since the iframe can't be touched using Vimeo's way of embedding, 7 | // let's add a new styling rule to have the same style as `vjs-tech` 8 | function injectCss() { 9 | if (cssInjected) { 10 | return; 11 | } 12 | cssInjected = true; 13 | const css = ` 14 | .vjs-vimeo iframe { 15 | position: absolute; 16 | top: 0; 17 | left: 0; 18 | width: 100%; 19 | height: 100%; 20 | } 21 | `; 22 | const head = document.head || document.getElementsByTagName('head')[0]; 23 | 24 | const style = document.createElement('style'); 25 | 26 | style.type = 'text/css'; 27 | 28 | if (style.styleSheet) { 29 | style.styleSheet.cssText = css; 30 | } else { 31 | style.appendChild(document.createTextNode(css)); 32 | } 33 | 34 | head.appendChild(style); 35 | } 36 | 37 | const Tech = videojs.getTech('Tech'); 38 | 39 | /** 40 | * Vimeo - Wrapper for Video Player API 41 | * 42 | * @param {Object=} options Object of option names and values 43 | * @param {Function=} ready Ready callback function 44 | * @extends Tech 45 | * @class Vimeo 46 | */ 47 | class Vimeo extends Tech { 48 | constructor(options, ready) { 49 | super(options, ready); 50 | 51 | injectCss(); 52 | this.setPoster(options.poster); 53 | this.initVimeoPlayer(); 54 | } 55 | 56 | initVimeoPlayer() { 57 | const vimeoOptions = { 58 | url: this.options_.source.src, 59 | byline: false, 60 | portrait: false, 61 | title: false 62 | }; 63 | 64 | if (this.options_.autoplay) { 65 | vimeoOptions.autoplay = true; 66 | } 67 | if (this.options_.height) { 68 | vimeoOptions.height = this.options_.height; 69 | } 70 | if (this.options_.width) { 71 | vimeoOptions.width = this.options_.width; 72 | } 73 | if (this.options_.maxheight) { 74 | vimeoOptions.maxheight = this.options_.maxheight; 75 | } 76 | if (this.options_.maxwidth) { 77 | vimeoOptions.maxwidth = this.options_.maxwidth; 78 | } 79 | if (this.options_.loop) { 80 | vimeoOptions.loop = this.options_.loop; 81 | } 82 | if (this.options_.color) { 83 | vimeoOptions.color = this.options_.color.replace(/^#/, ''); 84 | } 85 | 86 | this._player = new VimeoPlayer(this.el(), vimeoOptions); 87 | this.initVimeoState(); 88 | 89 | ['play', 'pause', 'ended', 'timeupdate', 'progress', 'seeked'].forEach(e => { 90 | this._player.on(e, (progress) => { 91 | if (this._vimeoState.progress.duration !== progress.duration) { 92 | this.trigger('durationchange'); 93 | } 94 | this._vimeoState.progress = progress; 95 | this.trigger(e); 96 | }); 97 | }); 98 | 99 | this._player.on('pause', () => (this._vimeoState.playing = false)); 100 | this._player.on('play', () => { 101 | this._vimeoState.playing = true; 102 | this._vimeoState.ended = false; 103 | }); 104 | this._player.on('ended', () => { 105 | this._vimeoState.playing = false; 106 | this._vimeoState.ended = true; 107 | }); 108 | this._player.on('volumechange', (v) => (this._vimeoState.volume = v)); 109 | this._player.on('error', e => this.trigger('error', e)); 110 | 111 | this.triggerReady(); 112 | } 113 | 114 | initVimeoState() { 115 | const state = this._vimeoState = { 116 | ended: false, 117 | playing: false, 118 | volume: 0, 119 | progress: { 120 | seconds: 0, 121 | percent: 0, 122 | duration: 0 123 | } 124 | }; 125 | 126 | this._player.getCurrentTime().then(time => (state.progress.seconds = time)); 127 | this._player.getDuration().then(time => (state.progress.duration = time)); 128 | this._player.getPaused().then(paused => (state.playing = !paused)); 129 | this._player.getVolume().then(volume => (state.volume = volume)); 130 | } 131 | 132 | createEl() { 133 | const div = videojs.dom.createEl('div', { 134 | id: this.options_.techId 135 | }); 136 | 137 | div.style.cssText = 'width:100%;height:100%;top:0;left:0;position:absolute'; 138 | div.className = 'vjs-vimeo'; 139 | 140 | return div; 141 | } 142 | 143 | controls() { 144 | return true; 145 | } 146 | 147 | supportsFullScreen() { 148 | return true; 149 | } 150 | 151 | src() { 152 | return this.options_.source; 153 | } 154 | 155 | currentSrc() { 156 | return this.options_.source.src; 157 | } 158 | 159 | currentTime() { 160 | return this._vimeoState.progress.seconds; 161 | } 162 | 163 | setCurrentTime(time) { 164 | this._player.setCurrentTime(time); 165 | } 166 | 167 | volume() { 168 | return this._vimeoState.volume; 169 | } 170 | 171 | setVolume(volume) { 172 | return this._player.setVolume(volume); 173 | } 174 | 175 | duration() { 176 | return this._vimeoState.progress.duration; 177 | } 178 | 179 | buffered() { 180 | const progress = this._vimeoState.progress; 181 | 182 | return videojs.createTimeRange(0, progress.percent * progress.duration); 183 | } 184 | 185 | paused() { 186 | return !this._vimeoState.playing; 187 | } 188 | 189 | pause() { 190 | this._player.pause(); 191 | } 192 | 193 | play() { 194 | this._player.play(); 195 | } 196 | 197 | muted() { 198 | return this._vimeoState.volume === 0; 199 | } 200 | 201 | ended() { 202 | return this._vimeoState.ended; 203 | } 204 | 205 | playbackRate() { 206 | return 1; 207 | } 208 | 209 | } 210 | 211 | Vimeo.prototype.featuresTimeupdateEvents = true; 212 | 213 | Vimeo.isSupported = function () { 214 | return true; 215 | }; 216 | 217 | // Add Source Handler pattern functions to this tech 218 | Tech.withSourceHandlers(Vimeo); 219 | 220 | Vimeo.nativeSourceHandler = { 221 | }; 222 | 223 | /** 224 | * Check if Vimeo can play the given videotype 225 | * 226 | * @param {string} source The mimetype to check 227 | * @return {string} 'maybe', or '' (empty string) 228 | */ 229 | Vimeo.nativeSourceHandler.canPlayType = function (source) { 230 | if (source === 'video/vimeo') { 231 | return 'maybe'; 232 | } 233 | 234 | return ''; 235 | }; 236 | 237 | /* 238 | * Check Vimeo can handle the source natively 239 | * 240 | * @param {Object} source The source object 241 | * @return {String} 'maybe', or '' (empty string) 242 | * @note: Copied over from YouTube — not sure this is relevant 243 | */ 244 | Vimeo.nativeSourceHandler.canHandleSource = function (source) { 245 | if (source.type) { 246 | return Vimeo.nativeSourceHandler.canPlayType(source.type); 247 | } else if (source.src) { 248 | return Vimeo.nativeSourceHandler.canPlayType(source.src); 249 | } 250 | 251 | return ''; 252 | }; 253 | 254 | // @note: Copied over from YouTube — not sure this is relevant 255 | Vimeo.nativeSourceHandler.handleSource = function (source, tech) { 256 | tech.src(source.src); 257 | }; 258 | 259 | // @note: Copied over from YouTube — not sure this is relevant 260 | Vimeo.nativeSourceHandler.dispose = function () { }; 261 | 262 | Vimeo.registerSourceHandler(Vimeo.nativeSourceHandler); 263 | 264 | // Older versions of VJS5 doesn't have the registerTech function 265 | if (typeof videojs.registerTech !== 'undefined') { 266 | videojs.registerTech('Vimeo', Vimeo); 267 | } else { 268 | videojs.registerComponent('Vimeo', Vimeo); 269 | } 270 | 271 | // Include the version number. 272 | Vimeo.VERSION = '0.0.1'; 273 | 274 | export default Vimeo; 275 | -------------------------------------------------------------------------------- /dist/videojs-vimeo.esm.js: -------------------------------------------------------------------------------- 1 | import videojs from 'video.js'; 2 | import VimeoPlayer from '@vimeo/player'; 3 | 4 | let cssInjected = false; 5 | 6 | // Since the iframe can't be touched using Vimeo's way of embedding, 7 | // let's add a new styling rule to have the same style as `vjs-tech` 8 | function injectCss() { 9 | if (cssInjected) { 10 | return; 11 | } 12 | cssInjected = true; 13 | const css = ` 14 | .vjs-vimeo iframe { 15 | position: absolute; 16 | top: 0; 17 | left: 0; 18 | width: 100%; 19 | height: 100%; 20 | } 21 | `; 22 | const head = document.head || document.getElementsByTagName('head')[0]; 23 | 24 | const style = document.createElement('style'); 25 | 26 | style.type = 'text/css'; 27 | 28 | if (style.styleSheet) { 29 | style.styleSheet.cssText = css; 30 | } else { 31 | style.appendChild(document.createTextNode(css)); 32 | } 33 | 34 | head.appendChild(style); 35 | } 36 | 37 | const Tech = videojs.getTech('Tech'); 38 | 39 | /** 40 | * Vimeo - Wrapper for Video Player API 41 | * 42 | * @param {Object=} options Object of option names and values 43 | * @param {Function=} ready Ready callback function 44 | * @extends Tech 45 | * @class Vimeo 46 | */ 47 | class Vimeo extends Tech { 48 | constructor(options, ready) { 49 | super(options, ready); 50 | 51 | injectCss(); 52 | this.setPoster(options.poster); 53 | this.initVimeoPlayer(); 54 | } 55 | 56 | initVimeoPlayer() { 57 | const vimeoOptions = { 58 | url: this.options_.source.src, 59 | byline: false, 60 | portrait: false, 61 | title: false 62 | }; 63 | 64 | if (this.options_.autoplay) { 65 | vimeoOptions.autoplay = true; 66 | } 67 | if (this.options_.height) { 68 | vimeoOptions.height = this.options_.height; 69 | } 70 | if (this.options_.width) { 71 | vimeoOptions.width = this.options_.width; 72 | } 73 | if (this.options_.maxheight) { 74 | vimeoOptions.maxheight = this.options_.maxheight; 75 | } 76 | if (this.options_.maxwidth) { 77 | vimeoOptions.maxwidth = this.options_.maxwidth; 78 | } 79 | if (this.options_.loop) { 80 | vimeoOptions.loop = this.options_.loop; 81 | } 82 | if (this.options_.color) { 83 | vimeoOptions.color = this.options_.color.replace(/^#/, ''); 84 | } 85 | 86 | this._player = new VimeoPlayer(this.el(), vimeoOptions); 87 | this.initVimeoState(); 88 | 89 | ['play', 'pause', 'ended', 'timeupdate', 'progress', 'seeked'].forEach(e => { 90 | this._player.on(e, (progress) => { 91 | if (this._vimeoState.progress.duration !== progress.duration) { 92 | this.trigger('durationchange'); 93 | } 94 | this._vimeoState.progress = progress; 95 | this.trigger(e); 96 | }); 97 | }); 98 | 99 | this._player.on('pause', () => (this._vimeoState.playing = false)); 100 | this._player.on('play', () => { 101 | this._vimeoState.playing = true; 102 | this._vimeoState.ended = false; 103 | }); 104 | this._player.on('ended', () => { 105 | this._vimeoState.playing = false; 106 | this._vimeoState.ended = true; 107 | }); 108 | this._player.on('volumechange', (v) => (this._vimeoState.volume = v)); 109 | this._player.on('error', e => this.trigger('error', e)); 110 | 111 | this.triggerReady(); 112 | } 113 | 114 | initVimeoState() { 115 | const state = this._vimeoState = { 116 | ended: false, 117 | playing: false, 118 | volume: 0, 119 | progress: { 120 | seconds: 0, 121 | percent: 0, 122 | duration: 0 123 | } 124 | }; 125 | 126 | this._player.getCurrentTime().then(time => (state.progress.seconds = time)); 127 | this._player.getDuration().then(time => (state.progress.duration = time)); 128 | this._player.getPaused().then(paused => (state.playing = !paused)); 129 | this._player.getVolume().then(volume => (state.volume = volume)); 130 | } 131 | 132 | createEl() { 133 | const div = videojs.dom.createEl('div', { 134 | id: this.options_.techId 135 | }); 136 | 137 | div.style.cssText = 'width:100%;height:100%;top:0;left:0;position:absolute'; 138 | div.className = 'vjs-vimeo'; 139 | 140 | return div; 141 | } 142 | 143 | controls() { 144 | return true; 145 | } 146 | 147 | supportsFullScreen() { 148 | return true; 149 | } 150 | 151 | src() { 152 | return this.options_.source; 153 | } 154 | 155 | currentSrc() { 156 | return this.options_.source.src; 157 | } 158 | 159 | currentTime() { 160 | return this._vimeoState.progress.seconds; 161 | } 162 | 163 | setCurrentTime(time) { 164 | this._player.setCurrentTime(time); 165 | } 166 | 167 | volume() { 168 | return this._vimeoState.volume; 169 | } 170 | 171 | setVolume(volume) { 172 | return this._player.setVolume(volume); 173 | } 174 | 175 | duration() { 176 | return this._vimeoState.progress.duration; 177 | } 178 | 179 | buffered() { 180 | const progress = this._vimeoState.progress; 181 | 182 | return videojs.createTimeRange(0, progress.percent * progress.duration); 183 | } 184 | 185 | paused() { 186 | return !this._vimeoState.playing; 187 | } 188 | 189 | pause() { 190 | this._player.pause(); 191 | } 192 | 193 | play() { 194 | this._player.play(); 195 | } 196 | 197 | muted() { 198 | return this._vimeoState.volume === 0; 199 | } 200 | 201 | ended() { 202 | return this._vimeoState.ended; 203 | } 204 | 205 | playbackRate() { 206 | return 1; 207 | } 208 | 209 | } 210 | 211 | Vimeo.prototype.featuresTimeupdateEvents = true; 212 | 213 | Vimeo.isSupported = function () { 214 | return true; 215 | }; 216 | 217 | // Add Source Handler pattern functions to this tech 218 | Tech.withSourceHandlers(Vimeo); 219 | 220 | Vimeo.nativeSourceHandler = { 221 | }; 222 | 223 | /** 224 | * Check if Vimeo can play the given videotype 225 | * 226 | * @param {string} source The mimetype to check 227 | * @return {string} 'maybe', or '' (empty string) 228 | */ 229 | Vimeo.nativeSourceHandler.canPlayType = function (source) { 230 | if (source === 'video/vimeo') { 231 | return 'maybe'; 232 | } 233 | 234 | return ''; 235 | }; 236 | 237 | /* 238 | * Check Vimeo can handle the source natively 239 | * 240 | * @param {Object} source The source object 241 | * @return {String} 'maybe', or '' (empty string) 242 | * @note: Copied over from YouTube — not sure this is relevant 243 | */ 244 | Vimeo.nativeSourceHandler.canHandleSource = function (source) { 245 | if (source.type) { 246 | return Vimeo.nativeSourceHandler.canPlayType(source.type); 247 | } else if (source.src) { 248 | return Vimeo.nativeSourceHandler.canPlayType(source.src); 249 | } 250 | 251 | return ''; 252 | }; 253 | 254 | // @note: Copied over from YouTube — not sure this is relevant 255 | Vimeo.nativeSourceHandler.handleSource = function (source, tech) { 256 | tech.src(source.src); 257 | }; 258 | 259 | // @note: Copied over from YouTube — not sure this is relevant 260 | Vimeo.nativeSourceHandler.dispose = function () { }; 261 | 262 | Vimeo.registerSourceHandler(Vimeo.nativeSourceHandler); 263 | 264 | // Older versions of VJS5 doesn't have the registerTech function 265 | if (typeof videojs.registerTech !== 'undefined') { 266 | videojs.registerTech('Vimeo', Vimeo); 267 | } else { 268 | videojs.registerComponent('Vimeo', Vimeo); 269 | } 270 | 271 | // Include the version number. 272 | Vimeo.VERSION = '0.0.1'; 273 | 274 | export default Vimeo; 275 | -------------------------------------------------------------------------------- /dist/videojs-vimeo.cjs.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } 4 | 5 | var videojs = _interopDefault(require('video.js')); 6 | var VimeoPlayer = _interopDefault(require('@vimeo/player')); 7 | 8 | let cssInjected = false; 9 | 10 | // Since the iframe can't be touched using Vimeo's way of embedding, 11 | // let's add a new styling rule to have the same style as `vjs-tech` 12 | function injectCss() { 13 | if (cssInjected) { 14 | return; 15 | } 16 | cssInjected = true; 17 | const css = ` 18 | .vjs-vimeo iframe { 19 | position: absolute; 20 | top: 0; 21 | left: 0; 22 | width: 100%; 23 | height: 100%; 24 | } 25 | `; 26 | const head = document.head || document.getElementsByTagName('head')[0]; 27 | 28 | const style = document.createElement('style'); 29 | 30 | style.type = 'text/css'; 31 | 32 | if (style.styleSheet) { 33 | style.styleSheet.cssText = css; 34 | } else { 35 | style.appendChild(document.createTextNode(css)); 36 | } 37 | 38 | head.appendChild(style); 39 | } 40 | 41 | const Tech = videojs.getTech('Tech'); 42 | 43 | /** 44 | * Vimeo - Wrapper for Video Player API 45 | * 46 | * @param {Object=} options Object of option names and values 47 | * @param {Function=} ready Ready callback function 48 | * @extends Tech 49 | * @class Vimeo 50 | */ 51 | class Vimeo extends Tech { 52 | constructor(options, ready) { 53 | super(options, ready); 54 | 55 | injectCss(); 56 | this.setPoster(options.poster); 57 | this.initVimeoPlayer(); 58 | } 59 | 60 | initVimeoPlayer() { 61 | const vimeoOptions = { 62 | url: this.options_.source.src, 63 | byline: false, 64 | portrait: false, 65 | title: false 66 | }; 67 | 68 | if (this.options_.autoplay) { 69 | vimeoOptions.autoplay = true; 70 | } 71 | if (this.options_.height) { 72 | vimeoOptions.height = this.options_.height; 73 | } 74 | if (this.options_.width) { 75 | vimeoOptions.width = this.options_.width; 76 | } 77 | if (this.options_.maxheight) { 78 | vimeoOptions.maxheight = this.options_.maxheight; 79 | } 80 | if (this.options_.maxwidth) { 81 | vimeoOptions.maxwidth = this.options_.maxwidth; 82 | } 83 | if (this.options_.loop) { 84 | vimeoOptions.loop = this.options_.loop; 85 | } 86 | if (this.options_.color) { 87 | vimeoOptions.color = this.options_.color.replace(/^#/, ''); 88 | } 89 | 90 | this._player = new VimeoPlayer(this.el(), vimeoOptions); 91 | this.initVimeoState(); 92 | 93 | ['play', 'pause', 'ended', 'timeupdate', 'progress', 'seeked'].forEach(e => { 94 | this._player.on(e, (progress) => { 95 | if (this._vimeoState.progress.duration !== progress.duration) { 96 | this.trigger('durationchange'); 97 | } 98 | this._vimeoState.progress = progress; 99 | this.trigger(e); 100 | }); 101 | }); 102 | 103 | this._player.on('pause', () => (this._vimeoState.playing = false)); 104 | this._player.on('play', () => { 105 | this._vimeoState.playing = true; 106 | this._vimeoState.ended = false; 107 | }); 108 | this._player.on('ended', () => { 109 | this._vimeoState.playing = false; 110 | this._vimeoState.ended = true; 111 | }); 112 | this._player.on('volumechange', (v) => (this._vimeoState.volume = v)); 113 | this._player.on('error', e => this.trigger('error', e)); 114 | 115 | this.triggerReady(); 116 | } 117 | 118 | initVimeoState() { 119 | const state = this._vimeoState = { 120 | ended: false, 121 | playing: false, 122 | volume: 0, 123 | progress: { 124 | seconds: 0, 125 | percent: 0, 126 | duration: 0 127 | } 128 | }; 129 | 130 | this._player.getCurrentTime().then(time => (state.progress.seconds = time)); 131 | this._player.getDuration().then(time => (state.progress.duration = time)); 132 | this._player.getPaused().then(paused => (state.playing = !paused)); 133 | this._player.getVolume().then(volume => (state.volume = volume)); 134 | } 135 | 136 | createEl() { 137 | const div = videojs.dom.createEl('div', { 138 | id: this.options_.techId 139 | }); 140 | 141 | div.style.cssText = 'width:100%;height:100%;top:0;left:0;position:absolute'; 142 | div.className = 'vjs-vimeo'; 143 | 144 | return div; 145 | } 146 | 147 | controls() { 148 | return true; 149 | } 150 | 151 | supportsFullScreen() { 152 | return true; 153 | } 154 | 155 | src() { 156 | return this.options_.source; 157 | } 158 | 159 | currentSrc() { 160 | return this.options_.source.src; 161 | } 162 | 163 | currentTime() { 164 | return this._vimeoState.progress.seconds; 165 | } 166 | 167 | setCurrentTime(time) { 168 | this._player.setCurrentTime(time); 169 | } 170 | 171 | volume() { 172 | return this._vimeoState.volume; 173 | } 174 | 175 | setVolume(volume) { 176 | return this._player.setVolume(volume); 177 | } 178 | 179 | duration() { 180 | return this._vimeoState.progress.duration; 181 | } 182 | 183 | buffered() { 184 | const progress = this._vimeoState.progress; 185 | 186 | return videojs.createTimeRange(0, progress.percent * progress.duration); 187 | } 188 | 189 | paused() { 190 | return !this._vimeoState.playing; 191 | } 192 | 193 | pause() { 194 | this._player.pause(); 195 | } 196 | 197 | play() { 198 | this._player.play(); 199 | } 200 | 201 | muted() { 202 | return this._vimeoState.volume === 0; 203 | } 204 | 205 | ended() { 206 | return this._vimeoState.ended; 207 | } 208 | 209 | playbackRate() { 210 | return 1; 211 | } 212 | 213 | } 214 | 215 | Vimeo.prototype.featuresTimeupdateEvents = true; 216 | 217 | Vimeo.isSupported = function () { 218 | return true; 219 | }; 220 | 221 | // Add Source Handler pattern functions to this tech 222 | Tech.withSourceHandlers(Vimeo); 223 | 224 | Vimeo.nativeSourceHandler = { 225 | }; 226 | 227 | /** 228 | * Check if Vimeo can play the given videotype 229 | * 230 | * @param {string} source The mimetype to check 231 | * @return {string} 'maybe', or '' (empty string) 232 | */ 233 | Vimeo.nativeSourceHandler.canPlayType = function (source) { 234 | if (source === 'video/vimeo') { 235 | return 'maybe'; 236 | } 237 | 238 | return ''; 239 | }; 240 | 241 | /* 242 | * Check Vimeo can handle the source natively 243 | * 244 | * @param {Object} source The source object 245 | * @return {String} 'maybe', or '' (empty string) 246 | * @note: Copied over from YouTube — not sure this is relevant 247 | */ 248 | Vimeo.nativeSourceHandler.canHandleSource = function (source) { 249 | if (source.type) { 250 | return Vimeo.nativeSourceHandler.canPlayType(source.type); 251 | } else if (source.src) { 252 | return Vimeo.nativeSourceHandler.canPlayType(source.src); 253 | } 254 | 255 | return ''; 256 | }; 257 | 258 | // @note: Copied over from YouTube — not sure this is relevant 259 | Vimeo.nativeSourceHandler.handleSource = function (source, tech) { 260 | tech.src(source.src); 261 | }; 262 | 263 | // @note: Copied over from YouTube — not sure this is relevant 264 | Vimeo.nativeSourceHandler.dispose = function () { }; 265 | 266 | Vimeo.registerSourceHandler(Vimeo.nativeSourceHandler); 267 | 268 | // Older versions of VJS5 doesn't have the registerTech function 269 | if (typeof videojs.registerTech !== 'undefined') { 270 | videojs.registerTech('Vimeo', Vimeo); 271 | } else { 272 | videojs.registerComponent('Vimeo', Vimeo); 273 | } 274 | 275 | // Include the version number. 276 | Vimeo.VERSION = '0.0.1'; 277 | 278 | module.exports = Vimeo; 279 | -------------------------------------------------------------------------------- /dist/videojs-vimeo.umd.js: -------------------------------------------------------------------------------- 1 | (function (global, factory) { 2 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('video.js')) : 3 | typeof define === 'function' && define.amd ? define(['video.js'], factory) : 4 | (global = global || self, global['videojs-vimeo'] = factory(global.videojs)); 5 | }(this, (function (videojs) { 'use strict'; 6 | 7 | videojs = videojs && videojs.hasOwnProperty('default') ? videojs['default'] : videojs; 8 | 9 | /*! @vimeo/player v2.10.0 | (c) 2019 Vimeo | MIT License | https://github.com/vimeo/player.js */ 10 | function _classCallCheck(instance, Constructor) { 11 | if (!(instance instanceof Constructor)) { 12 | throw new TypeError("Cannot call a class as a function"); 13 | } 14 | } 15 | 16 | function _defineProperties(target, props) { 17 | for (var i = 0; i < props.length; i++) { 18 | var descriptor = props[i]; 19 | descriptor.enumerable = descriptor.enumerable || false; 20 | descriptor.configurable = true; 21 | if ("value" in descriptor) descriptor.writable = true; 22 | Object.defineProperty(target, descriptor.key, descriptor); 23 | } 24 | } 25 | 26 | function _createClass(Constructor, protoProps, staticProps) { 27 | if (protoProps) _defineProperties(Constructor.prototype, protoProps); 28 | if (staticProps) _defineProperties(Constructor, staticProps); 29 | return Constructor; 30 | } 31 | 32 | /** 33 | * @module lib/functions 34 | */ 35 | 36 | /** 37 | * Check to see this is a node environment. 38 | * @type {Boolean} 39 | */ 40 | 41 | /* global global */ 42 | var isNode = typeof global !== 'undefined' && {}.toString.call(global) === '[object global]'; 43 | /** 44 | * Get the name of the method for a given getter or setter. 45 | * 46 | * @param {string} prop The name of the property. 47 | * @param {string} type Either “get” or “set”. 48 | * @return {string} 49 | */ 50 | 51 | function getMethodName(prop, type) { 52 | if (prop.indexOf(type.toLowerCase()) === 0) { 53 | return prop; 54 | } 55 | 56 | return "".concat(type.toLowerCase()).concat(prop.substr(0, 1).toUpperCase()).concat(prop.substr(1)); 57 | } 58 | /** 59 | * Check to see if the object is a DOM Element. 60 | * 61 | * @param {*} element The object to check. 62 | * @return {boolean} 63 | */ 64 | 65 | function isDomElement(element) { 66 | return Boolean(element && element.nodeType === 1 && 'nodeName' in element && element.ownerDocument && element.ownerDocument.defaultView); 67 | } 68 | /** 69 | * Check to see whether the value is a number. 70 | * 71 | * @see http://dl.dropboxusercontent.com/u/35146/js/tests/isNumber.html 72 | * @param {*} value The value to check. 73 | * @param {boolean} integer Check if the value is an integer. 74 | * @return {boolean} 75 | */ 76 | 77 | function isInteger(value) { 78 | // eslint-disable-next-line eqeqeq 79 | return !isNaN(parseFloat(value)) && isFinite(value) && Math.floor(value) == value; 80 | } 81 | /** 82 | * Check to see if the URL is a Vimeo url. 83 | * 84 | * @param {string} url The url string. 85 | * @return {boolean} 86 | */ 87 | 88 | function isVimeoUrl(url) { 89 | return /^(https?:)?\/\/((player|www)\.)?vimeo\.com(?=$|\/)/.test(url); 90 | } 91 | /** 92 | * Get the Vimeo URL from an element. 93 | * The element must have either a data-vimeo-id or data-vimeo-url attribute. 94 | * 95 | * @param {object} oEmbedParameters The oEmbed parameters. 96 | * @return {string} 97 | */ 98 | 99 | function getVimeoUrl() { 100 | var oEmbedParameters = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; 101 | var id = oEmbedParameters.id; 102 | var url = oEmbedParameters.url; 103 | var idOrUrl = id || url; 104 | 105 | if (!idOrUrl) { 106 | throw new Error('An id or url must be passed, either in an options object or as a data-vimeo-id or data-vimeo-url attribute.'); 107 | } 108 | 109 | if (isInteger(idOrUrl)) { 110 | return "https://vimeo.com/".concat(idOrUrl); 111 | } 112 | 113 | if (isVimeoUrl(idOrUrl)) { 114 | return idOrUrl.replace('http:', 'https:'); 115 | } 116 | 117 | if (id) { 118 | throw new TypeError("\u201C".concat(id, "\u201D is not a valid video id.")); 119 | } 120 | 121 | throw new TypeError("\u201C".concat(idOrUrl, "\u201D is not a vimeo.com url.")); 122 | } 123 | 124 | var arrayIndexOfSupport = typeof Array.prototype.indexOf !== 'undefined'; 125 | var postMessageSupport = typeof window !== 'undefined' && typeof window.postMessage !== 'undefined'; 126 | 127 | if (!isNode && (!arrayIndexOfSupport || !postMessageSupport)) { 128 | throw new Error('Sorry, the Vimeo Player API is not available in this browser.'); 129 | } 130 | 131 | var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; 132 | 133 | function createCommonjsModule(fn, module) { 134 | return module = { exports: {} }, fn(module, module.exports), module.exports; 135 | } 136 | 137 | /*! 138 | * weakmap-polyfill v2.0.0 - ECMAScript6 WeakMap polyfill 139 | * https://github.com/polygonplanet/weakmap-polyfill 140 | * Copyright (c) 2015-2016 polygon planet 141 | * @license MIT 142 | */ 143 | (function (self) { 144 | 145 | if (self.WeakMap) { 146 | return; 147 | } 148 | 149 | var hasOwnProperty = Object.prototype.hasOwnProperty; 150 | 151 | var defineProperty = function (object, name, value) { 152 | if (Object.defineProperty) { 153 | Object.defineProperty(object, name, { 154 | configurable: true, 155 | writable: true, 156 | value: value 157 | }); 158 | } else { 159 | object[name] = value; 160 | } 161 | }; 162 | 163 | self.WeakMap = function () { 164 | // ECMA-262 23.3 WeakMap Objects 165 | function WeakMap() { 166 | if (this === void 0) { 167 | throw new TypeError("Constructor WeakMap requires 'new'"); 168 | } 169 | 170 | defineProperty(this, '_id', genId('_WeakMap')); // ECMA-262 23.3.1.1 WeakMap([iterable]) 171 | 172 | if (arguments.length > 0) { 173 | // Currently, WeakMap `iterable` argument is not supported 174 | throw new TypeError('WeakMap iterable is not supported'); 175 | } 176 | } // ECMA-262 23.3.3.2 WeakMap.prototype.delete(key) 177 | 178 | 179 | defineProperty(WeakMap.prototype, 'delete', function (key) { 180 | checkInstance(this, 'delete'); 181 | 182 | if (!isObject(key)) { 183 | return false; 184 | } 185 | 186 | var entry = key[this._id]; 187 | 188 | if (entry && entry[0] === key) { 189 | delete key[this._id]; 190 | return true; 191 | } 192 | 193 | return false; 194 | }); // ECMA-262 23.3.3.3 WeakMap.prototype.get(key) 195 | 196 | defineProperty(WeakMap.prototype, 'get', function (key) { 197 | checkInstance(this, 'get'); 198 | 199 | if (!isObject(key)) { 200 | return void 0; 201 | } 202 | 203 | var entry = key[this._id]; 204 | 205 | if (entry && entry[0] === key) { 206 | return entry[1]; 207 | } 208 | 209 | return void 0; 210 | }); // ECMA-262 23.3.3.4 WeakMap.prototype.has(key) 211 | 212 | defineProperty(WeakMap.prototype, 'has', function (key) { 213 | checkInstance(this, 'has'); 214 | 215 | if (!isObject(key)) { 216 | return false; 217 | } 218 | 219 | var entry = key[this._id]; 220 | 221 | if (entry && entry[0] === key) { 222 | return true; 223 | } 224 | 225 | return false; 226 | }); // ECMA-262 23.3.3.5 WeakMap.prototype.set(key, value) 227 | 228 | defineProperty(WeakMap.prototype, 'set', function (key, value) { 229 | checkInstance(this, 'set'); 230 | 231 | if (!isObject(key)) { 232 | throw new TypeError('Invalid value used as weak map key'); 233 | } 234 | 235 | var entry = key[this._id]; 236 | 237 | if (entry && entry[0] === key) { 238 | entry[1] = value; 239 | return this; 240 | } 241 | 242 | defineProperty(key, this._id, [key, value]); 243 | return this; 244 | }); 245 | 246 | function checkInstance(x, methodName) { 247 | if (!isObject(x) || !hasOwnProperty.call(x, '_id')) { 248 | throw new TypeError(methodName + ' method called on incompatible receiver ' + typeof x); 249 | } 250 | } 251 | 252 | function genId(prefix) { 253 | return prefix + '_' + rand() + '.' + rand(); 254 | } 255 | 256 | function rand() { 257 | return Math.random().toString().substring(2); 258 | } 259 | 260 | defineProperty(WeakMap, '_polyfill', true); 261 | return WeakMap; 262 | }(); 263 | 264 | function isObject(x) { 265 | return Object(x) === x; 266 | } 267 | })(typeof self !== 'undefined' ? self : typeof window !== 'undefined' ? window : typeof commonjsGlobal !== 'undefined' ? commonjsGlobal : commonjsGlobal); 268 | 269 | var npo_src = createCommonjsModule(function (module) { 270 | /*! Native Promise Only 271 | v0.8.1 (c) Kyle Simpson 272 | MIT License: http://getify.mit-license.org 273 | */ 274 | (function UMD(name, context, definition) { 275 | // special form of UMD for polyfilling across evironments 276 | context[name] = context[name] || definition(); 277 | 278 | if (module.exports) { 279 | module.exports = context[name]; 280 | } 281 | })("Promise", typeof commonjsGlobal != "undefined" ? commonjsGlobal : commonjsGlobal, function DEF() { 282 | 283 | var builtInProp, 284 | cycle, 285 | scheduling_queue, 286 | ToString = Object.prototype.toString, 287 | timer = typeof setImmediate != "undefined" ? function timer(fn) { 288 | return setImmediate(fn); 289 | } : setTimeout; // dammit, IE8. 290 | 291 | try { 292 | Object.defineProperty({}, "x", {}); 293 | 294 | builtInProp = function builtInProp(obj, name, val, config) { 295 | return Object.defineProperty(obj, name, { 296 | value: val, 297 | writable: true, 298 | configurable: config !== false 299 | }); 300 | }; 301 | } catch (err) { 302 | builtInProp = function builtInProp(obj, name, val) { 303 | obj[name] = val; 304 | return obj; 305 | }; 306 | } // Note: using a queue instead of array for efficiency 307 | 308 | 309 | scheduling_queue = function Queue() { 310 | var first, last, item; 311 | 312 | function Item(fn, self) { 313 | this.fn = fn; 314 | this.self = self; 315 | this.next = void 0; 316 | } 317 | 318 | return { 319 | add: function add(fn, self) { 320 | item = new Item(fn, self); 321 | 322 | if (last) { 323 | last.next = item; 324 | } else { 325 | first = item; 326 | } 327 | 328 | last = item; 329 | item = void 0; 330 | }, 331 | drain: function drain() { 332 | var f = first; 333 | first = last = cycle = void 0; 334 | 335 | while (f) { 336 | f.fn.call(f.self); 337 | f = f.next; 338 | } 339 | } 340 | }; 341 | }(); 342 | 343 | function schedule(fn, self) { 344 | scheduling_queue.add(fn, self); 345 | 346 | if (!cycle) { 347 | cycle = timer(scheduling_queue.drain); 348 | } 349 | } // promise duck typing 350 | 351 | 352 | function isThenable(o) { 353 | var _then, 354 | o_type = typeof o; 355 | 356 | if (o != null && (o_type == "object" || o_type == "function")) { 357 | _then = o.then; 358 | } 359 | 360 | return typeof _then == "function" ? _then : false; 361 | } 362 | 363 | function notify() { 364 | for (var i = 0; i < this.chain.length; i++) { 365 | notifyIsolated(this, this.state === 1 ? this.chain[i].success : this.chain[i].failure, this.chain[i]); 366 | } 367 | 368 | this.chain.length = 0; 369 | } // NOTE: This is a separate function to isolate 370 | // the `try..catch` so that other code can be 371 | // optimized better 372 | 373 | 374 | function notifyIsolated(self, cb, chain) { 375 | var ret, _then; 376 | 377 | try { 378 | if (cb === false) { 379 | chain.reject(self.msg); 380 | } else { 381 | if (cb === true) { 382 | ret = self.msg; 383 | } else { 384 | ret = cb.call(void 0, self.msg); 385 | } 386 | 387 | if (ret === chain.promise) { 388 | chain.reject(TypeError("Promise-chain cycle")); 389 | } else if (_then = isThenable(ret)) { 390 | _then.call(ret, chain.resolve, chain.reject); 391 | } else { 392 | chain.resolve(ret); 393 | } 394 | } 395 | } catch (err) { 396 | chain.reject(err); 397 | } 398 | } 399 | 400 | function resolve(msg) { 401 | var _then, 402 | self = this; // already triggered? 403 | 404 | 405 | if (self.triggered) { 406 | return; 407 | } 408 | 409 | self.triggered = true; // unwrap 410 | 411 | if (self.def) { 412 | self = self.def; 413 | } 414 | 415 | try { 416 | if (_then = isThenable(msg)) { 417 | schedule(function () { 418 | var def_wrapper = new MakeDefWrapper(self); 419 | 420 | try { 421 | _then.call(msg, function $resolve$() { 422 | resolve.apply(def_wrapper, arguments); 423 | }, function $reject$() { 424 | reject.apply(def_wrapper, arguments); 425 | }); 426 | } catch (err) { 427 | reject.call(def_wrapper, err); 428 | } 429 | }); 430 | } else { 431 | self.msg = msg; 432 | self.state = 1; 433 | 434 | if (self.chain.length > 0) { 435 | schedule(notify, self); 436 | } 437 | } 438 | } catch (err) { 439 | reject.call(new MakeDefWrapper(self), err); 440 | } 441 | } 442 | 443 | function reject(msg) { 444 | var self = this; // already triggered? 445 | 446 | if (self.triggered) { 447 | return; 448 | } 449 | 450 | self.triggered = true; // unwrap 451 | 452 | if (self.def) { 453 | self = self.def; 454 | } 455 | 456 | self.msg = msg; 457 | self.state = 2; 458 | 459 | if (self.chain.length > 0) { 460 | schedule(notify, self); 461 | } 462 | } 463 | 464 | function iteratePromises(Constructor, arr, resolver, rejecter) { 465 | for (var idx = 0; idx < arr.length; idx++) { 466 | (function IIFE(idx) { 467 | Constructor.resolve(arr[idx]).then(function $resolver$(msg) { 468 | resolver(idx, msg); 469 | }, rejecter); 470 | })(idx); 471 | } 472 | } 473 | 474 | function MakeDefWrapper(self) { 475 | this.def = self; 476 | this.triggered = false; 477 | } 478 | 479 | function MakeDef(self) { 480 | this.promise = self; 481 | this.state = 0; 482 | this.triggered = false; 483 | this.chain = []; 484 | this.msg = void 0; 485 | } 486 | 487 | function Promise(executor) { 488 | if (typeof executor != "function") { 489 | throw TypeError("Not a function"); 490 | } 491 | 492 | if (this.__NPO__ !== 0) { 493 | throw TypeError("Not a promise"); 494 | } // instance shadowing the inherited "brand" 495 | // to signal an already "initialized" promise 496 | 497 | 498 | this.__NPO__ = 1; 499 | var def = new MakeDef(this); 500 | 501 | this["then"] = function then(success, failure) { 502 | var o = { 503 | success: typeof success == "function" ? success : true, 504 | failure: typeof failure == "function" ? failure : false 505 | }; // Note: `then(..)` itself can be borrowed to be used against 506 | // a different promise constructor for making the chained promise, 507 | // by substituting a different `this` binding. 508 | 509 | o.promise = new this.constructor(function extractChain(resolve, reject) { 510 | if (typeof resolve != "function" || typeof reject != "function") { 511 | throw TypeError("Not a function"); 512 | } 513 | 514 | o.resolve = resolve; 515 | o.reject = reject; 516 | }); 517 | def.chain.push(o); 518 | 519 | if (def.state !== 0) { 520 | schedule(notify, def); 521 | } 522 | 523 | return o.promise; 524 | }; 525 | 526 | this["catch"] = function $catch$(failure) { 527 | return this.then(void 0, failure); 528 | }; 529 | 530 | try { 531 | executor.call(void 0, function publicResolve(msg) { 532 | resolve.call(def, msg); 533 | }, function publicReject(msg) { 534 | reject.call(def, msg); 535 | }); 536 | } catch (err) { 537 | reject.call(def, err); 538 | } 539 | } 540 | 541 | var PromisePrototype = builtInProp({}, "constructor", Promise, 542 | /*configurable=*/ 543 | false); // Note: Android 4 cannot use `Object.defineProperty(..)` here 544 | 545 | Promise.prototype = PromisePrototype; // built-in "brand" to signal an "uninitialized" promise 546 | 547 | builtInProp(PromisePrototype, "__NPO__", 0, 548 | /*configurable=*/ 549 | false); 550 | builtInProp(Promise, "resolve", function Promise$resolve(msg) { 551 | var Constructor = this; // spec mandated checks 552 | // note: best "isPromise" check that's practical for now 553 | 554 | if (msg && typeof msg == "object" && msg.__NPO__ === 1) { 555 | return msg; 556 | } 557 | 558 | return new Constructor(function executor(resolve, reject) { 559 | if (typeof resolve != "function" || typeof reject != "function") { 560 | throw TypeError("Not a function"); 561 | } 562 | 563 | resolve(msg); 564 | }); 565 | }); 566 | builtInProp(Promise, "reject", function Promise$reject(msg) { 567 | return new this(function executor(resolve, reject) { 568 | if (typeof resolve != "function" || typeof reject != "function") { 569 | throw TypeError("Not a function"); 570 | } 571 | 572 | reject(msg); 573 | }); 574 | }); 575 | builtInProp(Promise, "all", function Promise$all(arr) { 576 | var Constructor = this; // spec mandated checks 577 | 578 | if (ToString.call(arr) != "[object Array]") { 579 | return Constructor.reject(TypeError("Not an array")); 580 | } 581 | 582 | if (arr.length === 0) { 583 | return Constructor.resolve([]); 584 | } 585 | 586 | return new Constructor(function executor(resolve, reject) { 587 | if (typeof resolve != "function" || typeof reject != "function") { 588 | throw TypeError("Not a function"); 589 | } 590 | 591 | var len = arr.length, 592 | msgs = Array(len), 593 | count = 0; 594 | iteratePromises(Constructor, arr, function resolver(idx, msg) { 595 | msgs[idx] = msg; 596 | 597 | if (++count === len) { 598 | resolve(msgs); 599 | } 600 | }, reject); 601 | }); 602 | }); 603 | builtInProp(Promise, "race", function Promise$race(arr) { 604 | var Constructor = this; // spec mandated checks 605 | 606 | if (ToString.call(arr) != "[object Array]") { 607 | return Constructor.reject(TypeError("Not an array")); 608 | } 609 | 610 | return new Constructor(function executor(resolve, reject) { 611 | if (typeof resolve != "function" || typeof reject != "function") { 612 | throw TypeError("Not a function"); 613 | } 614 | 615 | iteratePromises(Constructor, arr, function resolver(idx, msg) { 616 | resolve(msg); 617 | }, reject); 618 | }); 619 | }); 620 | return Promise; 621 | }); 622 | }); 623 | 624 | /** 625 | * @module lib/callbacks 626 | */ 627 | var callbackMap = new WeakMap(); 628 | /** 629 | * Store a callback for a method or event for a player. 630 | * 631 | * @param {Player} player The player object. 632 | * @param {string} name The method or event name. 633 | * @param {(function(this:Player, *): void|{resolve: function, reject: function})} callback 634 | * The callback to call or an object with resolve and reject functions for a promise. 635 | * @return {void} 636 | */ 637 | 638 | function storeCallback(player, name, callback) { 639 | var playerCallbacks = callbackMap.get(player.element) || {}; 640 | 641 | if (!(name in playerCallbacks)) { 642 | playerCallbacks[name] = []; 643 | } 644 | 645 | playerCallbacks[name].push(callback); 646 | callbackMap.set(player.element, playerCallbacks); 647 | } 648 | /** 649 | * Get the callbacks for a player and event or method. 650 | * 651 | * @param {Player} player The player object. 652 | * @param {string} name The method or event name 653 | * @return {function[]} 654 | */ 655 | 656 | function getCallbacks(player, name) { 657 | var playerCallbacks = callbackMap.get(player.element) || {}; 658 | return playerCallbacks[name] || []; 659 | } 660 | /** 661 | * Remove a stored callback for a method or event for a player. 662 | * 663 | * @param {Player} player The player object. 664 | * @param {string} name The method or event name 665 | * @param {function} [callback] The specific callback to remove. 666 | * @return {boolean} Was this the last callback? 667 | */ 668 | 669 | function removeCallback(player, name, callback) { 670 | var playerCallbacks = callbackMap.get(player.element) || {}; 671 | 672 | if (!playerCallbacks[name]) { 673 | return true; 674 | } // If no callback is passed, remove all callbacks for the event 675 | 676 | 677 | if (!callback) { 678 | playerCallbacks[name] = []; 679 | callbackMap.set(player.element, playerCallbacks); 680 | return true; 681 | } 682 | 683 | var index = playerCallbacks[name].indexOf(callback); 684 | 685 | if (index !== -1) { 686 | playerCallbacks[name].splice(index, 1); 687 | } 688 | 689 | callbackMap.set(player.element, playerCallbacks); 690 | return playerCallbacks[name] && playerCallbacks[name].length === 0; 691 | } 692 | /** 693 | * Return the first stored callback for a player and event or method. 694 | * 695 | * @param {Player} player The player object. 696 | * @param {string} name The method or event name. 697 | * @return {function} The callback, or false if there were none 698 | */ 699 | 700 | function shiftCallbacks(player, name) { 701 | var playerCallbacks = getCallbacks(player, name); 702 | 703 | if (playerCallbacks.length < 1) { 704 | return false; 705 | } 706 | 707 | var callback = playerCallbacks.shift(); 708 | removeCallback(player, name, callback); 709 | return callback; 710 | } 711 | /** 712 | * Move callbacks associated with an element to another element. 713 | * 714 | * @param {HTMLElement} oldElement The old element. 715 | * @param {HTMLElement} newElement The new element. 716 | * @return {void} 717 | */ 718 | 719 | function swapCallbacks(oldElement, newElement) { 720 | var playerCallbacks = callbackMap.get(oldElement); 721 | callbackMap.set(newElement, playerCallbacks); 722 | callbackMap.delete(oldElement); 723 | } 724 | 725 | /** 726 | * @module lib/embed 727 | */ 728 | var oEmbedParameters = ['autopause', 'autoplay', 'background', 'byline', 'color', 'controls', 'dnt', 'height', 'id', 'loop', 'maxheight', 'maxwidth', 'muted', 'playsinline', 'portrait', 'responsive', 'speed', 'texttrack', 'title', 'transparent', 'url', 'width']; 729 | /** 730 | * Get the 'data-vimeo'-prefixed attributes from an element as an object. 731 | * 732 | * @param {HTMLElement} element The element. 733 | * @param {Object} [defaults={}] The default values to use. 734 | * @return {Object} 735 | */ 736 | 737 | function getOEmbedParameters(element) { 738 | var defaults = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 739 | return oEmbedParameters.reduce(function (params, param) { 740 | var value = element.getAttribute("data-vimeo-".concat(param)); 741 | 742 | if (value || value === '') { 743 | params[param] = value === '' ? 1 : value; 744 | } 745 | 746 | return params; 747 | }, defaults); 748 | } 749 | /** 750 | * Create an embed from oEmbed data inside an element. 751 | * 752 | * @param {object} data The oEmbed data. 753 | * @param {HTMLElement} element The element to put the iframe in. 754 | * @return {HTMLIFrameElement} The iframe embed. 755 | */ 756 | 757 | function createEmbed(_ref, element) { 758 | var html = _ref.html; 759 | 760 | if (!element) { 761 | throw new TypeError('An element must be provided'); 762 | } 763 | 764 | if (element.getAttribute('data-vimeo-initialized') !== null) { 765 | return element.querySelector('iframe'); 766 | } 767 | 768 | var div = document.createElement('div'); 769 | div.innerHTML = html; 770 | element.appendChild(div.firstChild); 771 | element.setAttribute('data-vimeo-initialized', 'true'); 772 | return element.querySelector('iframe'); 773 | } 774 | /** 775 | * Make an oEmbed call for the specified URL. 776 | * 777 | * @param {string} videoUrl The vimeo.com url for the video. 778 | * @param {Object} [params] Parameters to pass to oEmbed. 779 | * @param {HTMLElement} element The element. 780 | * @return {Promise} 781 | */ 782 | 783 | function getOEmbedData(videoUrl) { 784 | var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 785 | var element = arguments.length > 2 ? arguments[2] : undefined; 786 | return new Promise(function (resolve, reject) { 787 | if (!isVimeoUrl(videoUrl)) { 788 | throw new TypeError("\u201C".concat(videoUrl, "\u201D is not a vimeo.com url.")); 789 | } 790 | 791 | var url = "https://vimeo.com/api/oembed.json?url=".concat(encodeURIComponent(videoUrl)); 792 | 793 | for (var param in params) { 794 | if (params.hasOwnProperty(param)) { 795 | url += "&".concat(param, "=").concat(encodeURIComponent(params[param])); 796 | } 797 | } 798 | 799 | var xhr = 'XDomainRequest' in window ? new XDomainRequest() : new XMLHttpRequest(); 800 | xhr.open('GET', url, true); 801 | 802 | xhr.onload = function () { 803 | if (xhr.status === 404) { 804 | reject(new Error("\u201C".concat(videoUrl, "\u201D was not found."))); 805 | return; 806 | } 807 | 808 | if (xhr.status === 403) { 809 | reject(new Error("\u201C".concat(videoUrl, "\u201D is not embeddable."))); 810 | return; 811 | } 812 | 813 | try { 814 | var json = JSON.parse(xhr.responseText); // Check api response for 403 on oembed 815 | 816 | if (json.domain_status_code === 403) { 817 | // We still want to create the embed to give users visual feedback 818 | createEmbed(json, element); 819 | reject(new Error("\u201C".concat(videoUrl, "\u201D is not embeddable."))); 820 | return; 821 | } 822 | 823 | resolve(json); 824 | } catch (error) { 825 | reject(error); 826 | } 827 | }; 828 | 829 | xhr.onerror = function () { 830 | var status = xhr.status ? " (".concat(xhr.status, ")") : ''; 831 | reject(new Error("There was an error fetching the embed code from Vimeo".concat(status, "."))); 832 | }; 833 | 834 | xhr.send(); 835 | }); 836 | } 837 | /** 838 | * Initialize all embeds within a specific element 839 | * 840 | * @param {HTMLElement} [parent=document] The parent element. 841 | * @return {void} 842 | */ 843 | 844 | function initializeEmbeds() { 845 | var parent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : document; 846 | var elements = [].slice.call(parent.querySelectorAll('[data-vimeo-id], [data-vimeo-url]')); 847 | 848 | var handleError = function handleError(error) { 849 | if ('console' in window && console.error) { 850 | console.error("There was an error creating an embed: ".concat(error)); 851 | } 852 | }; 853 | 854 | elements.forEach(function (element) { 855 | try { 856 | // Skip any that have data-vimeo-defer 857 | if (element.getAttribute('data-vimeo-defer') !== null) { 858 | return; 859 | } 860 | 861 | var params = getOEmbedParameters(element); 862 | var url = getVimeoUrl(params); 863 | getOEmbedData(url, params, element).then(function (data) { 864 | return createEmbed(data, element); 865 | }).catch(handleError); 866 | } catch (error) { 867 | handleError(error); 868 | } 869 | }); 870 | } 871 | /** 872 | * Resize embeds when messaged by the player. 873 | * 874 | * @param {HTMLElement} [parent=document] The parent element. 875 | * @return {void} 876 | */ 877 | 878 | function resizeEmbeds() { 879 | var parent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : document; 880 | 881 | // Prevent execution if users include the player.js script multiple times. 882 | if (window.VimeoPlayerResizeEmbeds_) { 883 | return; 884 | } 885 | 886 | window.VimeoPlayerResizeEmbeds_ = true; 887 | 888 | var onMessage = function onMessage(event) { 889 | if (!isVimeoUrl(event.origin)) { 890 | return; 891 | } // 'spacechange' is fired only on embeds with cards 892 | 893 | 894 | if (!event.data || event.data.event !== 'spacechange') { 895 | return; 896 | } 897 | 898 | var iframes = parent.querySelectorAll('iframe'); 899 | 900 | for (var i = 0; i < iframes.length; i++) { 901 | if (iframes[i].contentWindow !== event.source) { 902 | continue; 903 | } // Change padding-bottom of the enclosing div to accommodate 904 | // card carousel without distorting aspect ratio 905 | 906 | 907 | var space = iframes[i].parentElement; 908 | space.style.paddingBottom = "".concat(event.data.data[0].bottom, "px"); 909 | break; 910 | } 911 | }; 912 | 913 | if (window.addEventListener) { 914 | window.addEventListener('message', onMessage, false); 915 | } else if (window.attachEvent) { 916 | window.attachEvent('onmessage', onMessage); 917 | } 918 | } 919 | 920 | /** 921 | * @module lib/postmessage 922 | */ 923 | /** 924 | * Parse a message received from postMessage. 925 | * 926 | * @param {*} data The data received from postMessage. 927 | * @return {object} 928 | */ 929 | 930 | function parseMessageData(data) { 931 | if (typeof data === 'string') { 932 | try { 933 | data = JSON.parse(data); 934 | } catch (error) { 935 | // If the message cannot be parsed, throw the error as a warning 936 | console.warn(error); 937 | return {}; 938 | } 939 | } 940 | 941 | return data; 942 | } 943 | /** 944 | * Post a message to the specified target. 945 | * 946 | * @param {Player} player The player object to use. 947 | * @param {string} method The API method to call. 948 | * @param {object} params The parameters to send to the player. 949 | * @return {void} 950 | */ 951 | 952 | function postMessage(player, method, params) { 953 | if (!player.element.contentWindow || !player.element.contentWindow.postMessage) { 954 | return; 955 | } 956 | 957 | var message = { 958 | method: method 959 | }; 960 | 961 | if (params !== undefined) { 962 | message.value = params; 963 | } // IE 8 and 9 do not support passing messages, so stringify them 964 | 965 | 966 | var ieVersion = parseFloat(navigator.userAgent.toLowerCase().replace(/^.*msie (\d+).*$/, '$1')); 967 | 968 | if (ieVersion >= 8 && ieVersion < 10) { 969 | message = JSON.stringify(message); 970 | } 971 | 972 | player.element.contentWindow.postMessage(message, player.origin); 973 | } 974 | /** 975 | * Parse the data received from a message event. 976 | * 977 | * @param {Player} player The player that received the message. 978 | * @param {(Object|string)} data The message data. Strings will be parsed into JSON. 979 | * @return {void} 980 | */ 981 | 982 | function processData(player, data) { 983 | data = parseMessageData(data); 984 | var callbacks = []; 985 | var param; 986 | 987 | if (data.event) { 988 | if (data.event === 'error') { 989 | var promises = getCallbacks(player, data.data.method); 990 | promises.forEach(function (promise) { 991 | var error = new Error(data.data.message); 992 | error.name = data.data.name; 993 | promise.reject(error); 994 | removeCallback(player, data.data.method, promise); 995 | }); 996 | } 997 | 998 | callbacks = getCallbacks(player, "event:".concat(data.event)); 999 | param = data.data; 1000 | } else if (data.method) { 1001 | var callback = shiftCallbacks(player, data.method); 1002 | 1003 | if (callback) { 1004 | callbacks.push(callback); 1005 | param = data.value; 1006 | } 1007 | } 1008 | 1009 | callbacks.forEach(function (callback) { 1010 | try { 1011 | if (typeof callback === 'function') { 1012 | callback.call(player, param); 1013 | return; 1014 | } 1015 | 1016 | callback.resolve(param); 1017 | } catch (e) {// empty 1018 | } 1019 | }); 1020 | } 1021 | 1022 | var playerMap = new WeakMap(); 1023 | var readyMap = new WeakMap(); 1024 | 1025 | var Player = 1026 | /*#__PURE__*/ 1027 | function () { 1028 | /** 1029 | * Create a Player. 1030 | * 1031 | * @param {(HTMLIFrameElement|HTMLElement|string|jQuery)} element A reference to the Vimeo 1032 | * player iframe, and id, or a jQuery object. 1033 | * @param {object} [options] oEmbed parameters to use when creating an embed in the element. 1034 | * @return {Player} 1035 | */ 1036 | function Player(element) { 1037 | var _this = this; 1038 | 1039 | var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 1040 | 1041 | _classCallCheck(this, Player); 1042 | 1043 | /* global jQuery */ 1044 | if (window.jQuery && element instanceof jQuery) { 1045 | if (element.length > 1 && window.console && console.warn) { 1046 | console.warn('A jQuery object with multiple elements was passed, using the first element.'); 1047 | } 1048 | 1049 | element = element[0]; 1050 | } // Find an element by ID 1051 | 1052 | 1053 | if (typeof document !== 'undefined' && typeof element === 'string') { 1054 | element = document.getElementById(element); 1055 | } // Not an element! 1056 | 1057 | 1058 | if (!isDomElement(element)) { 1059 | throw new TypeError('You must pass either a valid element or a valid id.'); 1060 | } 1061 | 1062 | var win = element.ownerDocument.defaultView; // Already initialized an embed in this div, so grab the iframe 1063 | 1064 | if (element.nodeName !== 'IFRAME') { 1065 | var iframe = element.querySelector('iframe'); 1066 | 1067 | if (iframe) { 1068 | element = iframe; 1069 | } 1070 | } // iframe url is not a Vimeo url 1071 | 1072 | 1073 | if (element.nodeName === 'IFRAME' && !isVimeoUrl(element.getAttribute('src') || '')) { 1074 | throw new Error('The player element passed isn’t a Vimeo embed.'); 1075 | } // If there is already a player object in the map, return that 1076 | 1077 | 1078 | if (playerMap.has(element)) { 1079 | return playerMap.get(element); 1080 | } 1081 | 1082 | this.element = element; 1083 | this.origin = '*'; 1084 | var readyPromise = new npo_src(function (resolve, reject) { 1085 | var onMessage = function onMessage(event) { 1086 | if (!isVimeoUrl(event.origin) || _this.element.contentWindow !== event.source) { 1087 | return; 1088 | } 1089 | 1090 | if (_this.origin === '*') { 1091 | _this.origin = event.origin; 1092 | } 1093 | 1094 | var data = parseMessageData(event.data); 1095 | var isError = data && data.event === 'error'; 1096 | var isReadyError = isError && data.data && data.data.method === 'ready'; 1097 | 1098 | if (isReadyError) { 1099 | var error = new Error(data.data.message); 1100 | error.name = data.data.name; 1101 | reject(error); 1102 | return; 1103 | } 1104 | 1105 | var isReadyEvent = data && data.event === 'ready'; 1106 | var isPingResponse = data && data.method === 'ping'; 1107 | 1108 | if (isReadyEvent || isPingResponse) { 1109 | _this.element.setAttribute('data-ready', 'true'); 1110 | 1111 | resolve(); 1112 | return; 1113 | } 1114 | 1115 | processData(_this, data); 1116 | }; 1117 | 1118 | if (win.addEventListener) { 1119 | win.addEventListener('message', onMessage, false); 1120 | } else if (win.attachEvent) { 1121 | win.attachEvent('onmessage', onMessage); 1122 | } 1123 | 1124 | if (_this.element.nodeName !== 'IFRAME') { 1125 | var params = getOEmbedParameters(element, options); 1126 | var url = getVimeoUrl(params); 1127 | getOEmbedData(url, params, element).then(function (data) { 1128 | var iframe = createEmbed(data, element); // Overwrite element with the new iframe, 1129 | // but store reference to the original element 1130 | 1131 | _this.element = iframe; 1132 | _this._originalElement = element; 1133 | swapCallbacks(element, iframe); 1134 | playerMap.set(_this.element, _this); 1135 | return data; 1136 | }).catch(reject); 1137 | } 1138 | }); // Store a copy of this Player in the map 1139 | 1140 | readyMap.set(this, readyPromise); 1141 | playerMap.set(this.element, this); // Send a ping to the iframe so the ready promise will be resolved if 1142 | // the player is already ready. 1143 | 1144 | if (this.element.nodeName === 'IFRAME') { 1145 | postMessage(this, 'ping'); 1146 | } 1147 | 1148 | return this; 1149 | } 1150 | /** 1151 | * Get a promise for a method. 1152 | * 1153 | * @param {string} name The API method to call. 1154 | * @param {Object} [args={}] Arguments to send via postMessage. 1155 | * @return {Promise} 1156 | */ 1157 | 1158 | 1159 | _createClass(Player, [{ 1160 | key: "callMethod", 1161 | value: function callMethod(name) { 1162 | var _this2 = this; 1163 | 1164 | var args = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 1165 | return new npo_src(function (resolve, reject) { 1166 | // We are storing the resolve/reject handlers to call later, so we 1167 | // can’t return here. 1168 | // eslint-disable-next-line promise/always-return 1169 | return _this2.ready().then(function () { 1170 | storeCallback(_this2, name, { 1171 | resolve: resolve, 1172 | reject: reject 1173 | }); 1174 | postMessage(_this2, name, args); 1175 | }).catch(reject); 1176 | }); 1177 | } 1178 | /** 1179 | * Get a promise for the value of a player property. 1180 | * 1181 | * @param {string} name The property name 1182 | * @return {Promise} 1183 | */ 1184 | 1185 | }, { 1186 | key: "get", 1187 | value: function get(name) { 1188 | var _this3 = this; 1189 | 1190 | return new npo_src(function (resolve, reject) { 1191 | name = getMethodName(name, 'get'); // We are storing the resolve/reject handlers to call later, so we 1192 | // can’t return here. 1193 | // eslint-disable-next-line promise/always-return 1194 | 1195 | return _this3.ready().then(function () { 1196 | storeCallback(_this3, name, { 1197 | resolve: resolve, 1198 | reject: reject 1199 | }); 1200 | postMessage(_this3, name); 1201 | }).catch(reject); 1202 | }); 1203 | } 1204 | /** 1205 | * Get a promise for setting the value of a player property. 1206 | * 1207 | * @param {string} name The API method to call. 1208 | * @param {mixed} value The value to set. 1209 | * @return {Promise} 1210 | */ 1211 | 1212 | }, { 1213 | key: "set", 1214 | value: function set(name, value) { 1215 | var _this4 = this; 1216 | 1217 | return new npo_src(function (resolve, reject) { 1218 | name = getMethodName(name, 'set'); 1219 | 1220 | if (value === undefined || value === null) { 1221 | throw new TypeError('There must be a value to set.'); 1222 | } // We are storing the resolve/reject handlers to call later, so we 1223 | // can’t return here. 1224 | // eslint-disable-next-line promise/always-return 1225 | 1226 | 1227 | return _this4.ready().then(function () { 1228 | storeCallback(_this4, name, { 1229 | resolve: resolve, 1230 | reject: reject 1231 | }); 1232 | postMessage(_this4, name, value); 1233 | }).catch(reject); 1234 | }); 1235 | } 1236 | /** 1237 | * Add an event listener for the specified event. Will call the 1238 | * callback with a single parameter, `data`, that contains the data for 1239 | * that event. 1240 | * 1241 | * @param {string} eventName The name of the event. 1242 | * @param {function(*)} callback The function to call when the event fires. 1243 | * @return {void} 1244 | */ 1245 | 1246 | }, { 1247 | key: "on", 1248 | value: function on(eventName, callback) { 1249 | if (!eventName) { 1250 | throw new TypeError('You must pass an event name.'); 1251 | } 1252 | 1253 | if (!callback) { 1254 | throw new TypeError('You must pass a callback function.'); 1255 | } 1256 | 1257 | if (typeof callback !== 'function') { 1258 | throw new TypeError('The callback must be a function.'); 1259 | } 1260 | 1261 | var callbacks = getCallbacks(this, "event:".concat(eventName)); 1262 | 1263 | if (callbacks.length === 0) { 1264 | this.callMethod('addEventListener', eventName).catch(function () {// Ignore the error. There will be an error event fired that 1265 | // will trigger the error callback if they are listening. 1266 | }); 1267 | } 1268 | 1269 | storeCallback(this, "event:".concat(eventName), callback); 1270 | } 1271 | /** 1272 | * Remove an event listener for the specified event. Will remove all 1273 | * listeners for that event if a `callback` isn’t passed, or only that 1274 | * specific callback if it is passed. 1275 | * 1276 | * @param {string} eventName The name of the event. 1277 | * @param {function} [callback] The specific callback to remove. 1278 | * @return {void} 1279 | */ 1280 | 1281 | }, { 1282 | key: "off", 1283 | value: function off(eventName, callback) { 1284 | if (!eventName) { 1285 | throw new TypeError('You must pass an event name.'); 1286 | } 1287 | 1288 | if (callback && typeof callback !== 'function') { 1289 | throw new TypeError('The callback must be a function.'); 1290 | } 1291 | 1292 | var lastCallback = removeCallback(this, "event:".concat(eventName), callback); // If there are no callbacks left, remove the listener 1293 | 1294 | if (lastCallback) { 1295 | this.callMethod('removeEventListener', eventName).catch(function (e) {// Ignore the error. There will be an error event fired that 1296 | // will trigger the error callback if they are listening. 1297 | }); 1298 | } 1299 | } 1300 | /** 1301 | * A promise to load a new video. 1302 | * 1303 | * @promise LoadVideoPromise 1304 | * @fulfill {number} The video with this id successfully loaded. 1305 | * @reject {TypeError} The id was not a number. 1306 | */ 1307 | 1308 | /** 1309 | * Load a new video into this embed. The promise will be resolved if 1310 | * the video is successfully loaded, or it will be rejected if it could 1311 | * not be loaded. 1312 | * 1313 | * @param {number|object} options The id of the video or an object with embed options. 1314 | * @return {LoadVideoPromise} 1315 | */ 1316 | 1317 | }, { 1318 | key: "loadVideo", 1319 | value: function loadVideo(options) { 1320 | return this.callMethod('loadVideo', options); 1321 | } 1322 | /** 1323 | * A promise to perform an action when the Player is ready. 1324 | * 1325 | * @todo document errors 1326 | * @promise LoadVideoPromise 1327 | * @fulfill {void} 1328 | */ 1329 | 1330 | /** 1331 | * Trigger a function when the player iframe has initialized. You do not 1332 | * need to wait for `ready` to trigger to begin adding event listeners 1333 | * or calling other methods. 1334 | * 1335 | * @return {ReadyPromise} 1336 | */ 1337 | 1338 | }, { 1339 | key: "ready", 1340 | value: function ready() { 1341 | var readyPromise = readyMap.get(this) || new npo_src(function (resolve, reject) { 1342 | reject(new Error('Unknown player. Probably unloaded.')); 1343 | }); 1344 | return npo_src.resolve(readyPromise); 1345 | } 1346 | /** 1347 | * A promise to add a cue point to the player. 1348 | * 1349 | * @promise AddCuePointPromise 1350 | * @fulfill {string} The id of the cue point to use for removeCuePoint. 1351 | * @reject {RangeError} the time was less than 0 or greater than the 1352 | * video’s duration. 1353 | * @reject {UnsupportedError} Cue points are not supported with the current 1354 | * player or browser. 1355 | */ 1356 | 1357 | /** 1358 | * Add a cue point to the player. 1359 | * 1360 | * @param {number} time The time for the cue point. 1361 | * @param {object} [data] Arbitrary data to be returned with the cue point. 1362 | * @return {AddCuePointPromise} 1363 | */ 1364 | 1365 | }, { 1366 | key: "addCuePoint", 1367 | value: function addCuePoint(time) { 1368 | var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 1369 | return this.callMethod('addCuePoint', { 1370 | time: time, 1371 | data: data 1372 | }); 1373 | } 1374 | /** 1375 | * A promise to remove a cue point from the player. 1376 | * 1377 | * @promise AddCuePointPromise 1378 | * @fulfill {string} The id of the cue point that was removed. 1379 | * @reject {InvalidCuePoint} The cue point with the specified id was not 1380 | * found. 1381 | * @reject {UnsupportedError} Cue points are not supported with the current 1382 | * player or browser. 1383 | */ 1384 | 1385 | /** 1386 | * Remove a cue point from the video. 1387 | * 1388 | * @param {string} id The id of the cue point to remove. 1389 | * @return {RemoveCuePointPromise} 1390 | */ 1391 | 1392 | }, { 1393 | key: "removeCuePoint", 1394 | value: function removeCuePoint(id) { 1395 | return this.callMethod('removeCuePoint', id); 1396 | } 1397 | /** 1398 | * A representation of a text track on a video. 1399 | * 1400 | * @typedef {Object} VimeoTextTrack 1401 | * @property {string} language The ISO language code. 1402 | * @property {string} kind The kind of track it is (captions or subtitles). 1403 | * @property {string} label The human‐readable label for the track. 1404 | */ 1405 | 1406 | /** 1407 | * A promise to enable a text track. 1408 | * 1409 | * @promise EnableTextTrackPromise 1410 | * @fulfill {VimeoTextTrack} The text track that was enabled. 1411 | * @reject {InvalidTrackLanguageError} No track was available with the 1412 | * specified language. 1413 | * @reject {InvalidTrackError} No track was available with the specified 1414 | * language and kind. 1415 | */ 1416 | 1417 | /** 1418 | * Enable the text track with the specified language, and optionally the 1419 | * specified kind (captions or subtitles). 1420 | * 1421 | * When set via the API, the track language will not change the viewer’s 1422 | * stored preference. 1423 | * 1424 | * @param {string} language The two‐letter language code. 1425 | * @param {string} [kind] The kind of track to enable (captions or subtitles). 1426 | * @return {EnableTextTrackPromise} 1427 | */ 1428 | 1429 | }, { 1430 | key: "enableTextTrack", 1431 | value: function enableTextTrack(language, kind) { 1432 | if (!language) { 1433 | throw new TypeError('You must pass a language.'); 1434 | } 1435 | 1436 | return this.callMethod('enableTextTrack', { 1437 | language: language, 1438 | kind: kind 1439 | }); 1440 | } 1441 | /** 1442 | * A promise to disable the active text track. 1443 | * 1444 | * @promise DisableTextTrackPromise 1445 | * @fulfill {void} The track was disabled. 1446 | */ 1447 | 1448 | /** 1449 | * Disable the currently-active text track. 1450 | * 1451 | * @return {DisableTextTrackPromise} 1452 | */ 1453 | 1454 | }, { 1455 | key: "disableTextTrack", 1456 | value: function disableTextTrack() { 1457 | return this.callMethod('disableTextTrack'); 1458 | } 1459 | /** 1460 | * A promise to pause the video. 1461 | * 1462 | * @promise PausePromise 1463 | * @fulfill {void} The video was paused. 1464 | */ 1465 | 1466 | /** 1467 | * Pause the video if it’s playing. 1468 | * 1469 | * @return {PausePromise} 1470 | */ 1471 | 1472 | }, { 1473 | key: "pause", 1474 | value: function pause() { 1475 | return this.callMethod('pause'); 1476 | } 1477 | /** 1478 | * A promise to play the video. 1479 | * 1480 | * @promise PlayPromise 1481 | * @fulfill {void} The video was played. 1482 | */ 1483 | 1484 | /** 1485 | * Play the video if it’s paused. **Note:** on iOS and some other 1486 | * mobile devices, you cannot programmatically trigger play. Once the 1487 | * viewer has tapped on the play button in the player, however, you 1488 | * will be able to use this function. 1489 | * 1490 | * @return {PlayPromise} 1491 | */ 1492 | 1493 | }, { 1494 | key: "play", 1495 | value: function play() { 1496 | return this.callMethod('play'); 1497 | } 1498 | /** 1499 | * A promise to unload the video. 1500 | * 1501 | * @promise UnloadPromise 1502 | * @fulfill {void} The video was unloaded. 1503 | */ 1504 | 1505 | /** 1506 | * Return the player to its initial state. 1507 | * 1508 | * @return {UnloadPromise} 1509 | */ 1510 | 1511 | }, { 1512 | key: "unload", 1513 | value: function unload() { 1514 | return this.callMethod('unload'); 1515 | } 1516 | /** 1517 | * Cleanup the player and remove it from the DOM 1518 | * 1519 | * It won't be usable and a new one should be constructed 1520 | * in order to do any operations. 1521 | * 1522 | * @return {Promise} 1523 | */ 1524 | 1525 | }, { 1526 | key: "destroy", 1527 | value: function destroy() { 1528 | var _this5 = this; 1529 | 1530 | return new npo_src(function (resolve) { 1531 | readyMap.delete(_this5); 1532 | playerMap.delete(_this5.element); 1533 | 1534 | if (_this5._originalElement) { 1535 | playerMap.delete(_this5._originalElement); 1536 | 1537 | _this5._originalElement.removeAttribute('data-vimeo-initialized'); 1538 | } 1539 | 1540 | if (_this5.element && _this5.element.nodeName === 'IFRAME' && _this5.element.parentNode) { 1541 | _this5.element.parentNode.removeChild(_this5.element); 1542 | } 1543 | 1544 | resolve(); 1545 | }); 1546 | } 1547 | /** 1548 | * A promise to get the autopause behavior of the video. 1549 | * 1550 | * @promise GetAutopausePromise 1551 | * @fulfill {boolean} Whether autopause is turned on or off. 1552 | * @reject {UnsupportedError} Autopause is not supported with the current 1553 | * player or browser. 1554 | */ 1555 | 1556 | /** 1557 | * Get the autopause behavior for this player. 1558 | * 1559 | * @return {GetAutopausePromise} 1560 | */ 1561 | 1562 | }, { 1563 | key: "getAutopause", 1564 | value: function getAutopause() { 1565 | return this.get('autopause'); 1566 | } 1567 | /** 1568 | * A promise to set the autopause behavior of the video. 1569 | * 1570 | * @promise SetAutopausePromise 1571 | * @fulfill {boolean} Whether autopause is turned on or off. 1572 | * @reject {UnsupportedError} Autopause is not supported with the current 1573 | * player or browser. 1574 | */ 1575 | 1576 | /** 1577 | * Enable or disable the autopause behavior of this player. 1578 | * 1579 | * By default, when another video is played in the same browser, this 1580 | * player will automatically pause. Unless you have a specific reason 1581 | * for doing so, we recommend that you leave autopause set to the 1582 | * default (`true`). 1583 | * 1584 | * @param {boolean} autopause 1585 | * @return {SetAutopausePromise} 1586 | */ 1587 | 1588 | }, { 1589 | key: "setAutopause", 1590 | value: function setAutopause(autopause) { 1591 | return this.set('autopause', autopause); 1592 | } 1593 | /** 1594 | * A promise to get the buffered property of the video. 1595 | * 1596 | * @promise GetBufferedPromise 1597 | * @fulfill {Array} Buffered Timeranges converted to an Array. 1598 | */ 1599 | 1600 | /** 1601 | * Get the buffered property of the video. 1602 | * 1603 | * @return {GetBufferedPromise} 1604 | */ 1605 | 1606 | }, { 1607 | key: "getBuffered", 1608 | value: function getBuffered() { 1609 | return this.get('buffered'); 1610 | } 1611 | /** 1612 | * A promise to get the color of the player. 1613 | * 1614 | * @promise GetColorPromise 1615 | * @fulfill {string} The hex color of the player. 1616 | */ 1617 | 1618 | /** 1619 | * Get the color for this player. 1620 | * 1621 | * @return {GetColorPromise} 1622 | */ 1623 | 1624 | }, { 1625 | key: "getColor", 1626 | value: function getColor() { 1627 | return this.get('color'); 1628 | } 1629 | /** 1630 | * A promise to set the color of the player. 1631 | * 1632 | * @promise SetColorPromise 1633 | * @fulfill {string} The color was successfully set. 1634 | * @reject {TypeError} The string was not a valid hex or rgb color. 1635 | * @reject {ContrastError} The color was set, but the contrast is 1636 | * outside of the acceptable range. 1637 | * @reject {EmbedSettingsError} The owner of the player has chosen to 1638 | * use a specific color. 1639 | */ 1640 | 1641 | /** 1642 | * Set the color of this player to a hex or rgb string. Setting the 1643 | * color may fail if the owner of the video has set their embed 1644 | * preferences to force a specific color. 1645 | * 1646 | * @param {string} color The hex or rgb color string to set. 1647 | * @return {SetColorPromise} 1648 | */ 1649 | 1650 | }, { 1651 | key: "setColor", 1652 | value: function setColor(color) { 1653 | return this.set('color', color); 1654 | } 1655 | /** 1656 | * A representation of a cue point. 1657 | * 1658 | * @typedef {Object} VimeoCuePoint 1659 | * @property {number} time The time of the cue point. 1660 | * @property {object} data The data passed when adding the cue point. 1661 | * @property {string} id The unique id for use with removeCuePoint. 1662 | */ 1663 | 1664 | /** 1665 | * A promise to get the cue points of a video. 1666 | * 1667 | * @promise GetCuePointsPromise 1668 | * @fulfill {VimeoCuePoint[]} The cue points added to the video. 1669 | * @reject {UnsupportedError} Cue points are not supported with the current 1670 | * player or browser. 1671 | */ 1672 | 1673 | /** 1674 | * Get an array of the cue points added to the video. 1675 | * 1676 | * @return {GetCuePointsPromise} 1677 | */ 1678 | 1679 | }, { 1680 | key: "getCuePoints", 1681 | value: function getCuePoints() { 1682 | return this.get('cuePoints'); 1683 | } 1684 | /** 1685 | * A promise to get the current time of the video. 1686 | * 1687 | * @promise GetCurrentTimePromise 1688 | * @fulfill {number} The current time in seconds. 1689 | */ 1690 | 1691 | /** 1692 | * Get the current playback position in seconds. 1693 | * 1694 | * @return {GetCurrentTimePromise} 1695 | */ 1696 | 1697 | }, { 1698 | key: "getCurrentTime", 1699 | value: function getCurrentTime() { 1700 | return this.get('currentTime'); 1701 | } 1702 | /** 1703 | * A promise to set the current time of the video. 1704 | * 1705 | * @promise SetCurrentTimePromise 1706 | * @fulfill {number} The actual current time that was set. 1707 | * @reject {RangeError} the time was less than 0 or greater than the 1708 | * video’s duration. 1709 | */ 1710 | 1711 | /** 1712 | * Set the current playback position in seconds. If the player was 1713 | * paused, it will remain paused. Likewise, if the player was playing, 1714 | * it will resume playing once the video has buffered. 1715 | * 1716 | * You can provide an accurate time and the player will attempt to seek 1717 | * to as close to that time as possible. The exact time will be the 1718 | * fulfilled value of the promise. 1719 | * 1720 | * @param {number} currentTime 1721 | * @return {SetCurrentTimePromise} 1722 | */ 1723 | 1724 | }, { 1725 | key: "setCurrentTime", 1726 | value: function setCurrentTime(currentTime) { 1727 | return this.set('currentTime', currentTime); 1728 | } 1729 | /** 1730 | * A promise to get the duration of the video. 1731 | * 1732 | * @promise GetDurationPromise 1733 | * @fulfill {number} The duration in seconds. 1734 | */ 1735 | 1736 | /** 1737 | * Get the duration of the video in seconds. It will be rounded to the 1738 | * nearest second before playback begins, and to the nearest thousandth 1739 | * of a second after playback begins. 1740 | * 1741 | * @return {GetDurationPromise} 1742 | */ 1743 | 1744 | }, { 1745 | key: "getDuration", 1746 | value: function getDuration() { 1747 | return this.get('duration'); 1748 | } 1749 | /** 1750 | * A promise to get the ended state of the video. 1751 | * 1752 | * @promise GetEndedPromise 1753 | * @fulfill {boolean} Whether or not the video has ended. 1754 | */ 1755 | 1756 | /** 1757 | * Get the ended state of the video. The video has ended if 1758 | * `currentTime === duration`. 1759 | * 1760 | * @return {GetEndedPromise} 1761 | */ 1762 | 1763 | }, { 1764 | key: "getEnded", 1765 | value: function getEnded() { 1766 | return this.get('ended'); 1767 | } 1768 | /** 1769 | * A promise to get the loop state of the player. 1770 | * 1771 | * @promise GetLoopPromise 1772 | * @fulfill {boolean} Whether or not the player is set to loop. 1773 | */ 1774 | 1775 | /** 1776 | * Get the loop state of the player. 1777 | * 1778 | * @return {GetLoopPromise} 1779 | */ 1780 | 1781 | }, { 1782 | key: "getLoop", 1783 | value: function getLoop() { 1784 | return this.get('loop'); 1785 | } 1786 | /** 1787 | * A promise to set the loop state of the player. 1788 | * 1789 | * @promise SetLoopPromise 1790 | * @fulfill {boolean} The loop state that was set. 1791 | */ 1792 | 1793 | /** 1794 | * Set the loop state of the player. When set to `true`, the player 1795 | * will start over immediately once playback ends. 1796 | * 1797 | * @param {boolean} loop 1798 | * @return {SetLoopPromise} 1799 | */ 1800 | 1801 | }, { 1802 | key: "setLoop", 1803 | value: function setLoop(loop) { 1804 | return this.set('loop', loop); 1805 | } 1806 | /** 1807 | * A promise to set the muted state of the player. 1808 | * 1809 | * @promise SetMutedPromise 1810 | * @fulfill {boolean} The muted state that was set. 1811 | */ 1812 | 1813 | /** 1814 | * Set the muted state of the player. When set to `true`, the player 1815 | * volume will be muted. 1816 | * 1817 | * @param {boolean} muted 1818 | * @return {SetMutedPromise} 1819 | */ 1820 | 1821 | }, { 1822 | key: "setMuted", 1823 | value: function setMuted(muted) { 1824 | return this.set('muted', muted); 1825 | } 1826 | /** 1827 | * A promise to get the muted state of the player. 1828 | * 1829 | * @promise GetMutedPromise 1830 | * @fulfill {boolean} Whether or not the player is muted. 1831 | */ 1832 | 1833 | /** 1834 | * Get the muted state of the player. 1835 | * 1836 | * @return {GetMutedPromise} 1837 | */ 1838 | 1839 | }, { 1840 | key: "getMuted", 1841 | value: function getMuted() { 1842 | return this.get('muted'); 1843 | } 1844 | /** 1845 | * A promise to get the paused state of the player. 1846 | * 1847 | * @promise GetLoopPromise 1848 | * @fulfill {boolean} Whether or not the video is paused. 1849 | */ 1850 | 1851 | /** 1852 | * Get the paused state of the player. 1853 | * 1854 | * @return {GetLoopPromise} 1855 | */ 1856 | 1857 | }, { 1858 | key: "getPaused", 1859 | value: function getPaused() { 1860 | return this.get('paused'); 1861 | } 1862 | /** 1863 | * A promise to get the playback rate of the player. 1864 | * 1865 | * @promise GetPlaybackRatePromise 1866 | * @fulfill {number} The playback rate of the player on a scale from 0.5 to 2. 1867 | */ 1868 | 1869 | /** 1870 | * Get the playback rate of the player on a scale from `0.5` to `2`. 1871 | * 1872 | * @return {GetPlaybackRatePromise} 1873 | */ 1874 | 1875 | }, { 1876 | key: "getPlaybackRate", 1877 | value: function getPlaybackRate() { 1878 | return this.get('playbackRate'); 1879 | } 1880 | /** 1881 | * A promise to set the playbackrate of the player. 1882 | * 1883 | * @promise SetPlaybackRatePromise 1884 | * @fulfill {number} The playback rate was set. 1885 | * @reject {RangeError} The playback rate was less than 0.5 or greater than 2. 1886 | */ 1887 | 1888 | /** 1889 | * Set the playback rate of the player on a scale from `0.5` to `2`. When set 1890 | * via the API, the playback rate will not be synchronized to other 1891 | * players or stored as the viewer's preference. 1892 | * 1893 | * @param {number} playbackRate 1894 | * @return {SetPlaybackRatePromise} 1895 | */ 1896 | 1897 | }, { 1898 | key: "setPlaybackRate", 1899 | value: function setPlaybackRate(playbackRate) { 1900 | return this.set('playbackRate', playbackRate); 1901 | } 1902 | /** 1903 | * A promise to get the played property of the video. 1904 | * 1905 | * @promise GetPlayedPromise 1906 | * @fulfill {Array} Played Timeranges converted to an Array. 1907 | */ 1908 | 1909 | /** 1910 | * Get the played property of the video. 1911 | * 1912 | * @return {GetPlayedPromise} 1913 | */ 1914 | 1915 | }, { 1916 | key: "getPlayed", 1917 | value: function getPlayed() { 1918 | return this.get('played'); 1919 | } 1920 | /** 1921 | * A promise to get the seekable property of the video. 1922 | * 1923 | * @promise GetSeekablePromise 1924 | * @fulfill {Array} Seekable Timeranges converted to an Array. 1925 | */ 1926 | 1927 | /** 1928 | * Get the seekable property of the video. 1929 | * 1930 | * @return {GetSeekablePromise} 1931 | */ 1932 | 1933 | }, { 1934 | key: "getSeekable", 1935 | value: function getSeekable() { 1936 | return this.get('seekable'); 1937 | } 1938 | /** 1939 | * A promise to get the seeking property of the player. 1940 | * 1941 | * @promise GetSeekingPromise 1942 | * @fulfill {boolean} Whether or not the player is currently seeking. 1943 | */ 1944 | 1945 | /** 1946 | * Get if the player is currently seeking. 1947 | * 1948 | * @return {GetSeekingPromise} 1949 | */ 1950 | 1951 | }, { 1952 | key: "getSeeking", 1953 | value: function getSeeking() { 1954 | return this.get('seeking'); 1955 | } 1956 | /** 1957 | * A promise to get the text tracks of a video. 1958 | * 1959 | * @promise GetTextTracksPromise 1960 | * @fulfill {VimeoTextTrack[]} The text tracks associated with the video. 1961 | */ 1962 | 1963 | /** 1964 | * Get an array of the text tracks that exist for the video. 1965 | * 1966 | * @return {GetTextTracksPromise} 1967 | */ 1968 | 1969 | }, { 1970 | key: "getTextTracks", 1971 | value: function getTextTracks() { 1972 | return this.get('textTracks'); 1973 | } 1974 | /** 1975 | * A promise to get the embed code for the video. 1976 | * 1977 | * @promise GetVideoEmbedCodePromise 1978 | * @fulfill {string} The `