Started on PIP support

This commit is contained in:
Sam 2016-09-13 00:16:27 +10:00
parent 46f82a4af3
commit d638cdcdd3
5 changed files with 121 additions and 113 deletions

2
demo/dist/demo.css vendored

File diff suppressed because one or more lines are too long

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

@ -9,7 +9,7 @@
;(function(root, factory) { ;(function(root, factory) {
'use strict'; 'use strict';
/*global define,module*/ /* global define,module */
if (typeof module === 'object' && typeof module.exports === 'object') { if (typeof module === 'object' && typeof module.exports === 'object') {
// Node, CommonJS-like // Node, CommonJS-like
@ -25,8 +25,7 @@
'use strict'; 'use strict';
// Globals // Globals
var fullscreen, var scroll = { x: 0, y: 0 },
scroll = { x: 0, y: 0 },
// Default config // Default config
defaults = { defaults = {
@ -118,6 +117,10 @@
enabled: 'plyr--fullscreen-enabled', enabled: 'plyr--fullscreen-enabled',
active: 'plyr--fullscreen-active' active: 'plyr--fullscreen-active'
}, },
pip: {
enabled: 'plyr--pip-enabled',
active: 'plyr--pip-active'
},
tabFocus: 'tab-focus' tabFocus: 'tab-focus'
}, },
captions: { captions: {
@ -191,7 +194,7 @@
// Credits: http://paypal.github.io/accessible-html5-video-player/ // Credits: http://paypal.github.io/accessible-html5-video-player/
// Unfortunately, due to mixed support, UA sniffing is required // Unfortunately, due to mixed support, UA sniffing is required
function _browserSniff() { function _getBrowser() {
var ua = navigator.userAgent, var ua = navigator.userAgent,
name = navigator.appName, name = navigator.appName,
fullVersion = '' + parseFloat(navigator.appVersion), fullVersion = '' + parseFloat(navigator.appVersion),
@ -270,32 +273,6 @@
}; };
} }
// Check for mime type support against a player instance
// Credits: http://diveintohtml5.info/everything.html
// Related: http://www.leanbackplyr.com/test/h5mt.html
function _supportMime(plyr, mimeType) {
var media = plyr.media;
if (plyr.type === 'video') {
// Check type
switch (mimeType) {
case 'video/webm': return !!(media.canPlayType && media.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/no/, ''));
case 'video/mp4': return !!(media.canPlayType && media.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"').replace(/no/, ''));
case 'video/ogg': return !!(media.canPlayType && media.canPlayType('video/ogg; codecs="theora"').replace(/no/, ''));
}
} else if (plyr.type === 'audio') {
// Check type
switch (mimeType) {
case 'audio/mpeg': return !!(media.canPlayType && media.canPlayType('audio/mpeg;').replace(/no/, ''));
case 'audio/ogg': return !!(media.canPlayType && media.canPlayType('audio/ogg; codecs="vorbis"').replace(/no/, ''));
case 'audio/wav': return !!(media.canPlayType && media.canPlayType('audio/wav; codecs="1"').replace(/no/, ''));
}
}
// If we got this far, we're stuffed
return false;
}
// Inject a script // Inject a script
function _injectScript(source) { function _injectScript(source) {
if (document.querySelectorAll('script[src="' + source + '"]').length) { if (document.querySelectorAll('script[src="' + source + '"]').length) {
@ -587,45 +564,38 @@
}; };
// Fullscreen API // Fullscreen API
function _fullscreen() { var _fullscreen;
var fullscreen = { (function() {
supportsFullScreen: false, // Determine the prefix
isFullScreen: function() { return false; }, var prefix = (function() {
requestFullScreen: function() {}, if (!_is.undefined(document.cancelFullScreen)) {
cancelFullScreen: function() {}, return '';
fullScreenEventName: '', } else {
element: null, // Check for fullscreen support by vendor prefix
prefix: '' ['webkit', 'o', 'moz', 'ms', 'khtml'].forEach(function(prefix) {
}, if (!_is.undefined(document[prefix + 'CancelFullScreen'])) {
browserPrefixes = 'webkit o moz ms khtml'.split(' '); return prefix;
} else if (!_is.undefined(document.msExitFullscreen) && document.msFullscreenEnabled) {
// Check for native support // Special case for MS (when isn't it?)
if (!_is.undefined(document.cancelFullScreen)) { return 'ms';
fullscreen.supportsFullScreen = true; }
} else { });
// Check for fullscreen support by vendor prefix
for (var i = 0, il = browserPrefixes.length; i < il; i++ ) {
fullscreen.prefix = browserPrefixes[i];
if (!_is.undefined(document[fullscreen.prefix + 'CancelFullScreen'])) {
fullscreen.supportsFullScreen = true;
break;
} else if (!_is.undefined(document.msExitFullscreen) && document.msFullscreenEnabled) {
// Special case for MS (when isn't it?)
fullscreen.prefix = 'ms';
fullscreen.supportsFullScreen = true;
break;
}
} }
}
// Update methods to do something useful // If we got this far, there's no support
if (fullscreen.supportsFullScreen) { return false;
})();
_fullscreen = {
// Yet again Microsoft awesomeness, // Yet again Microsoft awesomeness,
// Sometimes the prefix is 'ms', sometimes 'MS' to keep you on your toes // Sometimes the prefix is 'ms', sometimes 'MS' to keep you on your toes
fullscreen.fullScreenEventName = (fullscreen.prefix === 'ms' ? 'MSFullscreenChange' : fullscreen.prefix + 'fullscreenchange'); eventType: (prefix === 'ms' ? 'MSFullscreenChange' : prefix + 'fullscreenchange'),
fullscreen.isFullScreen = function(element) { // Is an element fullscreen
isFullScreen: function(element) {
if (!_support.fullscreen) {
return false;
}
if (_is.undefined(element)) { if (_is.undefined(element)) {
element = document.body; element = document.body;
} }
@ -635,29 +605,40 @@
case 'moz': case 'moz':
return document.mozFullScreenElement === element; return document.mozFullScreenElement === element;
default: default:
return document[this.prefix + 'FullscreenElement'] === element; return document[prefix + 'FullscreenElement'] === element;
}
},
requestFullScreen: function(element) {
if (!_support.fullscreen) {
return false;
} }
};
fullscreen.requestFullScreen = function(element) {
if (_is.undefined(element)) { if (_is.undefined(element)) {
element = document.body; element = document.body;
} }
return (this.prefix === '') ? element.requestFullScreen() : element[this.prefix + (this.prefix === 'ms' ? 'RequestFullscreen' : 'RequestFullScreen')](); return (prefix === '') ? element.requestFullScreen() : element[prefix + (prefix === 'ms' ? 'RequestFullscreen' : 'RequestFullScreen')]();
}; },
fullscreen.cancelFullScreen = function() { cancelFullScreen: function() {
return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + (this.prefix === 'ms' ? 'ExitFullscreen' : 'CancelFullScreen')](); if (!_support.fullscreen) {
}; return false;
fullscreen.element = function() { }
return (this.prefix === '') ? document.fullscreenElement : document[this.prefix + 'FullscreenElement']; return (prefix === '') ? document.cancelFullScreen() : document[prefix + (prefix === 'ms' ? 'ExitFullscreen' : 'CancelFullScreen')]();
}; },
} element: function() {
if (!_support.fullscreen) {
return null;
}
return (prefix === '') ? document.fullscreenElement : document[prefix + 'FullscreenElement'];
}
};
})();
return fullscreen; // Check for support
} var _support = {
// Fullscreen support and set prefix
// Local storage fullscreen: _fullscreen.prefix !== false,
var _storage = { // Local storage mode
supported: (function() { // We can't assume if local storage is present that we can use it
storage: (function() {
if (!('localStorage' in window)) { if (!('localStorage' in window)) {
return false; return false;
} }
@ -682,7 +663,37 @@
} }
return false; return false;
})() })(),
// Picture-in-picture support
// Safari only currently
pip: function(plyr) {
return _is.function(plyr.media.webkitSetPresentationMode);
},
// Check for mime type support against a player instance
// Credits: http://diveintohtml5.info/everything.html
// Related: http://www.leanbackplyr.com/test/h5mt.html
mime: function(plyr, type) {
var media = plyr.media;
if (plyr.type === 'video') {
// Check type
switch (type) {
case 'video/webm': return !!(media.canPlayType && media.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/no/, ''));
case 'video/mp4': return !!(media.canPlayType && media.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"').replace(/no/, ''));
case 'video/ogg': return !!(media.canPlayType && media.canPlayType('video/ogg; codecs="theora"').replace(/no/, ''));
}
} else if (plyr.type === 'audio') {
// Check type
switch (type) {
case 'audio/mpeg': return !!(media.canPlayType && media.canPlayType('audio/mpeg;').replace(/no/, ''));
case 'audio/ogg': return !!(media.canPlayType && media.canPlayType('audio/ogg; codecs="vorbis"').replace(/no/, ''));
case 'audio/wav': return !!(media.canPlayType && media.canPlayType('audio/wav; codecs="1"').replace(/no/, ''));
}
}
// If we got this far, we're stuffed
return false;
}
}; };
// Player instance // Player instance
@ -867,8 +878,6 @@
// Settings button // Settings button
if (_inArray(config.controls, 'settings')) { if (_inArray(config.controls, 'settings')) {
html.push( html.push(
'<div class="plyr__menu">', '<div class="plyr__menu">',
'<button type="button" id="plyr-settings-toggle-{id}" data-plyr="settings" aria-haspopup="true" aria-controls="plyr-settings-{id}" aria-expanded="false">', '<button type="button" id="plyr-settings-toggle-{id}" data-plyr="settings" aria-haspopup="true" aria-controls="plyr-settings-{id}" aria-expanded="false">',
@ -888,7 +897,7 @@
'</button>', '</button>',
'</li>', '</li>',
'<li>', '<li>',
'<button type="button" data-plyr="slide-speed">', '<button type="button" data-plyr="slide-quality">',
config.i18n.quality + ' <span class="plyr__menu__value">Auto</span>', config.i18n.quality + ' <span class="plyr__menu__value">Auto</span>',
'</button>', '</button>',
'</li>', '</li>',
@ -923,7 +932,7 @@
if ((plyr.type !== 'audio' || config.fullscreen.allowAudio) && config.fullscreen.enabled) { if ((plyr.type !== 'audio' || config.fullscreen.allowAudio) && config.fullscreen.enabled) {
// Check for native support // Check for native support
var nativeSupport = fullscreen.supportsFullScreen; var nativeSupport = _support.fullscreen;
if (nativeSupport || (config.fullscreen.fallback && !_inFrame())) { if (nativeSupport || (config.fullscreen.fallback && !_inFrame())) {
_log((nativeSupport ? 'Native' : 'Fallback') + ' fullscreen enabled'); _log((nativeSupport ? 'Native' : 'Fallback') + ' fullscreen enabled');
@ -1435,7 +1444,7 @@
plyr.storage = {}; plyr.storage = {};
// Bail if we don't have localStorage support or it's disabled // Bail if we don't have localStorage support or it's disabled
if (!_storage.supported || !config.storage.enabled) { if (!_support.storage || !config.storage.enabled) {
return; return;
} }
@ -1463,7 +1472,7 @@
// Save a value back to local storage // Save a value back to local storage
function _updateStorage(value) { function _updateStorage(value) {
// Bail if we don't have localStorage support or it's disabled // Bail if we don't have localStorage support or it's disabled
if (!_storage.supported || !config.storage.enabled) { if (!_support.storage || !config.storage.enabled) {
return; return;
} }
@ -1492,6 +1501,9 @@
_toggleClass(plyr.container, config.classes.type.replace('{0}', 'video'), true); _toggleClass(plyr.container, config.classes.type.replace('{0}', 'video'), true);
} }
// Check for picture-in-picture support
_toggleClass(plyr.container, config.classes.pip.enabled, _support.pip(plyr));
// If there's no autoplay attribute, assume the video is stopped and add state class // If there's no autoplay attribute, assume the video is stopped and add state class
_toggleClass(plyr.container, config.classes.stopped, config.autoplay); _toggleClass(plyr.container, config.classes.stopped, config.autoplay);
@ -2126,27 +2138,27 @@
// Toggle fullscreen // Toggle fullscreen
function _toggleFullscreen(event) { function _toggleFullscreen(event) {
// Check for native support // Check for native support
var nativeSupport = fullscreen.supportsFullScreen; var nativeSupport = _support.fullscreen;
if (nativeSupport) { if (nativeSupport) {
// If it's a fullscreen change event, update the UI // If it's a fullscreen change event, update the UI
if (event && event.type === fullscreen.fullScreenEventName) { if (event && event.type === _fullscreen.eventType) {
plyr.isFullscreen = fullscreen.isFullScreen(plyr.container); plyr.isFullscreen = _fullscreen.isFullScreen(plyr.container);
} else { } else {
// Else it's a user request to enter or exit // Else it's a user request to enter or exit
if (!fullscreen.isFullScreen(plyr.container)) { if (!_fullscreen.isFullScreen(plyr.container)) {
// Save scroll position // Save scroll position
_saveScrollPosition(); _saveScrollPosition();
// Request full screen // Request full screen
fullscreen.requestFullScreen(plyr.container); _fullscreen.requestFullScreen(plyr.container);
} else { } else {
// Bail from fullscreen // Bail from fullscreen
fullscreen.cancelFullScreen(); _fullscreen.cancelFullScreen();
} }
// Check if we're actually full screen (it could fail) // Check if we're actually full screen (it could fail)
plyr.isFullscreen = fullscreen.isFullScreen(plyr.container); plyr.isFullscreen = _fullscreen.isFullScreen(plyr.container);
return; return;
} }
@ -3009,7 +3021,7 @@
// Escape is handle natively when in full screen // Escape is handle natively when in full screen
// So we only need to worry about non native // So we only need to worry about non native
if (!fullscreen.supportsFullScreen && plyr.isFullscreen && code === 27) { if (!_support.fullscreen && plyr.isFullscreen && code === 27) {
_toggleFullscreen(); _toggleFullscreen();
} }
@ -3073,8 +3085,8 @@
_proxyListener(plyr.buttons.fullscreen, 'click', config.listeners.fullscreen, _toggleFullscreen); _proxyListener(plyr.buttons.fullscreen, 'click', config.listeners.fullscreen, _toggleFullscreen);
// Handle user exiting fullscreen by escaping etc // Handle user exiting fullscreen by escaping etc
if (fullscreen.supportsFullScreen) { if (_support.fullscreen) {
_on(document, fullscreen.fullScreenEventName, _toggleFullscreen); _on(document, _fullscreen.eventType, _toggleFullscreen);
} }
// Captions // Captions
@ -3086,8 +3098,6 @@
target = document.querySelector('#' + toggle.getAttribute('aria-controls')), target = document.querySelector('#' + toggle.getAttribute('aria-controls')),
show = (toggle.getAttribute('aria-expanded') === 'false'); show = (toggle.getAttribute('aria-expanded') === 'false');
console.log(target, toggle);
toggle.setAttribute('aria-expanded', show); toggle.setAttribute('aria-expanded', show);
target.setAttribute('aria-hidden', !show); target.setAttribute('aria-hidden', !show);
}); });
@ -3332,11 +3342,8 @@
return null; return null;
} }
// Setup the fullscreen api
fullscreen = _fullscreen();
// Sniff out the browser // Sniff out the browser
plyr.browser = _browserSniff(); plyr.browser = _getBrowser();
// Bail if nothing to setup // Bail if nothing to setup
if (!_is.htmlElement(plyr.media)) { if (!_is.htmlElement(plyr.media)) {
@ -3495,7 +3502,7 @@
toggleFullscreen: _toggleFullscreen, toggleFullscreen: _toggleFullscreen,
toggleControls: _toggleControls, toggleControls: _toggleControls,
isFullscreen: function() { return plyr.isFullscreen || false; }, isFullscreen: function() { return plyr.isFullscreen || false; },
support: function(mimeType) { return _supportMime(plyr, mimeType); }, support: function(mimeType) { return _support.mime(plyr, mimeType); },
destroy: _destroy destroy: _destroy
}; };
@ -3566,7 +3573,7 @@
// Check for support // Check for support
function supported(type) { function supported(type) {
var browser = _browserSniff(), var browser = _getBrowser(),
isOldIE = (browser.isIE && browser.version <= 9), isOldIE = (browser.isIE && browser.version <= 9),
isIos = browser.isIos, isIos = browser.isIos,
isIphone = /iPhone|iPod/i.test(navigator.userAgent), isIphone = /iPhone|iPod/i.test(navigator.userAgent),

View File

@ -30,6 +30,7 @@
max-width: 100%; max-width: 100%;
min-width: 200px; min-width: 200px;
font-family: @plyr-font-family; font-family: @plyr-font-family;
font-weight: 500;
direction: ltr; direction: ltr;
& when (@plyr-border-box = true) { & when (@plyr-border-box = true) {
@ -239,7 +240,6 @@
color: @plyr-captions-color; color: @plyr-captions-color;
font-size: @plyr-font-size-captions-base; font-size: @plyr-font-size-captions-base;
text-align: center; text-align: center;
font-weight: 400;
span { span {
border-radius: 2px; border-radius: 2px;
@ -519,7 +519,7 @@
.plyr__menu__value { .plyr__menu__value {
margin-left: auto; margin-left: auto;
padding-left: 25px; padding-left: 25px;
font-weight: 400; font-weight: 500;
color: fade(@plyr-menu-color, 80%); color: fade(@plyr-menu-color, 80%);
} }
@ -553,6 +553,7 @@
color: @plyr-tooltip-color; color: @plyr-tooltip-color;
font-size: @plyr-font-size-small; font-size: @plyr-font-size-small;
font-weight: 500;
line-height: 1.3; line-height: 1.3;
transform: translate(-50%, 10px) scale(.8); transform: translate(-50%, 10px) scale(.8);