From 05ab972a1af80ddffbe446d4700e851fea7e33d6 Mon Sep 17 00:00:00 2001 From: Steve Heffernan Date: Thu, 2 May 2013 19:03:29 -0700 Subject: [PATCH] Broke up controls.js into multiple files. Cleaned up media.js files also. --- Gruntfile.js | 4 +- build/source-loader.js | 17 +- src/js/control-bar/control-bar.js | 87 +++ src/js/control-bar/fullscreen-toggle.js | 28 + src/js/control-bar/mute-toggle.js | 69 ++ src/js/control-bar/play-toggle.js | 44 ++ src/js/control-bar/progress-control.js | 171 ++++ src/js/control-bar/time-display.js | 133 ++++ src/js/control-bar/volume-control.js | 134 ++++ src/js/control-bar/volume-menu-button.js | 48 ++ src/js/controls.js | 738 ------------------ .../flash.externs.js} | 0 src/js/{media.flash.js => media/flash.js} | 0 src/js/{media.html5.js => media/html5.js} | 0 src/js/{media.loader.js => media/loader.js} | 0 src/js/{ => media}/media.js | 0 16 files changed, 728 insertions(+), 745 deletions(-) create mode 100644 src/js/control-bar/control-bar.js create mode 100644 src/js/control-bar/fullscreen-toggle.js create mode 100644 src/js/control-bar/mute-toggle.js create mode 100644 src/js/control-bar/play-toggle.js create mode 100644 src/js/control-bar/progress-control.js create mode 100644 src/js/control-bar/time-display.js create mode 100644 src/js/control-bar/volume-control.js create mode 100644 src/js/control-bar/volume-menu-button.js delete mode 100644 src/js/controls.js rename src/js/{media.flash.externs.js => media/flash.externs.js} (100%) rename src/js/{media.flash.js => media/flash.js} (100%) rename src/js/{media.html5.js => media/html5.js} (100%) rename src/js/{media.loader.js => media/loader.js} (100%) rename src/js/{ => media}/media.js (100%) diff --git a/Gruntfile.js b/Gruntfile.js index 5d9b89ac5..688a13784 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -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' } }, diff --git a/build/source-loader.js b/build/source-loader.js index 0627d4ede..af58d8ad6 100644 --- a/build/source-loader.js +++ b/build/source-loader.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", diff --git a/src/js/control-bar/control-bar.js b/src/js/control-bar/control-bar.js new file mode 100644 index 000000000..20510cd83 --- /dev/null +++ b/src/js/control-bar/control-bar.js @@ -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'); +}; \ No newline at end of file diff --git a/src/js/control-bar/fullscreen-toggle.js b/src/js/control-bar/fullscreen-toggle.js new file mode 100644 index 000000000..285732324 --- /dev/null +++ b/src/js/control-bar/fullscreen-toggle.js @@ -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" + } +}; \ No newline at end of file diff --git a/src/js/control-bar/mute-toggle.js b/src/js/control-bar/mute-toggle.js new file mode 100644 index 000000000..aafedcaec --- /dev/null +++ b/src/js/control-bar/mute-toggle.js @@ -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: '
Mute
' + }); +}; + +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); +}; \ No newline at end of file diff --git a/src/js/control-bar/play-toggle.js b/src/js/control-bar/play-toggle.js new file mode 100644 index 000000000..5b624dc24 --- /dev/null +++ b/src/js/control-bar/play-toggle.js @@ -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" +}; \ No newline at end of file diff --git a/src/js/control-bar/progress-control.js b/src/js/control-bar/progress-control.js new file mode 100644 index 000000000..66ef195ca --- /dev/null +++ b/src/js/control-bar/progress-control.js @@ -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: 'Loaded: 0%' + }); +}; + +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: 'Progress: 0%' + }); +}; + +/** + * 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' + }); +}; \ No newline at end of file diff --git a/src/js/control-bar/time-display.js b/src/js/control-bar/time-display.js new file mode 100644 index 000000000..81e430d65 --- /dev/null +++ b/src/js/control-bar/time-display.js @@ -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: 'Current Time ' + '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 = 'Current Time ' + 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: 'Duration Time ' + '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 = 'Duration Time ' + 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: '
/
' + }); +}; + +/** + * 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: 'Remaining Time ' + '-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 = 'Remaining Time ' + '-'+ 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()); +}; \ No newline at end of file diff --git a/src/js/control-bar/volume-control.js b/src/js/control-bar/volume-control.js new file mode 100644 index 000000000..86bc5b617 --- /dev/null +++ b/src/js/control-bar/volume-control.js @@ -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: '' + }); +}; + +/** + * 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' + }); + }; \ No newline at end of file diff --git a/src/js/control-bar/volume-menu-button.js b/src/js/control-bar/volume-menu-button.js new file mode 100644 index 000000000..21b2836f8 --- /dev/null +++ b/src/js/control-bar/volume-menu-button.js @@ -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: '
Mute
' + }); +}; +vjs.VolumeMenuButton.prototype.update = vjs.MuteToggle.prototype.update; diff --git a/src/js/controls.js b/src/js/controls.js deleted file mode 100644 index 3a3cbc88c..000000000 --- a/src/js/controls.js +++ /dev/null @@ -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: 'Current Time ' + '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 = 'Current Time ' + 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: 'Duration Time ' + '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 = 'Duration Time ' + 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: '
/
' - }); -}; - -/** - * 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: 'Remaining Time ' + '-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 = 'Remaining Time ' + '-'+ 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: 'Loaded: 0%' - }); -}; - -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: 'Progress: 0%' - }); -}; - -/** - * 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: '' - }); -}; - -/** - * 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: '
Mute
' - }); -}; - -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: '
Mute
' - }); -}; -vjs.VolumeMenuButton.prototype.update = vjs.MuteToggle.prototype.update; diff --git a/src/js/media.flash.externs.js b/src/js/media/flash.externs.js similarity index 100% rename from src/js/media.flash.externs.js rename to src/js/media/flash.externs.js diff --git a/src/js/media.flash.js b/src/js/media/flash.js similarity index 100% rename from src/js/media.flash.js rename to src/js/media/flash.js diff --git a/src/js/media.html5.js b/src/js/media/html5.js similarity index 100% rename from src/js/media.html5.js rename to src/js/media/html5.js diff --git a/src/js/media.loader.js b/src/js/media/loader.js similarity index 100% rename from src/js/media.loader.js rename to src/js/media/loader.js diff --git a/src/js/media.js b/src/js/media/media.js similarity index 100% rename from src/js/media.js rename to src/js/media/media.js