2013-01-10 13:06:12 -08:00
/ * *
* @ fileoverview Controls classes for Video . js buttons , sliders , etc .
* /
2012-12-30 21:45:50 -08:00
/ * *
* Base class for all control elements
2013-01-04 16:58:23 -08:00
* @ param { vjs . Player | Object } player
2012-12-30 21:45:50 -08:00
* @ param { Object = } options
* @ constructor
* /
2013-01-04 16:58:23 -08:00
vjs . Control = function ( player , options ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , player , options ) ;
} ;
2013-01-04 16:58:23 -08:00
goog . inherits ( vjs . Control , vjs . Component ) ;
2012-12-30 21:45:50 -08:00
2013-01-04 16:58:23 -08:00
vjs . Control . prototype . buildCSSClass = function ( ) {
2013-01-10 13:06:12 -08:00
return 'vjs-control ' + goog . base ( this , 'buildCSSClass' ) ;
2012-12-30 21:45:50 -08:00
} ;
2011-11-29 11:40:05 -08:00
2012-03-16 12:29:38 -07:00
/ * C o n t r o l B a r
=== === === === === === === === === === === === === === === === === === === === === === === === === === == * /
2012-12-30 21:45:50 -08:00
/ * *
* Container of main controls
2013-01-04 16:58:23 -08:00
* @ param { vjs . Player | Object } player
2012-12-30 21:45:50 -08:00
* @ param { Object = } options
* @ constructor
* /
2013-01-04 16:58:23 -08:00
vjs . ControlBar = function ( player , options ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , player , options ) ;
2013-01-10 13:06:12 -08:00
player . one ( 'play' , vjs . bind ( this , function ( ) {
2013-03-07 17:32:47 -05:00
var touchstart ;
2012-12-30 21:45:50 -08:00
this . fadeIn ( ) ;
2013-01-16 20:24:38 -05:00
this . player _ . on ( 'mouseover' , vjs . bind ( this , this . fadeIn ) ) ;
this . player _ . on ( 'mouseout' , vjs . bind ( this , this . fadeOut ) ) ;
2013-03-07 17:32:47 -05:00
touchstart = false ;
this . player _ . on ( 'touchstart' , function ( ) {
touchstart = true ;
} ) ;
this . player _ . on ( 'touchmove' , function ( ) {
touchstart = false ;
} ) ;
this . player _ . on ( 'touchend' , vjs . bind ( this , function ( ) {
var idx ;
if ( touchstart ) {
idx = this . el ( ) . className . search ( 'fade-in' ) ;
if ( idx !== - 1 ) {
this . fadeOut ( ) ;
} else {
this . fadeIn ( ) ;
}
}
touchstart = false ;
} ) ) ;
2012-12-30 21:45:50 -08:00
} ) ) ;
} ;
2013-01-04 16:58:23 -08:00
goog . inherits ( vjs . ControlBar , vjs . Component ) ;
2012-12-30 21:45:50 -08:00
2013-01-17 21:03:25 -05:00
vjs . ControlBar . prototype . options _ = {
2013-01-10 13:06:12 -08:00
loadEvent : 'play' ,
2012-12-30 21:45:50 -08:00
children : {
2013-01-10 13:06:12 -08:00
'playToggle' : { } ,
'currentTimeDisplay' : { } ,
'timeDivider' : { } ,
'durationDisplay' : { } ,
'remainingTimeDisplay' : { } ,
'progressControl' : { } ,
2013-01-19 21:48:25 -05:00
'fullscreenToggle' : { } ,
2013-01-10 13:06:12 -08:00
'volumeControl' : { } ,
'muteToggle' : { }
2012-12-30 21:45:50 -08:00
}
} ;
2012-03-16 12:29:38 -07:00
2013-01-04 16:58:23 -08:00
vjs . ControlBar . prototype . createEl = function ( ) {
2013-01-10 13:06:12 -08:00
return vjs . createEl ( 'div' , {
className : 'vjs-control-bar'
2012-12-30 21:45:50 -08:00
} ) ;
} ;
2012-03-16 12:29:38 -07:00
2013-01-04 16:58:23 -08:00
vjs . ControlBar . prototype . fadeIn = function ( ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , 'fadeIn' ) ;
2013-01-16 20:24:38 -05:00
this . player _ . trigger ( 'controlsvisible' ) ;
2012-12-30 21:45:50 -08:00
} ;
2012-03-16 12:29:38 -07:00
2013-01-04 16:58:23 -08:00
vjs . ControlBar . prototype . fadeOut = function ( ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , 'fadeOut' ) ;
2013-01-16 20:24:38 -05:00
this . player _ . trigger ( 'controlshidden' ) ;
2012-12-30 21:45:50 -08:00
} ;
2012-03-16 12:29:38 -07:00
2013-01-04 16:58:23 -08:00
vjs . ControlBar . prototype . lockShowing = function ( ) {
2013-01-10 13:06:12 -08:00
this . el _ . style . opacity = '1' ;
2012-12-30 21:45:50 -08:00
} ;
2012-03-16 12:29:38 -07:00
2011-11-29 11:40:05 -08:00
/ * B u t t o n - B a s e c l a s s f o r a l l b u t t o n s
=== === === === === === === === === === === === === === === === === === === === === === === === === === == * /
2012-12-30 21:45:50 -08:00
/ * *
* Base class for all buttons
2013-01-04 16:58:23 -08:00
* @ param { vjs . Player | Object } player
2012-12-30 21:45:50 -08:00
* @ param { Object = } options
* @ constructor
* /
2013-01-04 16:58:23 -08:00
vjs . Button = function ( player , options ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , player , options ) ;
2013-01-10 13:06:12 -08:00
this . on ( 'click' , this . onClick ) ;
this . on ( 'focus' , this . onFocus ) ;
this . on ( 'blur' , this . onBlur ) ;
2012-12-30 21:45:50 -08:00
} ;
2013-01-04 16:58:23 -08:00
goog . inherits ( vjs . Button , vjs . Control ) ;
2012-12-30 21:45:50 -08:00
2013-01-16 11:09:56 -05:00
vjs . Button . prototype . createEl = function ( type , props ) {
2012-12-30 21:45:50 -08:00
// Add standard Aria and Tabindex info
2013-01-25 17:36:40 -08:00
props = vjs . obj . merge ( {
2012-12-30 21:45:50 -08:00
className : this . buildCSSClass ( ) ,
2013-01-10 13:06:12 -08:00
innerHTML : '<div><span class="vjs-control-text">' + ( this . buttonText || 'Need Text' ) + '</span></div>' ,
role : 'button' ,
2013-01-19 22:46:02 -05:00
'aria-live' : 'polite' , // let the screen reader user know that the text of the button may change
2012-12-30 21:45:50 -08:00
tabIndex : 0
2013-01-16 11:09:56 -05:00
} , props ) ;
2012-12-30 21:45:50 -08:00
2013-01-16 11:09:56 -05:00
return goog . base ( this , 'createEl' , type , props ) ;
2012-12-30 21:45:50 -08:00
} ;
2011-11-29 11:40:05 -08:00
// Click - Override with specific functionality for button
2013-01-04 16:58:23 -08:00
vjs . Button . prototype . onClick = function ( ) { } ;
2011-11-29 11:40:05 -08:00
// Focus - Add keyboard functionality to element
2013-01-04 16:58:23 -08:00
vjs . Button . prototype . onFocus = function ( ) {
2013-01-10 13:06:12 -08:00
vjs . on ( document , 'keyup' , vjs . bind ( this , this . onKeyPress ) ) ;
2012-12-30 21:45:50 -08:00
} ;
2011-11-29 11:40:05 -08:00
// KeyPress (document level) - Trigger click when keys are pressed
2013-01-04 16:58:23 -08:00
vjs . Button . prototype . onKeyPress = function ( event ) {
2012-12-30 21:45:50 -08:00
// Check for space bar (32) or enter (13) keys
if ( event . which == 32 || event . which == 13 ) {
event . preventDefault ( ) ;
this . onClick ( ) ;
2011-11-29 11:40:05 -08:00
}
2012-12-30 21:45:50 -08:00
} ;
2011-11-29 11:40:05 -08:00
2012-12-30 21:45:50 -08:00
// Blur - Remove keyboard triggers
2013-01-04 16:58:23 -08:00
vjs . Button . prototype . onBlur = function ( ) {
2013-01-10 13:06:12 -08:00
vjs . off ( document , 'keyup' , vjs . bind ( this , this . onKeyPress ) ) ;
} ;
2011-11-29 11:40:05 -08:00
/ * P l a y B u t t o n
=== === === === === === === === === === === === === === === === === === === === === === === === === === == * /
2012-12-30 21:45:50 -08:00
/ * *
* Basic play button
2013-01-04 16:58:23 -08:00
* @ param { vjs . Player | Object } player
2012-12-30 21:45:50 -08:00
* @ param { Object = } options
* @ constructor
* /
2013-01-04 16:58:23 -08:00
vjs . PlayButton = function ( player , options ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , player , options ) ;
} ;
2013-01-04 16:58:23 -08:00
goog . inherits ( vjs . PlayButton , vjs . Button ) ;
2012-12-30 21:45:50 -08:00
2013-01-10 13:06:12 -08:00
vjs . PlayButton . prototype . buttonText = 'Play' ;
2012-12-30 21:45:50 -08:00
2013-01-04 16:58:23 -08:00
vjs . PlayButton . prototype . buildCSSClass = function ( ) {
2013-01-10 13:06:12 -08:00
return 'vjs-play-button ' + goog . base ( this , 'buildCSSClass' ) ;
2012-12-30 21:45:50 -08:00
} ;
2013-01-04 16:58:23 -08:00
vjs . PlayButton . prototype . onClick = function ( ) {
2013-01-16 20:24:38 -05:00
this . player _ . play ( ) ;
2013-01-10 13:06:12 -08:00
} ;
2011-11-29 11:40:05 -08:00
/ * P a u s e B u t t o n
=== === === === === === === === === === === === === === === === === === === === === === === === === === == * /
2012-12-30 21:45:50 -08:00
/ * *
* Basic pause button
2013-01-04 16:58:23 -08:00
* @ param { vjs . Player | Object } player
2012-12-30 21:45:50 -08:00
* @ param { Object = } options
* @ constructor
* /
2013-01-04 16:58:23 -08:00
vjs . PauseButton = function ( player , options ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , player , options ) ;
} ;
2013-01-04 16:58:23 -08:00
goog . inherits ( vjs . PauseButton , vjs . Button ) ;
2012-12-30 21:45:50 -08:00
2013-01-10 13:06:12 -08:00
vjs . PauseButton . prototype . buttonText = 'Play' ;
2012-12-30 21:45:50 -08:00
2013-01-04 16:58:23 -08:00
vjs . PauseButton . prototype . buildCSSClass = function ( ) {
2013-01-10 13:06:12 -08:00
return 'vjs-pause-button ' + goog . base ( this , 'buildCSSClass' ) ;
2012-12-30 21:45:50 -08:00
} ;
2013-01-04 16:58:23 -08:00
vjs . PauseButton . prototype . onClick = function ( ) {
2013-01-16 20:24:38 -05:00
this . player _ . pause ( ) ;
2012-12-30 21:45:50 -08:00
} ;
2011-11-29 11:40:05 -08:00
/ * P l a y T o g g l e - P l a y o r P a u s e M e d i a
=== === === === === === === === === === === === === === === === === === === === === === === === === === == * /
2012-12-30 21:45:50 -08:00
/ * *
* Button to toggle between play and pause
2013-01-04 16:58:23 -08:00
* @ param { vjs . Player | Object } player
2012-12-30 21:45:50 -08:00
* @ param { Object = } options
* @ constructor
* /
2013-01-04 16:58:23 -08:00
vjs . PlayToggle = function ( player , options ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , player , options ) ;
2013-01-10 13:06:12 -08:00
player . on ( 'play' , vjs . bind ( this , this . onPlay ) ) ;
player . on ( 'pause' , vjs . bind ( this , this . onPause ) ) ;
2012-12-30 21:45:50 -08:00
} ;
2013-01-04 16:58:23 -08:00
goog . inherits ( vjs . PlayToggle , vjs . Button ) ;
2012-12-30 21:45:50 -08:00
2013-01-10 13:06:12 -08:00
vjs . PlayToggle . prototype . buttonText = 'Play' ;
2012-12-30 21:45:50 -08:00
2013-01-04 16:58:23 -08:00
vjs . PlayToggle . prototype . buildCSSClass = function ( ) {
2013-01-10 13:06:12 -08:00
return 'vjs-play-control ' + goog . base ( this , 'buildCSSClass' ) ;
2012-12-30 21:45:50 -08:00
} ;
2011-11-29 11:40:05 -08:00
// OnClick - Toggle between play and pause
2013-01-04 16:58:23 -08:00
vjs . PlayToggle . prototype . onClick = function ( ) {
2013-01-16 20:24:38 -05:00
if ( this . player _ . paused ( ) ) {
this . player _ . play ( ) ;
2012-12-30 21:45:50 -08:00
} else {
2013-01-16 20:24:38 -05:00
this . player _ . pause ( ) ;
2012-12-30 21:45:50 -08:00
}
} ;
2011-11-29 11:40:05 -08:00
// OnPlay - Add the vjs-playing class to the element so it can change appearance
2013-01-04 16:58:23 -08:00
vjs . PlayToggle . prototype . onPlay = function ( ) {
2013-01-10 13:06:12 -08:00
vjs . removeClass ( this . el _ , 'vjs-paused' ) ;
vjs . addClass ( this . el _ , 'vjs-playing' ) ;
2013-01-19 22:46:02 -05:00
this . el _ . children [ 0 ] . children [ 0 ] . innerHTML = 'Pause' ; // change the button text to "Pause"
2012-12-30 21:45:50 -08:00
} ;
2011-11-29 11:40:05 -08:00
// OnPause - Add the vjs-paused class to the element so it can change appearance
2013-01-04 16:58:23 -08:00
vjs . PlayToggle . prototype . onPause = function ( ) {
2013-01-10 13:06:12 -08:00
vjs . removeClass ( this . el _ , 'vjs-playing' ) ;
vjs . addClass ( this . el _ , 'vjs-paused' ) ;
2013-01-19 22:46:02 -05:00
this . el _ . children [ 0 ] . children [ 0 ] . innerHTML = 'Play' ; // change the button text to "Play"
2013-01-10 13:06:12 -08:00
} ;
2011-11-29 11:40:05 -08:00
/ * F u l l s c r e e n T o g g l e B e h a v i o r s
=== === === === === === === === === === === === === === === === === === === === === === === === === === == * /
2012-12-30 21:45:50 -08:00
/ * *
* Toggle fullscreen video
2013-01-04 16:58:23 -08:00
* @ param { vjs . Player | Object } player
2012-12-30 21:45:50 -08:00
* @ param { Object = } options
* @ constructor
* /
2013-01-04 16:58:23 -08:00
vjs . FullscreenToggle = function ( player , options ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , player , options ) ;
} ;
2013-01-04 16:58:23 -08:00
goog . inherits ( vjs . FullscreenToggle , vjs . Button ) ;
2012-12-30 21:45:50 -08:00
2013-01-10 13:06:12 -08:00
vjs . FullscreenToggle . prototype . buttonText = 'Fullscreen' ;
2012-12-30 21:45:50 -08:00
2013-01-04 16:58:23 -08:00
vjs . FullscreenToggle . prototype . buildCSSClass = function ( ) {
2013-01-10 13:06:12 -08:00
return 'vjs-fullscreen-control ' + goog . base ( this , 'buildCSSClass' ) ;
2012-12-30 21:45:50 -08:00
} ;
2013-01-04 16:58:23 -08:00
vjs . FullscreenToggle . prototype . onClick = function ( ) {
2013-01-16 20:24:38 -05:00
if ( ! this . player _ . isFullScreen ) {
this . player _ . requestFullScreen ( ) ;
2013-01-19 22:46:02 -05:00
this . el _ . children [ 0 ] . children [ 0 ] . innerHTML = 'Non-Fullscreen' ; // change the button text to "Non-Fullscreen"
2012-12-30 21:45:50 -08:00
} else {
2013-01-16 20:24:38 -05:00
this . player _ . cancelFullScreen ( ) ;
2013-01-19 22:46:02 -05:00
this . el _ . children [ 0 ] . children [ 0 ] . innerHTML = 'Fullscreen' ; // change the button to "Fullscreen"
2011-11-29 11:40:05 -08:00
}
2012-12-30 21:45:50 -08:00
} ;
2011-11-29 11:40:05 -08:00
/ * B i g P l a y B u t t o n
=== === === === === === === === === === === === === === === === === === === === === === === === === === == * /
2012-12-30 21:45:50 -08:00
/ * *
* Initial play button . Shows before the video has played .
2013-01-04 16:58:23 -08:00
* @ param { vjs . Player | Object } player
2012-12-30 21:45:50 -08:00
* @ param { Object = } options
* @ constructor
* /
2013-01-04 16:58:23 -08:00
vjs . BigPlayButton = function ( player , options ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , player , options ) ;
2013-03-11 18:03:56 -04:00
player . on ( 'play' , vjs . bind ( this , function ( ) {
this . hide ( ) ;
player . on ( 'showBigPlayButton' , vjs . bind ( this , function ( event ) {
console . log ( event ) ;
this . show ( ) ;
} ) ) ;
} ) ) ;
2013-01-21 16:43:03 -08:00
// player.on('ended', vjs.bind(this, this.show));
2012-12-30 21:45:50 -08:00
} ;
2013-01-04 16:58:23 -08:00
goog . inherits ( vjs . BigPlayButton , vjs . Button ) ;
2012-12-30 21:45:50 -08:00
2013-01-04 16:58:23 -08:00
vjs . BigPlayButton . prototype . createEl = function ( ) {
2013-01-10 13:06:12 -08:00
return goog . base ( this , 'createEl' , 'div' , {
className : 'vjs-big-play-button' ,
2013-01-19 22:16:26 -05:00
innerHTML : '<span></span>' ,
'aria-label' : 'play video'
2012-12-30 21:45:50 -08:00
} ) ;
} ;
2013-01-04 16:58:23 -08:00
vjs . BigPlayButton . prototype . onClick = function ( ) {
2012-12-30 21:45:50 -08:00
// Go back to the beginning if big play button is showing at the end.
// Have to check for current time otherwise it might throw a 'not ready' error.
2013-03-11 18:03:56 -04:00
//if(this.player_.currentTime()) {
//this.player_.currentTime(0);
//}
2013-01-16 20:24:38 -05:00
this . player _ . play ( ) ;
2012-12-30 21:45:50 -08:00
} ;
2011-11-29 11:40:05 -08:00
2011-12-21 17:59:36 -08:00
/ * L o a d i n g S p i n n e r
=== === === === === === === === === === === === === === === === === === === === === === === === === === == * /
2012-12-30 21:45:50 -08:00
/ * *
* Loading spinner for waiting events
2013-01-04 16:58:23 -08:00
* @ param { vjs . Player | Object } player
2012-12-30 21:45:50 -08:00
* @ param { Object = } options
* @ constructor
* /
2013-01-04 16:58:23 -08:00
vjs . LoadingSpinner = function ( player , options ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , player , options ) ;
2013-01-10 13:06:12 -08:00
player . on ( 'canplay' , vjs . bind ( this , this . hide ) ) ;
player . on ( 'canplaythrough' , vjs . bind ( this , this . hide ) ) ;
player . on ( 'playing' , vjs . bind ( this , this . hide ) ) ;
player . on ( 'seeked' , vjs . bind ( this , this . hide ) ) ;
2012-12-30 21:45:50 -08:00
2013-01-10 13:06:12 -08:00
player . on ( 'seeking' , vjs . bind ( this , this . show ) ) ;
2012-12-30 21:45:50 -08:00
// in some browsers seeking does not trigger the 'playing' event,
// so we also need to trap 'seeked' if we are going to set a
// 'seeking' event
2013-01-10 13:06:12 -08:00
player . on ( 'seeked' , vjs . bind ( this , this . hide ) ) ;
2012-12-30 21:45:50 -08:00
2013-01-10 13:06:12 -08:00
player . on ( 'error' , vjs . bind ( this , this . show ) ) ;
2012-12-30 21:45:50 -08:00
// Not showing spinner on stalled any more. Browsers may stall and then not trigger any events that would remove the spinner.
// Checked in Chrome 16 and Safari 5.1.2. http://help.videojs.com/discussions/problems/883-why-is-the-download-progress-showing
2013-01-10 13:06:12 -08:00
// player.on('stalled', vjs.bind(this, this.show));
2012-12-30 21:45:50 -08:00
2013-01-10 13:06:12 -08:00
player . on ( 'waiting' , vjs . bind ( this , this . show ) ) ;
2012-12-30 21:45:50 -08:00
} ;
2013-01-04 16:58:23 -08:00
goog . inherits ( vjs . LoadingSpinner , vjs . Component ) ;
2012-12-30 21:45:50 -08:00
2013-01-04 16:58:23 -08:00
vjs . LoadingSpinner . prototype . createEl = function ( ) {
2012-12-30 21:45:50 -08:00
var classNameSpinner , innerHtmlSpinner ;
2013-01-16 20:24:38 -05:00
if ( typeof this . player _ . el ( ) . style . WebkitBorderRadius == 'string'
|| typeof this . player _ . el ( ) . style . MozBorderRadius == 'string'
|| typeof this . player _ . el ( ) . style . KhtmlBorderRadius == 'string'
|| typeof this . player _ . el ( ) . style . borderRadius == 'string' )
2012-12-30 21:45:50 -08:00
{
2013-01-10 13:06:12 -08:00
classNameSpinner = 'vjs-loading-spinner' ;
innerHtmlSpinner = '<div class="ball1"></div><div class="ball2"></div><div class="ball3"></div><div class="ball4"></div><div class="ball5"></div><div class="ball6"></div><div class="ball7"></div><div class="ball8"></div>' ;
2012-12-30 21:45:50 -08:00
} else {
2013-01-10 13:06:12 -08:00
classNameSpinner = 'vjs-loading-spinner-fallback' ;
innerHtmlSpinner = '' ;
2012-12-30 21:45:50 -08:00
}
2011-12-21 17:59:36 -08:00
2013-01-10 13:06:12 -08:00
return goog . base ( this , 'createEl' , 'div' , {
2012-12-30 21:45:50 -08:00
className : classNameSpinner ,
innerHTML : innerHtmlSpinner
} ) ;
} ;
2011-12-21 17:59:36 -08:00
2011-11-29 11:40:05 -08:00
/ * T i m e
=== === === === === === === === === === === === === === === === === === === === === === === === === === == * /
2012-12-30 21:45:50 -08:00
/ * *
* Displays the current time
2013-01-04 16:58:23 -08:00
* @ param { vjs . Player | Object } player
2012-12-30 21:45:50 -08:00
* @ param { Object = } options
* @ constructor
* /
2013-01-04 16:58:23 -08:00
vjs . CurrentTimeDisplay = function ( player , options ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , player , options ) ;
2013-01-10 13:06:12 -08:00
player . on ( 'timeupdate' , vjs . bind ( this , this . updateContent ) ) ;
2012-12-30 21:45:50 -08:00
} ;
2013-01-04 16:58:23 -08:00
goog . inherits ( vjs . CurrentTimeDisplay , vjs . Component ) ;
2012-12-30 21:45:50 -08:00
2013-01-04 16:58:23 -08:00
vjs . CurrentTimeDisplay . prototype . createEl = function ( ) {
2013-01-10 13:06:12 -08:00
var el = goog . base ( this , 'createEl' , 'div' , {
className : 'vjs-current-time vjs-time-controls vjs-control'
2012-12-30 21:45:50 -08:00
} ) ;
2013-01-10 13:06:12 -08:00
this . content = vjs . createEl ( 'div' , {
className : 'vjs-current-time-display' ,
2013-01-20 07:26:48 -05:00
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
2012-12-30 21:45:50 -08:00
} ) ;
2013-01-10 13:06:12 -08:00
el . appendChild ( vjs . createEl ( 'div' ) . appendChild ( this . content ) ) ;
2012-12-30 21:45:50 -08:00
return el ;
} ;
2013-01-04 16:58:23 -08:00
vjs . CurrentTimeDisplay . prototype . updateContent = function ( ) {
2012-12-30 21:45:50 -08:00
// Allows for smooth scrubbing, when player can't keep up.
2013-01-16 20:24:38 -05:00
var time = ( this . player _ . scrubbing ) ? this . player _ . getCache ( ) . currentTime : this . player _ . currentTime ( ) ;
2013-01-20 07:26:48 -05:00
this . content . innerHTML = '<span class="vjs-control-text">Current Time </span>' + vjs . formatTime ( time , this . player _ . duration ( ) ) ;
2012-12-30 21:45:50 -08:00
} ;
/ * *
* Displays the duration
2013-01-04 16:58:23 -08:00
* @ param { vjs . Player | Object } player
2012-12-30 21:45:50 -08:00
* @ param { Object = } options
* @ constructor
* /
2013-01-04 16:58:23 -08:00
vjs . DurationDisplay = function ( player , options ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , player , options ) ;
2013-02-14 19:27:54 -05:00
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.
2012-12-30 21:45:50 -08:00
} ;
2013-01-04 16:58:23 -08:00
goog . inherits ( vjs . DurationDisplay , vjs . Component ) ;
2012-12-30 21:45:50 -08:00
2013-01-04 16:58:23 -08:00
vjs . DurationDisplay . prototype . createEl = function ( ) {
2013-01-10 13:06:12 -08:00
var el = goog . base ( this , 'createEl' , 'div' , {
className : 'vjs-duration vjs-time-controls vjs-control'
2012-12-30 21:45:50 -08:00
} ) ;
2013-01-10 13:06:12 -08:00
this . content = vjs . createEl ( 'div' , {
className : 'vjs-duration-display' ,
2013-02-14 19:27:54 -05:00
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
2012-12-30 21:45:50 -08:00
} ) ;
2013-01-10 13:06:12 -08:00
el . appendChild ( vjs . createEl ( 'div' ) . appendChild ( this . content ) ) ;
2012-12-30 21:45:50 -08:00
return el ;
} ;
2013-01-04 16:58:23 -08:00
vjs . DurationDisplay . prototype . updateContent = function ( ) {
2013-01-20 07:26:48 -05:00
if ( this . player _ . duration ( ) ) {
2013-02-14 19:27:54 -05:00
this . content . innerHTML = '<span class="vjs-control-text">Duration Time </span>' + '-' + vjs . formatTime ( this . player _ . duration ( ) ) ; // label the duration time for screen reader users
2013-01-20 07:26:48 -05:00
}
2012-12-30 21:45:50 -08:00
} ;
/ * *
* Time Separator ( Not used in main skin , but still available , and could be used as a 'spare element' )
2013-01-04 16:58:23 -08:00
* @ param { vjs . Player | Object } player
2012-12-30 21:45:50 -08:00
* @ param { Object = } options
* @ constructor
* /
2013-01-04 16:58:23 -08:00
vjs . TimeDivider = function ( player , options ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , player , options ) ;
} ;
2013-01-04 16:58:23 -08:00
goog . inherits ( vjs . TimeDivider , vjs . Component ) ;
2012-12-30 21:45:50 -08:00
2013-01-04 16:58:23 -08:00
vjs . TimeDivider . prototype . createEl = function ( ) {
2013-01-10 13:06:12 -08:00
return goog . base ( this , 'createEl' , 'div' , {
className : 'vjs-time-divider' ,
2012-12-30 21:45:50 -08:00
innerHTML : '<div><span>/</span></div>'
} ) ;
} ;
/ * *
* Displays the time left in the video
2013-01-04 16:58:23 -08:00
* @ param { vjs . Player | Object } player
2012-12-30 21:45:50 -08:00
* @ param { Object = } options
* @ constructor
* /
2013-01-04 16:58:23 -08:00
vjs . RemainingTimeDisplay = function ( player , options ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , player , options ) ;
2013-01-10 13:06:12 -08:00
player . on ( 'timeupdate' , vjs . bind ( this , this . updateContent ) ) ;
2012-12-30 21:45:50 -08:00
} ;
2013-01-04 16:58:23 -08:00
goog . inherits ( vjs . RemainingTimeDisplay , vjs . Component ) ;
2012-12-30 21:45:50 -08:00
2013-01-04 16:58:23 -08:00
vjs . RemainingTimeDisplay . prototype . createEl = function ( ) {
2013-01-10 13:06:12 -08:00
var el = goog . base ( this , 'createEl' , 'div' , {
className : 'vjs-remaining-time vjs-time-controls vjs-control'
2012-12-30 21:45:50 -08:00
} ) ;
2013-01-10 13:06:12 -08:00
this . content = vjs . createEl ( 'div' , {
className : 'vjs-remaining-time-display' ,
2013-01-20 07:26:48 -05:00
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
2012-12-30 21:45:50 -08:00
} ) ;
2013-01-10 13:06:12 -08:00
el . appendChild ( vjs . createEl ( 'div' ) . appendChild ( this . content ) ) ;
2012-12-30 21:45:50 -08:00
return el ;
} ;
2013-01-04 16:58:23 -08:00
vjs . RemainingTimeDisplay . prototype . updateContent = function ( ) {
2013-01-20 07:26:48 -05:00
if ( this . player _ . duration ( ) ) {
if ( this . player _ . duration ( ) ) {
this . content . innerHTML = '<span class="vjs-control-text">Remaining Time </span>' + '-' + vjs . formatTime ( this . player _ . remainingTime ( ) ) ;
}
}
2012-12-30 21:45:50 -08:00
// Allows for smooth scrubbing, when player can't keep up.
2013-01-16 20:24:38 -05:00
// var time = (this.player_.scrubbing) ? this.player_.getCache().currentTime : this.player_.currentTime();
// this.content.innerHTML = vjs.formatTime(time, this.player_.duration());
2012-12-30 21:45:50 -08:00
} ;
/ * S l i d e r
=== === === === === === === === === === === === === === === === === === === === === === === === === === == * /
/ * *
* Parent for seek bar and volume slider
2013-01-04 16:58:23 -08:00
* @ param { vjs . Player | Object } player
2012-12-30 21:45:50 -08:00
* @ param { Object = } options
* @ constructor
* /
2013-01-04 16:58:23 -08:00
vjs . Slider = function ( player , options ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , player , options ) ;
2011-11-29 11:40:05 -08:00
2012-12-30 21:45:50 -08:00
// Set property names to bar and handle to match with the child Slider class is looking for
2013-01-17 21:03:25 -05:00
this . bar = this . getChild ( this . options _ [ 'barName' ] ) ;
this . handle = this . getChild ( this . options _ [ 'handleName' ] ) ;
2011-11-29 11:40:05 -08:00
2013-01-17 21:03:25 -05:00
// console.log('asdf', this.bar, this.childNameIndex_, this.options_)
2011-11-29 11:40:05 -08:00
2013-01-04 16:58:23 -08:00
player . on ( this . playerEvent , vjs . bind ( this , this . update ) ) ;
2011-11-29 11:40:05 -08:00
2013-01-10 13:06:12 -08:00
this . on ( 'mousedown' , this . onMouseDown ) ;
2013-03-07 17:00:27 -05:00
this . on ( 'touchstart' , this . onMouseDown ) ;
2013-01-10 13:06:12 -08:00
this . on ( 'focus' , this . onFocus ) ;
this . on ( 'blur' , this . onBlur ) ;
2011-11-29 11:40:05 -08:00
2013-01-16 20:24:38 -05:00
this . player _ . on ( 'controlsvisible' , vjs . bind ( this , this . update ) ) ;
2011-11-29 11:40:05 -08:00
2012-12-30 21:45:50 -08:00
// This is actually to fix the volume handle position. http://twitter.com/#!/gerritvanaaken/status/159046254519787520
2013-01-16 20:24:38 -05:00
// this.player_.one('timeupdate', vjs.bind(this, this.update));
2011-11-29 11:40:05 -08:00
2013-01-04 16:58:23 -08:00
player . ready ( vjs . bind ( this , this . update ) ) ;
2013-03-12 11:45:59 -04:00
this . boundEvents = { } ;
2012-12-30 21:45:50 -08:00
} ;
2013-01-04 16:58:23 -08:00
goog . inherits ( vjs . Slider , vjs . Component ) ;
2011-11-29 11:40:05 -08:00
2013-01-16 11:09:56 -05:00
vjs . Slider . prototype . createEl = function ( type , props ) {
2013-01-25 17:36:40 -08:00
props = vjs . obj . merge ( {
2013-01-10 13:06:12 -08:00
role : 'slider' ,
'aria-valuenow' : 0 ,
'aria-valuemin' : 0 ,
'aria-valuemax' : 100 ,
2012-12-30 21:45:50 -08:00
tabIndex : 0
2013-01-16 11:09:56 -05:00
} , props ) ;
2011-11-29 11:40:05 -08:00
2013-01-16 11:09:56 -05:00
return goog . base ( this , 'createEl' , type , props ) ;
2012-12-30 21:45:50 -08:00
} ;
2011-11-29 11:40:05 -08:00
2013-01-04 16:58:23 -08:00
vjs . Slider . prototype . onMouseDown = function ( event ) {
2012-12-30 21:45:50 -08:00
event . preventDefault ( ) ;
2013-01-04 16:58:23 -08:00
vjs . blockTextSelection ( ) ;
2011-11-29 11:40:05 -08:00
2013-03-12 11:45:59 -04:00
this . boundEvents . move = vjs . bind ( this , this . onMouseMove ) ;
this . boundEvents . end = vjs . bind ( this , this . onMouseUp ) ;
vjs . on ( document , 'mousemove' , this . boundEvents . move ) ;
vjs . on ( document , 'mouseup' , this . boundEvents . end ) ;
vjs . on ( document , 'touchmove' , this . boundEvents . move ) ;
vjs . on ( document , 'touchend' , this . boundEvents . end ) ;
2011-11-29 11:40:05 -08:00
2012-12-30 21:45:50 -08:00
this . onMouseMove ( event ) ;
} ;
2011-11-29 11:40:05 -08:00
2013-01-10 13:06:12 -08:00
vjs . Slider . prototype . onMouseUp = function ( ) {
2013-01-04 16:58:23 -08:00
vjs . unblockTextSelection ( ) ;
2013-03-12 11:45:59 -04:00
vjs . off ( document , 'mousemove' , this . boundEvents . move , false ) ;
vjs . off ( document , 'mouseup' , this . boundEvents . end , false ) ;
vjs . off ( document , 'touchmove' , this . boundEvents . move , false ) ;
vjs . off ( document , 'touchend' , this . boundEvents . end , false ) ;
2011-11-29 11:40:05 -08:00
2012-12-30 21:45:50 -08:00
this . update ( ) ;
} ;
2011-11-29 11:40:05 -08:00
2013-01-04 16:58:23 -08:00
vjs . Slider . prototype . update = function ( ) {
2013-02-22 22:26:58 -05:00
// In VolumeBar init we have a setTimeout for update that pops and update to the end of the
// execution stack. The player is destroyed before then update will cause an error
if ( ! this . el _ ) return ;
2012-12-30 21:45:50 -08:00
// If scrubbing, we could use a cached value to make the handle keep up with the user's mouse.
// On HTML5 browsers scrubbing is really smooth, but some flash players are slow, so we might want to utilize this later.
2013-01-16 20:24:38 -05:00
// var progress = (this.player_.scrubbing) ? this.player_.getCache().currentTime / this.player_.duration() : this.player_.currentTime() / this.player_.duration();
2011-11-29 11:40:05 -08:00
2012-12-30 21:45:50 -08:00
var barProgress ,
2013-01-10 13:06:12 -08:00
progress = this . getPercent ( ) ,
2012-12-30 21:45:50 -08:00
handle = this . handle ,
bar = this . bar ;
2011-11-29 11:40:05 -08:00
2012-12-30 21:45:50 -08:00
// Protect against no duration and other division issues
if ( isNaN ( progress ) ) { progress = 0 ; }
2011-11-29 11:40:05 -08:00
2012-12-30 21:45:50 -08:00
barProgress = progress ;
2011-11-29 11:40:05 -08:00
2012-12-30 21:45:50 -08:00
// If there is a handle, we need to account for the handle in our calculation for progress bar
// so that it doesn't fall short of or extend past the handle.
if ( handle ) {
2011-11-29 11:40:05 -08:00
2012-12-30 21:45:50 -08:00
var box = this . el _ ,
boxWidth = box . offsetWidth ,
2011-11-29 11:40:05 -08:00
2013-01-10 13:06:12 -08:00
handleWidth = handle . el ( ) . offsetWidth ,
2011-11-29 11:40:05 -08:00
2012-12-30 21:45:50 -08:00
// The width of the handle in percent of the containing box
// In IE, widths may not be ready yet causing NaN
handlePercent = ( handleWidth ) ? handleWidth / boxWidth : 0 ,
2011-11-29 11:40:05 -08:00
2012-12-30 21:45:50 -08:00
// Get the adjusted size of the box, considering that the handle's center never touches the left or right side.
// There is a margin of half the handle's width on both sides.
2013-01-10 13:06:12 -08:00
boxAdjustedPercent = 1 - handlePercent ,
2011-11-29 11:40:05 -08:00
2012-12-30 21:45:50 -08:00
// Adjust the progress that we'll use to set widths to the new adjusted box width
2013-01-10 13:06:12 -08:00
adjustedProgress = progress * boxAdjustedPercent ;
2011-11-29 11:40:05 -08:00
2013-01-10 13:06:12 -08:00
// The bar does reach the left side, so we need to account for this in the bar's width
barProgress = adjustedProgress + ( handlePercent / 2 ) ;
2011-11-29 11:40:05 -08:00
2012-12-30 21:45:50 -08:00
// Move the handle from the left based on the adjected progress
2013-01-10 13:06:12 -08:00
handle . el ( ) . style . left = vjs . round ( adjustedProgress * 100 , 2 ) + '%' ;
2012-12-30 21:45:50 -08:00
}
2011-12-05 11:28:18 -08:00
2012-12-30 21:45:50 -08:00
// Set the new bar width
2013-01-10 13:06:12 -08:00
bar . el ( ) . style . width = vjs . round ( barProgress * 100 , 2 ) + '%' ;
2012-12-30 21:45:50 -08:00
} ;
2011-12-05 11:28:18 -08:00
2013-01-04 16:58:23 -08:00
vjs . Slider . prototype . calculateDistance = function ( event ) {
2012-12-30 21:45:50 -08:00
var box = this . el _ ,
2013-01-04 16:58:23 -08:00
boxX = vjs . findPosX ( box ) ,
2012-12-30 21:45:50 -08:00
boxW = box . offsetWidth ,
2013-03-12 11:40:40 -04:00
handle = this . handle ,
pageX = event . pageX ;
2011-12-05 11:28:18 -08:00
2012-12-30 21:45:50 -08:00
if ( handle ) {
2013-01-10 13:06:12 -08:00
var handleW = handle . el ( ) . offsetWidth ;
2012-01-28 16:27:03 -08:00
2012-12-30 21:45:50 -08:00
// Adjusted X and Width, so handle doesn't go outside the bar
boxX = boxX + ( handleW / 2 ) ;
boxW = boxW - handleW ;
}
2011-12-05 11:28:18 -08:00
2013-03-12 11:40:40 -04:00
if ( pageX === 0 && event . changedTouches ) {
pageX = event . changedTouches [ 0 ] . pageX ;
}
2012-12-30 21:45:50 -08:00
// Percent that the click is through the adjusted area
2013-03-12 11:40:40 -04:00
return Math . max ( 0 , Math . min ( 1 , ( pageX - boxX ) / boxW ) ) ;
2012-12-30 21:45:50 -08:00
} ;
2011-12-05 11:28:18 -08:00
2013-01-10 13:06:12 -08:00
vjs . Slider . prototype . onFocus = function ( ) {
vjs . on ( document , 'keyup' , vjs . bind ( this , this . onKeyPress ) ) ;
2012-12-30 21:45:50 -08:00
} ;
2011-12-05 11:28:18 -08:00
2013-01-04 16:58:23 -08:00
vjs . Slider . prototype . onKeyPress = function ( event ) {
2012-12-30 21:45:50 -08:00
if ( event . which == 37 ) { // Left Arrow
event . preventDefault ( ) ;
this . stepBack ( ) ;
} else if ( event . which == 39 ) { // Right Arrow
2011-12-05 11:28:18 -08:00
event . preventDefault ( ) ;
2012-12-30 21:45:50 -08:00
this . stepForward ( ) ;
}
} ;
2011-12-05 11:28:18 -08:00
2013-01-10 13:06:12 -08:00
vjs . Slider . prototype . onBlur = function ( ) {
vjs . off ( document , 'keyup' , vjs . bind ( this , this . onKeyPress ) ) ;
2012-12-30 21:45:50 -08:00
} ;
2011-12-05 11:28:18 -08:00
2012-12-30 21:45:50 -08:00
/ * P r o g r e s s
=== === === === === === === === === === === === === === === === === === === === === === === === === === == * /
2011-12-21 17:59:36 -08:00
2012-12-30 21:45:50 -08:00
/ * *
* Seek , Load Progress , and Play Progress
2013-01-04 16:58:23 -08:00
* @ param { vjs . Player | Object } player
2012-12-30 21:45:50 -08:00
* @ param { Object = } options
* @ constructor
* /
2013-01-04 16:58:23 -08:00
vjs . ProgressControl = function ( player , options ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , player , options ) ;
} ;
2013-01-04 16:58:23 -08:00
goog . inherits ( vjs . ProgressControl , vjs . Component ) ;
2012-12-30 21:45:50 -08:00
2013-01-17 21:03:25 -05:00
vjs . ProgressControl . prototype . options _ = {
2012-12-30 21:45:50 -08:00
children : {
2013-01-10 13:06:12 -08:00
'seekBar' : { }
2012-12-30 21:45:50 -08:00
}
} ;
2013-01-04 16:58:23 -08:00
vjs . ProgressControl . prototype . createEl = function ( ) {
2013-01-10 13:06:12 -08:00
return goog . base ( this , 'createEl' , 'div' , {
className : 'vjs-progress-control vjs-control'
2012-12-30 21:45:50 -08:00
} ) ;
} ;
/ * *
* Seek Bar and holder for the progress bars
2013-01-04 16:58:23 -08:00
* @ param { vjs . Player | Object } player
2012-12-30 21:45:50 -08:00
* @ param { Object = } options
* @ constructor
* /
2013-01-04 16:58:23 -08:00
vjs . SeekBar = function ( player , options ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , player , options ) ;
2013-01-20 07:26:48 -05:00
player . on ( 'timeupdate' , vjs . bind ( this , this . updateARIAAttributes ) ) ;
player . ready ( vjs . bind ( this , this . updateARIAAttributes ) ) ;
2012-12-30 21:45:50 -08:00
} ;
2013-01-04 16:58:23 -08:00
goog . inherits ( vjs . SeekBar , vjs . Slider ) ;
2012-12-30 21:45:50 -08:00
2013-01-17 21:03:25 -05:00
vjs . SeekBar . prototype . options _ = {
2012-12-30 21:45:50 -08:00
children : {
2013-01-10 13:06:12 -08:00
'loadProgressBar' : { } ,
'playProgressBar' : { } ,
'seekHandle' : { }
2011-12-05 11:28:18 -08:00
} ,
2013-01-10 13:06:12 -08:00
'barName' : 'playProgressBar' ,
'handleName' : 'seekHandle'
2012-12-30 21:45:50 -08:00
} ;
2011-12-05 11:28:18 -08:00
2013-01-10 13:06:12 -08:00
vjs . SeekBar . prototype . playerEvent = 'timeupdate' ;
2011-12-05 11:28:18 -08:00
2013-01-04 16:58:23 -08:00
vjs . SeekBar . prototype . createEl = function ( ) {
2013-01-10 13:06:12 -08:00
return goog . base ( this , 'createEl' , 'div' , {
2013-01-20 07:26:48 -05:00
className : 'vjs-progress-holder' ,
'aria-label' : 'video progress bar'
2012-12-30 21:45:50 -08:00
} ) ;
} ;
2012-01-09 16:28:26 -08:00
2013-01-20 07:26:48 -05:00
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)
} ;
2013-01-04 16:58:23 -08:00
vjs . SeekBar . prototype . getPercent = function ( ) {
2013-01-16 20:24:38 -05:00
return this . player _ . currentTime ( ) / this . player _ . duration ( ) ;
2012-12-30 21:45:50 -08:00
} ;
2012-01-27 15:04:25 -08:00
2013-01-04 16:58:23 -08:00
vjs . SeekBar . prototype . onMouseDown = function ( event ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , 'onMouseDown' , event ) ;
2011-12-05 11:28:18 -08:00
2013-01-16 20:24:38 -05:00
this . player _ . scrubbing = true ;
2012-01-27 15:04:25 -08:00
2013-01-16 20:24:38 -05:00
this . videoWasPlaying = ! this . player _ . paused ( ) ;
this . player _ . pause ( ) ;
2012-12-30 21:45:50 -08:00
} ;
2011-12-05 11:28:18 -08:00
2013-01-04 16:58:23 -08:00
vjs . SeekBar . prototype . onMouseMove = function ( event ) {
2013-01-16 20:24:38 -05:00
var newTime = this . calculateDistance ( event ) * this . player _ . duration ( ) ;
2011-12-05 11:28:18 -08:00
2012-12-30 21:45:50 -08:00
// Don't let video end while scrubbing.
2013-01-16 20:24:38 -05:00
if ( newTime == this . player _ . duration ( ) ) { newTime = newTime - 0.1 ; }
2011-12-05 11:28:18 -08:00
2012-12-30 21:45:50 -08:00
// Set new time (tell player to seek to new time)
2013-01-16 20:24:38 -05:00
this . player _ . currentTime ( newTime ) ;
2012-12-30 21:45:50 -08:00
} ;
2011-12-05 11:28:18 -08:00
2013-01-04 16:58:23 -08:00
vjs . SeekBar . prototype . onMouseUp = function ( event ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , 'onMouseUp' , event ) ;
2011-12-05 11:28:18 -08:00
2013-01-16 20:24:38 -05:00
this . player _ . scrubbing = false ;
2012-12-30 21:45:50 -08:00
if ( this . videoWasPlaying ) {
2013-01-16 20:24:38 -05:00
this . player _ . play ( ) ;
2012-12-30 21:45:50 -08:00
}
} ;
2013-01-04 16:58:23 -08:00
vjs . SeekBar . prototype . stepForward = function ( ) {
2013-01-20 07:26:48 -05:00
this . player _ . currentTime ( this . player _ . currentTime ( ) + 5 ) ; // more quickly fast forward for keyboard-only users
2012-12-30 21:45:50 -08:00
} ;
2013-01-04 16:58:23 -08:00
vjs . SeekBar . prototype . stepBack = function ( ) {
2013-01-20 07:26:48 -05:00
this . player _ . currentTime ( this . player _ . currentTime ( ) - 5 ) ; // more quickly rewind for keyboard-only users
2012-12-30 21:45:50 -08:00
} ;
/ * *
* Shows load progres
2013-01-04 16:58:23 -08:00
* @ param { vjs . Player | Object } player
2012-12-30 21:45:50 -08:00
* @ param { Object = } options
* @ constructor
* /
2013-01-04 16:58:23 -08:00
vjs . LoadProgressBar = function ( player , options ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , player , options ) ;
2013-01-10 13:06:12 -08:00
player . on ( 'progress' , vjs . bind ( this , this . update ) ) ;
2012-12-30 21:45:50 -08:00
} ;
2013-01-04 16:58:23 -08:00
goog . inherits ( vjs . LoadProgressBar , vjs . Component ) ;
2012-12-30 21:45:50 -08:00
2013-01-04 16:58:23 -08:00
vjs . LoadProgressBar . prototype . createEl = function ( ) {
2013-01-10 13:06:12 -08:00
return goog . base ( this , 'createEl' , 'div' , {
className : 'vjs-load-progress' ,
2012-12-30 21:45:50 -08:00
innerHTML : '<span class="vjs-control-text">Loaded: 0%</span>'
} ) ;
} ;
2013-01-04 16:58:23 -08:00
vjs . LoadProgressBar . prototype . update = function ( ) {
2013-01-16 20:24:38 -05:00
if ( this . el _ . style ) { this . el _ . style . width = vjs . round ( this . player _ . bufferedPercent ( ) * 100 , 2 ) + '%' ; }
2012-12-30 21:45:50 -08:00
} ;
/ * *
* Shows play progress
2013-01-04 16:58:23 -08:00
* @ param { vjs . Player | Object } player
2012-12-30 21:45:50 -08:00
* @ param { Object = } options
* @ constructor
* /
2013-01-04 16:58:23 -08:00
vjs . PlayProgressBar = function ( player , options ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , player , options ) ;
} ;
2013-01-04 16:58:23 -08:00
goog . inherits ( vjs . PlayProgressBar , vjs . Component ) ;
2012-12-30 21:45:50 -08:00
2013-01-04 16:58:23 -08:00
vjs . PlayProgressBar . prototype . createEl = function ( ) {
2013-01-10 13:06:12 -08:00
return goog . base ( this , 'createEl' , 'div' , {
className : 'vjs-play-progress' ,
2012-12-30 21:45:50 -08:00
innerHTML : '<span class="vjs-control-text">Progress: 0%</span>'
} ) ;
} ;
/ * *
* SeekBar Behavior includes play progress bar , and seek handle
* Needed so it can determine seek position based on handle position / size
2013-01-04 16:58:23 -08:00
* @ param { vjs . Player | Object } player
2012-12-30 21:45:50 -08:00
* @ param { Object = } options
* @ constructor
* /
2013-01-04 16:58:23 -08:00
vjs . SeekHandle = function ( player , options ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , player , options ) ;
} ;
2013-01-04 16:58:23 -08:00
goog . inherits ( vjs . SeekHandle , vjs . Component ) ;
2012-12-30 21:45:50 -08:00
2013-01-04 16:58:23 -08:00
vjs . SeekHandle . prototype . createEl = function ( ) {
2013-01-10 13:06:12 -08:00
return goog . base ( this , 'createEl' , 'div' , {
className : 'vjs-seek-handle' ,
2012-12-30 21:45:50 -08:00
innerHTML : '<span class="vjs-control-text">00:00</span>'
} ) ;
} ;
/ * *
* Control the volume
2013-01-04 16:58:23 -08:00
* @ param { vjs . Player | Object } player
2012-12-30 21:45:50 -08:00
* @ param { Object = } options
* @ constructor
* /
2013-01-04 16:58:23 -08:00
vjs . VolumeControl = function ( player , options ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , player , options ) ;
2013-03-01 17:11:20 -05:00
// 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 ( ) ;
}
} ) ) ;
2012-12-30 21:45:50 -08:00
} ;
2013-01-04 16:58:23 -08:00
goog . inherits ( vjs . VolumeControl , vjs . Component ) ;
2012-12-30 21:45:50 -08:00
2013-01-17 21:03:25 -05:00
vjs . VolumeControl . prototype . options _ = {
2012-12-30 21:45:50 -08:00
children : {
2013-01-10 13:06:12 -08:00
'volumeBar' : { }
2012-12-30 21:45:50 -08:00
}
} ;
2013-01-04 16:58:23 -08:00
vjs . VolumeControl . prototype . createEl = function ( ) {
2013-01-10 13:06:12 -08:00
return goog . base ( this , 'createEl' , 'div' , {
className : 'vjs-volume-control vjs-control'
2012-12-30 21:45:50 -08:00
} ) ;
} ;
/ * *
* Contains volume level
2013-01-04 16:58:23 -08:00
* @ param { vjs . Player | Object } player
2012-12-30 21:45:50 -08:00
* @ param { Object = } options
* @ constructor
* /
2013-01-04 16:58:23 -08:00
vjs . VolumeBar = function ( player , options ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , player , options ) ;
2013-01-19 23:34:46 -05:00
player . on ( 'volumechange' , vjs . bind ( this , this . updateARIAAttributes ) ) ;
player . ready ( vjs . bind ( this , this . updateARIAAttributes ) ) ;
2013-02-08 16:06:15 +03:00
setTimeout ( vjs . bind ( this , this . update ) , 0 ) ; // update when elements is in DOM
2012-12-30 21:45:50 -08:00
} ;
2013-01-04 16:58:23 -08:00
goog . inherits ( vjs . VolumeBar , vjs . Slider ) ;
2012-12-30 21:45:50 -08:00
2013-01-19 23:34:46 -05:00
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 ) + '%' ) ;
} ;
2013-01-17 21:03:25 -05:00
vjs . VolumeBar . prototype . options _ = {
2012-12-30 21:45:50 -08:00
children : {
2013-01-10 13:06:12 -08:00
'volumeLevel' : { } ,
'volumeHandle' : { }
2011-12-05 11:28:18 -08:00
} ,
2013-01-10 13:06:12 -08:00
'barName' : 'volumeLevel' ,
'handleName' : 'volumeHandle'
2012-12-30 21:45:50 -08:00
} ;
2011-12-05 11:28:18 -08:00
2013-01-10 13:06:12 -08:00
vjs . VolumeBar . prototype . playerEvent = 'volumechange' ;
2011-12-05 11:28:18 -08:00
2013-01-04 16:58:23 -08:00
vjs . VolumeBar . prototype . createEl = function ( ) {
2013-01-10 13:06:12 -08:00
return goog . base ( this , 'createEl' , 'div' , {
2013-01-19 23:34:46 -05:00
className : 'vjs-volume-bar' ,
'aria-label' : 'volume level'
2012-12-30 21:45:50 -08:00
} ) ;
} ;
2011-12-05 11:28:18 -08:00
2013-01-04 16:58:23 -08:00
vjs . VolumeBar . prototype . onMouseMove = function ( event ) {
2013-01-16 20:24:38 -05:00
this . player _ . volume ( this . calculateDistance ( event ) ) ;
2012-12-30 21:45:50 -08:00
} ;
2011-12-05 11:28:18 -08:00
2013-01-04 16:58:23 -08:00
vjs . VolumeBar . prototype . getPercent = function ( ) {
2013-01-16 20:24:38 -05:00
return this . player _ . volume ( ) ;
2012-12-30 21:45:50 -08:00
} ;
2013-01-04 16:58:23 -08:00
vjs . VolumeBar . prototype . stepForward = function ( ) {
2013-01-16 20:24:38 -05:00
this . player _ . volume ( this . player _ . volume ( ) + 0.1 ) ;
2012-12-30 21:45:50 -08:00
} ;
2013-01-04 16:58:23 -08:00
vjs . VolumeBar . prototype . stepBack = function ( ) {
2013-01-16 20:24:38 -05:00
this . player _ . volume ( this . player _ . volume ( ) - 0.1 ) ;
2012-12-30 21:45:50 -08:00
} ;
/ * *
* Shows volume level
2013-01-04 16:58:23 -08:00
* @ param { vjs . Player | Object } player
2012-12-30 21:45:50 -08:00
* @ param { Object = } options
* @ constructor
* /
2013-01-04 16:58:23 -08:00
vjs . VolumeLevel = function ( player , options ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , player , options ) ;
} ;
2013-01-04 16:58:23 -08:00
goog . inherits ( vjs . VolumeLevel , vjs . Component ) ;
2012-12-30 21:45:50 -08:00
2013-01-04 16:58:23 -08:00
vjs . VolumeLevel . prototype . createEl = function ( ) {
2013-01-10 13:06:12 -08:00
return goog . base ( this , 'createEl' , 'div' , {
className : 'vjs-volume-level' ,
2012-12-30 21:45:50 -08:00
innerHTML : '<span class="vjs-control-text"></span>'
} ) ;
} ;
/ * *
* Change volume level
2013-01-04 16:58:23 -08:00
* @ param { vjs . Player | Object } player
2012-12-30 21:45:50 -08:00
* @ param { Object = } options
* @ constructor
* /
2013-01-04 16:58:23 -08:00
vjs . VolumeHandle = function ( player , options ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , player , options ) ;
} ;
2013-01-04 16:58:23 -08:00
goog . inherits ( vjs . VolumeHandle , vjs . Component ) ;
2012-12-30 21:45:50 -08:00
2013-01-04 16:58:23 -08:00
vjs . VolumeHandle . prototype . createEl = function ( ) {
2013-01-10 13:06:12 -08:00
return goog . base ( this , 'createEl' , 'div' , {
className : 'vjs-volume-handle' ,
2012-12-30 21:45:50 -08:00
innerHTML : '<span class="vjs-control-text"></span>'
// tabindex: 0,
2013-01-10 13:06:12 -08:00
// role: 'slider', 'aria-valuenow': 0, 'aria-valuemin': 0, 'aria-valuemax': 100
2012-12-30 21:45:50 -08:00
} ) ;
} ;
/ * *
* Mute the audio
2013-01-04 16:58:23 -08:00
* @ param { vjs . Player | Object } player
2012-12-30 21:45:50 -08:00
* @ param { Object = } options
* @ constructor
* /
2013-01-04 16:58:23 -08:00
vjs . MuteToggle = function ( player , options ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , player , options ) ;
2013-01-10 13:06:12 -08:00
player . on ( 'volumechange' , vjs . bind ( this , this . update ) ) ;
2013-03-01 17:11:20 -05:00
// 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 ( ) ;
}
} ) ) ;
2012-12-30 21:45:50 -08:00
} ;
2013-01-04 16:58:23 -08:00
goog . inherits ( vjs . MuteToggle , vjs . Button ) ;
2012-12-30 21:45:50 -08:00
2013-01-04 16:58:23 -08:00
vjs . MuteToggle . prototype . createEl = function ( ) {
2013-01-10 13:06:12 -08:00
return goog . base ( this , 'createEl' , 'div' , {
className : 'vjs-mute-control vjs-control' ,
2012-12-30 21:45:50 -08:00
innerHTML : '<div><span class="vjs-control-text">Mute</span></div>'
} ) ;
} ;
2013-01-10 13:06:12 -08:00
vjs . MuteToggle . prototype . onClick = function ( ) {
2013-01-16 20:24:38 -05:00
this . player _ . muted ( this . player _ . muted ( ) ? false : true ) ;
2012-12-30 21:45:50 -08:00
} ;
2013-01-10 13:06:12 -08:00
vjs . MuteToggle . prototype . update = function ( ) {
2013-01-16 20:24:38 -05:00
var vol = this . player _ . volume ( ) ,
2012-12-30 21:45:50 -08:00
level = 3 ;
2013-01-16 20:24:38 -05:00
if ( vol === 0 || this . player _ . muted ( ) ) {
2012-12-30 21:45:50 -08:00
level = 0 ;
} else if ( vol < 0.33 ) {
level = 1 ;
} else if ( vol < 0.67 ) {
level = 2 ;
2011-12-05 11:28:18 -08:00
}
2013-02-22 22:26:58 -05:00
2013-01-19 22:46:02 -05:00
// 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"
}
}
2011-12-05 11:28:18 -08:00
2012-12-30 21:45:50 -08:00
/* TODO improve muted icon classes */
for ( var i = 0 ; i < 4 ; i ++ ) {
2013-01-10 13:06:12 -08:00
vjs . removeClass ( this . el _ , 'vjs-vol-' + i ) ;
}
vjs . addClass ( this . el _ , 'vjs-vol-' + level ) ;
} ;
2011-12-05 11:28:18 -08:00
2012-12-30 21:45:50 -08:00
/ * P o s t e r I m a g e
2011-11-29 11:40:05 -08:00
=== === === === === === === === === === === === === === === === === === === === === === === === === === == * /
2012-12-30 21:45:50 -08:00
/ * *
* Poster image . Shows before the video plays .
2013-01-04 16:58:23 -08:00
* @ param { vjs . Player | Object } player
2012-12-30 21:45:50 -08:00
* @ param { Object = } options
* @ constructor
* /
2013-01-04 16:58:23 -08:00
vjs . PosterImage = function ( player , options ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , player , options ) ;
2013-01-18 18:06:15 -08:00
if ( ! player . poster ( ) ) {
2012-12-30 21:45:50 -08:00
this . hide ( ) ;
}
2011-11-29 11:40:05 -08:00
2013-01-10 13:06:12 -08:00
player . on ( 'play' , vjs . bind ( this , this . hide ) ) ;
2012-12-30 21:45:50 -08:00
} ;
2013-01-04 16:58:23 -08:00
goog . inherits ( vjs . PosterImage , vjs . Button ) ;
2011-11-29 11:40:05 -08:00
2013-01-04 16:58:23 -08:00
vjs . PosterImage . prototype . createEl = function ( ) {
2013-03-01 17:44:54 -05:00
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 } ) ) ;
}
2011-11-29 11:40:05 -08:00
}
2013-03-01 17:44:54 -05:00
2012-12-30 21:45:50 -08:00
return el ;
} ;
2011-11-29 11:40:05 -08:00
2013-01-04 16:58:23 -08:00
vjs . PosterImage . prototype . onClick = function ( ) {
2013-01-16 20:24:38 -05:00
this . player _ . play ( ) ;
2013-01-10 13:06:12 -08:00
} ;
2011-11-29 11:40:05 -08:00
2012-12-30 21:45:50 -08:00
/ * M e n u
=== === === === === === === === === === === === === === === === === === === === === === === === === === == * /
/ * *
* The base for text track and settings menu buttons .
2013-01-04 16:58:23 -08:00
* @ param { vjs . Player | Object } player
2012-12-30 21:45:50 -08:00
* @ param { Object = } options
* @ constructor
* /
2013-01-04 16:58:23 -08:00
vjs . Menu = function ( player , options ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , player , options ) ;
} ;
2013-01-04 16:58:23 -08:00
goog . inherits ( vjs . Menu , vjs . Component ) ;
2012-12-30 21:45:50 -08:00
2013-01-04 16:58:23 -08:00
vjs . Menu . prototype . addItem = function ( component ) {
this . addChild ( component ) ;
2013-01-10 13:06:12 -08:00
component . on ( 'click' , vjs . bind ( this , function ( ) {
2012-12-30 21:45:50 -08:00
this . unlockShowing ( ) ;
} ) ) ;
} ;
2013-01-04 16:58:23 -08:00
vjs . Menu . prototype . createEl = function ( ) {
2013-01-10 13:06:12 -08:00
return goog . base ( this , 'createEl' , 'ul' , {
className : 'vjs-menu'
2012-12-30 21:45:50 -08:00
} ) ;
} ;
/ * *
* Menu item
2013-01-04 16:58:23 -08:00
* @ param { vjs . Player | Object } player
2012-12-30 21:45:50 -08:00
* @ param { Object = } options
* @ constructor
* /
2013-01-04 16:58:23 -08:00
vjs . MenuItem = function ( player , options ) {
2012-12-30 21:45:50 -08:00
goog . base ( this , player , options ) ;
2013-01-17 20:45:22 -05:00
if ( options [ 'selected' ] ) {
2013-01-10 13:06:12 -08:00
this . addClass ( 'vjs-selected' ) ;
2013-01-20 07:26:48 -05:00
this . el _ . setAttribute ( 'aria-selected' , true ) ;
} else {
this . el _ . setAttribute ( 'aria-selected' , false ) ;
2012-12-30 21:45:50 -08:00
}
} ;
2013-01-04 16:58:23 -08:00
goog . inherits ( vjs . MenuItem , vjs . Button ) ;
2012-12-30 21:45:50 -08:00
2013-01-16 11:09:56 -05:00
vjs . MenuItem . prototype . createEl = function ( type , props ) {
2013-01-25 17:36:40 -08:00
return goog . base ( this , 'createEl' , 'li' , vjs . obj . merge ( {
2013-01-10 13:06:12 -08:00
className : 'vjs-menu-item' ,
2013-01-17 21:03:25 -05:00
innerHTML : this . options _ [ 'label' ]
2013-01-16 11:09:56 -05:00
} , props ) ) ;
2012-12-30 21:45:50 -08:00
} ;
2013-01-04 16:58:23 -08:00
vjs . MenuItem . prototype . onClick = function ( ) {
2012-12-30 21:45:50 -08:00
this . selected ( true ) ;
} ;
2013-01-04 16:58:23 -08:00
vjs . MenuItem . prototype . selected = function ( selected ) {
2012-12-30 21:45:50 -08:00
if ( selected ) {
2013-01-10 13:06:12 -08:00
this . addClass ( 'vjs-selected' ) ;
2013-01-20 07:26:48 -05:00
this . el _ . setAttribute ( 'aria-selected' , true ) ;
2012-12-30 21:45:50 -08:00
} else {
2013-01-10 13:06:12 -08:00
this . removeClass ( 'vjs-selected' ) ;
2013-01-20 07:26:48 -05:00
this . el _ . setAttribute ( 'aria-selected' , false ) ;
2012-12-30 21:45:50 -08:00
}
} ;