mirror of
https://github.com/videojs/video.js.git
synced 2025-01-17 10:46:00 +02:00
Merge branch 'master' of git://github.com/zencoder/video-js
This commit is contained in:
commit
8c6138797a
6
.gitignore
vendored
6
.gitignore
vendored
@ -8,5 +8,11 @@ test/*.map
|
||||
|
||||
node_modules
|
||||
npm-debug.log
|
||||
|
||||
sandbox/*
|
||||
!sandbox/*.example
|
||||
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
*.orig
|
||||
|
@ -45,10 +45,22 @@ body.vjs-full-window {
|
||||
|
||||
/* Poster Styles */
|
||||
.vjs-poster {
|
||||
margin: 0 auto; padding: 0; cursor: pointer;
|
||||
|
||||
/* Scale with the size of the player div. Works when poster is vertically shorter, but stretches when it's less wide. */
|
||||
position: relative; width: 100%; max-height: 100%;
|
||||
background-repeat: no-repeat;
|
||||
background-position: 50% 50%;
|
||||
background-size: contain;
|
||||
cursor: pointer;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
.vjs-poster img {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
max-height: 100%;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Text Track Styles */
|
||||
@ -330,7 +342,7 @@ so you can upgrade to newer versions easier. You can remove all these styles by
|
||||
---------------------------------------------------------*/
|
||||
.vjs-default-skin .vjs-big-play-button {
|
||||
display: block; /* Start hidden */ z-index: 2;
|
||||
position: absolute; top: 50%; left: 50%; width: 8.0em; height: 8.0em; margin: -42px 0 0 -42px; text-align: center; vertical-align: center; cursor: pointer !important;
|
||||
position: absolute; top: 50%; left: 50%; width: 8.0em; height: 8.0em; margin: -42px 0 0 -42px; text-align: center; vertical-align: middle; cursor: pointer !important;
|
||||
border: 0.2em solid #fff; opacity: 0.95;
|
||||
-webkit-border-radius: 25px; -moz-border-radius: 25px; border-radius: 25px;
|
||||
|
||||
|
@ -23,7 +23,7 @@ vjs.Component = function(player, options, ready){
|
||||
|
||||
this.name_ = options['name'] || null;
|
||||
|
||||
// Create element if one wasn't provided in potions
|
||||
// Create element if one wasn't provided in options
|
||||
this.el_ = options['el'] || this.createEl();
|
||||
|
||||
this.children_ = [];
|
||||
@ -288,8 +288,8 @@ vjs.Component.prototype.addChild = function(child, options){
|
||||
|
||||
// Add the UI object's element to the container div (box)
|
||||
// Having an element is not required
|
||||
if (typeof component.el === 'function' && component.el()) {
|
||||
this.el_.appendChild(component.el());
|
||||
if (typeof component['el'] === 'function' && component['el']()) {
|
||||
this.el_.appendChild(component['el']());
|
||||
}
|
||||
|
||||
// Return so it can stored on parent object if desired.
|
||||
@ -618,6 +618,8 @@ vjs.Component.prototype.dimension = function(widthOrHeight, num, skipListeners){
|
||||
// Check if using css width/height (% or px) and adjust
|
||||
if ((''+num).indexOf('%') !== -1 || (''+num).indexOf('px') !== -1) {
|
||||
this.el_.style[widthOrHeight] = num;
|
||||
} else if (num === 'auto') {
|
||||
this.el_.style[widthOrHeight] = '';
|
||||
} else {
|
||||
this.el_.style[widthOrHeight] = num+'px';
|
||||
}
|
||||
|
49
src/js/controls.js
vendored
49
src/js/controls.js
vendored
@ -786,6 +786,18 @@ vjs.SeekHandle.prototype.createEl = function(){
|
||||
*/
|
||||
vjs.VolumeControl = function(player, options){
|
||||
goog.base(this, player, options);
|
||||
|
||||
// hide volume controls when they're not supported by the current tech
|
||||
if (player.tech && player.tech.features.volumeControl === false) {
|
||||
this.hide();
|
||||
}
|
||||
player.on('loadstart', vjs.bind(this, function(){
|
||||
if (player.tech.features.volumeControl === false) {
|
||||
this.hide();
|
||||
} else {
|
||||
this.show();
|
||||
}
|
||||
}));
|
||||
};
|
||||
goog.inherits(vjs.VolumeControl, vjs.Component);
|
||||
|
||||
@ -903,6 +915,18 @@ vjs.MuteToggle = function(player, options){
|
||||
goog.base(this, player, options);
|
||||
|
||||
player.on('volumechange', vjs.bind(this, this.update));
|
||||
|
||||
// hide mute toggle if the current tech doesn't support volume control
|
||||
if (player.tech && player.tech.features.volumeControl === false) {
|
||||
this.hide();
|
||||
}
|
||||
player.on('loadstart', vjs.bind(this, function(){
|
||||
if (player.tech.features.volumeControl === false) {
|
||||
this.hide();
|
||||
} else {
|
||||
this.show();
|
||||
}
|
||||
}));
|
||||
};
|
||||
goog.inherits(vjs.MuteToggle, vjs.Button);
|
||||
|
||||
@ -969,17 +993,22 @@ vjs.PosterImage = function(player, options){
|
||||
goog.inherits(vjs.PosterImage, vjs.Button);
|
||||
|
||||
vjs.PosterImage.prototype.createEl = function(){
|
||||
var el = vjs.createEl('img', {
|
||||
className: 'vjs-poster',
|
||||
|
||||
// Don't want poster to be tabbable.
|
||||
tabIndex: -1
|
||||
});
|
||||
|
||||
// src throws errors if no poster was defined.
|
||||
if (this.player_.poster()) {
|
||||
el.src = this.player_.poster();
|
||||
var el = vjs.createEl('div', {
|
||||
className: 'vjs-poster',
|
||||
|
||||
// Don't want poster to be tabbable.
|
||||
tabIndex: -1
|
||||
}),
|
||||
poster = this.player_.poster();
|
||||
|
||||
if (poster) {
|
||||
if ('backgroundSize' in el.style) {
|
||||
el.style.backgroundImage = 'url("' + poster + '")';
|
||||
} else {
|
||||
el.appendChild(vjs.createEl('img', { src: poster }));
|
||||
}
|
||||
}
|
||||
|
||||
return el;
|
||||
};
|
||||
|
||||
|
@ -75,7 +75,6 @@ vjs.options = {
|
||||
// Default of web browser is 300x150. Should rely on source width/height.
|
||||
'width': 300,
|
||||
'height': 150,
|
||||
|
||||
// defaultVolume: 0.85,
|
||||
'defaultVolume': 0.00, // The freakin seaguls are driving me crazy!
|
||||
|
||||
|
@ -269,8 +269,8 @@ vjs.USER_AGENT = navigator.userAgent;
|
||||
* @type {Boolean}
|
||||
* @constant
|
||||
*/
|
||||
vjs.IS_IPHONE = !!vjs.USER_AGENT.match(/iPad/i);
|
||||
vjs.IS_IPAD = !!vjs.USER_AGENT.match(/iPhone/i);
|
||||
vjs.IS_IPHONE = !!vjs.USER_AGENT.match(/iPhone/i);
|
||||
vjs.IS_IPAD = !!vjs.USER_AGENT.match(/iPad/i);
|
||||
vjs.IS_IPOD = !!vjs.USER_AGENT.match(/iPod/i);
|
||||
vjs.IS_IOS = vjs.IS_IPHONE || vjs.IS_IPAD || vjs.IS_IPOD;
|
||||
|
||||
|
@ -68,6 +68,9 @@ vjs.Html5.prototype.createEl = function(){
|
||||
className:'vjs-tech'
|
||||
});
|
||||
}
|
||||
// associate the player with the new tag
|
||||
el['player'] = player;
|
||||
|
||||
vjs.insertFirst(el, player.el());
|
||||
}
|
||||
|
||||
@ -204,6 +207,12 @@ vjs.Html5.canPlaySource = function(srcObj){
|
||||
// Check Media Type
|
||||
};
|
||||
|
||||
vjs.Html5.canControlVolume = function(){
|
||||
var volume = vjs.TEST_VID.volume;
|
||||
vjs.TEST_VID.volume = (volume / 2) + 0.1;
|
||||
return volume !== vjs.TEST_VID.volume;
|
||||
};
|
||||
|
||||
// List of all HTML5 events (various uses).
|
||||
vjs.Html5.Events = 'loadstart,suspend,abort,error,emptied,stalled,loadedmetadata,loadeddata,canplay,canplaythrough,playing,waiting,seeking,seeked,ended,durationchange,timeupdate,progress,play,pause,ratechange,volumechange'.split(',');
|
||||
|
||||
@ -221,8 +230,10 @@ vjs.Html5.prototype.features = {
|
||||
: false,
|
||||
|
||||
// In iOS, if you move a video element in the DOM, it breaks video playback.
|
||||
movingMediaElementInDOM: !vjs.IS_IOS
|
||||
movingMediaElementInDOM: !vjs.IS_IOS,
|
||||
|
||||
// volume cannot be changed from 1 on iOS
|
||||
volumeControl: vjs.Html5.canControlVolume()
|
||||
};
|
||||
|
||||
// Android
|
||||
|
@ -169,11 +169,11 @@ vjs.Player.prototype.createEl = function(){
|
||||
// Default state of video is paused
|
||||
this.addClass('vjs-paused');
|
||||
|
||||
// Make box use width/height of tag, or default 300x150
|
||||
// Make box use width/height of tag, or rely on default implementation
|
||||
// Enforce with CSS since width/height attrs don't work on divs
|
||||
this.width(this.options_['width'], true); // (true) Skip resize listener on load
|
||||
this.height(this.options_['height'], true);
|
||||
|
||||
|
||||
// Wrap video tag in div (el/box) container
|
||||
if (tag.parentNode) {
|
||||
tag.parentNode.insertBefore(el, tag);
|
||||
@ -220,7 +220,7 @@ vjs.Player.prototype.loadTech = function(techName, source){
|
||||
};
|
||||
|
||||
// Grab tech-specific options from player options and add source and parent element to use.
|
||||
var techOptions = vjs.obj.merge({ source: source, parentEl: this.el_ }, this.options_[techName.toLowerCase()]);
|
||||
var techOptions = vjs.obj.merge({ 'source': source, 'parentEl': this.el_ }, this.options_[techName.toLowerCase()]);
|
||||
|
||||
if (source) {
|
||||
if (source.src == this.cache_.src && this.cache_.currentTime > 0) {
|
||||
|
@ -26,6 +26,7 @@
|
||||
'test/unit/player.js',
|
||||
'test/unit/core.js',
|
||||
'test/unit/media.html5.js',
|
||||
'test/unit/controls.js',
|
||||
'test/unit/plugins.js'
|
||||
];
|
||||
var compiledTests = "build/files/test.minified.video.js";
|
||||
|
@ -184,4 +184,9 @@ test('should change the width and height of a component', function(){
|
||||
|
||||
comp.width(321);
|
||||
ok(comp.width() === 321, 'integer values working');
|
||||
|
||||
comp.width('auto');
|
||||
comp.height('auto');
|
||||
ok(comp.width() === 1000, 'forced width was removed');
|
||||
ok(comp.height() === 0, 'forced height was removed');
|
||||
});
|
||||
|
78
test/unit/controls.js
vendored
Normal file
78
test/unit/controls.js
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
module('Controls');
|
||||
|
||||
test('should hide volume control if it\'s not supported', function() {
|
||||
var noop, player, volumeControl, muteToggle;
|
||||
noop = function(){};
|
||||
player = {
|
||||
id: noop,
|
||||
on: noop,
|
||||
ready: noop,
|
||||
tech: {
|
||||
features: {
|
||||
volumeControl: false
|
||||
}
|
||||
}
|
||||
};
|
||||
volumeControl = new vjs.VolumeControl(player);
|
||||
muteToggle = new vjs.MuteToggle(player);
|
||||
|
||||
equal(volumeControl.el().style.display, 'none', 'volumeControl is not hidden');
|
||||
equal(muteToggle.el().style.display, 'none', 'muteToggle is not hidden');
|
||||
});
|
||||
|
||||
test('should test and toggle volume control on `loadstart`', function(){
|
||||
var noop, listeners, player, volumeControl, muteToggle;
|
||||
noop = function(){};
|
||||
listeners = [];
|
||||
player = {
|
||||
id: noop,
|
||||
on: function(event, callback){
|
||||
listeners.push(callback);
|
||||
},
|
||||
ready: noop,
|
||||
volume: function(){
|
||||
return 1;
|
||||
},
|
||||
muted: function(){
|
||||
return false;
|
||||
},
|
||||
tech: {
|
||||
features: {
|
||||
volumeControl: true
|
||||
}
|
||||
}
|
||||
};
|
||||
volumeControl = new vjs.VolumeControl(player);
|
||||
muteToggle = new vjs.MuteToggle(player);
|
||||
|
||||
equal(volumeControl.el().style.display,
|
||||
'',
|
||||
'volumeControl is hidden initially');
|
||||
equal(muteToggle.el().style.display,
|
||||
'',
|
||||
'muteToggle is hidden initially');
|
||||
|
||||
player.tech.features.volumeControl = false;
|
||||
listeners.forEach(function(listener) {
|
||||
listener();
|
||||
});
|
||||
|
||||
equal(volumeControl.el().style.display,
|
||||
'none',
|
||||
'volumeControl does not hide itself');
|
||||
equal(muteToggle.el().style.display,
|
||||
'none',
|
||||
'muteToggle does not hide itself');
|
||||
|
||||
player.tech.features.volumeControl = true;
|
||||
listeners.forEach(function(listener) {
|
||||
listener();
|
||||
});
|
||||
|
||||
equal(volumeControl.el().style.display,
|
||||
'block',
|
||||
'volumeControl does not show itself');
|
||||
equal(muteToggle.el().style.display,
|
||||
'block',
|
||||
'muteToggle does not show itself');
|
||||
});
|
@ -1 +1,37 @@
|
||||
module('HTML5');
|
||||
|
||||
test('should detect whether the volume can be changed', function(){
|
||||
var testVid, ConstVolumeVideo;
|
||||
if (!{}['__defineSetter__']) {
|
||||
ok(true, 'your browser does not support this test, skipping it');
|
||||
return;
|
||||
}
|
||||
testVid = vjs.TEST_VID;
|
||||
ConstVolumeVideo = function(){
|
||||
this.volume = 1;
|
||||
this.__defineSetter__('volume', function(){});
|
||||
};
|
||||
vjs.TEST_VID = new ConstVolumeVideo();
|
||||
|
||||
ok(!vjs.Html5.canControlVolume());
|
||||
vjs.TEST_VID = testVid;
|
||||
});
|
||||
|
||||
test('should re-link the player if the tech is moved', function(){
|
||||
var player, tech, el;
|
||||
el = document.createElement('div');
|
||||
el.innerHTML = '<div />';
|
||||
player = {
|
||||
id: function(){ return 'id'; },
|
||||
el: function(){ return el; },
|
||||
options_: {},
|
||||
ready: function(){}
|
||||
};
|
||||
tech = new vjs.Html5(player, {});
|
||||
tech.features = {
|
||||
movingMediaElementInDOM: false
|
||||
};
|
||||
tech.createEl();
|
||||
|
||||
strictEqual(player, tech.el()['player']);
|
||||
});
|
@ -155,6 +155,14 @@ test('should set the width and height of the player', function(){
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
test('should not force width and height', function() {
|
||||
var player = PlayerTest.makePlayer({ width: 'auto', height: 'auto' });
|
||||
ok(player.el().style.width === '', 'Width is not forced');
|
||||
ok(player.el().style.height === '', 'Height is not forced');
|
||||
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
test('should accept options from multiple sources and override in correct order', function(){
|
||||
var tag = PlayerTest.makeTag();
|
||||
var container = document.createElement('div');
|
||||
|
Loading…
Reference in New Issue
Block a user