mirror of
https://github.com/videojs/video.js.git
synced 2024-11-28 08:58:46 +02:00
@heff updated the poster to use CSS styles to display; fixed the poster not showing if not originally set. closes #1568
This commit is contained in:
parent
a6019d4207
commit
af02d158da
@ -25,6 +25,7 @@
|
||||
"process",
|
||||
|
||||
"PlayerTest",
|
||||
"TestHelpers",
|
||||
"asyncTest",
|
||||
"deepEqual",
|
||||
"equal",
|
||||
|
@ -7,6 +7,7 @@ CHANGELOG
|
||||
* @OlehTsvirko added a Ukrainian translation ([view](https://github.com/videojs/video.js/pull/1562))
|
||||
* @OlehTsvirko added a Russian translation ([view](https://github.com/videojs/video.js/pull/1563))
|
||||
* @thijstriemstra added a Dutch translation ([view](https://github.com/videojs/video.js/pull/1566))
|
||||
* @heff updated the poster to use CSS styles to display; fixed the poster not showing if not originally set ([view](https://github.com/videojs/video.js/pull/1568))
|
||||
|
||||
--------------------
|
||||
|
||||
|
@ -936,6 +936,22 @@ body.vjs-full-window {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Hide the poster after the video has started playing */
|
||||
.video-js.vjs-has-started .vjs-poster {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Don't hide the poster if we're playing audio */
|
||||
.video-js.vjs-audio.vjs-has-started .vjs-poster {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Hide the poster when controls are disabled because it's clickable
|
||||
and the native poster can take over */
|
||||
.video-js.vjs-controls-disabled .vjs-poster {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Hide the poster when native controls are used otherwise it covers them */
|
||||
.video-js.vjs-using-native-controls .vjs-poster {
|
||||
display: none;
|
||||
|
@ -47,8 +47,14 @@ vjs.Component = vjs.CoreObject.extend({
|
||||
// Updated options with supplied options
|
||||
options = this.options(options);
|
||||
|
||||
// Get ID from options, element, or create using player ID and unique ID
|
||||
this.id_ = options['id'] || ((options['el'] && options['el']['id']) ? options['el']['id'] : player.id() + '_component_' + vjs.guid++ );
|
||||
// Get ID from options or options element if one is supplied
|
||||
this.id_ = options['id'] || (options['el'] && options['el']['id']);
|
||||
|
||||
// If there was no ID from the options, generate one
|
||||
if (!this.id_) {
|
||||
// Don't require the player ID function in the case of mock players
|
||||
this.id_ = ((player.id && player.id()) || 'no_player') + '_component_' + vjs.guid++;
|
||||
}
|
||||
|
||||
this.name_ = options['name'] || null;
|
||||
|
||||
@ -976,6 +982,11 @@ vjs.Component.prototype.emitTapEvents = function(){
|
||||
vjs.Component.prototype.enableTouchActivity = function() {
|
||||
var report, touchHolding, touchEnd;
|
||||
|
||||
// Don't continue if the root player doesn't support reporting user activity
|
||||
if (!this.player().reportUserActivity) {
|
||||
return;
|
||||
}
|
||||
|
||||
// listener for reporting that the user is active
|
||||
report = vjs.bind(this.player(), this.player().reportUserActivity);
|
||||
|
||||
|
@ -412,6 +412,7 @@ vjs.IS_FIREFOX = (/Firefox/i).test(vjs.USER_AGENT);
|
||||
vjs.IS_CHROME = (/Chrome/i).test(vjs.USER_AGENT);
|
||||
|
||||
vjs.TOUCH_ENABLED = !!(('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch);
|
||||
vjs.BACKGROUND_SIZE_SUPPORTED = 'backgroundSize' in vjs.TEST_VID.style;
|
||||
|
||||
/**
|
||||
* Apply attributes to an HTML element.
|
||||
|
@ -55,9 +55,10 @@ vjs.Player = vjs.Component.extend({
|
||||
this.cache_ = {};
|
||||
|
||||
// Set poster
|
||||
this.poster_ = options['poster'];
|
||||
this.poster_ = options['poster'] || '';
|
||||
|
||||
// Set controls
|
||||
this.controls_ = options['controls'];
|
||||
this.controls_ = !!options['controls'];
|
||||
// Original tag settings stored in options
|
||||
// now remove immediately so native controls don't flash.
|
||||
// May be turned back on by HTML5 tech if nativeControlsForTouch is true
|
||||
@ -1284,6 +1285,12 @@ vjs.Player.prototype.poster = function(src){
|
||||
return this.poster_;
|
||||
}
|
||||
|
||||
// The correct way to remove a poster is to set as an empty string
|
||||
// other falsey values will throw errors
|
||||
if (!src) {
|
||||
src = '';
|
||||
}
|
||||
|
||||
// update the internal poster variable
|
||||
this.poster_ = src;
|
||||
|
||||
|
101
src/js/poster.js
101
src/js/poster.js
@ -12,27 +12,23 @@ vjs.PosterImage = vjs.Button.extend({
|
||||
init: function(player, options){
|
||||
vjs.Button.call(this, player, options);
|
||||
|
||||
if (player.poster()) {
|
||||
this.src(player.poster());
|
||||
}
|
||||
|
||||
if (!player.poster() || !player.controls()) {
|
||||
this.hide();
|
||||
}
|
||||
|
||||
player.on('posterchange', vjs.bind(this, function(){
|
||||
this.src(player.poster());
|
||||
}));
|
||||
|
||||
if (!player.isAudio()) {
|
||||
player.on('play', vjs.bind(this, this.hide));
|
||||
}
|
||||
this.update();
|
||||
player.on('posterchange', vjs.bind(this, this.update));
|
||||
}
|
||||
});
|
||||
|
||||
// use the test el to check for backgroundSize style support
|
||||
var _backgroundSizeSupported = 'backgroundSize' in vjs.TEST_VID.style;
|
||||
/**
|
||||
* Clean up the poster image
|
||||
*/
|
||||
vjs.PosterImage.prototype.dispose = function(){
|
||||
this.player().off('posterchange', this.update);
|
||||
vjs.Button.prototype.dispose.call(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create the poster image element
|
||||
* @return {Element}
|
||||
*/
|
||||
vjs.PosterImage.prototype.createEl = function(){
|
||||
var el = vjs.createEl('div', {
|
||||
className: 'vjs-poster',
|
||||
@ -41,40 +37,63 @@ vjs.PosterImage.prototype.createEl = function(){
|
||||
tabIndex: -1
|
||||
});
|
||||
|
||||
if (!_backgroundSizeSupported) {
|
||||
// setup an img element as a fallback for IE8
|
||||
el.appendChild(vjs.createEl('img'));
|
||||
// To ensure the poster image resizes while maintaining its original aspect
|
||||
// ratio, use a div with `background-size` when available. For browsers that
|
||||
// do not support `background-size` (e.g. IE8), fall back on using a regular
|
||||
// img element.
|
||||
if (!vjs.BACKGROUND_SIZE_SUPPORTED) {
|
||||
this.fallbackImg_ = vjs.createEl('img');
|
||||
el.appendChild(this.fallbackImg_);
|
||||
}
|
||||
|
||||
return el;
|
||||
};
|
||||
|
||||
vjs.PosterImage.prototype.src = function(url){
|
||||
var el = this.el();
|
||||
/**
|
||||
* Event handler for updates to the player's poster source
|
||||
*/
|
||||
vjs.PosterImage.prototype.update = function(){
|
||||
var url = this.player().poster();
|
||||
|
||||
// getter
|
||||
// can't think of a need for a getter here
|
||||
// see #838 if on is needed in the future
|
||||
// still don't want a getter to set src as undefined
|
||||
if (url === undefined) {
|
||||
return;
|
||||
}
|
||||
this.setSrc(url);
|
||||
|
||||
// setter
|
||||
// To ensure the poster image resizes while maintaining its original aspect
|
||||
// ratio, use a div with `background-size` when available. For browsers that
|
||||
// do not support `background-size` (e.g. IE8), fall back on using a regular
|
||||
// img element.
|
||||
if (_backgroundSizeSupported) {
|
||||
el.style.backgroundImage = 'url("' + url + '")';
|
||||
// If there's no poster source we should display:none on this component
|
||||
// so it's not still clickable or right-clickable
|
||||
if (url) {
|
||||
// Remove the display style property that hide() adds
|
||||
// as opposed to show() which sets display to block
|
||||
// In the future it might be worth creating an `unhide` component method
|
||||
this.el_.style.display = '';
|
||||
} else {
|
||||
el.firstChild.src = url;
|
||||
this.hide();
|
||||
}
|
||||
};
|
||||
|
||||
vjs.PosterImage.prototype.onClick = function(){
|
||||
// Only accept clicks when controls are enabled
|
||||
if (this.player().controls()) {
|
||||
this.player_.play();
|
||||
/**
|
||||
* Set the poster source depending on the display method
|
||||
*/
|
||||
vjs.PosterImage.prototype.setSrc = function(url){
|
||||
var backgroundImage;
|
||||
|
||||
if (this.fallbackImg_) {
|
||||
this.fallbackImg_.src = url;
|
||||
} else {
|
||||
backgroundImage = '';
|
||||
// Any falsey values should stay as an empty string, otherwise
|
||||
// this will throw an extra error
|
||||
if (url) {
|
||||
backgroundImage = 'url("' + url + '")';
|
||||
}
|
||||
|
||||
this.el_.style.backgroundImage = backgroundImage;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Event handler for clicks on the poster image
|
||||
*/
|
||||
vjs.PosterImage.prototype.onClick = function(){
|
||||
// We don't want a click to trigger playback when controls are disabled
|
||||
// but CSS should be hiding the poster to prevent that from happening
|
||||
this.player_.play();
|
||||
};
|
||||
|
@ -3,6 +3,9 @@
|
||||
<head>
|
||||
<title>Video.js Test Suite</title>
|
||||
|
||||
<!-- Video.js CSS -->
|
||||
<link rel="stylesheet" href="../build/files/video-js.css" type="text/css">
|
||||
|
||||
<!-- Sinon -->
|
||||
<script src="../node_modules/sinon/pkg/sinon.js"></script>
|
||||
<script src="../node_modules/sinon/pkg/sinon-ie.js"></script>
|
||||
@ -11,9 +14,6 @@
|
||||
<link rel="stylesheet" href="../node_modules/qunitjs/qunit/qunit.css" />
|
||||
<script src="../node_modules/qunitjs/qunit/qunit.js"></script>
|
||||
|
||||
<!-- Video.js CSS -->
|
||||
<link rel="stylesheet" href="../build/files/video-js.css" type="text/css">
|
||||
|
||||
<script type="text/javascript">
|
||||
(function(){
|
||||
|
||||
|
@ -59,6 +59,7 @@ module.exports = function(config) {
|
||||
customLaunchers: customLaunchers,
|
||||
|
||||
files: [
|
||||
'../build/files/video-js.css',
|
||||
'../test/karma-qunit-shim.js',
|
||||
"../src/js/core.js",
|
||||
"../src/js/core-object.js",
|
||||
|
@ -7,6 +7,7 @@ module.exports = function(config) {
|
||||
singleRun: true,
|
||||
|
||||
files: [
|
||||
'../build/files/video-js.min.css',
|
||||
'../test/karma-qunit-shim.js',
|
||||
'../node_modules/sinon/pkg/sinon.js',
|
||||
'../build/files/minified.video.js',
|
||||
|
@ -7,6 +7,7 @@ module.exports = function(config) {
|
||||
singleRun: true,
|
||||
|
||||
files: [
|
||||
'../build/files/video-js.min.css',
|
||||
'../test/karma-qunit-shim.js',
|
||||
'../node_modules/sinon/pkg/sinon.js',
|
||||
'../build/files/test.minified.video.js'
|
||||
|
@ -3,6 +3,9 @@
|
||||
<head>
|
||||
<title>Video.js Test Suite</title>
|
||||
|
||||
<!-- Video.js CSS -->
|
||||
<link rel="stylesheet" href="../build/files/video-js.css" type="text/css">
|
||||
|
||||
<!-- Sinon -->
|
||||
<script src="../node_modules/sinon/pkg/sinon.js"></script>
|
||||
<script src="../node_modules/sinon/pkg/sinon-ie.js"></script>
|
||||
@ -11,9 +14,6 @@
|
||||
<link rel="stylesheet" href="../node_modules/qunitjs/qunit/qunit.css" />
|
||||
<script src="../node_modules/qunitjs/qunit/qunit.js"></script>
|
||||
|
||||
<!-- Video.js CSS -->
|
||||
<link rel="stylesheet" href="../build/files/video-js.css" type="text/css">
|
||||
|
||||
<!-- SOURCE COMPILED WITH TESTS
|
||||
grunt-contrib-qunit doesn't support query vars, so making this script
|
||||
so we can automatically run compiled tests too.
|
||||
|
@ -1,49 +1,91 @@
|
||||
module('PosterImage');
|
||||
module('PosterImage', {
|
||||
'setup': function(){
|
||||
// Store the original background support so we can test different vals
|
||||
this.origVal = vjs.BACKGROUND_SIZE_SUPPORTED;
|
||||
this.poster1 = 'http://example.com/poster.jpg';
|
||||
this.poster2 = 'http://example.com/UPDATED.jpg';
|
||||
|
||||
test('should update the poster source', function(){
|
||||
var player, posterImage, posterEl, poster1, poster2;
|
||||
|
||||
poster1 = 'http://example.com/poster.jpg';
|
||||
poster2 = 'http://example.com/UPDATED.jpg';
|
||||
|
||||
player = PlayerTest.makePlayer({ poster: poster1 });
|
||||
|
||||
posterImage = new vjs.PosterImage(player);
|
||||
posterEl = posterImage.el();
|
||||
|
||||
// check alternative methods for displaying the poster
|
||||
function checkPosterSource(src) {
|
||||
var modern, oldIE;
|
||||
|
||||
// in modern browsers we use backgroundImage to display the poster
|
||||
modern = posterEl.style.backgroundImage.toString().indexOf(src) !== -1;
|
||||
// otherwise we create an image elemement
|
||||
oldIE = posterEl.firstChild && posterEl.firstChild.src === src;
|
||||
|
||||
if (modern || oldIE) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
// Create a mock player object that responds as a player would
|
||||
this.mockPlayer = {
|
||||
poster_: this.poster1,
|
||||
poster: function(){
|
||||
return this.poster_;
|
||||
},
|
||||
handler_: null,
|
||||
on: function(type, handler){
|
||||
this.handler_ = handler;
|
||||
},
|
||||
trigger: function(type){
|
||||
this.handler_.call();
|
||||
}
|
||||
};
|
||||
},
|
||||
'teardown': function(){
|
||||
vjs.BACKGROUND_SIZE_SUPPORTED = this.origVal;
|
||||
}
|
||||
|
||||
ok(checkPosterSource(poster1), 'displays the correct poster');
|
||||
|
||||
posterImage.src(poster2);
|
||||
ok(checkPosterSource(poster2), 'displays the correct poster after updating');
|
||||
|
||||
posterImage.src();
|
||||
ok(checkPosterSource(poster2), 'doesnt change poster when attempting a get');
|
||||
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
test('should not hide the poster if audio track is used', function() {
|
||||
var audio = document.createElement('audio'),
|
||||
poster = 'http://example.com/poster.jpg',
|
||||
player = PlayerTest.makePlayer({ 'poster': poster, 'controls': true }, audio),
|
||||
posterImage = new vjs.PosterImage(player),
|
||||
posterEl = posterImage.el();
|
||||
test('should create and update a poster image', function(){
|
||||
var posterImage;
|
||||
|
||||
player.trigger('play');
|
||||
equal(posterEl.style.display, '', 'poster image is not hidden when audio track is used');
|
||||
vjs.BACKGROUND_SIZE_SUPPORTED = true;
|
||||
posterImage = new vjs.PosterImage(this.mockPlayer);
|
||||
equal(posterImage.el().style.backgroundImage, 'url('+this.poster1+')', 'Background image used');
|
||||
|
||||
// Update with a new poster source and check the new value
|
||||
this.mockPlayer.poster_ = this.poster2;
|
||||
this.mockPlayer.trigger('posterchange');
|
||||
equal(posterImage.el().style.backgroundImage, 'url('+this.poster2+')', 'Background image updated');
|
||||
});
|
||||
|
||||
test('should create and update a fallback image in older browsers', function(){
|
||||
var posterImage;
|
||||
|
||||
vjs.BACKGROUND_SIZE_SUPPORTED = false;
|
||||
posterImage = new vjs.PosterImage(this.mockPlayer);
|
||||
equal(posterImage.fallbackImg_.src, this.poster1, 'Fallback image created');
|
||||
|
||||
// Update with a new poster source and check the new value
|
||||
this.mockPlayer.poster_ = this.poster2;
|
||||
this.mockPlayer.trigger('posterchange');
|
||||
equal(posterImage.fallbackImg_.src, this.poster2, 'Fallback image updated');
|
||||
});
|
||||
|
||||
test('should remove itself from the document flow when there is no poster', function(){
|
||||
var posterImage;
|
||||
|
||||
posterImage = new vjs.PosterImage(this.mockPlayer);
|
||||
equal(posterImage.el().style.display, '', 'Poster image shows by default');
|
||||
|
||||
// Update with an empty string
|
||||
this.mockPlayer.poster_ = '';
|
||||
this.mockPlayer.trigger('posterchange');
|
||||
equal(posterImage.el().style.display, 'none', 'Poster image hides with an empty source');
|
||||
|
||||
// Updated with a valid source
|
||||
this.mockPlayer.poster_ = this.poster2;
|
||||
this.mockPlayer.trigger('posterchange');
|
||||
equal(posterImage.el().style.display, '', 'Poster image shows again when there is a source');
|
||||
});
|
||||
|
||||
test('should hide the poster in the appropriate player states', function(){
|
||||
var posterImage = new vjs.PosterImage(this.mockPlayer);
|
||||
var playerDiv = document.createElement('div');
|
||||
var fixture = document.getElementById('qunit-fixture');
|
||||
var el = posterImage.el();
|
||||
|
||||
// Remove the source so when we add to the DOM it doesn't throw an error
|
||||
// We want to poster to still think it has a real source so it doesn't hide itself
|
||||
posterImage.setSrc('');
|
||||
|
||||
// Add the elements to the DOM so styles are computed
|
||||
playerDiv.appendChild(el);
|
||||
fixture.appendChild(playerDiv);
|
||||
|
||||
playerDiv.className = 'video-js vjs-has-started';
|
||||
equal(TestHelpers.getComputedStyle(el, 'display'), 'none', 'The poster hides when the video has started');
|
||||
|
||||
playerDiv.className = 'video-js vjs-has-started vjs-audio';
|
||||
equal(TestHelpers.getComputedStyle(el, 'display'), 'block', 'The poster continues to show when playing audio');
|
||||
});
|
||||
|
||||
|
@ -19,3 +19,18 @@ var PlayerTest = {
|
||||
return player = new videojs.Player(videoTag, playerOptions);
|
||||
}
|
||||
};
|
||||
|
||||
var TestHelpers = {
|
||||
getComputedStyle: function(el, rule){
|
||||
var val;
|
||||
|
||||
if(window.getComputedStyle){
|
||||
val = window.getComputedStyle(el, null).getPropertyValue(rule);
|
||||
// IE8
|
||||
} else if(el.currentStyle){
|
||||
val = el.currentStyle[rule];
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user