Compare commits

...

23 Commits

Author SHA1 Message Date
333619f1e3 Remove pointer-events: none on embed <iframe> to comply with YouTube ToS 2018-06-21 14:26:40 +10:00
17dcb63c26 Merge branch 'develop'
# Conflicts:
#	dist/plyr.js.map
#	dist/plyr.min.js
#	dist/plyr.min.js.map
#	dist/plyr.polyfilled.js.map
#	dist/plyr.polyfilled.min.js
#	dist/plyr.polyfilled.min.js.map
2018-06-21 09:11:05 +10:00
e04b90c9c0 Ads only on HTML5 and .is cleanup 2018-06-21 09:06:28 +10:00
f62e1da01a Merge pull request #1057 from meyt/patch-1
Fix i18n defaults path on README
2018-06-20 22:46:50 +10:00
2fe949629f Fix i18n defaults path 2018-06-20 16:00:51 +04:30
20f2ddc11d Merge pull request #1056 from friday/volume
Minor increaseVolume and decreaseVolume changes
2018-06-20 16:53:43 +10:00
004528a65c Avoid conditions in volume scroll event listener 2018-06-19 17:22:12 +02:00
39c7bd40c2 Make decreaseVolume wrap increaseVolume for code reuse 2018-06-19 16:29:52 +02:00
43879e08f4 Make (increase/decrease)Volume methods ignore invalid input instead of raising / lowering to the min / max 2018-06-19 16:27:06 +02:00
5ed7aa6620 v3.3.17 2018-06-19 16:58:38 +10:00
47750b6aad v3.3.17
-   Fix YouTube muting after seeking with the progress slider
-   Respect preload="none" when setting quality if the media hasn't been loaded some other way
2018-06-19 16:57:32 +10:00
de7832eb8b Merge branch 'develop' 2018-06-19 16:40:54 +10:00
52ea5bd0ab Merge pull request #1052 from friday/youtube-audio-fix
Fix YouTube muting after seeking with the progress slider.
2018-06-19 04:15:07 +02:00
457d112df7 Fix #1045: YouTube mutes when seeking after play 2018-06-19 04:03:59 +02:00
22cdec9d38 Merge pull request #1051 from friday/quality-2
Respect preload="none" when setting quality if the media hasn't been loaded some other way
2018-06-19 11:48:44 +10:00
d72e502107 Fixes #1044: Don't load the new source if preload is disabled and the current source hasn't been loaded 2018-06-19 03:39:18 +02:00
94055f0772 Replace filter()[0] with find() 2018-06-19 03:35:57 +02:00
ede9323524 v3.3.16 2018-06-19 09:16:14 +10:00
c45f428f61 Built files 2018-06-19 09:14:10 +10:00
b61ba02f3d Fix issue with play button not changing state (fixes #1048) 2018-06-19 09:12:21 +10:00
ea4d91d2a0 v3.3.15 2018-06-18 23:21:03 +10:00
22d524ac9d Removed 1440p so I can afford to eat 2018-06-18 22:16:12 +10:00
8584f6a1db v3.3.14 2018-06-18 22:01:56 +10:00
31 changed files with 528 additions and 461 deletions

View File

@ -1,3 +1,30 @@
# v3.3.19
- Remove `pointer-events: none` on embed `<iframe>` to comply with YouTube ToS
# 3.3.18
- Ads are now only supported on HTML5 videos as it violates terms of service for YouTube and Vimeo 😢
- Fix i18n defaults path on README (thanks @meyt!)
- Minor increaseVolume and decreaseVolume changes (thanks @friday!)
# v3.3.17
- Fix YouTube muting after seeking with the progress slider (thanks @friday!)
- Respect preload="none" when setting quality if the media hasn't been loaded some other way (thanks @friday!)
# v3.3.16
- Fixed regression relating the play button status (fixes #1048)
# v3.3.15
- Fix for error relating to play buttons when switching source
# v3.3.14
- Fix sprite loading regression
# v3.3.13
You guessed it, a load of awesome changes from contributors:

2
demo/dist/demo.css vendored

File diff suppressed because one or more lines are too long

11
demo/dist/demo.js vendored
View File

@ -1874,7 +1874,7 @@ typeof navigator === "object" && (function () {
// webpack (using a build step causes webpack #1617). Grunt verifies that
// this value matches package.json during build.
// See: https://github.com/getsentry/raven-js/issues/465
VERSION: '3.26.2',
VERSION: '3.26.3',
debug: false,
@ -2351,7 +2351,9 @@ typeof navigator === "object" && (function () {
return;
}
if (this._globalOptions.stacktrace || (options && options.stacktrace)) {
// Always attempt to get stacktrace if message is empty.
// It's the only way to provide any helpful information to the user.
if (this._globalOptions.stacktrace || options.stacktrace || data.message === '') {
// fingerprint on msg, not stack trace (legacy behavior, could be revisited)
data.fingerprint = data.fingerprint == null ? msg : data.fingerprint;
@ -3508,6 +3510,11 @@ typeof navigator === "object" && (function () {
options
);
var ex = data.exception.values[0];
if (ex.type == null && ex.value === '') {
ex.value = 'Unrecoverable error caught';
}
// Move mechanism from options to exception interface
// We do this, as requiring user to pass `{exception:{mechanism:{ ... }}}` would be
// too much

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -96,7 +96,7 @@
<source src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-576p.mp4" type="video/mp4" size="576">
<source src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-720p.mp4" type="video/mp4" size="720">
<source src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-1080p.mp4" type="video/mp4" size="1080">
<source src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-1440p.mp4" type="video/mp4" size="1440">
<!-- <source src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-1440p.mp4" type="video/mp4" size="1440"> -->
<!-- Caption files -->
<track kind="captions" label="English" srclang="en" src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt"

View File

@ -143,7 +143,11 @@ import Raven from 'raven-js';
// Set a new source
function newSource(type, init) {
// Bail if new type isn't known, it's the current type, or current type is empty (video is default) and new type is video
if (!(type in types) || (!init && type === currentType) || (!currentType.length && type === types.video)) {
if (
!(type in types) ||
(!init && type === currentType) ||
(!currentType.length && type === types.video)
) {
return;
}
@ -215,10 +219,12 @@ import Raven from 'raven-js';
case types.youtube:
player.source = {
type: 'video',
sources: [{
src: 'https://youtube.com/watch?v=bTqVqk7FSmY',
provider: 'youtube',
}],
sources: [
{
src: 'https://youtube.com/watch?v=bTqVqk7FSmY',
provider: 'youtube',
},
],
};
break;
@ -226,10 +232,12 @@ import Raven from 'raven-js';
case types.vimeo:
player.source = {
type: 'video',
sources: [{
src: 'https://vimeo.com/76979871',
provider: 'vimeo',
}],
sources: [
{
src: 'https://vimeo.com/76979871',
provider: 'vimeo',
},
],
};
break;

2
dist/plyr.css vendored

File diff suppressed because one or more lines are too long

330
dist/plyr.js vendored
View File

@ -11,60 +11,92 @@ typeof navigator === "object" && (function (global, factory) {
var getConstructor = function getConstructor(input) {
return input !== null && typeof input !== 'undefined' ? input.constructor : null;
};
var instanceOf = function instanceOf(input, constructor) {
return Boolean(input && constructor && input instanceof constructor);
};
var isNullOrUndefined = function isNullOrUndefined(input) {
return input === null || typeof input === 'undefined';
};
var isObject = function isObject(input) {
return getConstructor(input) === Object;
};
var isNumber = function isNumber(input) {
return getConstructor(input) === Number && !Number.isNaN(input);
};
var isString = function isString(input) {
return getConstructor(input) === String;
};
var isBoolean = function isBoolean(input) {
return getConstructor(input) === Boolean;
};
var isFunction = function isFunction(input) {
return getConstructor(input) === Function;
};
var isArray = function isArray(input) {
return Array.isArray(input);
};
var isWeakMap = function isWeakMap(input) {
return instanceOf(input, WeakMap);
};
var isNodeList = function isNodeList(input) {
return instanceOf(input, NodeList);
};
var isElement = function isElement(input) {
return instanceOf(input, Element);
};
var isTextNode = function isTextNode(input) {
return getConstructor(input) === Text;
};
var isEvent = function isEvent(input) {
return instanceOf(input, Event);
};
var isCue = function isCue(input) {
return instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue);
};
var isTrack = function isTrack(input) {
return instanceOf(input, TextTrack) || !isNullOrUndefined(input) && isString(input.kind);
};
var isEmpty = function isEmpty(input) {
return isNullOrUndefined(input) || (isString(input) || isArray(input) || isNodeList(input)) && !input.length || isObject(input) && !Object.keys(input).length;
};
var isUrl = function isUrl(input) {
// Accept a URL object
if (instanceOf(input, window.URL)) {
return true;
}
// Add the protocol if required
var string = input;
if (!input.startsWith('http://') || !input.startsWith('https://')) {
string = 'http://' + input;
}
try {
return !isEmpty(new URL(string).hostname);
} catch (e) {
return false;
}
};
var is = {
object: function object(input) {
return getConstructor(input) === Object;
},
number: function number(input) {
return getConstructor(input) === Number && !Number.isNaN(input);
},
string: function string(input) {
return getConstructor(input) === String;
},
boolean: function boolean(input) {
return getConstructor(input) === Boolean;
},
function: function _function(input) {
return getConstructor(input) === Function;
},
array: function array(input) {
return !is.nullOrUndefined(input) && Array.isArray(input);
},
weakMap: function weakMap(input) {
return instanceOf(input, WeakMap);
},
nodeList: function nodeList(input) {
return instanceOf(input, NodeList);
},
element: function element(input) {
return instanceOf(input, Element);
},
textNode: function textNode(input) {
return getConstructor(input) === Text;
},
event: function event(input) {
return instanceOf(input, Event);
},
cue: function cue(input) {
return instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue);
},
track: function track(input) {
return instanceOf(input, TextTrack) || !is.nullOrUndefined(input) && is.string(input.kind);
},
url: function url(input) {
return !is.nullOrUndefined(input) && /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-/]))?/.test(input);
},
nullOrUndefined: function nullOrUndefined(input) {
return input === null || typeof input === 'undefined';
},
empty: function empty(input) {
return is.nullOrUndefined(input) || (is.string(input) || is.array(input) || is.nodeList(input)) && !input.length || is.object(input) && !Object.keys(input).length;
}
nullOrUndefined: isNullOrUndefined,
object: isObject,
number: isNumber,
string: isString,
boolean: isBoolean,
function: isFunction,
array: isArray,
weakMap: isWeakMap,
nodeList: isNodeList,
element: isElement,
textNode: isTextNode,
event: isEvent,
cue: isCue,
track: isTrack,
url: isUrl,
empty: isEmpty
};
// ==========================================================================
@ -769,22 +801,17 @@ typeof navigator === "object" && (function (global, factory) {
// Quality
Object.defineProperty(player.media, 'quality', {
get: function get$$1() {
get: function get() {
// Get sources
var sources = html5.getSources.call(player);
var _sources$filter = sources.filter(function (source) {
var source = sources.find(function (source) {
return source.getAttribute('src') === player.source;
}),
_sources$filter2 = slicedToArray(_sources$filter, 1),
source = _sources$filter2[0];
});
// Return size, if match is found
return source && Number(source.getAttribute('size'));
},
set: function set$$1(input) {
set: function set(input) {
// Get sources
var sources = html5.getSources.call(player);
@ -799,25 +826,30 @@ typeof navigator === "object" && (function (global, factory) {
}
// Get current state
var currentTime = player.currentTime,
playing = player.playing;
var _player$media = player.media,
currentTime = _player$media.currentTime,
paused = _player$media.paused,
preload = _player$media.preload,
readyState = _player$media.readyState;
// Set new source
player.media.src = source.getAttribute('src');
// Restore time
var onLoadedMetaData = function onLoadedMetaData() {
player.currentTime = currentTime;
};
player.once('loadedmetadata', onLoadedMetaData);
// Prevent loading if preload="none" and the current source isn't loaded (#1044)
if (preload !== 'none' || readyState) {
// Restore time
player.once('loadedmetadata', function () {
player.currentTime = currentTime;
// Load new source
player.media.load();
// Resume playing
if (!paused) {
player.play();
}
});
// Resume playing
if (playing) {
player.play();
// Load new source
player.media.load();
}
// Trigger change event
@ -1137,6 +1169,51 @@ typeof navigator === "object" && (function (global, factory) {
return Storage;
}();
// ==========================================================================
// Fetch wrapper
// Using XHR to avoid issues with older browsers
// ==========================================================================
function fetch(url) {
var responseType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'text';
return new Promise(function (resolve, reject) {
try {
var request = new XMLHttpRequest();
// Check for CORS support
if (!('withCredentials' in request)) {
return;
}
request.addEventListener('load', function () {
if (responseType === 'text') {
try {
resolve(JSON.parse(request.responseText));
} catch (e) {
resolve(request.responseText);
}
} else {
resolve(request.response);
}
});
request.addEventListener('error', function () {
throw new Error(request.status);
});
request.open('GET', url, true);
// Set the required response type
request.responseType = responseType;
request.send();
} catch (e) {
reject(e);
}
});
}
// ==========================================================================
// Load an external SVG sprite
@ -2709,51 +2786,6 @@ typeof navigator === "object" && (function (global, factory) {
}
};
// ==========================================================================
// Fetch wrapper
// Using XHR to avoid issues with older browsers
// ==========================================================================
function fetch$1(url) {
var responseType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'text';
return new Promise(function (resolve, reject) {
try {
var request = new XMLHttpRequest();
// Check for CORS support
if (!('withCredentials' in request)) {
return;
}
request.addEventListener('load', function () {
if (responseType === 'text') {
try {
resolve(JSON.parse(request.responseText));
} catch (e) {
resolve(request.responseText);
}
} else {
resolve(request.response);
}
});
request.addEventListener('error', function () {
throw new Error(request.statusText);
});
request.open('GET', url, true);
// Set the required response type
request.responseType = responseType;
request.send();
} catch (e) {
reject(e);
}
});
}
// ==========================================================================
/**
@ -2833,7 +2865,7 @@ typeof navigator === "object" && (function (global, factory) {
var url = parseUrl(src);
if (url !== null && url.hostname !== window.location.href.hostname && ['http:', 'https:'].includes(url.protocol)) {
fetch$1(src, 'blob').then(function (blob) {
fetch(src, 'blob').then(function (blob) {
track.setAttribute('src', window.URL.createObjectURL(blob));
}).catch(function () {
removeElement(track);
@ -3997,11 +4029,9 @@ typeof navigator === "object" && (function (global, factory) {
}
// If there's a play button, set label
if (is.nodeList(this.elements.buttons.play)) {
Array.from(this.elements.buttons.play).forEach(function (button) {
button.setAttribute('aria-label', label);
});
}
Array.from(this.elements.buttons.play || []).forEach(function (button) {
button.setAttribute('aria-label', label);
});
// Set iframe title
// https://github.com/sampotts/plyr/issues/124
@ -4081,7 +4111,7 @@ typeof navigator === "object" && (function (global, factory) {
toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped);
// Set state
Array.from(this.elements.buttons.play).forEach(function (target) {
Array.from(this.elements.buttons.play || []).forEach(function (target) {
target.pressed = _this3.playing;
});
@ -4779,33 +4809,28 @@ typeof navigator === "object" && (function (global, factory) {
// Detect "natural" scroll - suppored on OS X Safari only
// Other browsers on OS X will be inverted until support improves
var inverted = event.webkitDirectionInvertedFromDevice;
var step = 1 / 50;
var direction = 0;
// Scroll down (or up on natural) to decrease
if (event.deltaY < 0 || event.deltaX > 0) {
if (inverted) {
_this4.player.decreaseVolume(step);
direction = -1;
} else {
_this4.player.increaseVolume(step);
direction = 1;
}
}
// Get delta from event. Invert if `inverted` is true
// Scroll up (or down on natural) to increase
if (event.deltaY > 0 || event.deltaX < 0) {
if (inverted) {
_this4.player.increaseVolume(step);
direction = 1;
} else {
_this4.player.decreaseVolume(step);
direction = -1;
}
}
var _map = [event.deltaX, -event.deltaY].map(function (value) {
return inverted ? -value : value;
}),
_map2 = slicedToArray(_map, 2),
x = _map2[0],
y = _map2[1];
// Using the biggest delta, normalize to 1 or -1 (or 0 if no delta)
var direction = Math.sign(Math.abs(x) > Math.abs(y) ? x : y);
// Change the volume by 2%
_this4.player.increaseVolume(direction / 50);
// Don't break page scrolling at max and min
if (direction === 1 && _this4.player.media.volume < 1 || direction === -1 && _this4.player.media.volume > 0) {
var volume = _this4.player.media.volume;
if (direction === 1 && volume < 1 || direction === -1 && volume > 0) {
event.preventDefault();
}
}, 'volume', false);
@ -5253,7 +5278,7 @@ typeof navigator === "object" && (function (global, factory) {
player.media = replaceElement(wrapper, player.media);
// Get poster image
fetch$1(format(player.config.urls.vimeo.api, id), 'json').then(function (response) {
fetch(format(player.config.urls.vimeo.api, id), 'json').then(function (response) {
if (is.empty(response)) {
return;
}
@ -5668,7 +5693,7 @@ typeof navigator === "object" && (function (global, factory) {
if (is.string(key) && !is.empty(key)) {
var url = format(this.config.urls.youtube.api, videoId, key);
fetch$1(url).then(function (result) {
fetch(url).then(function (result) {
if (is.object(result)) {
_this2.config.title = result.items[0].snippet.title;
ui.setTitle.call(_this2);
@ -5824,8 +5849,8 @@ typeof navigator === "object" && (function (global, factory) {
return Number(instance.getCurrentTime());
},
set: function set(time) {
// If paused, mute audio preventively (YouTube starts playing on seek if the video hasn't been played yet).
if (player.paused) {
// If paused and never played, mute audio preventively (YouTube starts playing on seek if the video hasn't been played yet).
if (player.paused && !player.embed.hasPlayed) {
player.embed.mute();
}
@ -6744,7 +6769,7 @@ typeof navigator === "object" && (function (global, factory) {
}, {
key: 'enabled',
get: function get$$1() {
return this.player.isVideo && this.player.config.ads.enabled && !is.empty(this.publisherId);
return this.player.isHTML5 && this.player.isVideo && this.player.config.ads.enabled && !is.empty(this.publisherId);
}
}, {
key: 'tagUrl',
@ -7301,7 +7326,7 @@ typeof navigator === "object" && (function (global, factory) {
*/
value: function increaseVolume(step) {
var volume = this.media.muted ? 0 : this.volume;
this.volume = volume + (is.number(step) ? step : 1);
this.volume = volume + (is.number(step) ? step : 0);
}
/**
@ -7312,8 +7337,7 @@ typeof navigator === "object" && (function (global, factory) {
}, {
key: 'decreaseVolume',
value: function decreaseVolume(step) {
var volume = this.media.muted ? 0 : this.volume;
this.volume = volume - (is.number(step) ? step : 1);
this.increaseVolume(-step);
}
/**

2
dist/plyr.js.map vendored

File diff suppressed because one or more lines are too long

2
dist/plyr.min.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -5397,60 +5397,92 @@ typeof navigator === "object" && (function (global, factory) {
var getConstructor = function getConstructor(input) {
return input !== null && typeof input !== 'undefined' ? input.constructor : null;
};
var instanceOf = function instanceOf(input, constructor) {
return Boolean(input && constructor && input instanceof constructor);
};
var isNullOrUndefined = function isNullOrUndefined(input) {
return input === null || typeof input === 'undefined';
};
var isObject = function isObject(input) {
return getConstructor(input) === Object;
};
var isNumber = function isNumber(input) {
return getConstructor(input) === Number && !Number.isNaN(input);
};
var isString = function isString(input) {
return getConstructor(input) === String;
};
var isBoolean = function isBoolean(input) {
return getConstructor(input) === Boolean;
};
var isFunction = function isFunction(input) {
return getConstructor(input) === Function;
};
var isArray = function isArray(input) {
return Array.isArray(input);
};
var isWeakMap = function isWeakMap(input) {
return instanceOf(input, WeakMap);
};
var isNodeList = function isNodeList(input) {
return instanceOf(input, NodeList);
};
var isElement = function isElement(input) {
return instanceOf(input, Element);
};
var isTextNode = function isTextNode(input) {
return getConstructor(input) === Text;
};
var isEvent = function isEvent(input) {
return instanceOf(input, Event);
};
var isCue = function isCue(input) {
return instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue);
};
var isTrack = function isTrack(input) {
return instanceOf(input, TextTrack) || !isNullOrUndefined(input) && isString(input.kind);
};
var isEmpty = function isEmpty(input) {
return isNullOrUndefined(input) || (isString(input) || isArray(input) || isNodeList(input)) && !input.length || isObject(input) && !Object.keys(input).length;
};
var isUrl = function isUrl(input) {
// Accept a URL object
if (instanceOf(input, window.URL)) {
return true;
}
// Add the protocol if required
var string = input;
if (!input.startsWith('http://') || !input.startsWith('https://')) {
string = 'http://' + input;
}
try {
return !isEmpty(new URL(string).hostname);
} catch (e) {
return false;
}
};
var is$1 = {
object: function object(input) {
return getConstructor(input) === Object;
},
number: function number(input) {
return getConstructor(input) === Number && !Number.isNaN(input);
},
string: function string(input) {
return getConstructor(input) === String;
},
boolean: function boolean(input) {
return getConstructor(input) === Boolean;
},
function: function _function(input) {
return getConstructor(input) === Function;
},
array: function array(input) {
return !is$1.nullOrUndefined(input) && Array.isArray(input);
},
weakMap: function weakMap(input) {
return instanceOf(input, WeakMap);
},
nodeList: function nodeList(input) {
return instanceOf(input, NodeList);
},
element: function element(input) {
return instanceOf(input, Element);
},
textNode: function textNode(input) {
return getConstructor(input) === Text;
},
event: function event(input) {
return instanceOf(input, Event);
},
cue: function cue(input) {
return instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue);
},
track: function track(input) {
return instanceOf(input, TextTrack) || !is$1.nullOrUndefined(input) && is$1.string(input.kind);
},
url: function url(input) {
return !is$1.nullOrUndefined(input) && /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-/]))?/.test(input);
},
nullOrUndefined: function nullOrUndefined(input) {
return input === null || typeof input === 'undefined';
},
empty: function empty(input) {
return is$1.nullOrUndefined(input) || (is$1.string(input) || is$1.array(input) || is$1.nodeList(input)) && !input.length || is$1.object(input) && !Object.keys(input).length;
}
nullOrUndefined: isNullOrUndefined,
object: isObject,
number: isNumber,
string: isString,
boolean: isBoolean,
function: isFunction,
array: isArray,
weakMap: isWeakMap,
nodeList: isNodeList,
element: isElement,
textNode: isTextNode,
event: isEvent,
cue: isCue,
track: isTrack,
url: isUrl,
empty: isEmpty
};
// ==========================================================================
@ -6158,16 +6190,11 @@ typeof navigator === "object" && (function (global, factory) {
get: function get() {
// Get sources
var sources = html5.getSources.call(player);
var _sources$filter = sources.filter(function (source) {
var source = sources.find(function (source) {
return source.getAttribute('src') === player.source;
}),
_sources$filter2 = slicedToArray(_sources$filter, 1),
source = _sources$filter2[0];
});
// Return size, if match is found
return source && Number(source.getAttribute('size'));
},
set: function set(input) {
@ -6185,25 +6212,30 @@ typeof navigator === "object" && (function (global, factory) {
}
// Get current state
var currentTime = player.currentTime,
playing = player.playing;
var _player$media = player.media,
currentTime = _player$media.currentTime,
paused = _player$media.paused,
preload = _player$media.preload,
readyState = _player$media.readyState;
// Set new source
player.media.src = source.getAttribute('src');
// Restore time
var onLoadedMetaData = function onLoadedMetaData() {
player.currentTime = currentTime;
};
player.once('loadedmetadata', onLoadedMetaData);
// Prevent loading if preload="none" and the current source isn't loaded (#1044)
if (preload !== 'none' || readyState) {
// Restore time
player.once('loadedmetadata', function () {
player.currentTime = currentTime;
// Load new source
player.media.load();
// Resume playing
if (!paused) {
player.play();
}
});
// Resume playing
if (playing) {
player.play();
// Load new source
player.media.load();
}
// Trigger change event
@ -6523,6 +6555,51 @@ typeof navigator === "object" && (function (global, factory) {
return Storage;
}();
// ==========================================================================
// Fetch wrapper
// Using XHR to avoid issues with older browsers
// ==========================================================================
function fetch(url) {
var responseType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'text';
return new Promise(function (resolve, reject) {
try {
var request = new XMLHttpRequest();
// Check for CORS support
if (!('withCredentials' in request)) {
return;
}
request.addEventListener('load', function () {
if (responseType === 'text') {
try {
resolve(JSON.parse(request.responseText));
} catch (e) {
resolve(request.responseText);
}
} else {
resolve(request.response);
}
});
request.addEventListener('error', function () {
throw new Error(request.status);
});
request.open('GET', url, true);
// Set the required response type
request.responseType = responseType;
request.send();
} catch (e) {
reject(e);
}
});
}
// ==========================================================================
// Load an external SVG sprite
@ -8095,51 +8172,6 @@ typeof navigator === "object" && (function (global, factory) {
}
};
// ==========================================================================
// Fetch wrapper
// Using XHR to avoid issues with older browsers
// ==========================================================================
function fetch$1(url) {
var responseType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'text';
return new Promise(function (resolve, reject) {
try {
var request = new XMLHttpRequest();
// Check for CORS support
if (!('withCredentials' in request)) {
return;
}
request.addEventListener('load', function () {
if (responseType === 'text') {
try {
resolve(JSON.parse(request.responseText));
} catch (e) {
resolve(request.responseText);
}
} else {
resolve(request.response);
}
});
request.addEventListener('error', function () {
throw new Error(request.statusText);
});
request.open('GET', url, true);
// Set the required response type
request.responseType = responseType;
request.send();
} catch (e) {
reject(e);
}
});
}
// ==========================================================================
/**
@ -8219,7 +8251,7 @@ typeof navigator === "object" && (function (global, factory) {
var url = parseUrl(src);
if (url !== null && url.hostname !== window.location.href.hostname && ['http:', 'https:'].includes(url.protocol)) {
fetch$1(src, 'blob').then(function (blob) {
fetch(src, 'blob').then(function (blob) {
track.setAttribute('src', window.URL.createObjectURL(blob));
}).catch(function () {
removeElement(track);
@ -9383,11 +9415,9 @@ typeof navigator === "object" && (function (global, factory) {
}
// If there's a play button, set label
if (is$1.nodeList(this.elements.buttons.play)) {
Array.from(this.elements.buttons.play).forEach(function (button) {
button.setAttribute('aria-label', label);
});
}
Array.from(this.elements.buttons.play || []).forEach(function (button) {
button.setAttribute('aria-label', label);
});
// Set iframe title
// https://github.com/sampotts/plyr/issues/124
@ -9467,7 +9497,7 @@ typeof navigator === "object" && (function (global, factory) {
toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped);
// Set state
Array.from(this.elements.buttons.play).forEach(function (target) {
Array.from(this.elements.buttons.play || []).forEach(function (target) {
target.pressed = _this3.playing;
});
@ -10165,33 +10195,28 @@ typeof navigator === "object" && (function (global, factory) {
// Detect "natural" scroll - suppored on OS X Safari only
// Other browsers on OS X will be inverted until support improves
var inverted = event.webkitDirectionInvertedFromDevice;
var step = 1 / 50;
var direction = 0;
// Scroll down (or up on natural) to decrease
if (event.deltaY < 0 || event.deltaX > 0) {
if (inverted) {
_this4.player.decreaseVolume(step);
direction = -1;
} else {
_this4.player.increaseVolume(step);
direction = 1;
}
}
// Get delta from event. Invert if `inverted` is true
// Scroll up (or down on natural) to increase
if (event.deltaY > 0 || event.deltaX < 0) {
if (inverted) {
_this4.player.increaseVolume(step);
direction = 1;
} else {
_this4.player.decreaseVolume(step);
direction = -1;
}
}
var _map = [event.deltaX, -event.deltaY].map(function (value) {
return inverted ? -value : value;
}),
_map2 = slicedToArray(_map, 2),
x = _map2[0],
y = _map2[1];
// Using the biggest delta, normalize to 1 or -1 (or 0 if no delta)
var direction = Math.sign(Math.abs(x) > Math.abs(y) ? x : y);
// Change the volume by 2%
_this4.player.increaseVolume(direction / 50);
// Don't break page scrolling at max and min
if (direction === 1 && _this4.player.media.volume < 1 || direction === -1 && _this4.player.media.volume > 0) {
var volume = _this4.player.media.volume;
if (direction === 1 && volume < 1 || direction === -1 && volume > 0) {
event.preventDefault();
}
}, 'volume', false);
@ -10633,7 +10658,7 @@ typeof navigator === "object" && (function (global, factory) {
player.media = replaceElement(wrapper, player.media);
// Get poster image
fetch$1(format(player.config.urls.vimeo.api, id), 'json').then(function (response) {
fetch(format(player.config.urls.vimeo.api, id), 'json').then(function (response) {
if (is$1.empty(response)) {
return;
}
@ -11048,7 +11073,7 @@ typeof navigator === "object" && (function (global, factory) {
if (is$1.string(key) && !is$1.empty(key)) {
var url = format(this.config.urls.youtube.api, videoId, key);
fetch$1(url).then(function (result) {
fetch(url).then(function (result) {
if (is$1.object(result)) {
_this2.config.title = result.items[0].snippet.title;
ui.setTitle.call(_this2);
@ -11204,8 +11229,8 @@ typeof navigator === "object" && (function (global, factory) {
return Number(instance.getCurrentTime());
},
set: function set(time) {
// If paused, mute audio preventively (YouTube starts playing on seek if the video hasn't been played yet).
if (player.paused) {
// If paused and never played, mute audio preventively (YouTube starts playing on seek if the video hasn't been played yet).
if (player.paused && !player.embed.hasPlayed) {
player.embed.mute();
}
@ -12124,7 +12149,7 @@ typeof navigator === "object" && (function (global, factory) {
}, {
key: 'enabled',
get: function get() {
return this.player.isVideo && this.player.config.ads.enabled && !is$1.empty(this.publisherId);
return this.player.isHTML5 && this.player.isVideo && this.player.config.ads.enabled && !is$1.empty(this.publisherId);
}
}, {
key: 'tagUrl',
@ -12681,7 +12706,7 @@ typeof navigator === "object" && (function (global, factory) {
*/
value: function increaseVolume(step) {
var volume = this.media.muted ? 0 : this.volume;
this.volume = volume + (is$1.number(step) ? step : 1);
this.volume = volume + (is$1.number(step) ? step : 0);
}
/**
@ -12692,8 +12717,7 @@ typeof navigator === "object" && (function (global, factory) {
}, {
key: 'decreaseVolume',
value: function decreaseVolume(step) {
var volume = this.media.muted ? 0 : this.volume;
this.volume = volume - (is$1.number(step) ? step : 1);
this.increaseVolume(-step);
}
/**

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
{
"name": "plyr",
"version": "3.3.13",
"version": "3.3.19",
"description": "A simple, accessible and customizable HTML5, YouTube and Vimeo media player",
"homepage": "https://plyr.io",
"main": "./dist/plyr.js",
@ -45,11 +45,11 @@
"rollup-plugin-node-resolve": "^3.3.0",
"run-sequence": "^2.2.1",
"stylelint": "^9.3.0",
"stylelint-config-prettier": "^3.2.0",
"stylelint-config-prettier": "^3.3.0",
"stylelint-config-recommended": "^2.1.0",
"stylelint-config-sass-guidelines": "^5.0.0",
"stylelint-order": "^0.8.1",
"stylelint-scss": "^3.1.2",
"stylelint-scss": "^3.1.3",
"stylelint-selector-bem-pattern": "^2.0.0"
},
"keywords": ["HTML5 Video", "HTML5 Audio", "Media Player", "DASH", "Shaka", "WordPress", "HLS"],
@ -74,7 +74,7 @@
"babel-polyfill": "^6.26.0",
"custom-event-polyfill": "^0.3.0",
"loadjs": "^3.5.4",
"raven-js": "^3.26.2",
"raven-js": "^3.26.3",
"url-polyfill": "^1.0.13"
}
}

View File

@ -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.
```html
<script src="https://cdn.plyr.io/3.3.13/plyr.js"></script>
<script src="https://cdn.plyr.io/3.3.19/plyr.js"></script>
```
...or...
```html
<script src="https://cdn.plyr.io/3.3.13/plyr.polyfilled.js"></script>
<script src="https://cdn.plyr.io/3.3.19/plyr.polyfilled.js"></script>
```
### CSS
@ -152,13 +152,13 @@ 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:
```html
<link rel="stylesheet" href="https://cdn.plyr.io/3.3.13/plyr.css">
<link rel="stylesheet" href="https://cdn.plyr.io/3.3.19/plyr.css">
```
### SVG Sprite
The SVG sprite is loaded automatically from our CDN (provided by [Fastly](https://www.fastly.com/)). To change this, see the [options](#options) below. For
reference, the CDN hosted SVG sprite can be found at `https://cdn.plyr.io/3.3.13/plyr.svg`.
reference, the CDN hosted SVG sprite can be found at `https://cdn.plyr.io/3.3.19/plyr.svg`.
## Ads
@ -286,7 +286,7 @@ Note the single quotes encapsulating the JSON and double quotes on the object ke
| `debug` | Boolean | `false` | Display debugging information in the console |
| `controls` | Array, Function or Element | `['play-large', 'play', 'progress', 'current-time', 'mute', 'volume', 'captions', 'settings', 'pip', 'airplay', 'fullscreen']` | If a function is passed, it is assumed your method will return either an element or HTML string for the controls. Three arguments will be passed to your function; `id` (the unique id for the player), `seektime` (the seektime step in seconds), and `title` (the media title). See [controls.md](controls.md) for more info on how the html needs to be structured. |
| `settings` | Array | `['captions', 'quality', 'speed', 'loop']` | If you're using the default controls are used then you can specify which settings to show in the menu |
| `i18n` | Object | See [defaults.js](/src/js/defaults.js) | Used for internationalization (i18n) of the text within the UI. |
| `i18n` | Object | See [defaults.js](/src/js/config/defaults.js) | Used for internationalization (i18n) of the text within the UI. |
| `loadSprite` | Boolean | `true` | Load the SVG sprite specified as the `iconUrl` option (if a URL). If `false`, it is assumed you are handling sprite loading yourself. |
| `iconUrl` | String | `null` | Specify a URL or path to the SVG sprite. See the [SVG section](#svg) for more info. |
| `iconPrefix` | String | `plyr` | Specify the id prefix for the icons used in the default controls (e.g. "plyr-play" would be "plyr"). This is to prevent clashes if you're using your own SVG sprite but with the default controls. Most people can ignore this option. |

View File

@ -39,7 +39,7 @@ const html5 = {
get() {
// Get sources
const sources = html5.getSources.call(player);
const [source] = sources.filter(source => source.getAttribute('src') === player.source);
const source = sources.find(source => source.getAttribute('src') === player.source);
// Return size, if match is found
return source && Number(source.getAttribute('size'));
@ -57,23 +57,25 @@ const html5 = {
}
// Get current state
const { currentTime, playing } = player;
const { currentTime, paused, preload, readyState } = player.media;
// Set new source
player.media.src = source.getAttribute('src');
// Restore time
const onLoadedMetaData = () => {
player.currentTime = currentTime;
};
player.once('loadedmetadata', onLoadedMetaData);
// Prevent loading if preload="none" and the current source isn't loaded (#1044)
if (preload !== 'none' || readyState) {
// Restore time
player.once('loadedmetadata', () => {
player.currentTime = currentTime;
// Load new source
player.media.load();
// Resume playing
if (!paused) {
player.play();
}
});
// Resume playing
if (playing) {
player.play();
// Load new source
player.media.load();
}
// Trigger change event

View File

@ -665,36 +665,20 @@ class Listeners {
// Detect "natural" scroll - suppored on OS X Safari only
// Other browsers on OS X will be inverted until support improves
const inverted = event.webkitDirectionInvertedFromDevice;
const step = 1 / 50;
let direction = 0;
// Scroll down (or up on natural) to decrease
if (event.deltaY < 0 || event.deltaX > 0) {
if (inverted) {
this.player.decreaseVolume(step);
direction = -1;
} else {
this.player.increaseVolume(step);
direction = 1;
}
}
// Get delta from event. Invert if `inverted` is true
const [x, y] = [event.deltaX, -event.deltaY]
.map(value => inverted ? -value : value);
// Scroll up (or down on natural) to increase
if (event.deltaY > 0 || event.deltaX < 0) {
if (inverted) {
this.player.increaseVolume(step);
direction = 1;
} else {
this.player.decreaseVolume(step);
direction = -1;
}
}
// Using the biggest delta, normalize to 1 or -1 (or 0 if no delta)
const direction = Math.sign(Math.abs(x) > Math.abs(y) ? x : y);
// Change the volume by 2%
this.player.increaseVolume(direction / 50);
// Don't break page scrolling at max and min
if (
(direction === 1 && this.player.media.volume < 1) ||
(direction === -1 && this.player.media.volume > 0)
) {
const { volume } = this.player.media;
if ((direction === 1 && volume < 1) || (direction === -1 && volume > 0)) {
event.preventDefault();
}
},

View File

@ -49,7 +49,9 @@ class Ads {
}
get enabled() {
return this.player.isVideo && this.player.config.ads.enabled && !is.empty(this.publisherId);
return (
this.player.isHTML5 && this.player.isVideo && this.player.config.ads.enabled && !is.empty(this.publisherId)
);
}
/**

View File

@ -270,8 +270,8 @@ const youtube = {
return Number(instance.getCurrentTime());
},
set(time) {
// If paused, mute audio preventively (YouTube starts playing on seek if the video hasn't been played yet).
if (player.paused) {
// If paused and never played, mute audio preventively (YouTube starts playing on seek if the video hasn't been played yet).
if (player.paused && !player.embed.hasPlayed) {
player.embed.mute();
}

View File

@ -1,6 +1,6 @@
// ==========================================================================
// Plyr
// plyr.js v3.3.13
// plyr.js v3.3.19
// https://github.com/sampotts/plyr
// License: The MIT License (MIT)
// ==========================================================================
@ -553,7 +553,7 @@ class Plyr {
*/
increaseVolume(step) {
const volume = this.media.muted ? 0 : this.volume;
this.volume = volume + (is.number(step) ? step : 1);
this.volume = volume + (is.number(step) ? step : 0);
}
/**
@ -561,8 +561,7 @@ class Plyr {
* @param {boolean} step - How much to decrease by (between 0 and 1)
*/
decreaseVolume(step) {
const volume = this.media.muted ? 0 : this.volume;
this.volume = volume - (is.number(step) ? step : 1);
this.increaseVolume(-step);
}
/**

View File

@ -1,6 +1,6 @@
// ==========================================================================
// Plyr Polyfilled Build
// plyr.js v3.3.13
// plyr.js v3.3.19
// https://github.com/sampotts/plyr
// License: The MIT License (MIT)
// ==========================================================================

View File

@ -135,11 +135,9 @@ const ui = {
}
// If there's a play button, set label
if (is.nodeList(this.elements.buttons.play)) {
Array.from(this.elements.buttons.play).forEach(button => {
button.setAttribute('aria-label', label);
});
}
Array.from(this.elements.buttons.play || []).forEach(button => {
button.setAttribute('aria-label', label);
});
// Set iframe title
// https://github.com/sampotts/plyr/issues/124
@ -214,7 +212,7 @@ const ui = {
toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped);
// Set state
Array.from(this.elements.buttons.play).forEach(target => {
Array.from(this.elements.buttons.play || []).forEach(target => {
target.pressed = this.playing;
});

View File

@ -26,7 +26,7 @@ export default function fetch(url, responseType = 'text') {
});
request.addEventListener('error', () => {
throw new Error(request.statusText);
throw new Error(request.status);
});
request.open('GET', url, true);

View File

@ -3,65 +3,61 @@
// ==========================================================================
const getConstructor = input => (input !== null && typeof input !== 'undefined' ? input.constructor : null);
const instanceOf = (input, constructor) => Boolean(input && constructor && input instanceof constructor);
const isNullOrUndefined = input => input === null || typeof input === 'undefined';
const isObject = input => getConstructor(input) === Object;
const isNumber = input => getConstructor(input) === Number && !Number.isNaN(input);
const isString = input => getConstructor(input) === String;
const isBoolean = input => getConstructor(input) === Boolean;
const isFunction = input => getConstructor(input) === Function;
const isArray = input => Array.isArray(input);
const isWeakMap = input => instanceOf(input, WeakMap);
const isNodeList = input => instanceOf(input, NodeList);
const isElement = input => instanceOf(input, Element);
const isTextNode = input => getConstructor(input) === Text;
const isEvent = input => instanceOf(input, Event);
const isCue = input => instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue);
const isTrack = input => instanceOf(input, TextTrack) || (!isNullOrUndefined(input) && isString(input.kind));
const is = {
object(input) {
return getConstructor(input) === Object;
},
number(input) {
return getConstructor(input) === Number && !Number.isNaN(input);
},
string(input) {
return getConstructor(input) === String;
},
boolean(input) {
return getConstructor(input) === Boolean;
},
function(input) {
return getConstructor(input) === Function;
},
array(input) {
return !is.nullOrUndefined(input) && Array.isArray(input);
},
weakMap(input) {
return instanceOf(input, WeakMap);
},
nodeList(input) {
return instanceOf(input, NodeList);
},
element(input) {
return instanceOf(input, Element);
},
textNode(input) {
return getConstructor(input) === Text;
},
event(input) {
return instanceOf(input, Event);
},
cue(input) {
return instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue);
},
track(input) {
return instanceOf(input, TextTrack) || (!is.nullOrUndefined(input) && is.string(input.kind));
},
url(input) {
return (
!is.nullOrUndefined(input) &&
/(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-/]))?/.test(input)
);
},
nullOrUndefined(input) {
return input === null || typeof input === 'undefined';
},
empty(input) {
return (
is.nullOrUndefined(input) ||
((is.string(input) || is.array(input) || is.nodeList(input)) && !input.length) ||
(is.object(input) && !Object.keys(input).length)
);
},
const isEmpty = input =>
isNullOrUndefined(input) ||
((isString(input) || isArray(input) || isNodeList(input)) && !input.length) ||
(isObject(input) && !Object.keys(input).length);
const isUrl = input => {
// Accept a URL object
if (instanceOf(input, window.URL)) {
return true;
}
// Add the protocol if required
let string = input;
if (!input.startsWith('http://') || !input.startsWith('https://')) {
string = `http://${input}`;
}
try {
return !isEmpty(new URL(string).hostname);
} catch (e) {
return false;
}
};
export default is;
export default {
nullOrUndefined: isNullOrUndefined,
object: isObject,
number: isNumber,
string: isString,
boolean: isBoolean,
function: isFunction,
array: isArray,
weakMap: isWeakMap,
nodeList: isNodeList,
element: isElement,
textNode: isTextNode,
event: isEvent,
cue: isCue,
track: isTrack,
url: isUrl,
empty: isEmpty,
};

View File

@ -3,6 +3,7 @@
// ==========================================================================
import Storage from './../storage';
import fetch from './fetch';
import is from './is';
// Load an external SVG sprite

View File

@ -27,11 +27,6 @@ $embed-padding: ((100 / 16) * 9);
$height: 240;
$offset: to-percentage(($height - $embed-padding) / ($height / 50));
// To allow mouse events to be captured if full support
iframe {
pointer-events: none;
}
// Only used for Vimeo
> .plyr__video-embed__container {
padding-bottom: to-percentage($height);

View File

@ -5000,9 +5000,9 @@ randomatic@^1.1.3:
is-number "^3.0.0"
kind-of "^4.0.0"
raven-js@^3.26.2:
version "3.26.2"
resolved "https://registry.yarnpkg.com/raven-js/-/raven-js-3.26.2.tgz#9153af2416e96ccf4e0b9cbc6c90c34dda0d7e88"
raven-js@^3.26.3:
version "3.26.3"
resolved "https://registry.yarnpkg.com/raven-js/-/raven-js-3.26.3.tgz#0efb49969b5b11ab965f7b0d6da4ca102b763cb0"
rc@^1.0.1, rc@^1.1.6:
version "1.2.6"
@ -5903,9 +5903,9 @@ style-search@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/style-search/-/style-search-0.1.0.tgz#7958c793e47e32e07d2b5cafe5c0bf8e12e77902"
stylelint-config-prettier@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/stylelint-config-prettier/-/stylelint-config-prettier-3.2.0.tgz#af32b7845adeeddbf0a0bd642ace4ca1e68958e2"
stylelint-config-prettier@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/stylelint-config-prettier/-/stylelint-config-prettier-3.3.0.tgz#cc22a4b5310c1919cee77131d6e220c60a62a480"
dependencies:
stylelint "^9.1.1"
@ -5938,9 +5938,9 @@ stylelint-scss@^2.0.0:
postcss-selector-parser "^3.1.1"
postcss-value-parser "^3.3.0"
stylelint-scss@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/stylelint-scss/-/stylelint-scss-3.1.2.tgz#3257c0600d197fe7642f3698944b47c91567f379"
stylelint-scss@^3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/stylelint-scss/-/stylelint-scss-3.1.3.tgz#28f881ae298c3f5db667b10b6cf94a1a219001d6"
dependencies:
lodash "^4.17.10"
postcss-media-query-parser "^0.2.3"