Handle no audio, more docs in code, fix for playing getter
This commit is contained in:
		
							
								
								
									
										2
									
								
								dist/plyr.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								dist/plyr.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										2
									
								
								dist/plyr.js.map
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								dist/plyr.js.map
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@ -329,6 +329,7 @@ Property | Getter | Setter | Description
 | 
				
			|||||||
`duration` | ✔ | - | Returns the duration for the current media.
 | 
					`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.
 | 
					`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.
 | 
					`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.
 | 
					`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.
 | 
					`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.
 | 
					`loop` | ✔ | ✔ | Gets or sets the current loop state of the player. The setter accepts a boolean.
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										27
									
								
								src/js/controls.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										27
									
								
								src/js/controls.js
									
									
									
									
										vendored
									
									
								
							@ -429,21 +429,8 @@ const controls = {
 | 
				
			|||||||
        const tab = this.elements.settings.tabs[setting];
 | 
					        const tab = this.elements.settings.tabs[setting];
 | 
				
			||||||
        const pane = this.elements.settings.panes[setting];
 | 
					        const pane = this.elements.settings.panes[setting];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (utils.is.htmlElement(tab)) {
 | 
					        utils.toggleHidden(tab, !toggle);
 | 
				
			||||||
            if (toggle) {
 | 
					        utils.toggleHidden(pane, !toggle);
 | 
				
			||||||
                tab.removeAttribute('hidden');
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                tab.setAttribute('hidden', '');
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (utils.is.htmlElement(pane)) {
 | 
					 | 
				
			||||||
            if (toggle) {
 | 
					 | 
				
			||||||
                pane.removeAttribute('hidden');
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                pane.setAttribute('hidden', '');
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Set the YouTube quality menu
 | 
					    // Set the YouTube quality menu
 | 
				
			||||||
@ -621,8 +608,8 @@ const controls = {
 | 
				
			|||||||
        const list = this.elements.settings.panes.loop.querySelector('ul');
 | 
					        const list = this.elements.settings.panes.loop.querySelector('ul');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Show the pane and tab
 | 
					        // Show the pane and tab
 | 
				
			||||||
        this.elements.settings.tabs.loop.removeAttribute('hidden');
 | 
					        utils.toggleHidden(this.elements.settings.tabs.loop, false);
 | 
				
			||||||
        this.elements.settings.panes.loop.removeAttribute('hidden');
 | 
					        utils.toggleHidden(this.elements.settings.panes.loop, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Toggle the pane and tab
 | 
					        // Toggle the pane and tab
 | 
				
			||||||
        const toggle = !utils.is.empty(this.loop.options);
 | 
					        const toggle = !utils.is.empty(this.loop.options);
 | 
				
			||||||
@ -746,8 +733,8 @@ const controls = {
 | 
				
			|||||||
        const list = this.elements.settings.panes.speed.querySelector('ul');
 | 
					        const list = this.elements.settings.panes.speed.querySelector('ul');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Show the pane and tab
 | 
					        // Show the pane and tab
 | 
				
			||||||
        this.elements.settings.tabs.speed.removeAttribute('hidden');
 | 
					        utils.toggleHidden(this.elements.settings.tabs.speed, false);
 | 
				
			||||||
        this.elements.settings.panes.speed.removeAttribute('hidden');
 | 
					        utils.toggleHidden(this.elements.settings.panes.speed, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Empty the menu
 | 
					        // Empty the menu
 | 
				
			||||||
        utils.emptyElement(list);
 | 
					        utils.emptyElement(list);
 | 
				
			||||||
@ -1015,6 +1002,8 @@ const controls = {
 | 
				
			|||||||
            volume.appendChild(range.label);
 | 
					            volume.appendChild(range.label);
 | 
				
			||||||
            volume.appendChild(range.input);
 | 
					            volume.appendChild(range.input);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.elements.volume = volume;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            container.appendChild(volume);
 | 
					            container.appendChild(volume);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -140,7 +140,6 @@ const defaults = {
 | 
				
			|||||||
        unmute: 'Unmute',
 | 
					        unmute: 'Unmute',
 | 
				
			||||||
        enableCaptions: 'Enable captions',
 | 
					        enableCaptions: 'Enable captions',
 | 
				
			||||||
        disableCaptions: 'Disable captions',
 | 
					        disableCaptions: 'Disable captions',
 | 
				
			||||||
        fullscreen: 'Fullscreen',
 | 
					 | 
				
			||||||
        enterFullscreen: 'Enter fullscreen',
 | 
					        enterFullscreen: 'Enter fullscreen',
 | 
				
			||||||
        exitFullscreen: 'Exit fullscreen',
 | 
					        exitFullscreen: 'Exit fullscreen',
 | 
				
			||||||
        frameTitle: 'Player for {title}',
 | 
					        frameTitle: 'Player for {title}',
 | 
				
			||||||
 | 
				
			|||||||
@ -232,6 +232,13 @@ const listeners = {
 | 
				
			|||||||
        // Display duration
 | 
					        // Display duration
 | 
				
			||||||
        utils.on(this.media, 'durationchange loadedmetadata', event => ui.durationUpdate.call(this, event));
 | 
					        utils.on(this.media, 'durationchange loadedmetadata', event => ui.durationUpdate.call(this, 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.media, 'loadeddata', () => {
 | 
				
			||||||
 | 
					            utils.toggleHidden(this.elements.volume, !this.hasAudio);
 | 
				
			||||||
 | 
					            utils.toggleHidden(this.elements.buttons.mute, !this.hasAudio);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Handle the media finishing
 | 
					        // Handle the media finishing
 | 
				
			||||||
        utils.on(this.media, 'ended', () => {
 | 
					        utils.on(this.media, 'ended', () => {
 | 
				
			||||||
            // Show poster on end
 | 
					            // Show poster on end
 | 
				
			||||||
@ -251,10 +258,10 @@ const listeners = {
 | 
				
			|||||||
        utils.on(this.media, 'volumechange', event => ui.updateVolume.call(this, event));
 | 
					        utils.on(this.media, 'volumechange', event => ui.updateVolume.call(this, event));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Handle native play/pause
 | 
					        // Handle native play/pause
 | 
				
			||||||
        utils.on(this.media, 'play pause ended', event => ui.checkPlaying.call(this, event));
 | 
					        utils.on(this.media, 'playing play pause ended', event => ui.checkPlaying.call(this, event));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Loading
 | 
					        // Loading
 | 
				
			||||||
        utils.on(this.media, 'waiting canplay seeked', event => ui.checkLoading.call(this, event));
 | 
					        utils.on(this.media, 'stalled waiting canplay seeked playing', event => ui.checkLoading.call(this, event));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Click video
 | 
					        // Click video
 | 
				
			||||||
        if (this.supported.ui && this.config.clickToPlay && this.type !== 'audio') {
 | 
					        if (this.supported.ui && this.config.clickToPlay && this.type !== 'audio') {
 | 
				
			||||||
 | 
				
			|||||||
@ -78,7 +78,7 @@ const media = {
 | 
				
			|||||||
                default:
 | 
					                default:
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        } else if (this.isHTML5) {
 | 
				
			||||||
            ui.setTitle.call(this);
 | 
					            ui.setTitle.call(this);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
				
			|||||||
@ -258,8 +258,11 @@ const vimeo = {
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        player.embed.on('play', () => {
 | 
					        player.embed.on('play', () => {
 | 
				
			||||||
            player.media.paused = false;
 | 
					            // Only fire play if paused before
 | 
				
			||||||
 | 
					            if (player.media.paused) {
 | 
				
			||||||
                utils.dispatchEvent.call(player, player.media, 'play');
 | 
					                utils.dispatchEvent.call(player, player.media, 'play');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            player.media.paused = false;
 | 
				
			||||||
            utils.dispatchEvent.call(player, player.media, 'playing');
 | 
					            utils.dispatchEvent.call(player, player.media, 'playing');
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -352,15 +352,18 @@ const youtube = {
 | 
				
			|||||||
                            break;
 | 
					                            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        case 1:
 | 
					                        case 1:
 | 
				
			||||||
                            player.media.paused = false;
 | 
					 | 
				
			||||||
                            player.media.seeking = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                            // If we were seeking, fire seeked event
 | 
					                            // If we were seeking, fire seeked event
 | 
				
			||||||
                            if (player.media.seeking) {
 | 
					                            if (player.media.seeking) {
 | 
				
			||||||
                                utils.dispatchEvent.call(player, player.media, 'seeked');
 | 
					                                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');
 | 
					                                utils.dispatchEvent.call(player, player.media, 'play');
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                            player.media.paused = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                            utils.dispatchEvent.call(player, player.media, 'playing');
 | 
					                            utils.dispatchEvent.call(player, player.media, 'playing');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                            // Poll to get playback progress
 | 
					                            // Poll to get playback progress
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										192
									
								
								src/js/plyr.js
									
									
									
									
									
								
							
							
						
						
									
										192
									
								
								src/js/plyr.js
									
									
									
									
									
								
							@ -279,14 +279,30 @@ class Plyr {
 | 
				
			|||||||
        return this;
 | 
					        return this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get paused state
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    get paused() {
 | 
					    get paused() {
 | 
				
			||||||
        return this.media.paused;
 | 
					        return this.media.paused;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get playing state
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    get playing() {
 | 
					    get playing() {
 | 
				
			||||||
        return this.currentTime > 0 && !this.paused && !this.ended && (this.isHTML5 ? this.media.readyState > 2 : true);
 | 
					        // Because the third party players don't fire timeupdate as frequently as HTML5,
 | 
				
			||||||
 | 
					        // we can't use the check for currentTime > 0 for those players which is a shame
 | 
				
			||||||
 | 
					        // readystate also does not exist for the embedded players
 | 
				
			||||||
 | 
					        if (this.isHTML5) {
 | 
				
			||||||
 | 
					            return !this.paused && !this.ended && this.currentTime > 0 && this.media.readyState > 2;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return !this.paused && !this.ended;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get ended state
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    get ended() {
 | 
					    get ended() {
 | 
				
			||||||
        return this.media.ended;
 | 
					        return this.media.ended;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -362,10 +378,16 @@ class Plyr {
 | 
				
			|||||||
        this.console.log(`Seeking to ${this.currentTime} seconds`);
 | 
					        this.console.log(`Seeking to ${this.currentTime} seconds`);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get current time
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    get currentTime() {
 | 
					    get currentTime() {
 | 
				
			||||||
        return Number(this.media.currentTime);
 | 
					        return Number(this.media.currentTime);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get seeking status
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    get seeking() {
 | 
					    get seeking() {
 | 
				
			||||||
        return this.media.seeking;
 | 
					        return this.media.seeking;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -435,21 +457,30 @@ class Plyr {
 | 
				
			|||||||
        return this.media.volume;
 | 
					        return this.media.volume;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Increase volume
 | 
					    /**
 | 
				
			||||||
 | 
					     * Increase volume
 | 
				
			||||||
 | 
					     * @param {boolean} step - How much to decrease by (between 0 and 1)
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    increaseVolume(step) {
 | 
					    increaseVolume(step) {
 | 
				
			||||||
        const volume = this.media.muted ? 0 : this.volume;
 | 
					        const volume = this.media.muted ? 0 : this.volume;
 | 
				
			||||||
        this.volume = volume + utils.is.number(step) ? step : 1;
 | 
					        this.volume = volume + utils.is.number(step) ? step : 1;
 | 
				
			||||||
        return this;
 | 
					        return this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Decrease volume
 | 
					    /**
 | 
				
			||||||
 | 
					     * Decrease volume
 | 
				
			||||||
 | 
					     * @param {boolean} step - How much to decrease by (between 0 and 1)
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    decreaseVolume(step) {
 | 
					    decreaseVolume(step) {
 | 
				
			||||||
        const volume = this.media.muted ? 0 : this.volume;
 | 
					        const volume = this.media.muted ? 0 : this.volume;
 | 
				
			||||||
        this.volume = volume - utils.is.number(step) ? step : 1;
 | 
					        this.volume = volume - utils.is.number(step) ? step : 1;
 | 
				
			||||||
        return this;
 | 
					        return this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Toggle mute
 | 
					    /**
 | 
				
			||||||
 | 
					     * Set muted state
 | 
				
			||||||
 | 
					     * @param {boolean} mute
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    set muted(mute) {
 | 
					    set muted(mute) {
 | 
				
			||||||
        let toggle = mute;
 | 
					        let toggle = mute;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -470,11 +501,34 @@ class Plyr {
 | 
				
			|||||||
        this.media.muted = toggle;
 | 
					        this.media.muted = toggle;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get current muted state
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    get muted() {
 | 
					    get muted() {
 | 
				
			||||||
        return this.media.muted;
 | 
					        return this.media.muted;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Playback speed
 | 
					    /**
 | 
				
			||||||
 | 
					     * Check if the media has audio
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    get hasAudio() {
 | 
				
			||||||
 | 
					        // Assume yes for all non HTML5 (as we can't tell...)
 | 
				
			||||||
 | 
					        if (!this.isHTML5) {
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Get audio tracks
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					            this.media.mozHasAudio ||
 | 
				
			||||||
 | 
					            Boolean(this.media.webkitAudioDecodedByteCount) ||
 | 
				
			||||||
 | 
					            Boolean(this.media.audioTracks && this.media.audioTracks.length)
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Set playback speed
 | 
				
			||||||
 | 
					     * @param {decimal} speed - the speed of playback (0.5-2.0)
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    set speed(input) {
 | 
					    set speed(input) {
 | 
				
			||||||
        let speed = null;
 | 
					        let speed = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -506,17 +560,24 @@ class Plyr {
 | 
				
			|||||||
        this.media.playbackRate = speed;
 | 
					        this.media.playbackRate = speed;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get current playback speed
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    get speed() {
 | 
					    get speed() {
 | 
				
			||||||
        return this.media.playbackRate;
 | 
					        return this.media.playbackRate;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Set playback quality
 | 
					    /**
 | 
				
			||||||
 | 
					     * Set playback quality
 | 
				
			||||||
 | 
					     * Currently YouTube only
 | 
				
			||||||
 | 
					     * @param {string} input - Quality level
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    set quality(input) {
 | 
					    set quality(input) {
 | 
				
			||||||
        let quality = null;
 | 
					        let quality = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (utils.is.string(input)) {
 | 
					        if (utils.is.string(input)) {
 | 
				
			||||||
            quality = input;
 | 
					            quality = input;
 | 
				
			||||||
        } else if (utils.is.number(storage.get.call(this).speed)) {
 | 
					        } else if (utils.is.number(storage.get.call(this).quality)) {
 | 
				
			||||||
            ({ quality } = storage.get.call(this));
 | 
					            ({ quality } = storage.get.call(this));
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            quality = this.config.quality.selected;
 | 
					            quality = this.config.quality.selected;
 | 
				
			||||||
@ -534,12 +595,18 @@ class Plyr {
 | 
				
			|||||||
        this.media.quality = quality;
 | 
					        this.media.quality = quality;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get current quality level
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    get quality() {
 | 
					    get quality() {
 | 
				
			||||||
        return this.media.quality;
 | 
					        return this.media.quality;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Toggle loop
 | 
					    /**
 | 
				
			||||||
    // TODO: Finish fancy new logic. Set the indicator on load as user may pass loop as config
 | 
					     * 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
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    set loop(input) {
 | 
					    set loop(input) {
 | 
				
			||||||
        const toggle = utils.is.boolean(input) ? input : this.config.loop.active;
 | 
					        const toggle = utils.is.boolean(input) ? input : this.config.loop.active;
 | 
				
			||||||
        this.config.loop.active = toggle;
 | 
					        this.config.loop.active = toggle;
 | 
				
			||||||
@ -589,22 +656,34 @@ class Plyr {
 | 
				
			|||||||
        } */
 | 
					        } */
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get current loop state
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    get loop() {
 | 
					    get loop() {
 | 
				
			||||||
        return this.media.loop;
 | 
					        return this.media.loop;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Media source
 | 
					    /**
 | 
				
			||||||
 | 
					     * Set new media source
 | 
				
			||||||
 | 
					     * @param {object} input - The new source object (see docs)
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    set source(input) {
 | 
					    set source(input) {
 | 
				
			||||||
        source.change.call(this, input);
 | 
					        source.change.call(this, input);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get current source
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    get source() {
 | 
					    get source() {
 | 
				
			||||||
        return this.media.currentSrc;
 | 
					        return this.media.currentSrc;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Poster image
 | 
					    /**
 | 
				
			||||||
 | 
					     * Set the poster image for a HTML5 video
 | 
				
			||||||
 | 
					     * @param {input} - the URL for the new poster image
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    set poster(input) {
 | 
					    set poster(input) {
 | 
				
			||||||
        if (this.type !== 'video') {
 | 
					        if (!this.isHTML5 || this.type !== 'video') {
 | 
				
			||||||
            this.console.warn('Poster can only be set on HTML5 video');
 | 
					            this.console.warn('Poster can only be set on HTML5 video');
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -614,25 +693,37 @@ class Plyr {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the current poster image
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    get poster() {
 | 
					    get poster() {
 | 
				
			||||||
        if (this.type !== 'video') {
 | 
					        if (!this.isHTML5 || this.type !== 'video') {
 | 
				
			||||||
            return null;
 | 
					            return null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return this.media.getAttribute('poster');
 | 
					        return this.media.getAttribute('poster');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Autoplay
 | 
					    /**
 | 
				
			||||||
    get autoplay() {
 | 
					     * Set the autoplay state
 | 
				
			||||||
        return this.config.autoplay;
 | 
					     * @param {boolean} input - Whether to autoplay or not
 | 
				
			||||||
    }
 | 
					     */
 | 
				
			||||||
 | 
					 | 
				
			||||||
    set autoplay(input) {
 | 
					    set autoplay(input) {
 | 
				
			||||||
        const toggle = utils.is.boolean(input) ? input : this.config.autoplay;
 | 
					        const toggle = utils.is.boolean(input) ? input : this.config.autoplay;
 | 
				
			||||||
        this.config.autoplay = toggle;
 | 
					        this.config.autoplay = toggle;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Toggle captions
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the current autoplay state
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    get autoplay() {
 | 
				
			||||||
 | 
					        return this.config.autoplay;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Toggle captions
 | 
				
			||||||
 | 
					     * @param {boolean} input - Whether to enable captions
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    toggleCaptions(input) {
 | 
					    toggleCaptions(input) {
 | 
				
			||||||
        // If there's no full support, or there's no caption toggle
 | 
					        // If there's no full support, or there's no caption toggle
 | 
				
			||||||
        if (!this.supported.ui || !utils.is.htmlElement(this.elements.buttons.captions)) {
 | 
					        if (!this.supported.ui || !utils.is.htmlElement(this.elements.buttons.captions)) {
 | 
				
			||||||
@ -665,7 +756,10 @@ class Plyr {
 | 
				
			|||||||
        return this;
 | 
					        return this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Caption language
 | 
					    /**
 | 
				
			||||||
 | 
					     * Set the captions language
 | 
				
			||||||
 | 
					     * @param {string} - Two character ISO language code (e.g. EN, FR, PT, etc)
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    set language(input) {
 | 
					    set language(input) {
 | 
				
			||||||
        // Nothing specified
 | 
					        // Nothing specified
 | 
				
			||||||
        if (!utils.is.string(input)) {
 | 
					        if (!utils.is.string(input)) {
 | 
				
			||||||
@ -701,12 +795,18 @@ class Plyr {
 | 
				
			|||||||
        utils.dispatchEvent.call(this, this.media, 'languagechange');
 | 
					        utils.dispatchEvent.call(this, this.media, 'languagechange');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the current captions language
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    get language() {
 | 
					    get language() {
 | 
				
			||||||
        return this.captions.language;
 | 
					        return this.captions.language;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Toggle fullscreen
 | 
					    /**
 | 
				
			||||||
    // Requires user input event
 | 
					     * Toggle fullscreen playback
 | 
				
			||||||
 | 
					     * Requires user input event
 | 
				
			||||||
 | 
					     * @param {event} event
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    toggleFullscreen(event) {
 | 
					    toggleFullscreen(event) {
 | 
				
			||||||
        // Check for native support
 | 
					        // Check for native support
 | 
				
			||||||
        if (fullscreen.enabled) {
 | 
					        if (fullscreen.enabled) {
 | 
				
			||||||
@ -759,9 +859,11 @@ class Plyr {
 | 
				
			|||||||
        return this;
 | 
					        return this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Toggle picture-in-picture
 | 
					    /**
 | 
				
			||||||
    // TODO: update player with state, support, enabled
 | 
					     * Toggle picture-in-picture playback on WebKit/MacOS
 | 
				
			||||||
    // TODO: detect outside changes
 | 
					     * TODO: update player with state, support, enabled
 | 
				
			||||||
 | 
					     * TODO: detect outside changes
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    set pip(input) {
 | 
					    set pip(input) {
 | 
				
			||||||
        const states = {
 | 
					        const states = {
 | 
				
			||||||
            pip: 'picture-in-picture',
 | 
					            pip: 'picture-in-picture',
 | 
				
			||||||
@ -780,6 +882,9 @@ class Plyr {
 | 
				
			|||||||
        this.media.webkitSetPresentationMode(toggle ? states.pip : states.inline);
 | 
					        this.media.webkitSetPresentationMode(toggle ? states.pip : states.inline);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the current picture-in-picture state
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    get pip() {
 | 
					    get pip() {
 | 
				
			||||||
        if (!support.pip) {
 | 
					        if (!support.pip) {
 | 
				
			||||||
            return null;
 | 
					            return null;
 | 
				
			||||||
@ -788,8 +893,10 @@ class Plyr {
 | 
				
			|||||||
        return this.media.webkitPresentationMode;
 | 
					        return this.media.webkitPresentationMode;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Trigger airplay
 | 
					    /**
 | 
				
			||||||
    // TODO: update player with state, support, enabled
 | 
					     * Trigger the airplay dialog
 | 
				
			||||||
 | 
					     * TODO: update player with state, support, enabled
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    airplay() {
 | 
					    airplay() {
 | 
				
			||||||
        // Bail if no support
 | 
					        // Bail if no support
 | 
				
			||||||
        if (!support.airplay) {
 | 
					        if (!support.airplay) {
 | 
				
			||||||
@ -802,7 +909,10 @@ class Plyr {
 | 
				
			|||||||
        return this;
 | 
					        return this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Show the player controls in fullscreen mode
 | 
					    /**
 | 
				
			||||||
 | 
					     * Toggle the player controls
 | 
				
			||||||
 | 
					     * @param {boolean} toggle - Whether to show the controls
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    toggleControls(toggle) {
 | 
					    toggleControls(toggle) {
 | 
				
			||||||
        // We need controls of course...
 | 
					        // We need controls of course...
 | 
				
			||||||
        if (!utils.is.htmlElement(this.elements.controls)) {
 | 
					        if (!utils.is.htmlElement(this.elements.controls)) {
 | 
				
			||||||
@ -897,25 +1007,41 @@ class Plyr {
 | 
				
			|||||||
        return this;
 | 
					        return this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Event listeners
 | 
					    /**
 | 
				
			||||||
 | 
					     * Add event listeners
 | 
				
			||||||
 | 
					     * @param {string} event - Event type
 | 
				
			||||||
 | 
					     * @param {function} callback - Callback for when event occurs
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    on(event, callback) {
 | 
					    on(event, callback) {
 | 
				
			||||||
        utils.on(this.elements.container, event, callback);
 | 
					        utils.on(this.elements.container, event, callback);
 | 
				
			||||||
        return this;
 | 
					        return this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Remove event listeners
 | 
				
			||||||
 | 
					     * @param {string} event - Event type
 | 
				
			||||||
 | 
					     * @param {function} callback - Callback for when event occurs
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    off(event, callback) {
 | 
					    off(event, callback) {
 | 
				
			||||||
        utils.off(this.elements.container, event, callback);
 | 
					        utils.off(this.elements.container, event, callback);
 | 
				
			||||||
        return this;
 | 
					        return this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Check for support
 | 
					    /**
 | 
				
			||||||
 | 
					     * Check for support for a mime type (HTML5 only)
 | 
				
			||||||
 | 
					     * @param {string} type - Mime type
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    supports(type) {
 | 
					    supports(type) {
 | 
				
			||||||
        return support.mime.call(this, type);
 | 
					        return support.mime.call(this, type);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Destroy an instance
 | 
					    /**
 | 
				
			||||||
    // Event listeners are removed when elements are removed
 | 
					     * Destroy an instance
 | 
				
			||||||
    // http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory
 | 
					     * 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)
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    destroy(callback, soft = false) {
 | 
					    destroy(callback, soft = false) {
 | 
				
			||||||
        const done = () => {
 | 
					        const done = () => {
 | 
				
			||||||
            // Reset overflow (incase destroyed while in fullscreen)
 | 
					            // Reset overflow (incase destroyed while in fullscreen)
 | 
				
			||||||
 | 
				
			|||||||
@ -144,7 +144,9 @@ const ui = {
 | 
				
			|||||||
            utils.toggleClass(this.elements.container, this.config.classNames.stopped, this.paused);
 | 
					            utils.toggleClass(this.elements.container, this.config.classNames.stopped, this.paused);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Set aria state
 | 
					            // Set aria state
 | 
				
			||||||
 | 
					            if (utils.is.array(this.elements.buttons.play)) {
 | 
				
			||||||
                Array.from(this.elements.buttons.play).forEach(button => utils.toggleState(button, this.playing));
 | 
					                Array.from(this.elements.buttons.play).forEach(button => utils.toggleState(button, this.playing));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Toggle controls
 | 
					            // Toggle controls
 | 
				
			||||||
            this.toggleControls(!this.playing);
 | 
					            this.toggleControls(!this.playing);
 | 
				
			||||||
@ -153,7 +155,7 @@ const ui = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Check if media is loading
 | 
					    // Check if media is loading
 | 
				
			||||||
    checkLoading(event) {
 | 
					    checkLoading(event) {
 | 
				
			||||||
        this.loading = event.type === 'waiting';
 | 
					        this.loading = ['stalled', 'waiting'].includes(event.type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Clear timer
 | 
					        // Clear timer
 | 
				
			||||||
        clearTimeout(this.timers.loading);
 | 
					        clearTimeout(this.timers.loading);
 | 
				
			||||||
 | 
				
			|||||||
@ -118,7 +118,7 @@ const utils = {
 | 
				
			|||||||
        if (!hasId || !document.querySelectorAll(`#${id}`).length) {
 | 
					        if (!hasId || !document.querySelectorAll(`#${id}`).length) {
 | 
				
			||||||
            // Create container
 | 
					            // Create container
 | 
				
			||||||
            const container = document.createElement('div');
 | 
					            const container = document.createElement('div');
 | 
				
			||||||
            container.setAttribute('hidden', '');
 | 
					            utils.toggleHidden(container, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (hasId) {
 | 
					            if (hasId) {
 | 
				
			||||||
                container.setAttribute('id', id);
 | 
					                container.setAttribute('id', id);
 | 
				
			||||||
@ -337,6 +337,19 @@ const utils = {
 | 
				
			|||||||
        return utils.is.htmlElement(element) && element.classList.contains(className);
 | 
					        return utils.is.htmlElement(element) && element.classList.contains(className);
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Toggle hidden attribute on an element
 | 
				
			||||||
 | 
					    toggleHidden(element, toggle) {
 | 
				
			||||||
 | 
					        if (!utils.is.htmlElement(element)) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (toggle) {
 | 
				
			||||||
 | 
					            element.setAttribute('hidden', '');
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            element.removeAttribute('hidden');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Element matches selector
 | 
					    // Element matches selector
 | 
				
			||||||
    matches(element, selector) {
 | 
					    matches(element, selector) {
 | 
				
			||||||
        const prototype = { Element };
 | 
					        const prototype = { Element };
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user