Handle no audio, more docs in code, fix for playing getter
This commit is contained in:
parent
f33bc5a5c6
commit
d3b31e595a
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', () => {
|
||||||
|
// Only fire play if paused before
|
||||||
|
if (player.media.paused) {
|
||||||
|
utils.dispatchEvent.call(player, player.media, 'play');
|
||||||
|
}
|
||||||
player.media.paused = false;
|
player.media.paused = false;
|
||||||
utils.dispatchEvent.call(player, player.media, 'play');
|
|
||||||
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');
|
||||||
|
}
|
||||||
|
player.media.paused = false;
|
||||||
|
|
||||||
utils.dispatchEvent.call(player, player.media, 'play');
|
|
||||||
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
|
||||||
Array.from(this.elements.buttons.play).forEach(button => utils.toggleState(button, this.playing));
|
if (utils.is.array(this.elements.buttons.play)) {
|
||||||
|
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 };
|
||||||
|
Loading…
x
Reference in New Issue
Block a user