Compare commits
22 Commits
v3.4.0-beta.2
...
v3.4.0
| Author | SHA1 | Date | |
|---|---|---|---|
| b57b7b2153 | |||
| 48bf368316 | |||
| 8f94ce86a0 | |||
| 10a9cf08f1 | |||
| 286d0d1794 | |||
| 95f6fa2731 | |||
| 1aeef81288 | |||
| 211ad6c8f5 | |||
| 468b20d227 | |||
| f6bc42c2bc | |||
| 2c01b8ba76 | |||
| 4e1df8677f | |||
| 6953a12e2a | |||
| 1d0db89194 | |||
| 297f297d18 | |||
| 059205c378 | |||
| f94e53ffb1 | |||
| a4f1fdec5d | |||
| 75374eb154 | |||
| dbf768b1bd | |||
| a8f8486cf4 | |||
| a343e58e53 |
@@ -3,6 +3,11 @@
|
|||||||
- Accessibility improvements (see #905)
|
- Accessibility improvements (see #905)
|
||||||
- Improvements to the way the controls work on iOS
|
- Improvements to the way the controls work on iOS
|
||||||
- Demo code clean up
|
- Demo code clean up
|
||||||
|
- YouTube quality selection removed due to their poor support for it. As a result, the `qualityrequested` event has been removed
|
||||||
|
- Controls spacing improvements
|
||||||
|
- Fix for pressed property missing with custom controls (Fixes #1062)
|
||||||
|
- Fix #1153: Captions language fallback (thanks @friday)
|
||||||
|
- Fix for setting pressed property of undefined (Fixes #1102)
|
||||||
|
|
||||||
# v3.3.23
|
# v3.3.23
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+3
-2
@@ -4118,9 +4118,10 @@ typeof navigator === "object" && (function () {
|
|||||||
|
|
||||||
// Remove class on blur
|
// Remove class on blur
|
||||||
document.addEventListener('focusout', function (event) {
|
document.addEventListener('focusout', function (event) {
|
||||||
if (container.contains(event.target)) {
|
if (!event.target.classList || container.contains(event.target)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
event.target.classList.remove(tabClassName);
|
event.target.classList.remove(tabClassName);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -4135,7 +4136,7 @@ typeof navigator === "object" && (function () {
|
|||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
var focused = document.activeElement;
|
var focused = document.activeElement;
|
||||||
|
|
||||||
if (!focused || container.contains(focused)) {
|
if (!focused || !focused.classList || container.contains(focused)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+3
-2
@@ -31,9 +31,10 @@ import Raven from 'raven-js';
|
|||||||
|
|
||||||
// Remove class on blur
|
// Remove class on blur
|
||||||
document.addEventListener('focusout', event => {
|
document.addEventListener('focusout', event => {
|
||||||
if (container.contains(event.target)) {
|
if (!event.target.classList || container.contains(event.target)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
event.target.classList.remove(tabClassName);
|
event.target.classList.remove(tabClassName);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -48,7 +49,7 @@ import Raven from 'raven-js';
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const focused = document.activeElement;
|
const focused = document.activeElement;
|
||||||
|
|
||||||
if (!focused || container.contains(focused)) {
|
if (!focused || !focused.classList || container.contains(focused)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+80
-133
@@ -886,6 +886,9 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
triggerEvent.call(player, player.media, 'qualitychange', false, {
|
triggerEvent.call(player, player.media, 'qualitychange', false, {
|
||||||
quality: input
|
quality: input
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Save to storage
|
||||||
|
player.storage.set({ quality: input });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -918,6 +921,30 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
|
// Remove duplicates in an array
|
||||||
|
function dedupe(array) {
|
||||||
|
if (!is.array(array)) {
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
return array.filter(function (item, index) {
|
||||||
|
return array.indexOf(item) === index;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the closest value in an array
|
||||||
|
function closest(array, value) {
|
||||||
|
if (!is.array(array) || !array.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return array.reduce(function (prev, curr) {
|
||||||
|
return Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==========================================================================
|
||||||
|
|
||||||
// Clone nested objects
|
// Clone nested objects
|
||||||
function cloneDeep(object) {
|
function cloneDeep(object) {
|
||||||
return JSON.parse(JSON.stringify(object));
|
return JSON.parse(JSON.stringify(object));
|
||||||
@@ -1096,30 +1123,6 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
// Remove duplicates in an array
|
|
||||||
function dedupe(array) {
|
|
||||||
if (!is.array(array)) {
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
return array.filter(function (item, index) {
|
|
||||||
return array.indexOf(item) === index;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the closest value in an array
|
|
||||||
function closest(array, value) {
|
|
||||||
if (!is.array(array) || !array.length) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return array.reduce(function (prev, curr) {
|
|
||||||
return Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==========================================================================
|
|
||||||
|
|
||||||
var Storage = function () {
|
var Storage = function () {
|
||||||
function Storage(player) {
|
function Storage(player) {
|
||||||
classCallCheck(this, Storage);
|
classCallCheck(this, Storage);
|
||||||
@@ -1604,20 +1607,6 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
this.elements.buttons[type] = button;
|
this.elements.buttons[type] = button;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle classname when pressed property is set
|
|
||||||
var className = this.config.classNames.controlPressed;
|
|
||||||
Object.defineProperty(button, 'pressed', {
|
|
||||||
enumerable: true,
|
|
||||||
get: function get$$1() {
|
|
||||||
return hasClass(button, className);
|
|
||||||
},
|
|
||||||
set: function set$$1() {
|
|
||||||
var pressed = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
|
||||||
|
|
||||||
toggleClass(button, className, pressed);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return button;
|
return button;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -2490,11 +2479,10 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
// Focus the first item if key interaction
|
// Focus the first item if key interaction
|
||||||
if (show && is.keyboardEvent(input)) {
|
if (show && is.keyboardEvent(input)) {
|
||||||
controls.focusFirstMenuItem.call(this, null, true);
|
controls.focusFirstMenuItem.call(this, null, true);
|
||||||
|
} else if (!show && !hidden) {
|
||||||
|
// If closing, re-focus the button
|
||||||
|
setFocus.call(this, button, is.keyboardEvent(input));
|
||||||
}
|
}
|
||||||
// If closing, re-focus the button
|
|
||||||
else if (!show && !hidden) {
|
|
||||||
setFocus.call(this, button, is.keyboardEvent(input));
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
@@ -2651,30 +2639,33 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
container.appendChild(controls.createTime.call(this, 'duration'));
|
container.appendChild(controls.createTime.call(this, 'duration'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle mute button
|
// Volume controls
|
||||||
if (this.config.controls.includes('mute')) {
|
if (this.config.controls.includes('mute') || this.config.controls.includes('volume')) {
|
||||||
container.appendChild(controls.createButton.call(this, 'mute'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Volume range control
|
|
||||||
if (this.config.controls.includes('volume')) {
|
|
||||||
var volume = createElement('div', {
|
var volume = createElement('div', {
|
||||||
class: 'plyr__volume'
|
class: 'plyr__volume'
|
||||||
});
|
});
|
||||||
|
|
||||||
// Set the attributes
|
// Toggle mute button
|
||||||
var attributes = {
|
if (this.config.controls.includes('mute')) {
|
||||||
max: 1,
|
volume.appendChild(controls.createButton.call(this, 'mute'));
|
||||||
step: 0.05,
|
}
|
||||||
value: this.config.volume
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create the volume range slider
|
// Volume range control
|
||||||
volume.appendChild(controls.createRange.call(this, 'volume', extend(attributes, {
|
if (this.config.controls.includes('volume')) {
|
||||||
id: 'plyr-volume-' + data.id
|
// Set the attributes
|
||||||
})));
|
var attributes = {
|
||||||
|
max: 1,
|
||||||
|
step: 0.05,
|
||||||
|
value: this.config.volume
|
||||||
|
};
|
||||||
|
|
||||||
this.elements.volume = volume;
|
// Create the volume range slider
|
||||||
|
volume.appendChild(controls.createRange.call(this, 'volume', extend(attributes, {
|
||||||
|
id: 'plyr-volume-' + data.id
|
||||||
|
})));
|
||||||
|
|
||||||
|
this.elements.volume = volume;
|
||||||
|
}
|
||||||
|
|
||||||
container.appendChild(volume);
|
container.appendChild(volume);
|
||||||
}
|
}
|
||||||
@@ -2836,6 +2827,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
this.elements.controls = container;
|
this.elements.controls = container;
|
||||||
|
|
||||||
|
// Set available quality levels
|
||||||
if (this.isHTML5) {
|
if (this.isHTML5) {
|
||||||
controls.setQualityMenu.call(this, html5.getQualityOptions.call(this));
|
controls.setQualityMenu.call(this, html5.getQualityOptions.call(this));
|
||||||
}
|
}
|
||||||
@@ -2948,6 +2940,25 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
controls.findElements.call(this);
|
controls.findElements.call(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add pressed property to buttons
|
||||||
|
if (!is.empty(this.elements.buttons)) {
|
||||||
|
// Toggle classname when pressed property is set
|
||||||
|
Object.values(this.elements.buttons).forEach(function (button) {
|
||||||
|
var className = _this10.config.classNames.controlPressed;
|
||||||
|
Object.defineProperty(button, 'pressed', {
|
||||||
|
enumerable: true,
|
||||||
|
get: function get$$1() {
|
||||||
|
return hasClass(button, className);
|
||||||
|
},
|
||||||
|
set: function set$$1() {
|
||||||
|
var pressed = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
||||||
|
|
||||||
|
toggleClass(button, className, pressed);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Edge sometimes doesn't finish the paint so force a redraw
|
// Edge sometimes doesn't finish the paint so force a redraw
|
||||||
if (window.navigator.userAgent.includes('Edge')) {
|
if (window.navigator.userAgent.includes('Edge')) {
|
||||||
repaint(target);
|
repaint(target);
|
||||||
@@ -3065,7 +3076,8 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
// * active: The state preferred by user settings or config
|
// * active: The state preferred by user settings or config
|
||||||
// * toggled: The real captions state
|
// * toggled: The real captions state
|
||||||
|
|
||||||
var languages = dedupe(Array.from(navigator.languages || navigator.language || navigator.userLanguage).map(function (language) {
|
var browserLanguages = navigator.languages || [navigator.language || navigator.userLanguage || 'en'];
|
||||||
|
var languages = dedupe(browserLanguages.map(function (language) {
|
||||||
return language.split('-')[0];
|
return language.split('-')[0];
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -3488,7 +3500,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
// Quality default
|
// Quality default
|
||||||
quality: {
|
quality: {
|
||||||
default: 576,
|
default: 576,
|
||||||
options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240, 'default']
|
options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240]
|
||||||
},
|
},
|
||||||
|
|
||||||
// Set loops
|
// Set loops
|
||||||
@@ -3638,7 +3650,10 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
'enterfullscreen', 'exitfullscreen', 'captionsenabled', 'captionsdisabled', 'languagechange', 'controlshidden', 'controlsshown', 'ready',
|
'enterfullscreen', 'exitfullscreen', 'captionsenabled', 'captionsdisabled', 'languagechange', 'controlshidden', 'controlsshown', 'ready',
|
||||||
|
|
||||||
// YouTube
|
// YouTube
|
||||||
'statechange', 'qualitychange', 'qualityrequested',
|
'statechange',
|
||||||
|
|
||||||
|
// Quality
|
||||||
|
'qualitychange',
|
||||||
|
|
||||||
// Ads
|
// Ads
|
||||||
'adsloaded', 'adscontentpause', 'adscontentresume', 'adstarted', 'adsmidpoint', 'adscomplete', 'adsallcomplete', 'adsimpression', 'adsclick'],
|
'adsloaded', 'adscontentpause', 'adscontentresume', 'adstarted', 'adsmidpoint', 'adscomplete', 'adsallcomplete', 'adsimpression', 'adsclick'],
|
||||||
@@ -3947,9 +3962,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
// iOS native fullscreen doesn't need the request step
|
// iOS native fullscreen doesn't need the request step
|
||||||
if (browser.isIos && this.player.config.fullscreen.iosNative) {
|
if (browser.isIos && this.player.config.fullscreen.iosNative) {
|
||||||
if (this.player.playing) {
|
this.target.webkitEnterFullscreen();
|
||||||
this.target.webkitEnterFullscreen();
|
|
||||||
}
|
|
||||||
} else if (!Fullscreen.native) {
|
} else if (!Fullscreen.native) {
|
||||||
toggleFallback.call(this, true);
|
toggleFallback.call(this, true);
|
||||||
} else if (!this.prefix) {
|
} else if (!this.prefix) {
|
||||||
@@ -4636,7 +4649,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
// Remove button states for fullscreen
|
// Remove button states for fullscreen
|
||||||
|
|
||||||
if (event.type === 'enterfullscreen') {
|
if (controls$$1 && event.type === 'enterfullscreen') {
|
||||||
controls$$1.pressed = false;
|
controls$$1.pressed = false;
|
||||||
controls$$1.hover = false;
|
controls$$1.hover = false;
|
||||||
}
|
}
|
||||||
@@ -4794,12 +4807,6 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
player.storage.set({ speed: player.speed });
|
player.storage.set({ speed: player.speed });
|
||||||
});
|
});
|
||||||
|
|
||||||
// Quality request
|
|
||||||
on.call(player, player.media, 'qualityrequested', function (event) {
|
|
||||||
// Save to storage
|
|
||||||
player.storage.set({ quality: event.detail.quality });
|
|
||||||
});
|
|
||||||
|
|
||||||
// Quality change
|
// Quality change
|
||||||
on.call(player, player.media, 'qualitychange', function (event) {
|
on.call(player, player.media, 'qualitychange', function (event) {
|
||||||
// Update UI
|
// Update UI
|
||||||
@@ -5879,43 +5886,6 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
return url.match(regex) ? RegExp.$2 : url;
|
return url.match(regex) ? RegExp.$2 : url;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Standardise YouTube quality unit
|
|
||||||
function mapQualityUnit(input) {
|
|
||||||
var qualities = {
|
|
||||||
hd2160: 2160,
|
|
||||||
hd1440: 1440,
|
|
||||||
hd1080: 1080,
|
|
||||||
hd720: 720,
|
|
||||||
large: 480,
|
|
||||||
medium: 360,
|
|
||||||
small: 240,
|
|
||||||
tiny: 144
|
|
||||||
};
|
|
||||||
|
|
||||||
var entry = Object.entries(qualities).find(function (entry) {
|
|
||||||
return entry.includes(input);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (entry) {
|
|
||||||
// Get the match corresponding to the input
|
|
||||||
return entry.find(function (value) {
|
|
||||||
return value !== input;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'default';
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapQualityUnits(levels) {
|
|
||||||
if (is.empty(levels)) {
|
|
||||||
return levels;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dedupe(levels.map(function (level) {
|
|
||||||
return mapQualityUnit(level);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set playback state and trigger change (only on actual change)
|
// Set playback state and trigger change (only on actual change)
|
||||||
function assurePlaybackState$1(play) {
|
function assurePlaybackState$1(play) {
|
||||||
if (play && !this.embed.hasPlayed) {
|
if (play && !this.embed.hasPlayed) {
|
||||||
@@ -6099,11 +6069,6 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
triggerEvent.call(player, player.media, 'error');
|
triggerEvent.call(player, player.media, 'error');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onPlaybackQualityChange: function onPlaybackQualityChange() {
|
|
||||||
triggerEvent.call(player, player.media, 'qualitychange', false, {
|
|
||||||
quality: player.media.quality
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onPlaybackRateChange: function onPlaybackRateChange(event) {
|
onPlaybackRateChange: function onPlaybackRateChange(event) {
|
||||||
// Get the instance
|
// Get the instance
|
||||||
var instance = event.target;
|
var instance = event.target;
|
||||||
@@ -6173,16 +6138,6 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Quality
|
|
||||||
Object.defineProperty(player.media, 'quality', {
|
|
||||||
get: function get() {
|
|
||||||
return mapQualityUnit(instance.getPlaybackQuality());
|
|
||||||
},
|
|
||||||
set: function set(input) {
|
|
||||||
instance.setPlaybackQuality(mapQualityUnit(input));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Volume
|
// Volume
|
||||||
var volume = player.config.volume;
|
var volume = player.config.volume;
|
||||||
|
|
||||||
@@ -6335,9 +6290,6 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
player.media.duration = instance.getDuration();
|
player.media.duration = instance.getDuration();
|
||||||
triggerEvent.call(player, player.media, 'durationchange');
|
triggerEvent.call(player, player.media, 'durationchange');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get quality
|
|
||||||
controls.setQualityMenu.call(player, mapQualityUnits(instance.getAvailableQualityLevels()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -8203,11 +8155,6 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
quality = value;
|
quality = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trigger request event
|
|
||||||
triggerEvent.call(this, this.media, 'qualityrequested', false, {
|
|
||||||
quality: quality
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update config
|
// Update config
|
||||||
config.selected = quality;
|
config.selected = quality;
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+141
-164
@@ -20,7 +20,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
var _core = createCommonjsModule(function (module) {
|
var _core = createCommonjsModule(function (module) {
|
||||||
var core = module.exports = { version: '2.5.3' };
|
var core = module.exports = { version: '2.5.7' };
|
||||||
if (typeof __e == 'number') __e = core; // eslint-disable-line no-undef
|
if (typeof __e == 'number') __e = core; // eslint-disable-line no-undef
|
||||||
});
|
});
|
||||||
var _core_1 = _core.version;
|
var _core_1 = _core.version;
|
||||||
@@ -333,11 +333,18 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var _shared = createCommonjsModule(function (module) {
|
||||||
var SHARED = '__core-js_shared__';
|
var SHARED = '__core-js_shared__';
|
||||||
var store = _global[SHARED] || (_global[SHARED] = {});
|
var store = _global[SHARED] || (_global[SHARED] = {});
|
||||||
var _shared = function (key) {
|
|
||||||
return store[key] || (store[key] = {});
|
(module.exports = function (key, value) {
|
||||||
};
|
return store[key] || (store[key] = value !== undefined ? value : {});
|
||||||
|
})('versions', []).push({
|
||||||
|
version: _core.version,
|
||||||
|
mode: 'global',
|
||||||
|
copyright: '© 2018 Denis Pushkarev (zloirock.ru)'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
var shared = _shared('keys');
|
var shared = _shared('keys');
|
||||||
|
|
||||||
@@ -741,12 +748,12 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
if ($slice !== undefined && end === undefined) return $slice.call(_anObject(this), start); // FF fix
|
if ($slice !== undefined && end === undefined) return $slice.call(_anObject(this), start); // FF fix
|
||||||
var len = _anObject(this).byteLength;
|
var len = _anObject(this).byteLength;
|
||||||
var first = _toAbsoluteIndex(start, len);
|
var first = _toAbsoluteIndex(start, len);
|
||||||
var final = _toAbsoluteIndex(end === undefined ? len : end, len);
|
var fin = _toAbsoluteIndex(end === undefined ? len : end, len);
|
||||||
var result = new (_speciesConstructor(this, $ArrayBuffer))(_toLength(final - first));
|
var result = new (_speciesConstructor(this, $ArrayBuffer))(_toLength(fin - first));
|
||||||
var viewS = new $DataView(this);
|
var viewS = new $DataView(this);
|
||||||
var viewT = new $DataView(result);
|
var viewT = new $DataView(result);
|
||||||
var index = 0;
|
var index = 0;
|
||||||
while (first < final) {
|
while (first < fin) {
|
||||||
viewT.setUint8(index++, viewS.getUint8(first++));
|
viewT.setUint8(index++, viewS.getUint8(first++));
|
||||||
} return result;
|
} return result;
|
||||||
}
|
}
|
||||||
@@ -991,7 +998,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
var VALUES_BUG = false;
|
var VALUES_BUG = false;
|
||||||
var proto = Base.prototype;
|
var proto = Base.prototype;
|
||||||
var $native = proto[ITERATOR$2] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT];
|
var $native = proto[ITERATOR$2] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT];
|
||||||
var $default = (!BUGGY && $native) || getMethod(DEFAULT);
|
var $default = $native || getMethod(DEFAULT);
|
||||||
var $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined;
|
var $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined;
|
||||||
var $anyNative = NAME == 'Array' ? proto.entries || $native : $native;
|
var $anyNative = NAME == 'Array' ? proto.entries || $native : $native;
|
||||||
var methods, key, IteratorPrototype;
|
var methods, key, IteratorPrototype;
|
||||||
@@ -1002,7 +1009,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
// Set @@toStringTag to native iterators
|
// Set @@toStringTag to native iterators
|
||||||
_setToStringTag(IteratorPrototype, TAG, true);
|
_setToStringTag(IteratorPrototype, TAG, true);
|
||||||
// fix for some old engines
|
// fix for some old engines
|
||||||
if (!_has(IteratorPrototype, ITERATOR$2)) _hide(IteratorPrototype, ITERATOR$2, returnThis);
|
if (typeof IteratorPrototype[ITERATOR$2] != 'function') _hide(IteratorPrototype, ITERATOR$2, returnThis);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// fix Array#{values, @@iterator}.name in V8 / FF
|
// fix Array#{values, @@iterator}.name in V8 / FF
|
||||||
@@ -2495,9 +2502,11 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
}
|
}
|
||||||
if (_has(ownDesc, 'value')) {
|
if (_has(ownDesc, 'value')) {
|
||||||
if (ownDesc.writable === false || !_isObject(receiver)) return false;
|
if (ownDesc.writable === false || !_isObject(receiver)) return false;
|
||||||
existingDescriptor = _objectGopd.f(receiver, propertyKey) || _propertyDesc(0);
|
if (existingDescriptor = _objectGopd.f(receiver, propertyKey)) {
|
||||||
existingDescriptor.value = V;
|
if (existingDescriptor.get || existingDescriptor.set || existingDescriptor.writable === false) return false;
|
||||||
_objectDp.f(receiver, propertyKey, existingDescriptor);
|
existingDescriptor.value = V;
|
||||||
|
_objectDp.f(receiver, propertyKey, existingDescriptor);
|
||||||
|
} else _objectDp.f(receiver, propertyKey, _propertyDesc(0, V));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return ownDesc.set === undefined ? false : (ownDesc.set.call(receiver, V), true);
|
return ownDesc.set === undefined ? false : (ownDesc.set.call(receiver, V), true);
|
||||||
@@ -2642,7 +2651,8 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
};
|
};
|
||||||
// environments with maybe non-completely correct, but existent Promise
|
// environments with maybe non-completely correct, but existent Promise
|
||||||
} else if (Promise$1 && Promise$1.resolve) {
|
} else if (Promise$1 && Promise$1.resolve) {
|
||||||
var promise = Promise$1.resolve();
|
// Promise.resolve without an argument throws an error in LG WebOS 2
|
||||||
|
var promise = Promise$1.resolve(undefined);
|
||||||
notify = function () {
|
notify = function () {
|
||||||
promise.then(flush);
|
promise.then(flush);
|
||||||
};
|
};
|
||||||
@@ -2699,6 +2709,10 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var navigator$1 = _global.navigator;
|
||||||
|
|
||||||
|
var _userAgent = navigator$1 && navigator$1.userAgent || '';
|
||||||
|
|
||||||
var _promiseResolve = function (C, x) {
|
var _promiseResolve = function (C, x) {
|
||||||
_anObject(C);
|
_anObject(C);
|
||||||
if (_isObject(x) && x.constructor === C) return x;
|
if (_isObject(x) && x.constructor === C) return x;
|
||||||
@@ -2713,9 +2727,12 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var PROMISE = 'Promise';
|
var PROMISE = 'Promise';
|
||||||
var TypeError$1 = _global.TypeError;
|
var TypeError$1 = _global.TypeError;
|
||||||
var process$2 = _global.process;
|
var process$2 = _global.process;
|
||||||
|
var versions = process$2 && process$2.versions;
|
||||||
|
var v8 = versions && versions.v8 || '';
|
||||||
var $Promise = _global[PROMISE];
|
var $Promise = _global[PROMISE];
|
||||||
var isNode$1 = _classof(process$2) == 'process';
|
var isNode$1 = _classof(process$2) == 'process';
|
||||||
var empty = function () { /* empty */ };
|
var empty = function () { /* empty */ };
|
||||||
@@ -2730,7 +2747,13 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
exec(empty, empty);
|
exec(empty, empty);
|
||||||
};
|
};
|
||||||
// unhandled rejections tracking support, NodeJS Promise without it fails @@species test
|
// unhandled rejections tracking support, NodeJS Promise without it fails @@species test
|
||||||
return (isNode$1 || typeof PromiseRejectionEvent == 'function') && promise.then(empty) instanceof FakePromise;
|
return (isNode$1 || typeof PromiseRejectionEvent == 'function')
|
||||||
|
&& promise.then(empty) instanceof FakePromise
|
||||||
|
// v8 6.6 (Node 10 and Chrome 66) have a bug with resolving custom thenables
|
||||||
|
// https://bugs.chromium.org/p/chromium/issues/detail?id=830565
|
||||||
|
// we can't detect it synchronously, so just check versions
|
||||||
|
&& v8.indexOf('6.6') !== 0
|
||||||
|
&& _userAgent.indexOf('Chrome/66') === -1;
|
||||||
} catch (e) { /* empty */ }
|
} catch (e) { /* empty */ }
|
||||||
}();
|
}();
|
||||||
|
|
||||||
@@ -2752,7 +2775,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
var resolve = reaction.resolve;
|
var resolve = reaction.resolve;
|
||||||
var reject = reaction.reject;
|
var reject = reaction.reject;
|
||||||
var domain = reaction.domain;
|
var domain = reaction.domain;
|
||||||
var result, then;
|
var result, then, exited;
|
||||||
try {
|
try {
|
||||||
if (handler) {
|
if (handler) {
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
@@ -2762,8 +2785,11 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
if (handler === true) result = value;
|
if (handler === true) result = value;
|
||||||
else {
|
else {
|
||||||
if (domain) domain.enter();
|
if (domain) domain.enter();
|
||||||
result = handler(value);
|
result = handler(value); // may throw
|
||||||
if (domain) domain.exit();
|
if (domain) {
|
||||||
|
domain.exit();
|
||||||
|
exited = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (result === reaction.promise) {
|
if (result === reaction.promise) {
|
||||||
reject(TypeError$1('Promise-chain cycle'));
|
reject(TypeError$1('Promise-chain cycle'));
|
||||||
@@ -2772,6 +2798,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
} else resolve(result);
|
} else resolve(result);
|
||||||
} else reject(value);
|
} else reject(value);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
if (domain && !exited) domain.exit();
|
||||||
reject(e);
|
reject(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -4154,10 +4181,6 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
return left ? stringFiller + S : S + stringFiller;
|
return left ? stringFiller + S : S + stringFiller;
|
||||||
};
|
};
|
||||||
|
|
||||||
var navigator$1 = _global.navigator;
|
|
||||||
|
|
||||||
var _userAgent = navigator$1 && navigator$1.userAgent || '';
|
|
||||||
|
|
||||||
// https://github.com/tc39/proposal-string-pad-start-end
|
// https://github.com/tc39/proposal-string-pad-start-end
|
||||||
|
|
||||||
|
|
||||||
@@ -5190,12 +5213,11 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
proto.toString = function() {
|
proto.toString = function() {
|
||||||
var searchString = '';
|
var searchArray = [];
|
||||||
this.forEach(function(value, name) {
|
this.forEach(function(value, name) {
|
||||||
if(searchString.length > 0) searchString+= '&';
|
searchArray.push(serializeParam(name) + '=' + serializeParam(value));
|
||||||
searchString += serializeParam(name) + '=' + serializeParam(value);
|
|
||||||
});
|
});
|
||||||
return searchString;
|
return searchArray.join("&");
|
||||||
};
|
};
|
||||||
|
|
||||||
global.URLSearchParams = URLSearchParams;
|
global.URLSearchParams = URLSearchParams;
|
||||||
@@ -5237,18 +5259,26 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
var URL = function(url, base) {
|
var URL = function(url, base) {
|
||||||
if(typeof url !== 'string') url = String(url);
|
if(typeof url !== 'string') url = String(url);
|
||||||
|
|
||||||
var doc = document.implementation.createHTMLDocument('');
|
// Only create another document if the base is different from current location.
|
||||||
window.doc = doc;
|
var doc = document, baseElement;
|
||||||
if(base) {
|
if(base && (global.location === void 0 || base !== global.location.href)) {
|
||||||
var baseElement = doc.createElement('base');
|
doc = document.implementation.createHTMLDocument('');
|
||||||
|
baseElement = doc.createElement('base');
|
||||||
baseElement.href = base;
|
baseElement.href = base;
|
||||||
doc.head.appendChild(baseElement);
|
doc.head.appendChild(baseElement);
|
||||||
|
try {
|
||||||
|
if(baseElement.href.indexOf(base) !== 0) throw new Error(baseElement.href);
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error("URL unable to set base " + base + " due to " + err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var anchorElement = doc.createElement('a');
|
var anchorElement = doc.createElement('a');
|
||||||
anchorElement.href = url;
|
anchorElement.href = url;
|
||||||
doc.body.appendChild(anchorElement);
|
if (baseElement) {
|
||||||
anchorElement.href = anchorElement.href; // force href to refresh
|
doc.body.appendChild(anchorElement);
|
||||||
|
anchorElement.href = anchorElement.href; // force href to refresh
|
||||||
|
}
|
||||||
|
|
||||||
if(anchorElement.protocol === ':' || !/:/.test(anchorElement.href)) {
|
if(anchorElement.protocol === ':' || !/:/.test(anchorElement.href)) {
|
||||||
throw new TypeError('Invalid URL');
|
throw new TypeError('Invalid URL');
|
||||||
@@ -6283,6 +6313,9 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
triggerEvent.call(player, player.media, 'qualitychange', false, {
|
triggerEvent.call(player, player.media, 'qualitychange', false, {
|
||||||
quality: input
|
quality: input
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Save to storage
|
||||||
|
player.storage.set({ quality: input });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -6315,6 +6348,30 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
|
// Remove duplicates in an array
|
||||||
|
function dedupe(array) {
|
||||||
|
if (!is$1.array(array)) {
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
return array.filter(function (item, index) {
|
||||||
|
return array.indexOf(item) === index;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the closest value in an array
|
||||||
|
function closest(array, value) {
|
||||||
|
if (!is$1.array(array) || !array.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return array.reduce(function (prev, curr) {
|
||||||
|
return Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==========================================================================
|
||||||
|
|
||||||
// Clone nested objects
|
// Clone nested objects
|
||||||
function cloneDeep(object) {
|
function cloneDeep(object) {
|
||||||
return JSON.parse(JSON.stringify(object));
|
return JSON.parse(JSON.stringify(object));
|
||||||
@@ -6493,30 +6550,6 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
// Remove duplicates in an array
|
|
||||||
function dedupe(array) {
|
|
||||||
if (!is$1.array(array)) {
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
return array.filter(function (item, index) {
|
|
||||||
return array.indexOf(item) === index;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the closest value in an array
|
|
||||||
function closest(array, value) {
|
|
||||||
if (!is$1.array(array) || !array.length) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return array.reduce(function (prev, curr) {
|
|
||||||
return Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==========================================================================
|
|
||||||
|
|
||||||
var Storage = function () {
|
var Storage = function () {
|
||||||
function Storage(player) {
|
function Storage(player) {
|
||||||
classCallCheck(this, Storage);
|
classCallCheck(this, Storage);
|
||||||
@@ -7001,20 +7034,6 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
this.elements.buttons[type] = button;
|
this.elements.buttons[type] = button;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle classname when pressed property is set
|
|
||||||
var className = this.config.classNames.controlPressed;
|
|
||||||
Object.defineProperty(button, 'pressed', {
|
|
||||||
enumerable: true,
|
|
||||||
get: function get() {
|
|
||||||
return hasClass(button, className);
|
|
||||||
},
|
|
||||||
set: function set() {
|
|
||||||
var pressed = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
|
||||||
|
|
||||||
toggleClass(button, className, pressed);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return button;
|
return button;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -7887,11 +7906,10 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
// Focus the first item if key interaction
|
// Focus the first item if key interaction
|
||||||
if (show && is$1.keyboardEvent(input)) {
|
if (show && is$1.keyboardEvent(input)) {
|
||||||
controls.focusFirstMenuItem.call(this, null, true);
|
controls.focusFirstMenuItem.call(this, null, true);
|
||||||
|
} else if (!show && !hidden) {
|
||||||
|
// If closing, re-focus the button
|
||||||
|
setFocus.call(this, button, is$1.keyboardEvent(input));
|
||||||
}
|
}
|
||||||
// If closing, re-focus the button
|
|
||||||
else if (!show && !hidden) {
|
|
||||||
setFocus.call(this, button, is$1.keyboardEvent(input));
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
@@ -8048,30 +8066,33 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
container.appendChild(controls.createTime.call(this, 'duration'));
|
container.appendChild(controls.createTime.call(this, 'duration'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle mute button
|
// Volume controls
|
||||||
if (this.config.controls.includes('mute')) {
|
if (this.config.controls.includes('mute') || this.config.controls.includes('volume')) {
|
||||||
container.appendChild(controls.createButton.call(this, 'mute'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Volume range control
|
|
||||||
if (this.config.controls.includes('volume')) {
|
|
||||||
var volume = createElement('div', {
|
var volume = createElement('div', {
|
||||||
class: 'plyr__volume'
|
class: 'plyr__volume'
|
||||||
});
|
});
|
||||||
|
|
||||||
// Set the attributes
|
// Toggle mute button
|
||||||
var attributes = {
|
if (this.config.controls.includes('mute')) {
|
||||||
max: 1,
|
volume.appendChild(controls.createButton.call(this, 'mute'));
|
||||||
step: 0.05,
|
}
|
||||||
value: this.config.volume
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create the volume range slider
|
// Volume range control
|
||||||
volume.appendChild(controls.createRange.call(this, 'volume', extend(attributes, {
|
if (this.config.controls.includes('volume')) {
|
||||||
id: 'plyr-volume-' + data.id
|
// Set the attributes
|
||||||
})));
|
var attributes = {
|
||||||
|
max: 1,
|
||||||
|
step: 0.05,
|
||||||
|
value: this.config.volume
|
||||||
|
};
|
||||||
|
|
||||||
this.elements.volume = volume;
|
// Create the volume range slider
|
||||||
|
volume.appendChild(controls.createRange.call(this, 'volume', extend(attributes, {
|
||||||
|
id: 'plyr-volume-' + data.id
|
||||||
|
})));
|
||||||
|
|
||||||
|
this.elements.volume = volume;
|
||||||
|
}
|
||||||
|
|
||||||
container.appendChild(volume);
|
container.appendChild(volume);
|
||||||
}
|
}
|
||||||
@@ -8233,6 +8254,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
this.elements.controls = container;
|
this.elements.controls = container;
|
||||||
|
|
||||||
|
// Set available quality levels
|
||||||
if (this.isHTML5) {
|
if (this.isHTML5) {
|
||||||
controls.setQualityMenu.call(this, html5.getQualityOptions.call(this));
|
controls.setQualityMenu.call(this, html5.getQualityOptions.call(this));
|
||||||
}
|
}
|
||||||
@@ -8345,6 +8367,25 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
controls.findElements.call(this);
|
controls.findElements.call(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add pressed property to buttons
|
||||||
|
if (!is$1.empty(this.elements.buttons)) {
|
||||||
|
// Toggle classname when pressed property is set
|
||||||
|
Object.values(this.elements.buttons).forEach(function (button) {
|
||||||
|
var className = _this10.config.classNames.controlPressed;
|
||||||
|
Object.defineProperty(button, 'pressed', {
|
||||||
|
enumerable: true,
|
||||||
|
get: function get() {
|
||||||
|
return hasClass(button, className);
|
||||||
|
},
|
||||||
|
set: function set() {
|
||||||
|
var pressed = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
||||||
|
|
||||||
|
toggleClass(button, className, pressed);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Edge sometimes doesn't finish the paint so force a redraw
|
// Edge sometimes doesn't finish the paint so force a redraw
|
||||||
if (window.navigator.userAgent.includes('Edge')) {
|
if (window.navigator.userAgent.includes('Edge')) {
|
||||||
repaint(target);
|
repaint(target);
|
||||||
@@ -8462,7 +8503,8 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
// * active: The state preferred by user settings or config
|
// * active: The state preferred by user settings or config
|
||||||
// * toggled: The real captions state
|
// * toggled: The real captions state
|
||||||
|
|
||||||
var languages = dedupe(Array.from(navigator.languages || navigator.language || navigator.userLanguage).map(function (language) {
|
var browserLanguages = navigator.languages || [navigator.language || navigator.userLanguage || 'en'];
|
||||||
|
var languages = dedupe(browserLanguages.map(function (language) {
|
||||||
return language.split('-')[0];
|
return language.split('-')[0];
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -8885,7 +8927,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
// Quality default
|
// Quality default
|
||||||
quality: {
|
quality: {
|
||||||
default: 576,
|
default: 576,
|
||||||
options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240, 'default']
|
options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240]
|
||||||
},
|
},
|
||||||
|
|
||||||
// Set loops
|
// Set loops
|
||||||
@@ -9035,7 +9077,10 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
'enterfullscreen', 'exitfullscreen', 'captionsenabled', 'captionsdisabled', 'languagechange', 'controlshidden', 'controlsshown', 'ready',
|
'enterfullscreen', 'exitfullscreen', 'captionsenabled', 'captionsdisabled', 'languagechange', 'controlshidden', 'controlsshown', 'ready',
|
||||||
|
|
||||||
// YouTube
|
// YouTube
|
||||||
'statechange', 'qualitychange', 'qualityrequested',
|
'statechange',
|
||||||
|
|
||||||
|
// Quality
|
||||||
|
'qualitychange',
|
||||||
|
|
||||||
// Ads
|
// Ads
|
||||||
'adsloaded', 'adscontentpause', 'adscontentresume', 'adstarted', 'adsmidpoint', 'adscomplete', 'adsallcomplete', 'adsimpression', 'adsclick'],
|
'adsloaded', 'adscontentpause', 'adscontentresume', 'adstarted', 'adsmidpoint', 'adscomplete', 'adsallcomplete', 'adsimpression', 'adsclick'],
|
||||||
@@ -9344,9 +9389,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
// iOS native fullscreen doesn't need the request step
|
// iOS native fullscreen doesn't need the request step
|
||||||
if (browser.isIos && this.player.config.fullscreen.iosNative) {
|
if (browser.isIos && this.player.config.fullscreen.iosNative) {
|
||||||
if (this.player.playing) {
|
this.target.webkitEnterFullscreen();
|
||||||
this.target.webkitEnterFullscreen();
|
|
||||||
}
|
|
||||||
} else if (!Fullscreen.native) {
|
} else if (!Fullscreen.native) {
|
||||||
toggleFallback.call(this, true);
|
toggleFallback.call(this, true);
|
||||||
} else if (!this.prefix) {
|
} else if (!this.prefix) {
|
||||||
@@ -10033,7 +10076,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
// Remove button states for fullscreen
|
// Remove button states for fullscreen
|
||||||
|
|
||||||
if (event.type === 'enterfullscreen') {
|
if (controls$$1 && event.type === 'enterfullscreen') {
|
||||||
controls$$1.pressed = false;
|
controls$$1.pressed = false;
|
||||||
controls$$1.hover = false;
|
controls$$1.hover = false;
|
||||||
}
|
}
|
||||||
@@ -10191,12 +10234,6 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
player.storage.set({ speed: player.speed });
|
player.storage.set({ speed: player.speed });
|
||||||
});
|
});
|
||||||
|
|
||||||
// Quality request
|
|
||||||
on.call(player, player.media, 'qualityrequested', function (event) {
|
|
||||||
// Save to storage
|
|
||||||
player.storage.set({ quality: event.detail.quality });
|
|
||||||
});
|
|
||||||
|
|
||||||
// Quality change
|
// Quality change
|
||||||
on.call(player, player.media, 'qualitychange', function (event) {
|
on.call(player, player.media, 'qualitychange', function (event) {
|
||||||
// Update UI
|
// Update UI
|
||||||
@@ -11270,43 +11307,6 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
return url.match(regex) ? RegExp.$2 : url;
|
return url.match(regex) ? RegExp.$2 : url;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Standardise YouTube quality unit
|
|
||||||
function mapQualityUnit(input) {
|
|
||||||
var qualities = {
|
|
||||||
hd2160: 2160,
|
|
||||||
hd1440: 1440,
|
|
||||||
hd1080: 1080,
|
|
||||||
hd720: 720,
|
|
||||||
large: 480,
|
|
||||||
medium: 360,
|
|
||||||
small: 240,
|
|
||||||
tiny: 144
|
|
||||||
};
|
|
||||||
|
|
||||||
var entry = Object.entries(qualities).find(function (entry) {
|
|
||||||
return entry.includes(input);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (entry) {
|
|
||||||
// Get the match corresponding to the input
|
|
||||||
return entry.find(function (value) {
|
|
||||||
return value !== input;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'default';
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapQualityUnits(levels) {
|
|
||||||
if (is$1.empty(levels)) {
|
|
||||||
return levels;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dedupe(levels.map(function (level) {
|
|
||||||
return mapQualityUnit(level);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set playback state and trigger change (only on actual change)
|
// Set playback state and trigger change (only on actual change)
|
||||||
function assurePlaybackState$1(play) {
|
function assurePlaybackState$1(play) {
|
||||||
if (play && !this.embed.hasPlayed) {
|
if (play && !this.embed.hasPlayed) {
|
||||||
@@ -11490,11 +11490,6 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
triggerEvent.call(player, player.media, 'error');
|
triggerEvent.call(player, player.media, 'error');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onPlaybackQualityChange: function onPlaybackQualityChange() {
|
|
||||||
triggerEvent.call(player, player.media, 'qualitychange', false, {
|
|
||||||
quality: player.media.quality
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onPlaybackRateChange: function onPlaybackRateChange(event) {
|
onPlaybackRateChange: function onPlaybackRateChange(event) {
|
||||||
// Get the instance
|
// Get the instance
|
||||||
var instance = event.target;
|
var instance = event.target;
|
||||||
@@ -11564,16 +11559,6 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Quality
|
|
||||||
Object.defineProperty(player.media, 'quality', {
|
|
||||||
get: function get() {
|
|
||||||
return mapQualityUnit(instance.getPlaybackQuality());
|
|
||||||
},
|
|
||||||
set: function set(input) {
|
|
||||||
instance.setPlaybackQuality(mapQualityUnit(input));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Volume
|
// Volume
|
||||||
var volume = player.config.volume;
|
var volume = player.config.volume;
|
||||||
|
|
||||||
@@ -11726,9 +11711,6 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
player.media.duration = instance.getDuration();
|
player.media.duration = instance.getDuration();
|
||||||
triggerEvent.call(player, player.media, 'durationchange');
|
triggerEvent.call(player, player.media, 'durationchange');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get quality
|
|
||||||
controls.setQualityMenu.call(player, mapQualityUnits(instance.getAvailableQualityLevels()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -13594,11 +13576,6 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
quality = value;
|
quality = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trigger request event
|
|
||||||
triggerEvent.call(this, this.media, 'qualityrequested', false, {
|
|
||||||
quality: quality
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update config
|
// Update config
|
||||||
config.selected = quality;
|
config.selected = quality;
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+14
-24
@@ -1,19 +1,10 @@
|
|||||||
{
|
{
|
||||||
"name": "plyr",
|
"name": "plyr",
|
||||||
"version": "3.4.0-beta.2",
|
"version": "3.4.0",
|
||||||
"description":
|
"description": "A simple, accessible and customizable HTML5, YouTube and Vimeo media player",
|
||||||
"A simple, accessible and customizable HTML5, YouTube and Vimeo media player",
|
|
||||||
"homepage": "https://plyr.io",
|
"homepage": "https://plyr.io",
|
||||||
"author": "Sam Potts <sam@potts.es>",
|
"author": "Sam Potts <sam@potts.es>",
|
||||||
"keywords": [
|
"keywords": ["HTML5 Video", "HTML5 Audio", "Media Player", "DASH", "Shaka", "WordPress", "HLS"],
|
||||||
"HTML5 Video",
|
|
||||||
"HTML5 Audio",
|
|
||||||
"Media Player",
|
|
||||||
"DASH",
|
|
||||||
"Shaka",
|
|
||||||
"WordPress",
|
|
||||||
"HLS"
|
|
||||||
],
|
|
||||||
"main": "./dist/plyr.js",
|
"main": "./dist/plyr.js",
|
||||||
"browser": "./dist/plyr.min.js",
|
"browser": "./dist/plyr.min.js",
|
||||||
"sass": "./src/sass/plyr.scss",
|
"sass": "./src/sass/plyr.scss",
|
||||||
@@ -32,8 +23,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "gulp build",
|
"build": "gulp build",
|
||||||
"lint": "eslint src/js && npm run-script remark",
|
"lint": "eslint src/js && npm run-script remark",
|
||||||
"remark":
|
"remark": "remark -f --use 'validate-links=repository:\"sampotts/plyr\"' '{,!(node_modules),.?**/}*.md'",
|
||||||
"remark -f --use 'validate-links=repository:\"sampotts/plyr\"' '{,!(node_modules),.?**/}*.md'",
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -42,21 +32,21 @@
|
|||||||
"babel-plugin-external-helpers": "^6.22.0",
|
"babel-plugin-external-helpers": "^6.22.0",
|
||||||
"babel-preset-env": "^1.7.0",
|
"babel-preset-env": "^1.7.0",
|
||||||
"del": "^3.0.0",
|
"del": "^3.0.0",
|
||||||
"eslint": "^5.2.0",
|
"eslint": "^5.3.0",
|
||||||
"eslint-config-airbnb-base": "^13.0.0",
|
"eslint-config-airbnb-base": "^13.1.0",
|
||||||
"eslint-config-prettier": "^2.9.0",
|
"eslint-config-prettier": "^2.9.0",
|
||||||
"eslint-plugin-import": "^2.13.0",
|
"eslint-plugin-import": "^2.14.0",
|
||||||
"fastly-purge": "^1.0.1",
|
"fastly-purge": "^1.0.1",
|
||||||
"git-branch": "^2.0.1",
|
"git-branch": "^2.0.1",
|
||||||
"gulp": "^3.9.1",
|
"gulp": "^3.9.1",
|
||||||
"gulp-autoprefixer": "^5.0.0",
|
"gulp-autoprefixer": "^5.0.0",
|
||||||
"gulp-better-rollup": "^3.3.0",
|
"gulp-better-rollup": "^3.3.0",
|
||||||
"gulp-clean-css": "^3.9.4",
|
"gulp-clean-css": "^3.10.0",
|
||||||
"gulp-concat": "^2.6.1",
|
"gulp-concat": "^2.6.1",
|
||||||
"gulp-filter": "^5.1.0",
|
"gulp-filter": "^5.1.0",
|
||||||
"gulp-header": "^2.0.5",
|
"gulp-header": "^2.0.5",
|
||||||
"gulp-open": "^3.0.1",
|
"gulp-open": "^3.0.1",
|
||||||
"gulp-postcss": "^7.0.1",
|
"gulp-postcss": "^8.0.0",
|
||||||
"gulp-rename": "^1.4.0",
|
"gulp-rename": "^1.4.0",
|
||||||
"gulp-replace": "^1.0.0",
|
"gulp-replace": "^1.0.0",
|
||||||
"gulp-s3": "^0.11.0",
|
"gulp-s3": "^0.11.0",
|
||||||
@@ -73,15 +63,15 @@
|
|||||||
"remark-cli": "^5.0.0",
|
"remark-cli": "^5.0.0",
|
||||||
"remark-validate-links": "^7.0.0",
|
"remark-validate-links": "^7.0.0",
|
||||||
"rollup-plugin-babel": "^3.0.7",
|
"rollup-plugin-babel": "^3.0.7",
|
||||||
"rollup-plugin-commonjs": "^9.1.4",
|
"rollup-plugin-commonjs": "^9.1.5",
|
||||||
"rollup-plugin-node-resolve": "^3.3.0",
|
"rollup-plugin-node-resolve": "^3.3.0",
|
||||||
"run-sequence": "^2.2.1",
|
"run-sequence": "^2.2.1",
|
||||||
"stylelint": "^9.4.0",
|
"stylelint": "^9.4.0",
|
||||||
"stylelint-config-prettier": "^3.3.0",
|
"stylelint-config-prettier": "^4.0.0",
|
||||||
"stylelint-config-recommended": "^2.1.0",
|
"stylelint-config-recommended": "^2.1.0",
|
||||||
"stylelint-config-sass-guidelines": "^5.0.0",
|
"stylelint-config-sass-guidelines": "^5.0.0",
|
||||||
"stylelint-order": "^0.8.1",
|
"stylelint-order": "^1.0.0",
|
||||||
"stylelint-scss": "^3.2.0",
|
"stylelint-scss": "^3.3.0",
|
||||||
"stylelint-selector-bem-pattern": "^2.0.0",
|
"stylelint-selector-bem-pattern": "^2.0.0",
|
||||||
"through2": "^2.0.3"
|
"through2": "^2.0.3"
|
||||||
},
|
},
|
||||||
@@ -90,6 +80,6 @@
|
|||||||
"custom-event-polyfill": "^1.0.6",
|
"custom-event-polyfill": "^1.0.6",
|
||||||
"loadjs": "^3.5.4",
|
"loadjs": "^3.5.4",
|
||||||
"raven-js": "^3.26.4",
|
"raven-js": "^3.26.4",
|
||||||
"url-polyfill": "^1.0.13"
|
"url-polyfill": "^1.0.14"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,26 +8,26 @@ A simple, lightweight, accessible and customizable HTML5, YouTube and Vimeo medi
|
|||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
* **Accessible** - full support for VTT captions and screen readers
|
- **Accessible** - full support for VTT captions and screen readers
|
||||||
* **[Customisable](#html)** - make the player look how you want with the markup you want
|
- **[Customisable](#html)** - make the player look how you want with the markup you want
|
||||||
* **Good HTML** - uses the _right_ elements. `<input type="range">` for volume and `<progress>` for progress and well, `<button>`s for buttons. There's no
|
- **Good HTML** - uses the _right_ elements. `<input type="range">` for volume and `<progress>` for progress and well, `<button>`s for buttons. There's no
|
||||||
`<span>` or `<a href="#">` button hacks
|
`<span>` or `<a href="#">` button hacks
|
||||||
* **Responsive** - works with any screen size
|
- **Responsive** - works with any screen size
|
||||||
* **HTML Video & Audio** - support for both formats
|
- **HTML Video & Audio** - support for both formats
|
||||||
* **[Embedded Video](#embeds)** - support for YouTube and Vimeo video playback
|
- **[Embedded Video](#embeds)** - support for YouTube and Vimeo video playback
|
||||||
* **[Monetization](#ads)** - make money from your videos
|
- **[Monetization](#ads)** - make money from your videos
|
||||||
* **[Streaming](#try-plyr-online)** - support for hls.js, Shaka and dash.js streaming playback
|
- **[Streaming](#try-plyr-online)** - support for hls.js, Shaka and dash.js streaming playback
|
||||||
* **[API](#api)** - toggle playback, volume, seeking, and more through a standardized API
|
- **[API](#api)** - toggle playback, volume, seeking, and more through a standardized API
|
||||||
* **[Events](#events)** - no messing around with Vimeo and YouTube APIs, all events are standardized across formats
|
- **[Events](#events)** - no messing around with Vimeo and YouTube APIs, all events are standardized across formats
|
||||||
* **[Fullscreen](#fullscreen)** - supports native fullscreen with fallback to "full window" modes
|
- **[Fullscreen](#fullscreen)** - supports native fullscreen with fallback to "full window" modes
|
||||||
* **[Shortcuts](#shortcuts)** - supports keyboard shortcuts
|
- **[Shortcuts](#shortcuts)** - supports keyboard shortcuts
|
||||||
* **Picture-in-Picture** - supports Safari's picture-in-picture mode
|
- **Picture-in-Picture** - supports Safari's picture-in-picture mode
|
||||||
* **Playsinline** - supports the `playsinline` attribute
|
- **Playsinline** - supports the `playsinline` attribute
|
||||||
* **Speed controls** - adjust speed on the fly
|
- **Speed controls** - adjust speed on the fly
|
||||||
* **Multiple captions** - support for multiple caption tracks
|
- **Multiple captions** - support for multiple caption tracks
|
||||||
* **i18n support** - support for internationalization of controls
|
- **i18n support** - support for internationalization of controls
|
||||||
* **No dependencies** - written in "vanilla" ES6 JavaScript, no jQuery required
|
- **No dependencies** - written in "vanilla" ES6 JavaScript, no jQuery required
|
||||||
* **SASS** - to include in your build processes
|
- **SASS** - to include in your build processes
|
||||||
|
|
||||||
Oh and yes, it works with Bootstrap.
|
Oh and yes, it works with Bootstrap.
|
||||||
|
|
||||||
@@ -132,13 +132,13 @@ See [initialising](#initialising) for more information on advanced setups.
|
|||||||
You can use our CDN (provided by [Fastly](https://www.fastly.com/)) for the JavaScript. There's 2 versions; one with and one without [polyfills](#polyfills). My recommendation would be to manage polyfills seperately as part of your application but to make life easier you can use the polyfilled build.
|
You can use our CDN (provided by [Fastly](https://www.fastly.com/)) for the JavaScript. There's 2 versions; one with and one without [polyfills](#polyfills). My recommendation would be to manage polyfills seperately as part of your application but to make life easier you can use the polyfilled build.
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<script src="https://cdn.plyr.io/3.4.0-beta.2/plyr.js"></script>
|
<script src="https://cdn.plyr.io/3.4.0/plyr.js"></script>
|
||||||
```
|
```
|
||||||
|
|
||||||
...or...
|
...or...
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<script src="https://cdn.plyr.io/3.4.0-beta.2/plyr.polyfilled.js"></script>
|
<script src="https://cdn.plyr.io/3.4.0/plyr.polyfilled.js"></script>
|
||||||
```
|
```
|
||||||
|
|
||||||
### CSS
|
### CSS
|
||||||
@@ -152,21 +152,21 @@ Include the `plyr.css` stylsheet into your `<head>`
|
|||||||
If you want to use our CDN (provided by [Fastly](https://www.fastly.com/)) for the default CSS, you can use the following:
|
If you want to use our CDN (provided by [Fastly](https://www.fastly.com/)) for the default CSS, you can use the following:
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<link rel="stylesheet" href="https://cdn.plyr.io/3.4.0-beta.2/plyr.css">
|
<link rel="stylesheet" href="https://cdn.plyr.io/3.4.0/plyr.css">
|
||||||
```
|
```
|
||||||
|
|
||||||
### SVG Sprite
|
### SVG Sprite
|
||||||
|
|
||||||
The SVG sprite is loaded automatically from our CDN (provided by [Fastly](https://www.fastly.com/)). To change this, see the [options](#options) below. For
|
The SVG sprite is loaded automatically from our CDN (provided by [Fastly](https://www.fastly.com/)). To change this, see the [options](#options) below. For
|
||||||
reference, the CDN hosted SVG sprite can be found at `https://cdn.plyr.io/3.4.0-beta.2/plyr.svg`.
|
reference, the CDN hosted SVG sprite can be found at `https://cdn.plyr.io/3.4.0/plyr.svg`.
|
||||||
|
|
||||||
## Ads
|
## Ads
|
||||||
|
|
||||||
Plyr has partnered up with [vi.ai](https://vi.ai/publisher-video-monetization/?aid=plyrio) to offer monetization options for your videos. Getting setup is easy:
|
Plyr has partnered up with [vi.ai](https://vi.ai/publisher-video-monetization/?aid=plyrio) to offer monetization options for your videos. Getting setup is easy:
|
||||||
|
|
||||||
* [Sign up for a vi.ai account](https://vi.ai/publisher-video-monetization/?aid=plyrio)
|
- [Sign up for a vi.ai account](https://vi.ai/publisher-video-monetization/?aid=plyrio)
|
||||||
* Grab your publisher ID from the code snippet
|
- Grab your publisher ID from the code snippet
|
||||||
* Enable ads in the [config options](#options) and enter your publisher ID
|
- Enable ads in the [config options](#options) and enter your publisher ID
|
||||||
|
|
||||||
Any questions regarding the ads can be sent straight to vi.ai and any issues with rendering raised through GitHub issues.
|
Any questions regarding the ads can be sent straight to vi.ai and any issues with rendering raised through GitHub issues.
|
||||||
|
|
||||||
@@ -213,10 +213,10 @@ WebVTT captions are supported. To add a caption track, check the HTML example ab
|
|||||||
|
|
||||||
You can specify a range of arguments for the constructor to use:
|
You can specify a range of arguments for the constructor to use:
|
||||||
|
|
||||||
* A CSS string selector that's compatible with [`querySelector`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector)
|
- A CSS string selector that's compatible with [`querySelector`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector)
|
||||||
* A [`HTMLElement`](https://developer.mozilla.org/en/docs/Web/API/HTMLElement)
|
- A [`HTMLElement`](https://developer.mozilla.org/en/docs/Web/API/HTMLElement)
|
||||||
* A [`NodeList`](https://developer.mozilla.org/en-US/docs/Web/API/NodeList)
|
- A [`NodeList`](https://developer.mozilla.org/en-US/docs/Web/API/NodeList)
|
||||||
* A [jQuery](https://jquery.com) object
|
- A [jQuery](https://jquery.com) object
|
||||||
|
|
||||||
_Note_: If a `NodeList`, `Array`, or jQuery object are passed, the first element will be used for setup. To setup multiple players, see [setting up multiple players](#setting-up-multiple-players) below.
|
_Note_: If a `NodeList`, `Array`, or jQuery object are passed, the first element will be used for setup. To setup multiple players, see [setting up multiple players](#setting-up-multiple-players) below.
|
||||||
|
|
||||||
@@ -286,11 +286,11 @@ Note the single quotes encapsulating the JSON and double quotes on the object ke
|
|||||||
| `debug` | Boolean | `false` | Display debugging information in the console |
|
| `debug` | Boolean | `false` | Display debugging information in the console |
|
||||||
| `controls` | Array, Function or Element | `['play-large', 'play', 'progress', 'current-time', 'mute', 'volume', 'captions', 'settings', 'pip', 'airplay', 'fullscreen']` | If a function is passed, it is assumed your method will return either an element or HTML string for the controls. Three arguments will be passed to your function; `id` (the unique id for the player), `seektime` (the seektime step in seconds), and `title` (the media title). See [controls.md](controls.md) for more info on how the html needs to be structured. |
|
| `controls` | Array, Function or Element | `['play-large', 'play', 'progress', 'current-time', 'mute', 'volume', 'captions', 'settings', 'pip', 'airplay', 'fullscreen']` | If a function is passed, it is assumed your method will return either an element or HTML string for the controls. Three arguments will be passed to your function; `id` (the unique id for the player), `seektime` (the seektime step in seconds), and `title` (the media title). See [controls.md](controls.md) for more info on how the html needs to be structured. |
|
||||||
| `settings` | Array | `['captions', 'quality', 'speed', 'loop']` | If you're using the default controls are used then you can specify which settings to show in the menu |
|
| `settings` | Array | `['captions', 'quality', 'speed', 'loop']` | If you're using the default controls are used then you can specify which settings to show in the menu |
|
||||||
| `i18n` | Object | See [defaults.js](/src/js/config/defaults.js) | Used for internationalization (i18n) of the text within the UI. |
|
| `i18n` | Object | See [defaults.js](/src/js/config/defaults.js) | Used for internationalization (i18n) of the text within the UI. |
|
||||||
| `loadSprite` | Boolean | `true` | Load the SVG sprite specified as the `iconUrl` option (if a URL). If `false`, it is assumed you are handling sprite loading yourself. |
|
| `loadSprite` | Boolean | `true` | Load the SVG sprite specified as the `iconUrl` option (if a URL). If `false`, it is assumed you are handling sprite loading yourself. |
|
||||||
| `iconUrl` | String | `null` | Specify a URL or path to the SVG sprite. See the [SVG section](#svg) for more info. |
|
| `iconUrl` | String | `null` | Specify a URL or path to the SVG sprite. See the [SVG section](#svg) for more info. |
|
||||||
| `iconPrefix` | String | `plyr` | Specify the id prefix for the icons used in the default controls (e.g. "plyr-play" would be "plyr"). This is to prevent clashes if you're using your own SVG sprite but with the default controls. Most people can ignore this option. |
|
| `iconPrefix` | String | `plyr` | Specify the id prefix for the icons used in the default controls (e.g. "plyr-play" would be "plyr"). This is to prevent clashes if you're using your own SVG sprite but with the default controls. Most people can ignore this option. |
|
||||||
| `blankUrl` | String | `https://cdn.plyr.io/static/blank.mp4` | Specify a URL or path to a blank video file used to properly cancel network requests. |
|
| `blankVideo` | String | `https://cdn.plyr.io/static/blank.mp4` | Specify a URL or path to a blank video file used to properly cancel network requests. |
|
||||||
| `autoplay` | Boolean | `false` | Autoplay the media on load. This is generally advised against on UX grounds. It is also disabled by default in some browsers. If the `autoplay` attribute is present on a `<video>` or `<audio>` element, this will be automatically set to true. |
|
| `autoplay` | Boolean | `false` | Autoplay the media on load. This is generally advised against on UX grounds. It is also disabled by default in some browsers. If the `autoplay` attribute is present on a `<video>` or `<audio>` element, this will be automatically set to true. |
|
||||||
| `autopause`¹ | Boolean | `true` | Only allow one player playing at once. |
|
| `autopause`¹ | Boolean | `true` | Only allow one player playing at once. |
|
||||||
| `seekTime` | Number | `10` | The time, in seconds, to seek when a user hits fast forward or rewind. |
|
| `seekTime` | Number | `10` | The time, in seconds, to seek when a user hits fast forward or rewind. |
|
||||||
@@ -307,7 +307,7 @@ Note the single quotes encapsulating the JSON and double quotes on the object ke
|
|||||||
| `invertTime` | Boolean | `true` | Display the current time as a countdown rather than an incremental counter. |
|
| `invertTime` | Boolean | `true` | Display the current time as a countdown rather than an incremental counter. |
|
||||||
| `toggleInvert` | Boolean | `true` | Allow users to click to toggle the above. |
|
| `toggleInvert` | Boolean | `true` | Allow users to click to toggle the above. |
|
||||||
| `listeners` | Object | `null` | Allows binding of event listeners to the controls before the default handlers. See the `defaults.js` for available listeners. If your handler prevents default on the event (`event.preventDefault()`), the default handler will not fire. |
|
| `listeners` | Object | `null` | Allows binding of event listeners to the controls before the default handlers. See the `defaults.js` for available listeners. If your handler prevents default on the event (`event.preventDefault()`), the default handler will not fire. |
|
||||||
| `captions` | Object | `{ active: false, language: 'auto', update: false }` | `active`: Toggles if captions should be active by default. `language`: Sets the default language to load (if available). 'auto' uses the browser language. `update`: Listen to changes to tracks and update menu. This is needed for some streaming libraries, but can result in unselectable language options). |
|
| `captions` | Object | `{ active: false, language: 'auto', update: false }` | `active`: Toggles if captions should be active by default. `language`: Sets the default language to load (if available). 'auto' uses the browser language. `update`: Listen to changes to tracks and update menu. This is needed for some streaming libraries, but can result in unselectable language options). |
|
||||||
| `fullscreen` | Object | `{ enabled: true, fallback: true, iosNative: false }` | `enabled`: Toggles whether fullscreen should be enabled. `fallback`: Allow fallback to a full-window solution. `iosNative`: whether to use native iOS fullscreen when entering fullscreen (no custom controls) |
|
| `fullscreen` | Object | `{ enabled: true, fallback: true, iosNative: false }` | `enabled`: Toggles whether fullscreen should be enabled. `fallback`: Allow fallback to a full-window solution. `iosNative`: whether to use native iOS fullscreen when entering fullscreen (no custom controls) |
|
||||||
| `ratio` | String | `16:9` | The aspect ratio you want to use for embedded players. |
|
| `ratio` | String | `16:9` | The aspect ratio you want to use for embedded players. |
|
||||||
| `storage` | Object | `{ enabled: true, key: 'plyr' }` | `enabled`: Allow use of local storage to store user settings. `key`: The key name to use. |
|
| `storage` | Object | `{ enabled: true, key: 'plyr' }` | `enabled`: Allow use of local storage to store user settings. `key`: The key name to use. |
|
||||||
@@ -365,9 +365,9 @@ player.fullscreen.enter(); // Enter fullscreen
|
|||||||
| `fullscreen.exit()` | - | Exit fullscreen. |
|
| `fullscreen.exit()` | - | Exit fullscreen. |
|
||||||
| `fullscreen.toggle()` | - | Toggle fullscreen. |
|
| `fullscreen.toggle()` | - | Toggle fullscreen. |
|
||||||
| `airplay()` | - | Trigger the airplay dialog on supported devices. |
|
| `airplay()` | - | Trigger the airplay dialog on supported devices. |
|
||||||
| `toggleControls(toggle)` | Boolean | Toggle the controls (video only). Takes optional truthy value to force it on/off. |
|
| `toggleControls(toggle)` | Boolean | Toggle the controls (video only). Takes optional truthy value to force it on/off. |
|
||||||
| `on(event, function)` | String, Function | Add an event listener for the specified event. |
|
| `on(event, function)` | String, Function | Add an event listener for the specified event. |
|
||||||
| `once(event, function)` | String, Function | Add an event listener for the specified event once. |
|
| `once(event, function)` | String, Function | Add an event listener for the specified event once. |
|
||||||
| `off(event, function)` | String, Function | Remove an event listener for the specified event. |
|
| `off(event, function)` | String, Function | Remove an event listener for the specified event. |
|
||||||
| `supports(type)` | String | Check support for a mime type. |
|
| `supports(type)` | String | Check support for a mime type. |
|
||||||
| `destroy()` | - | Destroy the instance and garbage collect any elements. |
|
| `destroy()` | - | Destroy the instance and garbage collect any elements. |
|
||||||
@@ -391,32 +391,32 @@ player.currentTime; // 10
|
|||||||
player.fullscreen.active; // false;
|
player.fullscreen.active; // false;
|
||||||
```
|
```
|
||||||
|
|
||||||
| Property | Getter | Setter | Description |
|
| Property | Getter | Setter | Description |
|
||||||
| -------------------- | ------ | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
| -------------------- | ------ | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `isHTML5` | ✓ | - | Returns a boolean indicating if the current player is HTML5. |
|
| `isHTML5` | ✓ | - | Returns a boolean indicating if the current player is HTML5. |
|
||||||
| `isEmbed` | ✓ | - | Returns a boolean indicating if the current player is an embedded player. |
|
| `isEmbed` | ✓ | - | Returns a boolean indicating if the current player is an embedded player. |
|
||||||
| `playing` | ✓ | - | Returns a boolean indicating if the current player is playing. |
|
| `playing` | ✓ | - | Returns a boolean indicating if the current player is playing. |
|
||||||
| `paused` | ✓ | - | Returns a boolean indicating if the current player is paused. |
|
| `paused` | ✓ | - | Returns a boolean indicating if the current player is paused. |
|
||||||
| `stopped` | ✓ | - | Returns a boolean indicating if the current player is stopped. |
|
| `stopped` | ✓ | - | Returns a boolean indicating if the current player is stopped. |
|
||||||
| `ended` | ✓ | - | Returns a boolean indicating if the current player has finished playback. |
|
| `ended` | ✓ | - | Returns a boolean indicating if the current player has finished playback. |
|
||||||
| `buffered` | ✓ | - | Returns a float between 0 and 1 indicating how much of the media is buffered |
|
| `buffered` | ✓ | - | Returns a float between 0 and 1 indicating how much of the media is buffered |
|
||||||
| `currentTime` | ✓ | ✓ | Gets or sets the currentTime for the player. The setter accepts a float in seconds. |
|
| `currentTime` | ✓ | ✓ | Gets or sets the currentTime for the player. The setter accepts a float in seconds. |
|
||||||
| `seeking` | ✓ | - | Returns a boolean indicating if the current player is seeking. |
|
| `seeking` | ✓ | - | Returns a boolean indicating if the current player is seeking. |
|
||||||
| `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. |
|
| `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. |
|
||||||
| `source` | ✓ | ✓ | Gets or sets the current source for the player. The setter accepts an object. See [source setter](#the-source-setter) below for examples. |
|
| `source` | ✓ | ✓ | Gets or sets the current source for the player. The setter accepts an object. See [source setter](#the-source-setter) below for examples. |
|
||||||
| `poster` | ✓ | ✓ | Gets or sets the current poster image for the player. The setter accepts a string; the URL for the updated poster image. |
|
| `poster` | ✓ | ✓ | Gets or sets the current poster image for the player. The setter accepts a string; the URL for the updated poster image. |
|
||||||
| `autoplay` | ✓ | ✓ | Gets or sets the autoplay state of the player. The setter accepts a boolean. |
|
| `autoplay` | ✓ | ✓ | Gets or sets the autoplay state of the player. The setter accepts a boolean. |
|
||||||
| `currentTrack` | ✓ | ✓ | Gets or sets the caption track by index. `-1` means the track is missing or captions is not active |
|
| `currentTrack` | ✓ | ✓ | Gets or sets the caption track by index. `-1` means the track is missing or captions is not active |
|
||||||
| `language` | ✓ | ✓ | Gets or sets the preferred captions language for the player. The setter accepts an ISO two-letter language code. Support for the languages is dependent on the captions you include. If your captions don't have any language data, or if you have multiple tracks with the same language, you may want to use `currentTrack` instead. |
|
| `language` | ✓ | ✓ | Gets or sets the preferred captions language for the player. The setter accepts an ISO two-letter language code. Support for the languages is dependent on the captions you include. If your captions don't have any language data, or if you have multiple tracks with the same language, you may want to use `currentTrack` instead. |
|
||||||
| `fullscreen.active` | ✓ | - | Returns a boolean indicating if the current player is in fullscreen mode. |
|
| `fullscreen.active` | ✓ | - | Returns a boolean indicating if the current player is in fullscreen mode. |
|
||||||
| `fullscreen.enabled` | ✓ | - | Returns a boolean indicating if the current player has fullscreen enabled. |
|
| `fullscreen.enabled` | ✓ | - | Returns a boolean indicating if the current player has fullscreen enabled. |
|
||||||
| `pip` | ✓ | ✓ | Gets or sets the picture-in-picture state of the player. The setter accepts a boolean. This currently only supported on Safari 10+ on MacOS Sierra+ and iOS 10+. |
|
| `pip` | ✓ | ✓ | Gets or sets the picture-in-picture state of the player. The setter accepts a boolean. This currently only supported on Safari 10+ on MacOS Sierra+ and iOS 10+. |
|
||||||
|
|
||||||
1. YouTube only. HTML5 will follow.
|
1. YouTube only. HTML5 will follow.
|
||||||
2. HTML5 only
|
2. HTML5 only
|
||||||
@@ -565,6 +565,7 @@ player.on('ready', event => {
|
|||||||
| `loadstart` | Sent when loading of the media begins. |
|
| `loadstart` | Sent when loading of the media begins. |
|
||||||
| `loadeddata` | The first frame of the media has finished loading. |
|
| `loadeddata` | The first frame of the media has finished loading. |
|
||||||
| `loadedmetadata` | The media's metadata has finished loading; all attributes now contain as much useful information as they're going to. |
|
| `loadedmetadata` | The media's metadata has finished loading; all attributes now contain as much useful information as they're going to. |
|
||||||
|
| `qualitychange` | The quality of playback has changed. |
|
||||||
| `canplay` | Sent when enough data is available that the media can be played, at least for a couple of frames. This corresponds to the `HAVE_ENOUGH_DATA` `readyState`. |
|
| `canplay` | Sent when enough data is available that the media can be played, at least for a couple of frames. This corresponds to the `HAVE_ENOUGH_DATA` `readyState`. |
|
||||||
| `canplaythrough` | Sent when the ready state changes to `CAN_PLAY_THROUGH`, indicating that the entire media can be played without interruption, assuming the download rate remains at least at the current level. _Note:_ Manually setting the `currentTime` will eventually fire a `canplaythrough` event in firefox. Other browsers might not fire this event. |
|
| `canplaythrough` | Sent when the ready state changes to `CAN_PLAY_THROUGH`, indicating that the entire media can be played without interruption, assuming the download rate remains at least at the current level. _Note:_ Manually setting the `currentTime` will eventually fire a `canplaythrough` event in firefox. Other browsers might not fire this event. |
|
||||||
| `stalled` | Sent when the user agent is trying to fetch media data, but data is unexpectedly not forthcoming. |
|
| `stalled` | Sent when the user agent is trying to fetch media data, but data is unexpectedly not forthcoming. |
|
||||||
@@ -575,11 +576,9 @@ player.on('ready', event => {
|
|||||||
|
|
||||||
#### YouTube only
|
#### YouTube only
|
||||||
|
|
||||||
| Event Type | Description |
|
| Event Type | Description |
|
||||||
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `statechange` | The state of the player has changed. The code can be accessed via `event.detail.code`. Possible values are `-1`: Unstarted, `0`: Ended, `1`: Playing, `2`: Paused, `3`: Buffering, `5`: Video cued. See the [YouTube Docs](https://developers.google.com/youtube/iframe_api_reference#onStateChange) for more information. |
|
| `statechange` | The state of the player has changed. The code can be accessed via `event.detail.code`. Possible values are `-1`: Unstarted, `0`: Ended, `1`: Playing, `2`: Paused, `3`: Buffering, `5`: Video cued. See the [YouTube Docs](https://developers.google.com/youtube/iframe_api_reference#onStateChange) for more information. |
|
||||||
| `qualitychange` | The quality of playback has changed. |
|
|
||||||
| `qualityrequested` | A change to playback quality has been requested. _Note:_ A change to quality can only be _requested_ via the API. There is no guarantee the quality will change to the level requested. You should listen to the `qualitychange` event for true changes. |
|
|
||||||
|
|
||||||
_Note:_ These events also bubble up the DOM. The event target will be the container element.
|
_Note:_ These events also bubble up the DOM. The event target will be the container element.
|
||||||
|
|
||||||
@@ -591,8 +590,8 @@ YouTube and Vimeo are currently supported and function much like a HTML5 video.
|
|||||||
to access the API's directly. You can do so via the `embed` property of your player object - e.g. `player.embed`. You can then use the relevant methods from the
|
to access the API's directly. You can do so via the `embed` property of your player object - e.g. `player.embed`. You can then use the relevant methods from the
|
||||||
third party APIs. More info on the respective API's here:
|
third party APIs. More info on the respective API's here:
|
||||||
|
|
||||||
* [YouTube iframe API Reference](https://developers.google.com/youtube/iframe_api_reference)
|
- [YouTube iframe API Reference](https://developers.google.com/youtube/iframe_api_reference)
|
||||||
* [Vimeo player.js Reference](https://github.com/vimeo/player.js)
|
- [Vimeo player.js Reference](https://github.com/vimeo/player.js)
|
||||||
|
|
||||||
_Note_: Not all API methods may work 100%. Your mileage may vary. It's better to use the Plyr API where possible.
|
_Note_: Not all API methods may work 100%. Your mileage may vary. It's better to use the Plyr API where possible.
|
||||||
|
|
||||||
@@ -652,9 +651,9 @@ const supported = Plyr.supported('video', 'html5', true);
|
|||||||
|
|
||||||
The arguments are:
|
The arguments are:
|
||||||
|
|
||||||
* Media type (`audio` or `video`)
|
- Media type (`audio` or `video`)
|
||||||
* Provider (`html5`, `youtube` or `vimeo`)
|
- Provider (`html5`, `youtube` or `vimeo`)
|
||||||
* Whether the player has the `playsinline` attribute (only applicable to iOS 10+)
|
- Whether the player has the `playsinline` attribute (only applicable to iOS 10+)
|
||||||
|
|
||||||
### Disable support programatically
|
### Disable support programatically
|
||||||
|
|
||||||
@@ -687,33 +686,33 @@ Plyr is developed by [@sam_potts](https://twitter.com/sam_potts) / [sampotts.me]
|
|||||||
|
|
||||||
Plyr costs money to run, not only my time. I donate my time for free as I enjoy building Plyr but unfortunately have to pay for domains, hosting, and more. Any help with costs is appreciated...
|
Plyr costs money to run, not only my time. I donate my time for free as I enjoy building Plyr but unfortunately have to pay for domains, hosting, and more. Any help with costs is appreciated...
|
||||||
|
|
||||||
* [Donate via Patron](https://www.patreon.com/plyr)
|
- [Donate via Patreon](https://www.patreon.com/plyr)
|
||||||
* [Donate via PayPal](https://www.paypal.me/pottsy/20usd)
|
- [Donate via PayPal](https://www.paypal.me/pottsy/20usd)
|
||||||
|
|
||||||
## Mentions
|
## Mentions
|
||||||
|
|
||||||
* [ProductHunt](https://www.producthunt.com/tech/plyr)
|
- [ProductHunt](https://www.producthunt.com/tech/plyr)
|
||||||
* [The Changelog](http://thechangelog.com/plyr-simple-html5-media-player-custom-controls-webvtt-captions/)
|
- [The Changelog](http://thechangelog.com/plyr-simple-html5-media-player-custom-controls-webvtt-captions/)
|
||||||
* [HTML5 Weekly #177](http://html5weekly.com/issues/177)
|
- [HTML5 Weekly #177](http://html5weekly.com/issues/177)
|
||||||
* [Responsive Design #149](http://us4.campaign-archive2.com/?u=559bc631fe5294fc66f5f7f89&id=451a61490f)
|
- [Responsive Design #149](http://us4.campaign-archive2.com/?u=559bc631fe5294fc66f5f7f89&id=451a61490f)
|
||||||
* [Web Design Weekly #174](https://web-design-weekly.com/2015/02/24/web-design-weekly-174/)
|
- [Web Design Weekly #174](https://web-design-weekly.com/2015/02/24/web-design-weekly-174/)
|
||||||
* [Hacker News](https://news.ycombinator.com/item?id=9136774)
|
- [Hacker News](https://news.ycombinator.com/item?id=9136774)
|
||||||
* [Web Platform Daily](http://webplatformdaily.org/releases/2015-03-04)
|
- [Web Platform Daily](http://webplatformdaily.org/releases/2015-03-04)
|
||||||
* [LayerVault Designer News](https://news.layervault.com/stories/45394-plyr--a-simple-html5-media-player)
|
- [LayerVault Designer News](https://news.layervault.com/stories/45394-plyr--a-simple-html5-media-player)
|
||||||
* [The Treehouse Show #131](https://teamtreehouse.com/library/episode-131-origami-react-responsive-hero-images)
|
- [The Treehouse Show #131](https://teamtreehouse.com/library/episode-131-origami-react-responsive-hero-images)
|
||||||
* [noupe.com](http://www.noupe.com/design/html5-plyr-is-a-responsive-and-accessible-video-player-94389.html)
|
- [noupe.com](http://www.noupe.com/design/html5-plyr-is-a-responsive-and-accessible-video-player-94389.html)
|
||||||
|
|
||||||
## Used by
|
## Used by
|
||||||
|
|
||||||
* [Selz.com](https://selz.com)
|
- [Selz.com](https://selz.com)
|
||||||
* [Peugeot.fr](http://www.peugeot.fr/marque-et-technologie/technologies/peugeot-i-cockpit.html)
|
- [Peugeot.fr](http://www.peugeot.fr/marque-et-technologie/technologies/peugeot-i-cockpit.html)
|
||||||
* [Peugeot.de](http://www.peugeot.de/modelle/modellberater/208-3-turer/fotos-videos.html)
|
- [Peugeot.de](http://www.peugeot.de/modelle/modellberater/208-3-turer/fotos-videos.html)
|
||||||
* [TomTom.com](http://prioritydriving.tomtom.com/)
|
- [TomTom.com](http://prioritydriving.tomtom.com/)
|
||||||
* [DIGBMX](http://digbmx.com/)
|
- [DIGBMX](http://digbmx.com/)
|
||||||
* [Grime Archive](https://grimearchive.com/)
|
- [Grime Archive](https://grimearchive.com/)
|
||||||
* [koel - A personal music streaming server that works.](http://koel.phanan.net/)
|
- [koel - A personal music streaming server that works.](http://koel.phanan.net/)
|
||||||
* [Oscar Radio](http://oscar-radio.xyz/)
|
- [Oscar Radio](http://oscar-radio.xyz/)
|
||||||
* [Sparkk TV](https://www.sparkktv.com/)
|
- [Sparkk TV](https://www.sparkktv.com/)
|
||||||
|
|
||||||
Let me know on [Twitter](https://twitter.com/sam_potts) I can add you to the above list. It'd be awesome to see how you're using Plyr :-)
|
Let me know on [Twitter](https://twitter.com/sam_potts) I can add you to the above list. It'd be awesome to see how you're using Plyr :-)
|
||||||
|
|
||||||
@@ -721,8 +720,8 @@ Let me know on [Twitter](https://twitter.com/sam_potts) I can add you to the abo
|
|||||||
|
|
||||||
Credit to the PayPal HTML5 Video player from which Plyr's caption functionality was originally ported from:
|
Credit to the PayPal HTML5 Video player from which Plyr's caption functionality was originally ported from:
|
||||||
|
|
||||||
* [PayPal's Accessible HTML5 Video Player](https://github.com/paypal/accessible-html5-video-player)
|
- [PayPal's Accessible HTML5 Video Player](https://github.com/paypal/accessible-html5-video-player)
|
||||||
* [An awesome guide for Plyr in Japanese!](http://syncer.jp/how-to-use-plyr-io) by [@arayutw](https://twitter.com/arayutw)
|
- [An awesome guide for Plyr in Japanese!](http://syncer.jp/how-to-use-plyr-io) by [@arayutw](https://twitter.com/arayutw)
|
||||||
|
|
||||||
## Thanks
|
## Thanks
|
||||||
|
|
||||||
|
|||||||
+3
-6
@@ -4,7 +4,6 @@
|
|||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
import controls from './controls';
|
import controls from './controls';
|
||||||
import i18n from './i18n';
|
|
||||||
import support from './support';
|
import support from './support';
|
||||||
import { dedupe } from './utils/arrays';
|
import { dedupe } from './utils/arrays';
|
||||||
import browser from './utils/browser';
|
import browser from './utils/browser';
|
||||||
@@ -18,6 +17,7 @@ import {
|
|||||||
} from './utils/elements';
|
} from './utils/elements';
|
||||||
import { on, triggerEvent } from './utils/events';
|
import { on, triggerEvent } from './utils/events';
|
||||||
import fetch from './utils/fetch';
|
import fetch from './utils/fetch';
|
||||||
|
import i18n from './utils/i18n';
|
||||||
import is from './utils/is';
|
import is from './utils/is';
|
||||||
import { getHTML } from './utils/strings';
|
import { getHTML } from './utils/strings';
|
||||||
import { parseUrl } from './utils/urls';
|
import { parseUrl } from './utils/urls';
|
||||||
@@ -83,11 +83,8 @@ const captions = {
|
|||||||
// * active: The state preferred by user settings or config
|
// * active: The state preferred by user settings or config
|
||||||
// * toggled: The real captions state
|
// * toggled: The real captions state
|
||||||
|
|
||||||
const languages = dedupe(
|
const browserLanguages = navigator.languages || [navigator.language || navigator.userLanguage || 'en'];
|
||||||
Array.from(navigator.languages || navigator.language || navigator.userLanguage).map(
|
const languages = dedupe(browserLanguages.map(language => language.split('-')[0]));
|
||||||
language => language.split('-')[0],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
let language = (this.storage.get('language') || this.config.captions.language || 'auto').toLowerCase();
|
let language = (this.storage.get('language') || this.config.captions.language || 'auto').toLowerCase();
|
||||||
|
|
||||||
|
|||||||
@@ -68,19 +68,7 @@ const defaults = {
|
|||||||
// Quality default
|
// Quality default
|
||||||
quality: {
|
quality: {
|
||||||
default: 576,
|
default: 576,
|
||||||
options: [
|
options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240],
|
||||||
4320,
|
|
||||||
2880,
|
|
||||||
2160,
|
|
||||||
1440,
|
|
||||||
1080,
|
|
||||||
720,
|
|
||||||
576,
|
|
||||||
480,
|
|
||||||
360,
|
|
||||||
240,
|
|
||||||
'default', // YouTube's "auto"
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Set loops
|
// Set loops
|
||||||
@@ -268,8 +256,9 @@ const defaults = {
|
|||||||
|
|
||||||
// YouTube
|
// YouTube
|
||||||
'statechange',
|
'statechange',
|
||||||
|
|
||||||
|
// Quality
|
||||||
'qualitychange',
|
'qualitychange',
|
||||||
'qualityrequested',
|
|
||||||
|
|
||||||
// Ads
|
// Ads
|
||||||
'adsloaded',
|
'adsloaded',
|
||||||
|
|||||||
Vendored
+48
-40
@@ -5,13 +5,13 @@
|
|||||||
|
|
||||||
import captions from './captions';
|
import captions from './captions';
|
||||||
import html5 from './html5';
|
import html5 from './html5';
|
||||||
import i18n from './i18n';
|
|
||||||
import support from './support';
|
import support from './support';
|
||||||
import { repaint, transitionEndEvent } from './utils/animation';
|
import { repaint, transitionEndEvent } from './utils/animation';
|
||||||
import { dedupe } from './utils/arrays';
|
import { dedupe } from './utils/arrays';
|
||||||
import browser from './utils/browser';
|
import browser from './utils/browser';
|
||||||
import { createElement, emptyElement, getAttributesFromSelector, getElement, getElements, hasClass, matches, removeElement, setAttributes, setFocus, toggleClass, toggleHidden } from './utils/elements';
|
import { createElement, emptyElement, getAttributesFromSelector, getElement, getElements, hasClass, matches, removeElement, setAttributes, setFocus, toggleClass, toggleHidden } from './utils/elements';
|
||||||
import { off, on } from './utils/events';
|
import { off, on } from './utils/events';
|
||||||
|
import i18n from './utils/i18n';
|
||||||
import is from './utils/is';
|
import is from './utils/is';
|
||||||
import loadSprite from './utils/loadSprite';
|
import loadSprite from './utils/loadSprite';
|
||||||
import { extend } from './utils/objects';
|
import { extend } from './utils/objects';
|
||||||
@@ -275,18 +275,6 @@ const controls = {
|
|||||||
this.elements.buttons[type] = button;
|
this.elements.buttons[type] = button;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle classname when pressed property is set
|
|
||||||
const className = this.config.classNames.controlPressed;
|
|
||||||
Object.defineProperty(button, 'pressed', {
|
|
||||||
enumerable: true,
|
|
||||||
get() {
|
|
||||||
return hasClass(button, className);
|
|
||||||
},
|
|
||||||
set(pressed = false) {
|
|
||||||
toggleClass(button, className, pressed);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return button;
|
return button;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -1142,9 +1130,8 @@ const controls = {
|
|||||||
// Focus the first item if key interaction
|
// Focus the first item if key interaction
|
||||||
if (show && is.keyboardEvent(input)) {
|
if (show && is.keyboardEvent(input)) {
|
||||||
controls.focusFirstMenuItem.call(this, null, true);
|
controls.focusFirstMenuItem.call(this, null, true);
|
||||||
}
|
} else if (!show && !hidden) {
|
||||||
// If closing, re-focus the button
|
// If closing, re-focus the button
|
||||||
else if (!show && !hidden) {
|
|
||||||
setFocus.call(this, button, is.keyboardEvent(input));
|
setFocus.call(this, button, is.keyboardEvent(input));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -1297,36 +1284,39 @@ const controls = {
|
|||||||
container.appendChild(controls.createTime.call(this, 'duration'));
|
container.appendChild(controls.createTime.call(this, 'duration'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle mute button
|
// Volume controls
|
||||||
if (this.config.controls.includes('mute')) {
|
if (this.config.controls.includes('mute') || this.config.controls.includes('volume')) {
|
||||||
container.appendChild(controls.createButton.call(this, 'mute'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Volume range control
|
|
||||||
if (this.config.controls.includes('volume')) {
|
|
||||||
const volume = createElement('div', {
|
const volume = createElement('div', {
|
||||||
class: 'plyr__volume',
|
class: 'plyr__volume',
|
||||||
});
|
});
|
||||||
|
|
||||||
// Set the attributes
|
// Toggle mute button
|
||||||
const attributes = {
|
if (this.config.controls.includes('mute')) {
|
||||||
max: 1,
|
volume.appendChild(controls.createButton.call(this, 'mute'));
|
||||||
step: 0.05,
|
}
|
||||||
value: this.config.volume,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create the volume range slider
|
// Volume range control
|
||||||
volume.appendChild(
|
if (this.config.controls.includes('volume')) {
|
||||||
controls.createRange.call(
|
// Set the attributes
|
||||||
this,
|
const attributes = {
|
||||||
'volume',
|
max: 1,
|
||||||
extend(attributes, {
|
step: 0.05,
|
||||||
id: `plyr-volume-${data.id}`,
|
value: this.config.volume,
|
||||||
}),
|
};
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
this.elements.volume = volume;
|
// Create the volume range slider
|
||||||
|
volume.appendChild(
|
||||||
|
controls.createRange.call(
|
||||||
|
this,
|
||||||
|
'volume',
|
||||||
|
extend(attributes, {
|
||||||
|
id: `plyr-volume-${data.id}`,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
this.elements.volume = volume;
|
||||||
|
}
|
||||||
|
|
||||||
container.appendChild(volume);
|
container.appendChild(volume);
|
||||||
}
|
}
|
||||||
@@ -1512,6 +1502,7 @@ const controls = {
|
|||||||
|
|
||||||
this.elements.controls = container;
|
this.elements.controls = container;
|
||||||
|
|
||||||
|
// Set available quality levels
|
||||||
if (this.isHTML5) {
|
if (this.isHTML5) {
|
||||||
controls.setQualityMenu.call(this, html5.getQualityOptions.call(this));
|
controls.setQualityMenu.call(this, html5.getQualityOptions.call(this));
|
||||||
}
|
}
|
||||||
@@ -1617,6 +1608,23 @@ const controls = {
|
|||||||
controls.findElements.call(this);
|
controls.findElements.call(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add pressed property to buttons
|
||||||
|
if (!is.empty(this.elements.buttons)) {
|
||||||
|
// Toggle classname when pressed property is set
|
||||||
|
Object.values(this.elements.buttons).forEach(button => {
|
||||||
|
const className = this.config.classNames.controlPressed;
|
||||||
|
Object.defineProperty(button, 'pressed', {
|
||||||
|
enumerable: true,
|
||||||
|
get() {
|
||||||
|
return hasClass(button, className);
|
||||||
|
},
|
||||||
|
set(pressed = false) {
|
||||||
|
toggleClass(button, className, pressed);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Edge sometimes doesn't finish the paint so force a redraw
|
// Edge sometimes doesn't finish the paint so force a redraw
|
||||||
if (window.navigator.userAgent.includes('Edge')) {
|
if (window.navigator.userAgent.includes('Edge')) {
|
||||||
repaint(target);
|
repaint(target);
|
||||||
|
|||||||
@@ -177,9 +177,7 @@ class Fullscreen {
|
|||||||
|
|
||||||
// iOS native fullscreen doesn't need the request step
|
// iOS native fullscreen doesn't need the request step
|
||||||
if (browser.isIos && this.player.config.fullscreen.iosNative) {
|
if (browser.isIos && this.player.config.fullscreen.iosNative) {
|
||||||
if (this.player.playing) {
|
this.target.webkitEnterFullscreen();
|
||||||
this.target.webkitEnterFullscreen();
|
|
||||||
}
|
|
||||||
} else if (!Fullscreen.native) {
|
} else if (!Fullscreen.native) {
|
||||||
toggleFallback.call(this, true);
|
toggleFallback.call(this, true);
|
||||||
} else if (!this.prefix) {
|
} else if (!this.prefix) {
|
||||||
|
|||||||
@@ -82,6 +82,9 @@ const html5 = {
|
|||||||
triggerEvent.call(player, player.media, 'qualitychange', false, {
|
triggerEvent.call(player, player.media, 'qualitychange', false, {
|
||||||
quality: input,
|
quality: input,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Save to storage
|
||||||
|
player.storage.set({ quality: input });
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
+1
-7
@@ -277,7 +277,7 @@ class Listeners {
|
|||||||
const { controls } = elements;
|
const { controls } = elements;
|
||||||
|
|
||||||
// Remove button states for fullscreen
|
// Remove button states for fullscreen
|
||||||
if (event.type === 'enterfullscreen') {
|
if (controls && event.type === 'enterfullscreen') {
|
||||||
controls.pressed = false;
|
controls.pressed = false;
|
||||||
controls.hover = false;
|
controls.hover = false;
|
||||||
}
|
}
|
||||||
@@ -430,12 +430,6 @@ class Listeners {
|
|||||||
player.storage.set({ speed: player.speed });
|
player.storage.set({ speed: player.speed });
|
||||||
});
|
});
|
||||||
|
|
||||||
// Quality request
|
|
||||||
on.call(player, player.media, 'qualityrequested', event => {
|
|
||||||
// Save to storage
|
|
||||||
player.storage.set({ quality: event.detail.quality });
|
|
||||||
});
|
|
||||||
|
|
||||||
// Quality change
|
// Quality change
|
||||||
on.call(player, player.media, 'qualitychange', event => {
|
on.call(player, player.media, 'qualitychange', event => {
|
||||||
// Update UI
|
// Update UI
|
||||||
|
|||||||
@@ -6,9 +6,9 @@
|
|||||||
|
|
||||||
/* global google */
|
/* global google */
|
||||||
|
|
||||||
import i18n from '../i18n';
|
|
||||||
import { createElement } from '../utils/elements';
|
import { createElement } from '../utils/elements';
|
||||||
import { triggerEvent } from '../utils/events';
|
import { triggerEvent } from '../utils/events';
|
||||||
|
import i18n from '../utils/i18n';
|
||||||
import is from '../utils/is';
|
import is from '../utils/is';
|
||||||
import loadScript from '../utils/loadScript';
|
import loadScript from '../utils/loadScript';
|
||||||
import { formatTime } from '../utils/time';
|
import { formatTime } from '../utils/time';
|
||||||
|
|||||||
@@ -2,9 +2,7 @@
|
|||||||
// YouTube plugin
|
// YouTube plugin
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
import controls from '../controls';
|
|
||||||
import ui from '../ui';
|
import ui from '../ui';
|
||||||
import { dedupe } from '../utils/arrays';
|
|
||||||
import { createElement, replaceElement, toggleClass } from '../utils/elements';
|
import { createElement, replaceElement, toggleClass } from '../utils/elements';
|
||||||
import { triggerEvent } from '../utils/events';
|
import { triggerEvent } from '../utils/events';
|
||||||
import fetch from '../utils/fetch';
|
import fetch from '../utils/fetch';
|
||||||
@@ -23,37 +21,6 @@ function parseId(url) {
|
|||||||
return url.match(regex) ? RegExp.$2 : url;
|
return url.match(regex) ? RegExp.$2 : url;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Standardise YouTube quality unit
|
|
||||||
function mapQualityUnit(input) {
|
|
||||||
const qualities = {
|
|
||||||
hd2160: 2160,
|
|
||||||
hd1440: 1440,
|
|
||||||
hd1080: 1080,
|
|
||||||
hd720: 720,
|
|
||||||
large: 480,
|
|
||||||
medium: 360,
|
|
||||||
small: 240,
|
|
||||||
tiny: 144,
|
|
||||||
};
|
|
||||||
|
|
||||||
const entry = Object.entries(qualities).find(entry => entry.includes(input));
|
|
||||||
|
|
||||||
if (entry) {
|
|
||||||
// Get the match corresponding to the input
|
|
||||||
return entry.find(value => value !== input);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'default';
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapQualityUnits(levels) {
|
|
||||||
if (is.empty(levels)) {
|
|
||||||
return levels;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dedupe(levels.map(level => mapQualityUnit(level)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set playback state and trigger change (only on actual change)
|
// Set playback state and trigger change (only on actual change)
|
||||||
function assurePlaybackState(play) {
|
function assurePlaybackState(play) {
|
||||||
if (play && !this.embed.hasPlayed) {
|
if (play && !this.embed.hasPlayed) {
|
||||||
@@ -225,11 +192,6 @@ const youtube = {
|
|||||||
triggerEvent.call(player, player.media, 'error');
|
triggerEvent.call(player, player.media, 'error');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onPlaybackQualityChange() {
|
|
||||||
triggerEvent.call(player, player.media, 'qualitychange', false, {
|
|
||||||
quality: player.media.quality,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onPlaybackRateChange(event) {
|
onPlaybackRateChange(event) {
|
||||||
// Get the instance
|
// Get the instance
|
||||||
const instance = event.target;
|
const instance = event.target;
|
||||||
@@ -299,16 +261,6 @@ const youtube = {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// Quality
|
|
||||||
Object.defineProperty(player.media, 'quality', {
|
|
||||||
get() {
|
|
||||||
return mapQualityUnit(instance.getPlaybackQuality());
|
|
||||||
},
|
|
||||||
set(input) {
|
|
||||||
instance.setPlaybackQuality(mapQualityUnit(input));
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Volume
|
// Volume
|
||||||
let { volume } = player.config;
|
let { volume } = player.config;
|
||||||
Object.defineProperty(player.media, 'volume', {
|
Object.defineProperty(player.media, 'volume', {
|
||||||
@@ -457,12 +409,6 @@ const youtube = {
|
|||||||
player.media.duration = instance.getDuration();
|
player.media.duration = instance.getDuration();
|
||||||
triggerEvent.call(player, player.media, 'durationchange');
|
triggerEvent.call(player, player.media, 'durationchange');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get quality
|
|
||||||
controls.setQualityMenu.call(
|
|
||||||
player,
|
|
||||||
mapQualityUnits(instance.getAvailableQualityLevels()),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|||||||
+1
-6
@@ -1,6 +1,6 @@
|
|||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
// Plyr
|
// Plyr
|
||||||
// plyr.js v3.4.0-beta.2
|
// plyr.js v3.4.0
|
||||||
// https://github.com/sampotts/plyr
|
// https://github.com/sampotts/plyr
|
||||||
// License: The MIT License (MIT)
|
// License: The MIT License (MIT)
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
@@ -698,11 +698,6 @@ class Plyr {
|
|||||||
quality = value;
|
quality = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trigger request event
|
|
||||||
triggerEvent.call(this, this.media, 'qualityrequested', false, {
|
|
||||||
quality,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update config
|
// Update config
|
||||||
config.selected = quality;
|
config.selected = quality;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
// Plyr Polyfilled Build
|
// Plyr Polyfilled Build
|
||||||
// plyr.js v3.4.0-beta.2
|
// plyr.js v3.4.0
|
||||||
// https://github.com/sampotts/plyr
|
// https://github.com/sampotts/plyr
|
||||||
// License: The MIT License (MIT)
|
// License: The MIT License (MIT)
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|||||||
+1
-1
@@ -4,11 +4,11 @@
|
|||||||
|
|
||||||
import captions from './captions';
|
import captions from './captions';
|
||||||
import controls from './controls';
|
import controls from './controls';
|
||||||
import i18n from './i18n';
|
|
||||||
import support from './support';
|
import support from './support';
|
||||||
import browser from './utils/browser';
|
import browser from './utils/browser';
|
||||||
import { getElement, toggleClass } from './utils/elements';
|
import { getElement, toggleClass } from './utils/elements';
|
||||||
import { ready, triggerEvent } from './utils/events';
|
import { ready, triggerEvent } from './utils/events';
|
||||||
|
import i18n from './utils/i18n';
|
||||||
import is from './utils/is';
|
import is from './utils/is';
|
||||||
import loadImage from './utils/loadImage';
|
import loadImage from './utils/loadImage';
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
// Plyr internationalization
|
// Plyr internationalization
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
import is from './utils/is';
|
import is from './is';
|
||||||
import { getDeep } from './utils/objects';
|
import { getDeep } from './objects';
|
||||||
import { replaceAll } from './utils/strings';
|
import { replaceAll } from './strings';
|
||||||
|
|
||||||
const i18n = {
|
const i18n = {
|
||||||
get(key = '', config = {}) {
|
get(key = '', config = {}) {
|
||||||
@@ -18,20 +18,24 @@
|
|||||||
> .plyr__control,
|
> .plyr__control,
|
||||||
.plyr__progress,
|
.plyr__progress,
|
||||||
.plyr__time,
|
.plyr__time,
|
||||||
.plyr__menu {
|
.plyr__menu,
|
||||||
margin-left: ($plyr-control-spacing / 2);
|
|
||||||
|
|
||||||
&:first-child,
|
|
||||||
&:first-child + [data-plyr='pause'] {
|
|
||||||
margin-left: 0;
|
|
||||||
margin-right: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.plyr__volume {
|
.plyr__volume {
|
||||||
margin-left: ($plyr-control-spacing / 2);
|
margin-left: ($plyr-control-spacing / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.plyr__menu + .plyr__control,
|
||||||
|
> .plyr__control + .plyr__menu,
|
||||||
|
> .plyr__control + .plyr__control,
|
||||||
|
.plyr__progress + .plyr__control {
|
||||||
|
margin-left: floor($plyr-control-spacing / 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
> .plyr__control:first-child,
|
||||||
|
> .plyr__control:first-child + [data-plyr='pause'] {
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
// Hide empty controls
|
// Hide empty controls
|
||||||
&:empty {
|
&:empty {
|
||||||
display: none;
|
display: none;
|
||||||
@@ -39,17 +43,12 @@
|
|||||||
|
|
||||||
@media (min-width: $plyr-bp-sm) {
|
@media (min-width: $plyr-bp-sm) {
|
||||||
> .plyr__control,
|
> .plyr__control,
|
||||||
|
.plyr__menu,
|
||||||
.plyr__progress,
|
.plyr__progress,
|
||||||
.plyr__time,
|
.plyr__time,
|
||||||
.plyr__menu {
|
.plyr__volume {
|
||||||
margin-left: $plyr-control-spacing;
|
margin-left: $plyr-control-spacing;
|
||||||
}
|
}
|
||||||
|
|
||||||
> .plyr__control + .plyr__control,
|
|
||||||
.plyr__menu + .plyr__control,
|
|
||||||
> .plyr__control + .plyr__menu {
|
|
||||||
margin-left: ($plyr-control-spacing / 2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,12 +71,15 @@
|
|||||||
bottom: 0;
|
bottom: 0;
|
||||||
color: $plyr-video-control-color;
|
color: $plyr-video-control-color;
|
||||||
left: 0;
|
left: 0;
|
||||||
padding: ($plyr-control-spacing * 3.5) $plyr-control-spacing
|
padding: ($plyr-control-spacing * 2) ($plyr-control-spacing / 2) ($plyr-control-spacing / 2);
|
||||||
$plyr-control-spacing;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
transition: opacity 0.4s ease-in-out, transform 0.4s ease-in-out;
|
transition: opacity 0.4s ease-in-out, transform 0.4s ease-in-out;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
|
|
||||||
|
@media (min-width: $plyr-bp-sm) {
|
||||||
|
padding: ($plyr-control-spacing * 3.5) $plyr-control-spacing $plyr-control-spacing;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hide video controls
|
// Hide video controls
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
color: $plyr-tooltip-color;
|
color: $plyr-tooltip-color;
|
||||||
font-size: $plyr-font-size-small;
|
font-size: $plyr-font-size-small;
|
||||||
font-weight: $plyr-font-weight-regular;
|
font-weight: $plyr-font-weight-regular;
|
||||||
|
left: 50%;
|
||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
margin-bottom: ($plyr-tooltip-padding * 2);
|
margin-bottom: ($plyr-tooltip-padding * 2);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
@@ -64,6 +65,7 @@
|
|||||||
|
|
||||||
// Last tooltip
|
// Last tooltip
|
||||||
.plyr__controls > .plyr__control:last-child .plyr__tooltip {
|
.plyr__controls > .plyr__control:last-child .plyr__tooltip {
|
||||||
|
left: auto;
|
||||||
right: 0;
|
right: 0;
|
||||||
transform: translate(0, 10px) scale(0.8);
|
transform: translate(0, 10px) scale(0.8);
|
||||||
transform-origin: 100% 100%;
|
transform-origin: 100% 100%;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
// --------------------------------------------------------------
|
// --------------------------------------------------------------
|
||||||
|
|
||||||
.plyr--video {
|
.plyr--video {
|
||||||
|
background: #000;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
// Menu open
|
// Menu open
|
||||||
|
|||||||
@@ -3,20 +3,23 @@
|
|||||||
// --------------------------------------------------------------
|
// --------------------------------------------------------------
|
||||||
|
|
||||||
.plyr__volume {
|
.plyr__volume {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
input[type='range'] {
|
input[type='range'] {
|
||||||
|
margin-left: ($plyr-control-spacing / 2);
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: $plyr-bp-sm) {
|
@media (min-width: $plyr-bp-sm) {
|
||||||
max-width: 50px;
|
max-width: 90px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: $plyr-bp-md) {
|
@media (min-width: $plyr-bp-md) {
|
||||||
max-width: 80px;
|
max-width: 110px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user