Loading tweaks, Microsoft Edge tweaks

This commit is contained in:
Sam Potts 2016-08-21 19:25:21 +10:00
parent aac0a5a3a9
commit a8062354ec
9 changed files with 95 additions and 124 deletions

View File

@ -20,12 +20,12 @@ And some other changes and bug fixes:
- `on()` to provide an easy way to listen to events
- `stop()` to, you guessed it, stop the player
- `destroy()` now works correctly for YouTube and Vimeo (fixes #272)
- New `destroyed` event when original element is restored (original element passed as event target)
- New `destroyed` event when `destroy()` has completed (original element is passed as event.target)
- Default volume is now 10 (max) rather than 5
- Sprite is only loaded once (fixes #259)
- Fixes for Vimeo post message bugs on source change or destroy (fixes #318)
- Save caption state in storage (fixes #311)
- Added keyboard shortcuts to the current focused player (with option to disable) (fixes #309)
- Added keyboard shortcuts to the current focused player (with `keyboardShortcuts` boolean option to disable) (fixes #309)
- Fix for captions bug (fixes #332)
- Change to AMD (fixes #298)

2
demo/dist/demo.css vendored

File diff suppressed because one or more lines are too long

View File

@ -73,8 +73,8 @@
</main>
<!-- Plyr core script -->
<!--<script src="../dist/plyr.js"></script>-->
<script src="../src/js/plyr.js"></script>
<script src="../dist/plyr.js"></script>
<!--<script src="../src/js/plyr.js"></script>-->
<!-- Docs script -->
<script src="dist/demo.js"></script>

2
dist/plyr.css vendored

File diff suppressed because one or more lines are too long

4
dist/plyr.js vendored

File diff suppressed because one or more lines are too long

View File

@ -13,16 +13,16 @@ We wanted a lightweight, accessible and customizable media player that supports
- **Lightweight** - under 10KB minified and gzipped
- **[Customisable](#html)** - make the player look how you want with the markup you want
- **Semantic** - 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
- **Responsive** - as you'd expect these days
- **Responsive** - works with any screen size
- **HTML Video & Audio** - support for both formats
- **[Embedded Video](#embeds)** - support for YouTube and Vimeo video playback
- **[Streaming](#streaming)** - support for hls.js, Shaka and dash.js streaming playback
- **[API](#api)** - toggle playback, volume, seeking, and more
- **[Universal events](#events)** - no messing around with Vimeo and YouTube APIs, all events are universal 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
- **i18n support** - support for internationalization of controls
- **No dependencies** - written in "vanilla" JavaScript, no jQuery required
- **SASS and LESS source** - to include in your build process
- **[Streaming](#streaming)** - support for hls.js, Shaka and dash.js streaming playback
- **SASS and LESS** - to include in your build processes
Oh and yes, it works with Bootstrap.
@ -78,7 +78,7 @@ More info is on [npm](https://www.npmjs.com/package/ember-cli-plyr) and [GitHub]
Here's a quick run through on getting up and running.
### HTML
Plyr extends upon the standard HTML5 markup so that's all you need for those types.
Plyr extends upon the standard HTML5 markup so that's all you need for those types. More info on advanced HTML markup can be found under [initialising](#initialising).
#### HTML5 Video
```html
@ -172,7 +172,7 @@ WebVTT captions are supported. To add a caption track, check the HTML example ab
#### Initialising
By default, Plyr looks for all `<video>`, `<audio>` and `[data-type]` elements with the document and initialises on any found. You can specify other options, including a different NodeList, HTMLElement, Array of HTMLElements or string selector as below:
By default, `setup()` will find all `<video>`, `<audio>` and `[data-type]` elements with the document and initialises on any found. Each target media element found will be wrapped in a `<div>` for styling and setup individually. You can specify a variety of arguments to `setup()` to use, including a different NodeList, HTMLElement, Array of HTMLElements or string selector as below:
Passing a [NodeList](https://developer.mozilla.org/en-US/docs/Web/API/NodeList):
```javascript
@ -197,14 +197,14 @@ Passing a [string selector](https://developer.mozilla.org/en-US/docs/Web/API/Doc
plyr.setup('.js-player', options);
```
The NodeList, HTMLElement or string selector can be the target `<video>`, `<audio>` or `[data-type]` (for embeds) element or a container element. If a container has several media elements inside, each media element will be wrapped in a `<div>` and setup individually.
The NodeList, HTMLElement or string selector can be the target `<video>`, `<audio>` or `[data-type]` (for embeds) element itself or a container element.
Passing just the options object:
```javascript
plyr.setup(options);
```
`setup()` will return an array of instances that can be used with the [#API](API) methods. See the [#API](API) section for more.
`setup()` will return an array of *instances* that can be used with the [API](#api) methods. See the [API](#api) section for more info.
#### RangeTouch
Some touch browsers (particularly Mobile Safari on iOS) seem to have issues with `<input type="range">` elements whereby touching the track to set the value doesn't work and sliding the thumb can be tricky. To combat this, I've created [RangeTouch](https://rangetouch.com) which I'd recommend including in your solution. It's a tiny script with a nice benefit for users on touch devices.
@ -476,7 +476,7 @@ Here's a list of the methods supported:
<tr>
<td><code>getEmbed()</code></td>
<td>&mdash;</td>
<td>Get the embed API to access those methods - either YouTube or Vimeo.</td>
<td>Get the [embed](#embed) API to access those methods - either YouTube or Vimeo.</td>
</tr>
<tr>
<td><code>getType()</code></td>
@ -486,12 +486,12 @@ Here's a list of the methods supported:
<tr>
<td><code>isReady()</code></td>
<td>&mdash;</td>
<td>Determine if the player is ready to accept API calls - this is because HTML5 is ready instantly but YouTube and Vimeo can take some time to load their APIs.</td>
<td>Determine if the player is loaded and UI ready - this is because HTML5 is ready instantly but YouTube and Vimeo can take some time to load their APIs.</td>
</tr>
<tr>
<td><code>on()</code></td>
<td>String, Function</td>
<td>Watch for an event (first argument) and run a callback function (second argument). This saves you doing your own <code>addEventListner</code>s.</td>
<td>Watch for an event (first argument) and run a callback function (second argument). This saves you doing your own <code>addEventListner</code> code.</td>
</tr>
<tr>
<td><code>play()</code></td>
@ -587,7 +587,7 @@ Here's a list of the methods supported:
<tr>
<td><code>destroy()</code></td>
<td>&mdash;</td>
<td>Destroys the plyr UI and any media event listeners, effectively restoring to the previous state before <code>setup()</code> was called.</td>
<td>Restores the original element, reversing the effects of <code>setup()</code>.</td>
</tr>
<tr>
<td><code>getCurrentTime()</code></td>
@ -687,7 +687,7 @@ Some more details on the object parameters
<tr>
<td><code>title</code></td>
<td>String</td>
<td>Title of the new media. Used for the aria labelling.</td>
<td>Title of the new media. Used for the `aria-label` attribute on the play button, and outer container.</td>
</tr>
<tr>
<td><code>sources</code></td>
@ -850,7 +850,7 @@ These events also bubble up the DOM. The event target will be the container elem
<tr>
<td><code>destroyed</code></td>
<td></td>
<td>When an instance is destroyed. The original element that replaced the container will be the event target.</td>
<td>When an instance is destroyed. The original element that replaced the container will be returned to your handler as the event target.</td>
</tr>
</tbody>
</table>

View File

@ -616,7 +616,7 @@
element: null,
prefix: ''
},
browserPrefixes = 'webkit moz o ms khtml'.split(' ');
browserPrefixes = 'webkit o ms khtml'.split(' ');
// Check for native support
if (!_is.undefined(document.cancelFullScreen)) {
@ -653,8 +653,6 @@
switch (this.prefix) {
case '':
return document.fullscreenElement === element;
case 'moz':
return document.mozFullScreenElement === element;
default:
return document[this.prefix + 'FullscreenElement'] === element;
}
@ -1657,7 +1655,7 @@
},
events: {
'onError': function(event) {
_triggerEvent(container, 'error', true, {
_triggerEvent(plyr.container, 'error', true, {
code: event.data,
embed: event.target
});
@ -1681,7 +1679,7 @@
};
plyr.media.duration = instance.getDuration();
plyr.media.paused = true;
plyr.media.currentTime = instance.getCurrentTime();
plyr.media.currentTime = 0;
plyr.media.muted = instance.isMuted();
// Set title
@ -1698,6 +1696,9 @@
// Trigger timeupdate
_triggerEvent(plyr.media, 'timeupdate');
// Trigger timeupdate
_triggerEvent(plyr.media, 'durationchange');
// Reset timer
window.clearInterval(timers.buffering);
@ -1722,9 +1723,6 @@
_triggerEvent(plyr.media, 'canplaythrough');
}
}, 200);
// Display duration if available
_displayDuration();
},
'onStateChange': function(event) {
// Get the instance
@ -1769,7 +1767,7 @@
break;
}
_triggerEvent(container, 'statechange', false, {
_triggerEvent(plyr.container, 'statechange', false, {
code: event.data
});
}
@ -1819,9 +1817,9 @@
plyr.embed.getDuration().then(function(value) {
plyr.media.duration = value;
// Display duration if available
_displayDuration();
// Trigger timeupdate
_triggerEvent(plyr.media, 'durationchange');
});
// TODO: Captions
@ -1895,8 +1893,12 @@
plyr.media.paused = true;
plyr.media.currentTime = 0;
// Update UI
_embedReady();
plyr.embed.getDuration(function(value) {
plyr.media.duration = value/1000;
// Update UI
_embedReady();
});
plyr.embed.getPosition(function(value) {
plyr.media.currentTime = value;
@ -1905,12 +1907,6 @@
_triggerEvent(plyr.media, 'timeupdate');
});
plyr.embed.getDuration(function(value) {
plyr.media.duration = value/1000;
// Display duration if available
_displayDuration();
});
plyr.embed.bind(window.SC.Widget.Events.PLAY, function() {
plyr.media.paused = false;
_triggerEvent(plyr.media, 'play');
@ -1942,11 +1938,6 @@
plyr.media.paused = true;
_triggerEvent(plyr.media, 'ended');
});
// Autoplay
if (config.autoplay) {
plyr.embed.play();
}
});
}
@ -2093,6 +2084,7 @@
// Check playing state
function _checkPlaying() {
_toggleClass(plyr.container, config.classes.playing, !plyr.media.paused);
_toggleClass(plyr.container, config.classes.stopped, plyr.media.paused);
_toggleControls(plyr.media.paused);
@ -2115,7 +2107,6 @@
function _toggleFullscreen(event) {
// Check for native support
var nativeSupport = fullscreen.supportsFullScreen;
if (nativeSupport) {
// If it's a fullscreen change event, update the UI
@ -2138,7 +2129,7 @@
}
// Check if we're actually full screen (it could fail)
// plyr.isFullscreen = fullscreen.isFullScreen(plyr.container);
plyr.isFullscreen = fullscreen.isFullScreen(plyr.container);
return;
}
@ -2349,7 +2340,11 @@
// Timer to prevent flicker when seeking
timers.loading = setTimeout(function() {
// Toggle container class hook
_toggleClass(plyr.container, config.classes.loading, loading);
// Show controls if loading, hide if done
_toggleControls(loading);
}, (loading ? 250 : 0));
}
@ -2578,14 +2573,15 @@
// Show the player controls in fullscreen mode
function _toggleControls(toggle) {
// Don't hide if config says not to, it's audio, or not loaded/ready
if (!config.hideControls || plyr.type === 'audio' || !_hasClass(plyr.container, config.classes.ready)) {
// Don't hide if config says not to, it's audio, or not ready or loading
if (!config.hideControls || plyr.type === 'audio') {
return;
}
var delay = 0,
isEnterFullscreen = false,
show = toggle;
show = toggle,
loading = _hasClass(plyr.container, config.classes.loading);
// Default to false if no boolean
if (!_is.boolean(toggle)) {
@ -2615,11 +2611,11 @@
window.clearTimeout(timers.hover);
// If the mouse is not over the controls, set a timeout to hide them
if (show || plyr.media.paused) {
if (show || plyr.media.paused || loading) {
_toggleClass(plyr.container, config.classes.hideControls, false);
// Always show controls when paused or if touch
if (plyr.media.paused) {
if (plyr.media.paused || loading) {
return;
}
@ -2686,6 +2682,9 @@
return;
}
// Remove ready class hook
_toggleClass(plyr.container, config.classes.ready, false);
// Pause playback
_pause();
@ -2698,22 +2697,19 @@
// Cancel current network requests
_cancelRequests();
// Remove ready class hook
_toggleClass(plyr.container, config.classes.ready, false);
// Setup new source
function setup() {
// Remove embed object
plyr.embed = null;
// Remove the old media
_remove(plyr.media);
// Remove video container
if (plyr.type === 'video' && plyr.videoContainer) {
_remove(plyr.videoContainer);
}
// Remove the old media
_remove(plyr.media);
// Reset class name
if (plyr.container) {
plyr.container.removeAttribute('class');
@ -2800,21 +2796,16 @@
// Load HTML5 sources
plyr.media.load();
}
// If HTML5 or embed but not fully supported, setupInterface and call ready now
if (_inArray(config.types.html5, plyr.type) || (_inArray(config.types.embed, plyr.type) && !plyr.supported.full)) {
// Setup interface
_setupInterface();
// Display duration if available
_displayDuration();
// Call ready
_ready();
}
// If embed but not fully supported, setupInterface and call ready now
else if (_inArray(config.types.embed, plyr.type) && !plyr.supported.full) {
_setupInterface();
_ready();
}
// Set aria title and iframe title
config.title = source.title;
@ -2906,13 +2897,11 @@
// Keyboard shortcuts
if (config.keyboardShorcuts) {
//var held = false;
var first = true;
_on(plyr.container, 'keyup keydown', function(event) {
_on(plyr.container, 'keydown keyup', function(event) {
var code = getKeyCode(event),
down = event.type === 'keydown',
first = true,
timer;
pressed = event.type === 'keydown';
// Seek by the number keys
function seekByKey() {
@ -2928,9 +2917,9 @@
_seek((duration / 10) * (code - 48));
}
function handleKey() {
console.log(code);
// Handle the key on keydown
// Reset on keyup
if (pressed) {
switch(code) {
// 0-9
case 48:
@ -2945,7 +2934,7 @@
case 57: if (first) { seekByKey() } break;
// Space and K key
case 32:
case 75: if (first) { _togglePlay() } break;
case 75: if (first) { _togglePlay(); } break;
// Arrow up
case 38: _increaseVolume(); break;
// Arrow down
@ -2971,16 +2960,8 @@
// First run completed
first = false;
}
if (down) {
handleKey();
// If a key is held for 200ms, run again
// Handy for volume and skip
timer = setTimeout(handleKey, 200);
}
else {
clearTimeout(timer);
first = true;
}
});
}
@ -3108,22 +3089,16 @@
// Handle the media finishing
_on(plyr.media, 'ended', function() {
// Clear
if (plyr.type === 'video') {
_setCaption();
}
// Reset UI
_checkPlaying();
// Seek to 0
_seek(0);
// Reset duration display
_displayDuration();
// Show poster on end
if(plyr.type === 'video' && config.showPosterOnEnd) {
// Clear
if (plyr.type === 'video') {
_setCaption();
}
// Restart
_seek();
// Re-load media
plyr.media.load();
}
@ -3136,7 +3111,7 @@
_on(plyr.media, 'volumechange', _updateVolume);
// Handle native play/pause
_on(plyr.media, 'play pause', _checkPlaying);
_on(plyr.media, 'play pause ended', _checkPlaying);
// Loading
_on(plyr.media, 'waiting canplay seeked', _checkLoading);
@ -3180,7 +3155,7 @@
}
// Proxy events to container
_on(plyr.media, config.events.join(' '), function(event) {
_on(plyr.media, config.events.concat(['keyup', 'keydown']).join(' '), function(event) {
_triggerEvent(plyr.container, event.type, true);
});
}
@ -3209,7 +3184,7 @@
plyr.media.load();
// Debugging
_log('Cancelled network requests for old media');
_log('Cancelled network requests');
}
// Destroy an instance
@ -3347,25 +3322,16 @@
_setupMedia();
// Setup interface
if (_inArray(config.types.html5, plyr.type)) {
// If embed but not fully supported, setupInterface (to avoid flash of controls) and call ready now
if (_inArray(config.types.html5, plyr.type) || (_inArray(config.types.embed, plyr.type) && !plyr.supported.full)) {
// Setup UI
_setupInterface();
// Set title on button and frame
_setTitle();
// Autoplay
if (config.autoplay) {
_play();
}
// Call ready
_ready();
}
// If embed but not fully supported, setupInterface (to avoid flash of controls) and call ready now
else if (_inArray(config.types.embed, plyr.type) && !plyr.supported.full) {
_setupInterface();
_ready();
// Set title on button and frame
_setTitle();
}
// Successful setup
@ -3429,9 +3395,6 @@
// Update the UI
_checkPlaying();
// Display duration
_displayDuration();
}
api = {
@ -3441,6 +3404,7 @@
getMedia: function() { return plyr.media; },
getType: function() { return plyr.type; },
isReady: function() { return _hasClass(plyr.container, config.classes.ready); },
isLoading: function() { return _hasClass(plyr.container, config.classes.loading); },
on: function(event, callback) { _on(plyr.container, event, callback); },
play: _play,
pause: _pause,
@ -3476,6 +3440,11 @@
// Store a refernce to instance
plyr.media.plyr = api;
// Autoplay
if (config.autoplay) {
_play();
}
}
// Initialize instance
@ -3670,7 +3639,7 @@
if (config.debug) {
var events = config.events.concat(['setup', 'ready', 'statechange', 'enterfullscreen', 'exitfullscreen', 'captionsenabled', 'captionsdisabled']);
_on(instance.getContainer(), events.join(' '), function() {
_on(instance.getContainer(), events.join(' '), function(event) {
console.log([config.logPrefix, 'event:', event.type].join(' '), event.detail.plyr);
});
}
@ -3704,7 +3673,9 @@
instances = [];
Array.prototype.slice.call(elements).forEach(function(element) {
instances.push(element.plyr);
if (_is.object(element.plyr)) {
instances.push(element.plyr);
}
});
return instances;

View File

@ -728,7 +728,7 @@
width: 100%;
z-index: 10000000;
background: #000;
border-radius: 0;
border-radius: 0 !important;
video {
height: 100%;

View File

@ -727,7 +727,7 @@
width: 100%;
z-index: 10000000;
background: #000;
border-radius: 0;
border-radius: 0 !important;
video {
height: 100%;