mirror of
https://github.com/videojs/video.js.git
synced 2024-11-24 08:42:25 +02:00
Broke up controls.js into multiple files.
Cleaned up media.js files also.
This commit is contained in:
parent
997b327fcd
commit
05ab972a1a
@ -35,12 +35,12 @@ module.exports = function(grunt) {
|
||||
minify: {
|
||||
source:{
|
||||
src: ['build/files/combined.video.js', 'build/compiler/goog.base.js', 'src/js/exports.js'],
|
||||
externs: ['src/js/media.flash.externs.js'],
|
||||
externs: ['src/js/media/flash.externs.js'],
|
||||
dest: 'build/files/minified.video.js'
|
||||
},
|
||||
tests: {
|
||||
src: ['build/files/combined.video.js', 'build/compiler/goog.base.js', 'src/js/exports.js', 'test/unit/*.js', '!test/unit/api.js'],
|
||||
externs: ['src/js/media.flash.externs.js', 'test/qunit/qunit-externs.js'],
|
||||
externs: ['src/js/media/flash.externs.js', 'test/qunit/qunit-externs.js'],
|
||||
dest: 'build/files/test.minified.video.js'
|
||||
}
|
||||
},
|
||||
|
@ -24,14 +24,21 @@ var sourceFiles = [
|
||||
"src/js/slider.js",
|
||||
"src/js/menu.js",
|
||||
"src/js/player.js",
|
||||
"src/js/controls.js",
|
||||
"src/js/control-bar/control-bar.js",
|
||||
"src/js/control-bar/play-toggle.js",
|
||||
"src/js/control-bar/time-display.js",
|
||||
"src/js/control-bar/fullscreen-toggle.js",
|
||||
"src/js/control-bar/progress-control.js",
|
||||
"src/js/control-bar/volume-control.js",
|
||||
"src/js/control-bar/mute-toggle.js",
|
||||
"src/js/control-bar/volume-menu-button.js",
|
||||
"src/js/poster.js",
|
||||
"src/js/loading-spinner.js",
|
||||
"src/js/big-play-button.js",
|
||||
"src/js/media.js",
|
||||
"src/js/media.html5.js",
|
||||
"src/js/media.flash.js",
|
||||
"src/js/media.loader.js",
|
||||
"src/js/media/media.js",
|
||||
"src/js/media/html5.js",
|
||||
"src/js/media/flash.js",
|
||||
"src/js/media/loader.js",
|
||||
"src/js/tracks.js",
|
||||
"src/js/json.js",
|
||||
"src/js/setup.js",
|
||||
|
87
src/js/control-bar/control-bar.js
Normal file
87
src/js/control-bar/control-bar.js
Normal file
@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Container of main controls
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.ControlBar = vjs.Component.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.Component.call(this, player, options);
|
||||
|
||||
if (!player.controls()) {
|
||||
this.disable();
|
||||
}
|
||||
|
||||
player.one('play', vjs.bind(this, function(){
|
||||
var touchstart,
|
||||
fadeIn = vjs.bind(this, this.fadeIn),
|
||||
fadeOut = vjs.bind(this, this.fadeOut);
|
||||
|
||||
this.fadeIn();
|
||||
|
||||
if ( !('ontouchstart' in window) ) {
|
||||
this.player_.on('mouseover', fadeIn);
|
||||
this.player_.on('mouseout', fadeOut);
|
||||
this.player_.on('pause', vjs.bind(this, this.lockShowing));
|
||||
this.player_.on('play', vjs.bind(this, this.unlockShowing));
|
||||
}
|
||||
|
||||
touchstart = false;
|
||||
this.player_.on('touchstart', function() {
|
||||
touchstart = true;
|
||||
});
|
||||
this.player_.on('touchmove', function() {
|
||||
touchstart = false;
|
||||
});
|
||||
this.player_.on('touchend', vjs.bind(this, function(event) {
|
||||
var idx;
|
||||
if (touchstart) {
|
||||
idx = this.el().className.search('fade-in');
|
||||
if (idx !== -1) {
|
||||
this.fadeOut();
|
||||
} else {
|
||||
this.fadeIn();
|
||||
}
|
||||
}
|
||||
touchstart = false;
|
||||
|
||||
if (!this.player_.paused()) {
|
||||
event.preventDefault();
|
||||
}
|
||||
}));
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
vjs.ControlBar.prototype.options_ = {
|
||||
loadEvent: 'play',
|
||||
children: {
|
||||
'playToggle': {},
|
||||
'currentTimeDisplay': {},
|
||||
'timeDivider': {},
|
||||
'durationDisplay': {},
|
||||
'remainingTimeDisplay': {},
|
||||
'progressControl': {},
|
||||
'fullscreenToggle': {},
|
||||
'volumeControl': {},
|
||||
'muteToggle': {}
|
||||
// 'volumeMenuButton': {}
|
||||
}
|
||||
};
|
||||
|
||||
vjs.ControlBar.prototype.createEl = function(){
|
||||
return vjs.createEl('div', {
|
||||
className: 'vjs-control-bar'
|
||||
});
|
||||
};
|
||||
|
||||
vjs.ControlBar.prototype.fadeIn = function(){
|
||||
vjs.Component.prototype.fadeIn.call(this);
|
||||
this.player_.trigger('controlsvisible');
|
||||
};
|
||||
|
||||
vjs.ControlBar.prototype.fadeOut = function(){
|
||||
vjs.Component.prototype.fadeOut.call(this);
|
||||
this.player_.trigger('controlshidden');
|
||||
};
|
28
src/js/control-bar/fullscreen-toggle.js
Normal file
28
src/js/control-bar/fullscreen-toggle.js
Normal file
@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Toggle fullscreen video
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.FullscreenToggle = vjs.Button.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.Button.call(this, player, options);
|
||||
}
|
||||
});
|
||||
|
||||
vjs.FullscreenToggle.prototype.buttonText = 'Fullscreen';
|
||||
|
||||
vjs.FullscreenToggle.prototype.buildCSSClass = function(){
|
||||
return 'vjs-fullscreen-control ' + vjs.Button.prototype.buildCSSClass.call(this);
|
||||
};
|
||||
|
||||
vjs.FullscreenToggle.prototype.onClick = function(){
|
||||
if (!this.player_.isFullScreen) {
|
||||
this.player_.requestFullScreen();
|
||||
this.el_.children[0].children[0].innerHTML = 'Non-Fullscreen'; // change the button text to "Non-Fullscreen"
|
||||
} else {
|
||||
this.player_.cancelFullScreen();
|
||||
this.el_.children[0].children[0].innerHTML = 'Fullscreen'; // change the button to "Fullscreen"
|
||||
}
|
||||
};
|
69
src/js/control-bar/mute-toggle.js
Normal file
69
src/js/control-bar/mute-toggle.js
Normal file
@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Mute the audio
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.MuteToggle = vjs.Button.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.Button.call(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 && player.tech.features.volumeControl === false) {
|
||||
this.addClass('vjs-hidden');
|
||||
}
|
||||
player.on('loadstart', vjs.bind(this, function(){
|
||||
if (player.tech.features && player.tech.features.volumeControl === false) {
|
||||
this.addClass('vjs-hidden');
|
||||
} else {
|
||||
this.removeClass('vjs-hidden');
|
||||
}
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
vjs.MuteToggle.prototype.createEl = function(){
|
||||
return vjs.Button.prototype.createEl.call(this, 'div', {
|
||||
className: 'vjs-mute-control vjs-control',
|
||||
innerHTML: '<div><span class="vjs-control-text">Mute</span></div>'
|
||||
});
|
||||
};
|
||||
|
||||
vjs.MuteToggle.prototype.onClick = function(){
|
||||
this.player_.muted( this.player_.muted() ? false : true );
|
||||
};
|
||||
|
||||
vjs.MuteToggle.prototype.update = function(){
|
||||
var vol = this.player_.volume(),
|
||||
level = 3;
|
||||
|
||||
if (vol === 0 || this.player_.muted()) {
|
||||
level = 0;
|
||||
} else if (vol < 0.33) {
|
||||
level = 1;
|
||||
} else if (vol < 0.67) {
|
||||
level = 2;
|
||||
}
|
||||
|
||||
// Don't rewrite the button text if the actual text doesn't change.
|
||||
// This causes unnecessary and confusing information for screen reader users.
|
||||
// This check is needed because this function gets called every time the volume level is changed.
|
||||
if(this.player_.muted()){
|
||||
if(this.el_.children[0].children[0].innerHTML!='Unmute'){
|
||||
this.el_.children[0].children[0].innerHTML = 'Unmute'; // change the button text to "Unmute"
|
||||
}
|
||||
} else {
|
||||
if(this.el_.children[0].children[0].innerHTML!='Mute'){
|
||||
this.el_.children[0].children[0].innerHTML = 'Mute'; // change the button text to "Mute"
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO improve muted icon classes */
|
||||
for (var i = 0; i < 4; i++) {
|
||||
vjs.removeClass(this.el_, 'vjs-vol-'+i);
|
||||
}
|
||||
vjs.addClass(this.el_, 'vjs-vol-'+level);
|
||||
};
|
44
src/js/control-bar/play-toggle.js
Normal file
44
src/js/control-bar/play-toggle.js
Normal file
@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Button to toggle between play and pause
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.PlayToggle = vjs.Button.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.Button.call(this, player, options);
|
||||
|
||||
player.on('play', vjs.bind(this, this.onPlay));
|
||||
player.on('pause', vjs.bind(this, this.onPause));
|
||||
}
|
||||
});
|
||||
|
||||
vjs.PlayToggle.prototype.buttonText = 'Play';
|
||||
|
||||
vjs.PlayToggle.prototype.buildCSSClass = function(){
|
||||
return 'vjs-play-control ' + vjs.Button.prototype.buildCSSClass.call(this);
|
||||
};
|
||||
|
||||
// OnClick - Toggle between play and pause
|
||||
vjs.PlayToggle.prototype.onClick = function(){
|
||||
if (this.player_.paused()) {
|
||||
this.player_.play();
|
||||
} else {
|
||||
this.player_.pause();
|
||||
}
|
||||
};
|
||||
|
||||
// OnPlay - Add the vjs-playing class to the element so it can change appearance
|
||||
vjs.PlayToggle.prototype.onPlay = function(){
|
||||
vjs.removeClass(this.el_, 'vjs-paused');
|
||||
vjs.addClass(this.el_, 'vjs-playing');
|
||||
this.el_.children[0].children[0].innerHTML = 'Pause'; // change the button text to "Pause"
|
||||
};
|
||||
|
||||
// OnPause - Add the vjs-paused class to the element so it can change appearance
|
||||
vjs.PlayToggle.prototype.onPause = function(){
|
||||
vjs.removeClass(this.el_, 'vjs-playing');
|
||||
vjs.addClass(this.el_, 'vjs-paused');
|
||||
this.el_.children[0].children[0].innerHTML = 'Play'; // change the button text to "Play"
|
||||
};
|
171
src/js/control-bar/progress-control.js
Normal file
171
src/js/control-bar/progress-control.js
Normal file
@ -0,0 +1,171 @@
|
||||
/**
|
||||
* Seek, Load Progress, and Play Progress
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.ProgressControl = vjs.Component.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.Component.call(this, player, options);
|
||||
}
|
||||
});
|
||||
|
||||
vjs.ProgressControl.prototype.options_ = {
|
||||
children: {
|
||||
'seekBar': {}
|
||||
}
|
||||
};
|
||||
|
||||
vjs.ProgressControl.prototype.createEl = function(){
|
||||
return vjs.Component.prototype.createEl.call(this, 'div', {
|
||||
className: 'vjs-progress-control vjs-control'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Seek Bar and holder for the progress bars
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.SeekBar = vjs.Slider.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.Slider.call(this, player, options);
|
||||
player.on('timeupdate', vjs.bind(this, this.updateARIAAttributes));
|
||||
player.ready(vjs.bind(this, this.updateARIAAttributes));
|
||||
}
|
||||
});
|
||||
|
||||
vjs.SeekBar.prototype.options_ = {
|
||||
children: {
|
||||
'loadProgressBar': {},
|
||||
'playProgressBar': {},
|
||||
'seekHandle': {}
|
||||
},
|
||||
'barName': 'playProgressBar',
|
||||
'handleName': 'seekHandle'
|
||||
};
|
||||
|
||||
vjs.SeekBar.prototype.playerEvent = 'timeupdate';
|
||||
|
||||
vjs.SeekBar.prototype.createEl = function(){
|
||||
return vjs.Slider.prototype.createEl.call(this, 'div', {
|
||||
className: 'vjs-progress-holder',
|
||||
'aria-label': 'video progress bar'
|
||||
});
|
||||
};
|
||||
|
||||
vjs.SeekBar.prototype.updateARIAAttributes = function(){
|
||||
// Allows for smooth scrubbing, when player can't keep up.
|
||||
var time = (this.player_.scrubbing) ? this.player_.getCache().currentTime : this.player_.currentTime();
|
||||
this.el_.setAttribute('aria-valuenow',vjs.round(this.getPercent()*100, 2)); // machine readable value of progress bar (percentage complete)
|
||||
this.el_.setAttribute('aria-valuetext',vjs.formatTime(time, this.player_.duration())); // human readable value of progress bar (time complete)
|
||||
};
|
||||
|
||||
vjs.SeekBar.prototype.getPercent = function(){
|
||||
return this.player_.currentTime() / this.player_.duration();
|
||||
};
|
||||
|
||||
vjs.SeekBar.prototype.onMouseDown = function(event){
|
||||
vjs.Slider.prototype.onMouseDown.call(this, event);
|
||||
|
||||
this.player_.scrubbing = true;
|
||||
|
||||
this.videoWasPlaying = !this.player_.paused();
|
||||
this.player_.pause();
|
||||
};
|
||||
|
||||
vjs.SeekBar.prototype.onMouseMove = function(event){
|
||||
var newTime = this.calculateDistance(event) * this.player_.duration();
|
||||
|
||||
// Don't let video end while scrubbing.
|
||||
if (newTime == this.player_.duration()) { newTime = newTime - 0.1; }
|
||||
|
||||
// Set new time (tell player to seek to new time)
|
||||
this.player_.currentTime(newTime);
|
||||
};
|
||||
|
||||
vjs.SeekBar.prototype.onMouseUp = function(event){
|
||||
vjs.Slider.prototype.onMouseUp.call(this, event);
|
||||
|
||||
this.player_.scrubbing = false;
|
||||
if (this.videoWasPlaying) {
|
||||
this.player_.play();
|
||||
}
|
||||
};
|
||||
|
||||
vjs.SeekBar.prototype.stepForward = function(){
|
||||
this.player_.currentTime(this.player_.currentTime() + 5); // more quickly fast forward for keyboard-only users
|
||||
};
|
||||
|
||||
vjs.SeekBar.prototype.stepBack = function(){
|
||||
this.player_.currentTime(this.player_.currentTime() - 5); // more quickly rewind for keyboard-only users
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Shows load progres
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.LoadProgressBar = vjs.Component.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.Component.call(this, player, options);
|
||||
player.on('progress', vjs.bind(this, this.update));
|
||||
}
|
||||
});
|
||||
|
||||
vjs.LoadProgressBar.prototype.createEl = function(){
|
||||
return vjs.Component.prototype.createEl.call(this, 'div', {
|
||||
className: 'vjs-load-progress',
|
||||
innerHTML: '<span class="vjs-control-text">Loaded: 0%</span>'
|
||||
});
|
||||
};
|
||||
|
||||
vjs.LoadProgressBar.prototype.update = function(){
|
||||
if (this.el_.style) { this.el_.style.width = vjs.round(this.player_.bufferedPercent() * 100, 2) + '%'; }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Shows play progress
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.PlayProgressBar = vjs.Component.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.Component.call(this, player, options);
|
||||
}
|
||||
});
|
||||
|
||||
vjs.PlayProgressBar.prototype.createEl = function(){
|
||||
return vjs.Component.prototype.createEl.call(this, 'div', {
|
||||
className: 'vjs-play-progress',
|
||||
innerHTML: '<span class="vjs-control-text">Progress: 0%</span>'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* SeekBar component includes play progress bar, and seek handle
|
||||
* Needed so it can determine seek position based on handle position/size
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.SeekHandle = vjs.SliderHandle.extend();
|
||||
|
||||
/** @inheritDoc */
|
||||
vjs.SeekHandle.prototype.defaultValue = '00:00';
|
||||
|
||||
/** @inheritDoc */
|
||||
vjs.SeekHandle.prototype.createEl = function(){
|
||||
return vjs.SliderHandle.prototype.createEl.call(this, 'div', {
|
||||
className: 'vjs-seek-handle'
|
||||
});
|
||||
};
|
133
src/js/control-bar/time-display.js
Normal file
133
src/js/control-bar/time-display.js
Normal file
@ -0,0 +1,133 @@
|
||||
/**
|
||||
* Displays the current time
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.CurrentTimeDisplay = vjs.Component.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.Component.call(this, player, options);
|
||||
|
||||
player.on('timeupdate', vjs.bind(this, this.updateContent));
|
||||
}
|
||||
});
|
||||
|
||||
vjs.CurrentTimeDisplay.prototype.createEl = function(){
|
||||
var el = vjs.Component.prototype.createEl.call(this, 'div', {
|
||||
className: 'vjs-current-time vjs-time-controls vjs-control'
|
||||
});
|
||||
|
||||
this.content = vjs.createEl('div', {
|
||||
className: 'vjs-current-time-display',
|
||||
innerHTML: '<span class="vjs-control-text">Current Time </span>' + '0:00', // label the current time for screen reader users
|
||||
'aria-live': 'off' // tell screen readers not to automatically read the time as it changes
|
||||
});
|
||||
|
||||
el.appendChild(vjs.createEl('div').appendChild(this.content));
|
||||
return el;
|
||||
};
|
||||
|
||||
vjs.CurrentTimeDisplay.prototype.updateContent = function(){
|
||||
// Allows for smooth scrubbing, when player can't keep up.
|
||||
var time = (this.player_.scrubbing) ? this.player_.getCache().currentTime : this.player_.currentTime();
|
||||
this.content.innerHTML = '<span class="vjs-control-text">Current Time </span>' + vjs.formatTime(time, this.player_.duration());
|
||||
};
|
||||
|
||||
/**
|
||||
* Displays the duration
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.DurationDisplay = vjs.Component.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.Component.call(this, player, options);
|
||||
|
||||
player.on('timeupdate', vjs.bind(this, this.updateContent)); // this might need to be changes to 'durationchange' instead of 'timeupdate' eventually, however the durationchange event fires before this.player_.duration() is set, so the value cannot be written out using this method. Once the order of durationchange and this.player_.duration() being set is figured out, this can be updated.
|
||||
}
|
||||
});
|
||||
|
||||
vjs.DurationDisplay.prototype.createEl = function(){
|
||||
var el = vjs.Component.prototype.createEl.call(this, 'div', {
|
||||
className: 'vjs-duration vjs-time-controls vjs-control'
|
||||
});
|
||||
|
||||
this.content = vjs.createEl('div', {
|
||||
className: 'vjs-duration-display',
|
||||
innerHTML: '<span class="vjs-control-text">Duration Time </span>' + '0:00', // label the duration time for screen reader users
|
||||
'aria-live': 'off' // tell screen readers not to automatically read the time as it changes
|
||||
});
|
||||
|
||||
el.appendChild(vjs.createEl('div').appendChild(this.content));
|
||||
return el;
|
||||
};
|
||||
|
||||
vjs.DurationDisplay.prototype.updateContent = function(){
|
||||
if (this.player_.duration()) {
|
||||
this.content.innerHTML = '<span class="vjs-control-text">Duration Time </span>' + vjs.formatTime(this.player_.duration()); // label the duration time for screen reader users
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Time Separator (Not used in main skin, but still available, and could be used as a 'spare element')
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.TimeDivider = vjs.Component.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.Component.call(this, player, options);
|
||||
}
|
||||
});
|
||||
|
||||
vjs.TimeDivider.prototype.createEl = function(){
|
||||
return vjs.Component.prototype.createEl.call(this, 'div', {
|
||||
className: 'vjs-time-divider',
|
||||
innerHTML: '<div><span>/</span></div>'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Displays the time left in the video
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.RemainingTimeDisplay = vjs.Component.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.Component.call(this, player, options);
|
||||
|
||||
player.on('timeupdate', vjs.bind(this, this.updateContent));
|
||||
}
|
||||
});
|
||||
|
||||
vjs.RemainingTimeDisplay.prototype.createEl = function(){
|
||||
var el = vjs.Component.prototype.createEl.call(this, 'div', {
|
||||
className: 'vjs-remaining-time vjs-time-controls vjs-control'
|
||||
});
|
||||
|
||||
this.content = vjs.createEl('div', {
|
||||
className: 'vjs-remaining-time-display',
|
||||
innerHTML: '<span class="vjs-control-text">Remaining Time </span>' + '-0:00', // label the remaining time for screen reader users
|
||||
'aria-live': 'off' // tell screen readers not to automatically read the time as it changes
|
||||
});
|
||||
|
||||
el.appendChild(vjs.createEl('div').appendChild(this.content));
|
||||
return el;
|
||||
};
|
||||
|
||||
vjs.RemainingTimeDisplay.prototype.updateContent = function(){
|
||||
if (this.player_.duration()) {
|
||||
if (this.player_.duration()) {
|
||||
this.content.innerHTML = '<span class="vjs-control-text">Remaining Time </span>' + '-'+ vjs.formatTime(this.player_.remainingTime());
|
||||
}
|
||||
}
|
||||
|
||||
// Allows for smooth scrubbing, when player can't keep up.
|
||||
// var time = (this.player_.scrubbing) ? this.player_.getCache().currentTime : this.player_.currentTime();
|
||||
// this.content.innerHTML = vjs.formatTime(time, this.player_.duration());
|
||||
};
|
134
src/js/control-bar/volume-control.js
Normal file
134
src/js/control-bar/volume-control.js
Normal file
@ -0,0 +1,134 @@
|
||||
/**
|
||||
* Control the volume
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.VolumeControl = vjs.Component.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.Component.call(this, player, options);
|
||||
|
||||
// hide volume controls when they're not supported by the current tech
|
||||
if (player.tech && player.tech.features && player.tech.features.volumeControl === false) {
|
||||
this.addClass('vjs-hidden');
|
||||
}
|
||||
player.on('loadstart', vjs.bind(this, function(){
|
||||
if (player.tech.features && player.tech.features.volumeControl === false) {
|
||||
this.addClass('vjs-hidden');
|
||||
} else {
|
||||
this.removeClass('vjs-hidden');
|
||||
}
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
vjs.VolumeControl.prototype.options_ = {
|
||||
children: {
|
||||
'volumeBar': {}
|
||||
}
|
||||
};
|
||||
|
||||
vjs.VolumeControl.prototype.createEl = function(){
|
||||
return vjs.Component.prototype.createEl.call(this, 'div', {
|
||||
className: 'vjs-volume-control vjs-control'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Contains volume level
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.VolumeBar = vjs.Slider.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.Slider.call(this, player, options);
|
||||
player.on('volumechange', vjs.bind(this, this.updateARIAAttributes));
|
||||
player.ready(vjs.bind(this, this.updateARIAAttributes));
|
||||
setTimeout(vjs.bind(this, this.update), 0); // update when elements is in DOM
|
||||
}
|
||||
});
|
||||
|
||||
vjs.VolumeBar.prototype.updateARIAAttributes = function(){
|
||||
// Current value of volume bar as a percentage
|
||||
this.el_.setAttribute('aria-valuenow',vjs.round(this.player_.volume()*100, 2));
|
||||
this.el_.setAttribute('aria-valuetext',vjs.round(this.player_.volume()*100, 2)+'%');
|
||||
};
|
||||
|
||||
vjs.VolumeBar.prototype.options_ = {
|
||||
children: {
|
||||
'volumeLevel': {},
|
||||
'volumeHandle': {}
|
||||
},
|
||||
'barName': 'volumeLevel',
|
||||
'handleName': 'volumeHandle'
|
||||
};
|
||||
|
||||
vjs.VolumeBar.prototype.playerEvent = 'volumechange';
|
||||
|
||||
vjs.VolumeBar.prototype.createEl = function(){
|
||||
return vjs.Slider.prototype.createEl.call(this, 'div', {
|
||||
className: 'vjs-volume-bar',
|
||||
'aria-label': 'volume level'
|
||||
});
|
||||
};
|
||||
|
||||
vjs.VolumeBar.prototype.onMouseMove = function(event) {
|
||||
this.player_.volume(this.calculateDistance(event));
|
||||
};
|
||||
|
||||
vjs.VolumeBar.prototype.getPercent = function(){
|
||||
if (this.player_.muted()) {
|
||||
return 0;
|
||||
} else {
|
||||
return this.player_.volume();
|
||||
}
|
||||
};
|
||||
|
||||
vjs.VolumeBar.prototype.stepForward = function(){
|
||||
this.player_.volume(this.player_.volume() + 0.1);
|
||||
};
|
||||
|
||||
vjs.VolumeBar.prototype.stepBack = function(){
|
||||
this.player_.volume(this.player_.volume() - 0.1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows volume level
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.VolumeLevel = vjs.Component.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.Component.call(this, player, options);
|
||||
}
|
||||
});
|
||||
|
||||
vjs.VolumeLevel.prototype.createEl = function(){
|
||||
return vjs.Component.prototype.createEl.call(this, 'div', {
|
||||
className: 'vjs-volume-level',
|
||||
innerHTML: '<span class="vjs-control-text"></span>'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Change volume level
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.VolumeHandle = vjs.SliderHandle.extend();
|
||||
|
||||
/** @inheritDoc */
|
||||
vjs.VolumeHandle.prototype.defaultValue = '00:00';
|
||||
|
||||
/** @inheritDoc */
|
||||
vjs.VolumeHandle.prototype.createEl = function(){
|
||||
return vjs.SliderHandle.prototype.createEl.call(this, 'div', {
|
||||
className: 'vjs-volume-handle'
|
||||
});
|
||||
};
|
48
src/js/control-bar/volume-menu-button.js
Normal file
48
src/js/control-bar/volume-menu-button.js
Normal file
@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Menu button with a popup for showing the volume slider.
|
||||
* @constructor
|
||||
*/
|
||||
vjs.VolumeMenuButton = vjs.MenuButton.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.MenuButton.call(this, player, options);
|
||||
|
||||
// Same listeners as MuteToggle
|
||||
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 && player.tech.features.volumeControl === false) {
|
||||
this.addClass('vjs-hidden');
|
||||
}
|
||||
player.on('loadstart', vjs.bind(this, function(){
|
||||
if (player.tech.features && player.tech.features.volumeControl === false) {
|
||||
this.addClass('vjs-hidden');
|
||||
} else {
|
||||
this.removeClass('vjs-hidden');
|
||||
}
|
||||
}));
|
||||
this.addClass('vjs-menu-button');
|
||||
}
|
||||
});
|
||||
|
||||
vjs.VolumeMenuButton.prototype.createMenu = function(){
|
||||
var menu = new vjs.Menu(this.player_, {
|
||||
contentElType: 'div'
|
||||
});
|
||||
var vc = new vjs.VolumeBar(this.player_, vjs.obj.merge({vertical: true}, this.options_.volumeBar));
|
||||
menu.addChild(vc);
|
||||
return menu;
|
||||
};
|
||||
|
||||
vjs.VolumeMenuButton.prototype.onClick = function(){
|
||||
vjs.MuteToggle.prototype.onClick.call(this);
|
||||
vjs.MenuButton.prototype.onClick.call(this);
|
||||
};
|
||||
|
||||
vjs.VolumeMenuButton.prototype.createEl = function(){
|
||||
return vjs.Button.prototype.createEl.call(this, 'div', {
|
||||
className: 'vjs-volume-menu-button vjs-menu-button vjs-control',
|
||||
innerHTML: '<div><span class="vjs-control-text">Mute</span></div>'
|
||||
});
|
||||
};
|
||||
vjs.VolumeMenuButton.prototype.update = vjs.MuteToggle.prototype.update;
|
738
src/js/controls.js
vendored
738
src/js/controls.js
vendored
@ -1,738 +0,0 @@
|
||||
/**
|
||||
* @fileoverview Controls classes for Video.js buttons, sliders, etc.
|
||||
*/
|
||||
|
||||
/* Control Bar
|
||||
================================================================================ */
|
||||
/**
|
||||
* Container of main controls
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.ControlBar = vjs.Component.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.Component.call(this, player, options);
|
||||
|
||||
if (!player.controls()) {
|
||||
this.disable();
|
||||
}
|
||||
|
||||
player.one('play', vjs.bind(this, function(){
|
||||
var touchstart,
|
||||
fadeIn = vjs.bind(this, this.fadeIn),
|
||||
fadeOut = vjs.bind(this, this.fadeOut);
|
||||
|
||||
this.fadeIn();
|
||||
|
||||
if ( !('ontouchstart' in window) ) {
|
||||
this.player_.on('mouseover', fadeIn);
|
||||
this.player_.on('mouseout', fadeOut);
|
||||
this.player_.on('pause', vjs.bind(this, this.lockShowing));
|
||||
this.player_.on('play', vjs.bind(this, this.unlockShowing));
|
||||
}
|
||||
|
||||
touchstart = false;
|
||||
this.player_.on('touchstart', function() {
|
||||
touchstart = true;
|
||||
});
|
||||
this.player_.on('touchmove', function() {
|
||||
touchstart = false;
|
||||
});
|
||||
this.player_.on('touchend', vjs.bind(this, function(event) {
|
||||
var idx;
|
||||
if (touchstart) {
|
||||
idx = this.el().className.search('fade-in');
|
||||
if (idx !== -1) {
|
||||
this.fadeOut();
|
||||
} else {
|
||||
this.fadeIn();
|
||||
}
|
||||
}
|
||||
touchstart = false;
|
||||
|
||||
if (!this.player_.paused()) {
|
||||
event.preventDefault();
|
||||
}
|
||||
}));
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
vjs.ControlBar.prototype.options_ = {
|
||||
loadEvent: 'play',
|
||||
children: {
|
||||
'playToggle': {},
|
||||
'currentTimeDisplay': {},
|
||||
'timeDivider': {},
|
||||
'durationDisplay': {},
|
||||
'remainingTimeDisplay': {},
|
||||
'progressControl': {},
|
||||
'fullscreenToggle': {},
|
||||
'volumeControl': {},
|
||||
'muteToggle': {}
|
||||
// 'volumeMenuButton': {}
|
||||
}
|
||||
};
|
||||
|
||||
vjs.ControlBar.prototype.createEl = function(){
|
||||
return vjs.createEl('div', {
|
||||
className: 'vjs-control-bar'
|
||||
});
|
||||
};
|
||||
|
||||
vjs.ControlBar.prototype.fadeIn = function(){
|
||||
vjs.Component.prototype.fadeIn.call(this);
|
||||
this.player_.trigger('controlsvisible');
|
||||
};
|
||||
|
||||
vjs.ControlBar.prototype.fadeOut = function(){
|
||||
vjs.Component.prototype.fadeOut.call(this);
|
||||
this.player_.trigger('controlshidden');
|
||||
};
|
||||
|
||||
/* Play Toggle - Play or Pause Media
|
||||
================================================================================ */
|
||||
/**
|
||||
* Button to toggle between play and pause
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.PlayToggle = vjs.Button.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.Button.call(this, player, options);
|
||||
|
||||
player.on('play', vjs.bind(this, this.onPlay));
|
||||
player.on('pause', vjs.bind(this, this.onPause));
|
||||
}
|
||||
});
|
||||
|
||||
vjs.PlayToggle.prototype.buttonText = 'Play';
|
||||
|
||||
vjs.PlayToggle.prototype.buildCSSClass = function(){
|
||||
return 'vjs-play-control ' + vjs.Button.prototype.buildCSSClass.call(this);
|
||||
};
|
||||
|
||||
// OnClick - Toggle between play and pause
|
||||
vjs.PlayToggle.prototype.onClick = function(){
|
||||
if (this.player_.paused()) {
|
||||
this.player_.play();
|
||||
} else {
|
||||
this.player_.pause();
|
||||
}
|
||||
};
|
||||
|
||||
// OnPlay - Add the vjs-playing class to the element so it can change appearance
|
||||
vjs.PlayToggle.prototype.onPlay = function(){
|
||||
vjs.removeClass(this.el_, 'vjs-paused');
|
||||
vjs.addClass(this.el_, 'vjs-playing');
|
||||
this.el_.children[0].children[0].innerHTML = 'Pause'; // change the button text to "Pause"
|
||||
};
|
||||
|
||||
// OnPause - Add the vjs-paused class to the element so it can change appearance
|
||||
vjs.PlayToggle.prototype.onPause = function(){
|
||||
vjs.removeClass(this.el_, 'vjs-playing');
|
||||
vjs.addClass(this.el_, 'vjs-paused');
|
||||
this.el_.children[0].children[0].innerHTML = 'Play'; // change the button text to "Play"
|
||||
};
|
||||
|
||||
|
||||
/* Fullscreen Toggle Behaviors
|
||||
================================================================================ */
|
||||
/**
|
||||
* Toggle fullscreen video
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.FullscreenToggle = vjs.Button.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.Button.call(this, player, options);
|
||||
}
|
||||
});
|
||||
|
||||
vjs.FullscreenToggle.prototype.buttonText = 'Fullscreen';
|
||||
|
||||
vjs.FullscreenToggle.prototype.buildCSSClass = function(){
|
||||
return 'vjs-fullscreen-control ' + vjs.Button.prototype.buildCSSClass.call(this);
|
||||
};
|
||||
|
||||
vjs.FullscreenToggle.prototype.onClick = function(){
|
||||
if (!this.player_.isFullScreen) {
|
||||
this.player_.requestFullScreen();
|
||||
this.el_.children[0].children[0].innerHTML = 'Non-Fullscreen'; // change the button text to "Non-Fullscreen"
|
||||
} else {
|
||||
this.player_.cancelFullScreen();
|
||||
this.el_.children[0].children[0].innerHTML = 'Fullscreen'; // change the button to "Fullscreen"
|
||||
}
|
||||
};
|
||||
|
||||
/* Time
|
||||
================================================================================ */
|
||||
|
||||
/**
|
||||
* Displays the current time
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.CurrentTimeDisplay = vjs.Component.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.Component.call(this, player, options);
|
||||
|
||||
player.on('timeupdate', vjs.bind(this, this.updateContent));
|
||||
}
|
||||
});
|
||||
|
||||
vjs.CurrentTimeDisplay.prototype.createEl = function(){
|
||||
var el = vjs.Component.prototype.createEl.call(this, 'div', {
|
||||
className: 'vjs-current-time vjs-time-controls vjs-control'
|
||||
});
|
||||
|
||||
this.content = vjs.createEl('div', {
|
||||
className: 'vjs-current-time-display',
|
||||
innerHTML: '<span class="vjs-control-text">Current Time </span>' + '0:00', // label the current time for screen reader users
|
||||
'aria-live': 'off' // tell screen readers not to automatically read the time as it changes
|
||||
});
|
||||
|
||||
el.appendChild(vjs.createEl('div').appendChild(this.content));
|
||||
return el;
|
||||
};
|
||||
|
||||
vjs.CurrentTimeDisplay.prototype.updateContent = function(){
|
||||
// Allows for smooth scrubbing, when player can't keep up.
|
||||
var time = (this.player_.scrubbing) ? this.player_.getCache().currentTime : this.player_.currentTime();
|
||||
this.content.innerHTML = '<span class="vjs-control-text">Current Time </span>' + vjs.formatTime(time, this.player_.duration());
|
||||
};
|
||||
|
||||
/**
|
||||
* Displays the duration
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.DurationDisplay = vjs.Component.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.Component.call(this, player, options);
|
||||
|
||||
player.on('timeupdate', vjs.bind(this, this.updateContent)); // this might need to be changes to 'durationchange' instead of 'timeupdate' eventually, however the durationchange event fires before this.player_.duration() is set, so the value cannot be written out using this method. Once the order of durationchange and this.player_.duration() being set is figured out, this can be updated.
|
||||
}
|
||||
});
|
||||
|
||||
vjs.DurationDisplay.prototype.createEl = function(){
|
||||
var el = vjs.Component.prototype.createEl.call(this, 'div', {
|
||||
className: 'vjs-duration vjs-time-controls vjs-control'
|
||||
});
|
||||
|
||||
this.content = vjs.createEl('div', {
|
||||
className: 'vjs-duration-display',
|
||||
innerHTML: '<span class="vjs-control-text">Duration Time </span>' + '0:00', // label the duration time for screen reader users
|
||||
'aria-live': 'off' // tell screen readers not to automatically read the time as it changes
|
||||
});
|
||||
|
||||
el.appendChild(vjs.createEl('div').appendChild(this.content));
|
||||
return el;
|
||||
};
|
||||
|
||||
vjs.DurationDisplay.prototype.updateContent = function(){
|
||||
if (this.player_.duration()) {
|
||||
this.content.innerHTML = '<span class="vjs-control-text">Duration Time </span>' + vjs.formatTime(this.player_.duration()); // label the duration time for screen reader users
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Time Separator (Not used in main skin, but still available, and could be used as a 'spare element')
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.TimeDivider = vjs.Component.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.Component.call(this, player, options);
|
||||
}
|
||||
});
|
||||
|
||||
vjs.TimeDivider.prototype.createEl = function(){
|
||||
return vjs.Component.prototype.createEl.call(this, 'div', {
|
||||
className: 'vjs-time-divider',
|
||||
innerHTML: '<div><span>/</span></div>'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Displays the time left in the video
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.RemainingTimeDisplay = vjs.Component.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.Component.call(this, player, options);
|
||||
|
||||
player.on('timeupdate', vjs.bind(this, this.updateContent));
|
||||
}
|
||||
});
|
||||
|
||||
vjs.RemainingTimeDisplay.prototype.createEl = function(){
|
||||
var el = vjs.Component.prototype.createEl.call(this, 'div', {
|
||||
className: 'vjs-remaining-time vjs-time-controls vjs-control'
|
||||
});
|
||||
|
||||
this.content = vjs.createEl('div', {
|
||||
className: 'vjs-remaining-time-display',
|
||||
innerHTML: '<span class="vjs-control-text">Remaining Time </span>' + '-0:00', // label the remaining time for screen reader users
|
||||
'aria-live': 'off' // tell screen readers not to automatically read the time as it changes
|
||||
});
|
||||
|
||||
el.appendChild(vjs.createEl('div').appendChild(this.content));
|
||||
return el;
|
||||
};
|
||||
|
||||
vjs.RemainingTimeDisplay.prototype.updateContent = function(){
|
||||
if (this.player_.duration()) {
|
||||
if (this.player_.duration()) {
|
||||
this.content.innerHTML = '<span class="vjs-control-text">Remaining Time </span>' + '-'+ vjs.formatTime(this.player_.remainingTime());
|
||||
}
|
||||
}
|
||||
|
||||
// Allows for smooth scrubbing, when player can't keep up.
|
||||
// var time = (this.player_.scrubbing) ? this.player_.getCache().currentTime : this.player_.currentTime();
|
||||
// this.content.innerHTML = vjs.formatTime(time, this.player_.duration());
|
||||
};
|
||||
|
||||
/* Progress
|
||||
================================================================================ */
|
||||
|
||||
/**
|
||||
* Seek, Load Progress, and Play Progress
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.ProgressControl = vjs.Component.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.Component.call(this, player, options);
|
||||
}
|
||||
});
|
||||
|
||||
vjs.ProgressControl.prototype.options_ = {
|
||||
children: {
|
||||
'seekBar': {}
|
||||
}
|
||||
};
|
||||
|
||||
vjs.ProgressControl.prototype.createEl = function(){
|
||||
return vjs.Component.prototype.createEl.call(this, 'div', {
|
||||
className: 'vjs-progress-control vjs-control'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Seek Bar and holder for the progress bars
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.SeekBar = vjs.Slider.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.Slider.call(this, player, options);
|
||||
player.on('timeupdate', vjs.bind(this, this.updateARIAAttributes));
|
||||
player.ready(vjs.bind(this, this.updateARIAAttributes));
|
||||
}
|
||||
});
|
||||
|
||||
vjs.SeekBar.prototype.options_ = {
|
||||
children: {
|
||||
'loadProgressBar': {},
|
||||
'playProgressBar': {},
|
||||
'seekHandle': {}
|
||||
},
|
||||
'barName': 'playProgressBar',
|
||||
'handleName': 'seekHandle'
|
||||
};
|
||||
|
||||
vjs.SeekBar.prototype.playerEvent = 'timeupdate';
|
||||
|
||||
vjs.SeekBar.prototype.createEl = function(){
|
||||
return vjs.Slider.prototype.createEl.call(this, 'div', {
|
||||
className: 'vjs-progress-holder',
|
||||
'aria-label': 'video progress bar'
|
||||
});
|
||||
};
|
||||
|
||||
vjs.SeekBar.prototype.updateARIAAttributes = function(){
|
||||
// Allows for smooth scrubbing, when player can't keep up.
|
||||
var time = (this.player_.scrubbing) ? this.player_.getCache().currentTime : this.player_.currentTime();
|
||||
this.el_.setAttribute('aria-valuenow',vjs.round(this.getPercent()*100, 2)); // machine readable value of progress bar (percentage complete)
|
||||
this.el_.setAttribute('aria-valuetext',vjs.formatTime(time, this.player_.duration())); // human readable value of progress bar (time complete)
|
||||
};
|
||||
|
||||
vjs.SeekBar.prototype.getPercent = function(){
|
||||
return this.player_.currentTime() / this.player_.duration();
|
||||
};
|
||||
|
||||
vjs.SeekBar.prototype.onMouseDown = function(event){
|
||||
vjs.Slider.prototype.onMouseDown.call(this, event);
|
||||
|
||||
this.player_.scrubbing = true;
|
||||
|
||||
this.videoWasPlaying = !this.player_.paused();
|
||||
this.player_.pause();
|
||||
};
|
||||
|
||||
vjs.SeekBar.prototype.onMouseMove = function(event){
|
||||
var newTime = this.calculateDistance(event) * this.player_.duration();
|
||||
|
||||
// Don't let video end while scrubbing.
|
||||
if (newTime == this.player_.duration()) { newTime = newTime - 0.1; }
|
||||
|
||||
// Set new time (tell player to seek to new time)
|
||||
this.player_.currentTime(newTime);
|
||||
};
|
||||
|
||||
vjs.SeekBar.prototype.onMouseUp = function(event){
|
||||
vjs.Slider.prototype.onMouseUp.call(this, event);
|
||||
|
||||
this.player_.scrubbing = false;
|
||||
if (this.videoWasPlaying) {
|
||||
this.player_.play();
|
||||
}
|
||||
};
|
||||
|
||||
vjs.SeekBar.prototype.stepForward = function(){
|
||||
this.player_.currentTime(this.player_.currentTime() + 5); // more quickly fast forward for keyboard-only users
|
||||
};
|
||||
|
||||
vjs.SeekBar.prototype.stepBack = function(){
|
||||
this.player_.currentTime(this.player_.currentTime() - 5); // more quickly rewind for keyboard-only users
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Shows load progres
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.LoadProgressBar = vjs.Component.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.Component.call(this, player, options);
|
||||
player.on('progress', vjs.bind(this, this.update));
|
||||
}
|
||||
});
|
||||
|
||||
vjs.LoadProgressBar.prototype.createEl = function(){
|
||||
return vjs.Component.prototype.createEl.call(this, 'div', {
|
||||
className: 'vjs-load-progress',
|
||||
innerHTML: '<span class="vjs-control-text">Loaded: 0%</span>'
|
||||
});
|
||||
};
|
||||
|
||||
vjs.LoadProgressBar.prototype.update = function(){
|
||||
if (this.el_.style) { this.el_.style.width = vjs.round(this.player_.bufferedPercent() * 100, 2) + '%'; }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Shows play progress
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.PlayProgressBar = vjs.Component.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.Component.call(this, player, options);
|
||||
}
|
||||
});
|
||||
|
||||
vjs.PlayProgressBar.prototype.createEl = function(){
|
||||
return vjs.Component.prototype.createEl.call(this, 'div', {
|
||||
className: 'vjs-play-progress',
|
||||
innerHTML: '<span class="vjs-control-text">Progress: 0%</span>'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* SeekBar component includes play progress bar, and seek handle
|
||||
* Needed so it can determine seek position based on handle position/size
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.SeekHandle = vjs.SliderHandle.extend();
|
||||
|
||||
/** @inheritDoc */
|
||||
vjs.SeekHandle.prototype.defaultValue = '00:00';
|
||||
|
||||
/** @inheritDoc */
|
||||
vjs.SeekHandle.prototype.createEl = function(){
|
||||
return vjs.SliderHandle.prototype.createEl.call(this, 'div', {
|
||||
className: 'vjs-seek-handle'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Control the volume
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.VolumeControl = vjs.Component.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.Component.call(this, player, options);
|
||||
|
||||
// hide volume controls when they're not supported by the current tech
|
||||
if (player.tech && player.tech.features && player.tech.features.volumeControl === false) {
|
||||
this.addClass('vjs-hidden');
|
||||
}
|
||||
player.on('loadstart', vjs.bind(this, function(){
|
||||
if (player.tech.features && player.tech.features.volumeControl === false) {
|
||||
this.addClass('vjs-hidden');
|
||||
} else {
|
||||
this.removeClass('vjs-hidden');
|
||||
}
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
vjs.VolumeControl.prototype.options_ = {
|
||||
children: {
|
||||
'volumeBar': {}
|
||||
}
|
||||
};
|
||||
|
||||
vjs.VolumeControl.prototype.createEl = function(){
|
||||
return vjs.Component.prototype.createEl.call(this, 'div', {
|
||||
className: 'vjs-volume-control vjs-control'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Contains volume level
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.VolumeBar = vjs.Slider.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.Slider.call(this, player, options);
|
||||
player.on('volumechange', vjs.bind(this, this.updateARIAAttributes));
|
||||
player.ready(vjs.bind(this, this.updateARIAAttributes));
|
||||
setTimeout(vjs.bind(this, this.update), 0); // update when elements is in DOM
|
||||
}
|
||||
});
|
||||
|
||||
vjs.VolumeBar.prototype.updateARIAAttributes = function(){
|
||||
// Current value of volume bar as a percentage
|
||||
this.el_.setAttribute('aria-valuenow',vjs.round(this.player_.volume()*100, 2));
|
||||
this.el_.setAttribute('aria-valuetext',vjs.round(this.player_.volume()*100, 2)+'%');
|
||||
};
|
||||
|
||||
vjs.VolumeBar.prototype.options_ = {
|
||||
children: {
|
||||
'volumeLevel': {},
|
||||
'volumeHandle': {}
|
||||
},
|
||||
'barName': 'volumeLevel',
|
||||
'handleName': 'volumeHandle'
|
||||
};
|
||||
|
||||
vjs.VolumeBar.prototype.playerEvent = 'volumechange';
|
||||
|
||||
vjs.VolumeBar.prototype.createEl = function(){
|
||||
return vjs.Slider.prototype.createEl.call(this, 'div', {
|
||||
className: 'vjs-volume-bar',
|
||||
'aria-label': 'volume level'
|
||||
});
|
||||
};
|
||||
|
||||
vjs.VolumeBar.prototype.onMouseMove = function(event) {
|
||||
this.player_.volume(this.calculateDistance(event));
|
||||
};
|
||||
|
||||
vjs.VolumeBar.prototype.getPercent = function(){
|
||||
if (this.player_.muted()) {
|
||||
return 0;
|
||||
} else {
|
||||
return this.player_.volume();
|
||||
}
|
||||
};
|
||||
|
||||
vjs.VolumeBar.prototype.stepForward = function(){
|
||||
this.player_.volume(this.player_.volume() + 0.1);
|
||||
};
|
||||
|
||||
vjs.VolumeBar.prototype.stepBack = function(){
|
||||
this.player_.volume(this.player_.volume() - 0.1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows volume level
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.VolumeLevel = vjs.Component.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.Component.call(this, player, options);
|
||||
}
|
||||
});
|
||||
|
||||
vjs.VolumeLevel.prototype.createEl = function(){
|
||||
return vjs.Component.prototype.createEl.call(this, 'div', {
|
||||
className: 'vjs-volume-level',
|
||||
innerHTML: '<span class="vjs-control-text"></span>'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Change volume level
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.VolumeHandle = vjs.SliderHandle.extend();
|
||||
|
||||
/** @inheritDoc */
|
||||
vjs.VolumeHandle.prototype.defaultValue = '00:00';
|
||||
|
||||
/** @inheritDoc */
|
||||
vjs.VolumeHandle.prototype.createEl = function(){
|
||||
return vjs.SliderHandle.prototype.createEl.call(this, 'div', {
|
||||
className: 'vjs-volume-handle'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Mute the audio
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
vjs.MuteToggle = vjs.Button.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.Button.call(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 && player.tech.features.volumeControl === false) {
|
||||
this.addClass('vjs-hidden');
|
||||
}
|
||||
player.on('loadstart', vjs.bind(this, function(){
|
||||
if (player.tech.features && player.tech.features.volumeControl === false) {
|
||||
this.addClass('vjs-hidden');
|
||||
} else {
|
||||
this.removeClass('vjs-hidden');
|
||||
}
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
vjs.MuteToggle.prototype.createEl = function(){
|
||||
return vjs.Button.prototype.createEl.call(this, 'div', {
|
||||
className: 'vjs-mute-control vjs-control',
|
||||
innerHTML: '<div><span class="vjs-control-text">Mute</span></div>'
|
||||
});
|
||||
};
|
||||
|
||||
vjs.MuteToggle.prototype.onClick = function(){
|
||||
this.player_.muted( this.player_.muted() ? false : true );
|
||||
};
|
||||
|
||||
vjs.MuteToggle.prototype.update = function(){
|
||||
var vol = this.player_.volume(),
|
||||
level = 3;
|
||||
|
||||
if (vol === 0 || this.player_.muted()) {
|
||||
level = 0;
|
||||
} else if (vol < 0.33) {
|
||||
level = 1;
|
||||
} else if (vol < 0.67) {
|
||||
level = 2;
|
||||
}
|
||||
|
||||
// Don't rewrite the button text if the actual text doesn't change.
|
||||
// This causes unnecessary and confusing information for screen reader users.
|
||||
// This check is needed because this function gets called every time the volume level is changed.
|
||||
if(this.player_.muted()){
|
||||
if(this.el_.children[0].children[0].innerHTML!='Unmute'){
|
||||
this.el_.children[0].children[0].innerHTML = 'Unmute'; // change the button text to "Unmute"
|
||||
}
|
||||
} else {
|
||||
if(this.el_.children[0].children[0].innerHTML!='Mute'){
|
||||
this.el_.children[0].children[0].innerHTML = 'Mute'; // change the button text to "Mute"
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO improve muted icon classes */
|
||||
for (var i = 0; i < 4; i++) {
|
||||
vjs.removeClass(this.el_, 'vjs-vol-'+i);
|
||||
}
|
||||
vjs.addClass(this.el_, 'vjs-vol-'+level);
|
||||
};
|
||||
|
||||
/**
|
||||
* Menu button with a popup for showing the volume slider.
|
||||
* @constructor
|
||||
*/
|
||||
vjs.VolumeMenuButton = vjs.MenuButton.extend({
|
||||
/** @constructor */
|
||||
init: function(player, options){
|
||||
vjs.MenuButton.call(this, player, options);
|
||||
|
||||
// Same listeners as MuteToggle
|
||||
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 && player.tech.features.volumeControl === false) {
|
||||
this.addClass('vjs-hidden');
|
||||
}
|
||||
player.on('loadstart', vjs.bind(this, function(){
|
||||
if (player.tech.features && player.tech.features.volumeControl === false) {
|
||||
this.addClass('vjs-hidden');
|
||||
} else {
|
||||
this.removeClass('vjs-hidden');
|
||||
}
|
||||
}));
|
||||
this.addClass('vjs-menu-button');
|
||||
}
|
||||
});
|
||||
|
||||
vjs.VolumeMenuButton.prototype.createMenu = function(){
|
||||
var menu = new vjs.Menu(this.player_, {
|
||||
contentElType: 'div'
|
||||
});
|
||||
var vc = new vjs.VolumeBar(this.player_, vjs.obj.merge({vertical: true}, this.options_.volumeBar));
|
||||
menu.addChild(vc);
|
||||
return menu;
|
||||
};
|
||||
|
||||
vjs.VolumeMenuButton.prototype.onClick = function(){
|
||||
vjs.MuteToggle.prototype.onClick.call(this);
|
||||
vjs.MenuButton.prototype.onClick.call(this);
|
||||
};
|
||||
|
||||
vjs.VolumeMenuButton.prototype.createEl = function(){
|
||||
return vjs.Button.prototype.createEl.call(this, 'div', {
|
||||
className: 'vjs-volume-menu-button vjs-menu-button vjs-control',
|
||||
innerHTML: '<div><span class="vjs-control-text">Mute</span></div>'
|
||||
});
|
||||
};
|
||||
vjs.VolumeMenuButton.prototype.update = vjs.MuteToggle.prototype.update;
|
Loading…
Reference in New Issue
Block a user