From 1d3ffb9244c148988e2aad30b5e4fc5345081a67 Mon Sep 17 00:00:00 2001 From: Gary Katsevman Date: Mon, 11 Aug 2014 18:58:49 -0400 Subject: [PATCH 1/3] Inherit tech 'features' from 'MediaTechController' Use vjs.obj.create to inherit 'features' from 'MediaTechController.prototype.features'. Because we are inheriting, if the defaults change (prototype.features), we can receive these updates in our tech if we had not changed properties of features manually. --- src/js/media/media.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/js/media/media.js b/src/js/media/media.js index 1d2e924df6..b87a5560d6 100644 --- a/src/js/media/media.js +++ b/src/js/media/media.js @@ -13,6 +13,11 @@ vjs.MediaTechController = vjs.Component.extend({ /** @constructor */ init: function(player, options, ready){ options = options || {}; + + // Make sure that `this.features` isn't directly tied to `vjs.MediaTechController.prototype.features` + // Using `vjs.obj.create` allows us to receive default updates from the prototype if we haven't changed the value. + this.features = vjs.obj.create(vjs.MediaTechController.prototype.features); + // we don't want the tech to report user activity automatically. // This is done manually in addControlsListeners options.reportTouchActivity = false; From 7a0226ba0be58b48bf58531965aa5cae1f5f7b12 Mon Sep 17 00:00:00 2001 From: Gary Katsevman Date: Tue, 12 Aug 2014 17:10:12 -0400 Subject: [PATCH 2/3] Promote 'features' to the prototype --- src/js/control-bar/mute-toggle.js | 4 ++-- .../control-bar/playback-rate-menu-button.js | 2 +- src/js/control-bar/volume-control.js | 4 ++-- src/js/control-bar/volume-menu-button.js | 4 ++-- src/js/exports.js | 9 ++++---- src/js/media/html5.js | 10 ++++----- src/js/media/media.js | 22 +++++++------------ src/js/player.js | 10 ++++----- 8 files changed, 29 insertions(+), 36 deletions(-) diff --git a/src/js/control-bar/mute-toggle.js b/src/js/control-bar/mute-toggle.js index 6f2b335ca6..961b29e3d0 100644 --- a/src/js/control-bar/mute-toggle.js +++ b/src/js/control-bar/mute-toggle.js @@ -13,11 +13,11 @@ vjs.MuteToggle = vjs.Button.extend({ 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) { + if (player.tech && player.tech['volumeControl'] === false) { this.addClass('vjs-hidden'); } player.on('loadstart', vjs.bind(this, function(){ - if (player.tech.features && player.tech.features['volumeControl'] === false) { + if (player.tech['volumeControl'] === false) { this.addClass('vjs-hidden'); } else { this.removeClass('vjs-hidden'); diff --git a/src/js/control-bar/playback-rate-menu-button.js b/src/js/control-bar/playback-rate-menu-button.js index c57512c4bb..1fd3c11d97 100644 --- a/src/js/control-bar/playback-rate-menu-button.js +++ b/src/js/control-bar/playback-rate-menu-button.js @@ -72,7 +72,7 @@ vjs.PlaybackRateMenuButton.prototype.onClick = function(){ vjs.PlaybackRateMenuButton.prototype.playbackRateSupported = function(){ return this.player().tech - && this.player().tech.features['playbackRate'] + && this.player().tech['playbackRate'] && this.player().options()['playbackRates'] && this.player().options()['playbackRates'].length > 0 ; diff --git a/src/js/control-bar/volume-control.js b/src/js/control-bar/volume-control.js index 64ec52d247..36c77a2262 100644 --- a/src/js/control-bar/volume-control.js +++ b/src/js/control-bar/volume-control.js @@ -11,11 +11,11 @@ vjs.VolumeControl = vjs.Component.extend({ 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) { + if (player.tech && player.tech['volumeControl'] === false) { this.addClass('vjs-hidden'); } player.on('loadstart', vjs.bind(this, function(){ - if (player.tech.features && player.tech.features['volumeControl'] === false) { + if (player.tech['volumeControl'] === false) { this.addClass('vjs-hidden'); } else { this.removeClass('vjs-hidden'); diff --git a/src/js/control-bar/volume-menu-button.js b/src/js/control-bar/volume-menu-button.js index 963e569e2f..05f6262644 100644 --- a/src/js/control-bar/volume-menu-button.js +++ b/src/js/control-bar/volume-menu-button.js @@ -11,11 +11,11 @@ vjs.VolumeMenuButton = vjs.MenuButton.extend({ 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) { + if (player.tech && player.tech.volumeControl === false) { this.addClass('vjs-hidden'); } player.on('loadstart', vjs.bind(this, function(){ - if (player.tech.features && player.tech.features.volumeControl === false) { + if (player.tech.volumeControl === false) { this.addClass('vjs-hidden'); } else { this.removeClass('vjs-hidden'); diff --git a/src/js/exports.js b/src/js/exports.js index 51ab773362..bc6e15f2c4 100644 --- a/src/js/exports.js +++ b/src/js/exports.js @@ -121,11 +121,10 @@ goog.exportSymbol('videojs.CaptionsButton', vjs.CaptionsButton); goog.exportSymbol('videojs.ChaptersButton', vjs.ChaptersButton); goog.exportSymbol('videojs.MediaTechController', vjs.MediaTechController); -goog.exportProperty(vjs.MediaTechController.prototype, 'features', vjs.MediaTechController.prototype.features); -goog.exportProperty(vjs.MediaTechController.prototype.features, 'volumeControl', vjs.MediaTechController.prototype.features.volumeControl); -goog.exportProperty(vjs.MediaTechController.prototype.features, 'fullscreenResize', vjs.MediaTechController.prototype.features.fullscreenResize); -goog.exportProperty(vjs.MediaTechController.prototype.features, 'progressEvents', vjs.MediaTechController.prototype.features.progressEvents); -goog.exportProperty(vjs.MediaTechController.prototype.features, 'timeupdateEvents', vjs.MediaTechController.prototype.features.timeupdateEvents); +goog.exportProperty(vjs.MediaTechController.prototype, 'volumeControl', vjs.MediaTechController.prototype.volumeControl); +goog.exportProperty(vjs.MediaTechController.prototype, 'fullscreenResize', vjs.MediaTechController.prototype.fullscreenResize); +goog.exportProperty(vjs.MediaTechController.prototype, 'progressEvents', vjs.MediaTechController.prototype.progressEvents); +goog.exportProperty(vjs.MediaTechController.prototype, 'timeupdateEvents', vjs.MediaTechController.prototype.timeupdateEvents); goog.exportProperty(vjs.MediaTechController.prototype, 'setPoster', vjs.MediaTechController.prototype.setPoster); diff --git a/src/js/media/html5.js b/src/js/media/html5.js index eb4b41218d..5c47e99ffc 100644 --- a/src/js/media/html5.js +++ b/src/js/media/html5.js @@ -13,16 +13,16 @@ vjs.Html5 = vjs.MediaTechController.extend({ /** @constructor */ init: function(player, options, ready){ // volume cannot be changed from 1 on iOS - this.features['volumeControl'] = vjs.Html5.canControlVolume(); + this['volumeControl'] = vjs.Html5.canControlVolume(); // just in case; or is it excessively... - this.features['playbackRate'] = vjs.Html5.canControlPlaybackRate(); + this['playbackRate'] = vjs.Html5.canControlPlaybackRate(); // In iOS, if you move a video element in the DOM, it breaks video playback. - this.features['movingMediaElementInDOM'] = !vjs.IS_IOS; + this['movingMediaElementInDOM'] = !vjs.IS_IOS; // HTML video is able to automatically resize when going to fullscreen - this.features['fullscreenResize'] = true; + this['fullscreenResize'] = true; vjs.MediaTechController.call(this, player, options, ready); this.setupTriggers(); @@ -72,7 +72,7 @@ vjs.Html5.prototype.createEl = function(){ // Check if this browser supports moving the element into the box. // On the iPhone video will break if you move the element, // So we have to create a brand new element. - if (!el || this.features['movingMediaElementInDOM'] === false) { + if (!el || this['movingMediaElementInDOM'] === false) { // If the original tag is still there, clone and remove it. if (el) { diff --git a/src/js/media/media.js b/src/js/media/media.js index b87a5560d6..2781a28fe0 100644 --- a/src/js/media/media.js +++ b/src/js/media/media.js @@ -14,10 +14,6 @@ vjs.MediaTechController = vjs.Component.extend({ init: function(player, options, ready){ options = options || {}; - // Make sure that `this.features` isn't directly tied to `vjs.MediaTechController.prototype.features` - // Using `vjs.obj.create` allows us to receive default updates from the prototype if we haven't changed the value. - this.features = vjs.obj.create(vjs.MediaTechController.prototype.features); - // we don't want the tech to report user activity automatically. // This is done manually in addControlsListeners options.reportTouchActivity = false; @@ -166,17 +162,15 @@ vjs.MediaTechController.prototype.onTap = function(){ */ vjs.MediaTechController.prototype.setPoster = function(){}; -vjs.MediaTechController.prototype.features = { - 'volumeControl': true, +vjs.MediaTechController.prototype[ 'volumeControl' ] = true; - // Resizing plugins using request fullscreen reloads the plugin - 'fullscreenResize': false, - 'playbackRate': false, +// Resizing plugins using request fullscreen reloads the plugin +vjs.MediaTechController.prototype[ 'fullscreenResize' ] = false; +vjs.MediaTechController.prototype[ 'playbackRate' ] = false; - // Optional events that we can manually mimic with timers - // currently not triggered by video-js-swf - 'progressEvents': false, - 'timeupdateEvents': false -}; +// Optional events that we can manually mimic with timers +// currently not triggered by video-js-swf +vjs.MediaTechController.prototype[ 'progressEvents' ] = false; +vjs.MediaTechController.prototype[ 'timeupdateEvents' ] = false; vjs.media = {}; diff --git a/src/js/player.js b/src/js/player.js index 781628b773..1071514a76 100644 --- a/src/js/player.js +++ b/src/js/player.js @@ -313,12 +313,12 @@ vjs.Player.prototype.loadTech = function(techName, source){ this.player_.triggerReady(); // Manually track progress in cases where the browser/flash player doesn't report it. - if (!this.features['progressEvents']) { + if (!this['progressEvents']) { this.player_.manualProgressOn(); } // Manually track timeudpates in cases where the browser/flash player doesn't report it. - if (!this.features['timeupdateEvents']) { + if (!this['timeupdateEvents']) { this.player_.manualTimeUpdatesOn(); } }; @@ -386,7 +386,7 @@ vjs.Player.prototype.manualProgressOn = function(){ this.tech.one('progress', function(){ // Update known progress support for this playback technology - this.features['progressEvents'] = true; + this['progressEvents'] = true; // Turn off manual progress tracking this.player_.manualProgressOff(); @@ -431,7 +431,7 @@ vjs.Player.prototype.manualTimeUpdatesOn = function(){ if (this.tech) { this.tech.one('timeupdate', function(){ // Update known progress support for this playback technology - this.features['timeupdateEvents'] = true; + this['timeupdateEvents'] = true; // Turn off manual progress tracking this.player_.manualTimeUpdatesOff(); }); @@ -1641,7 +1641,7 @@ vjs.Player.prototype.playbackRate = function(rate) { return this; } - if (this.tech && this.tech.features && this.tech.features['playbackRate']) { + if (this.tech && this.tech['playbackRate']) { return this.techGet('playbackRate'); } else { return 1.0; From 786ffee580e3107dda328d28c54130b7a0c29c99 Mon Sep 17 00:00:00 2001 From: Gary Katsevman Date: Tue, 12 Aug 2014 17:51:50 -0400 Subject: [PATCH 3/3] Append Feature to 'features'. Update tests. --- src/js/control-bar/mute-toggle.js | 4 ++-- src/js/control-bar/playback-rate-menu-button.js | 2 +- src/js/control-bar/volume-control.js | 4 ++-- src/js/control-bar/volume-menu-button.js | 4 ++-- src/js/exports.js | 9 +++++---- src/js/media/html5.js | 6 +++--- src/js/media/media.js | 11 +++++------ src/js/player.js | 10 +++++----- test/unit/controls.js | 12 ++++-------- test/unit/mediafaker.js | 1 - 10 files changed, 29 insertions(+), 34 deletions(-) diff --git a/src/js/control-bar/mute-toggle.js b/src/js/control-bar/mute-toggle.js index 961b29e3d0..9f8358ffc0 100644 --- a/src/js/control-bar/mute-toggle.js +++ b/src/js/control-bar/mute-toggle.js @@ -13,11 +13,11 @@ vjs.MuteToggle = vjs.Button.extend({ 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['volumeControl'] === false) { + if (player.tech && player.tech['volumeControlFeature'] === false) { this.addClass('vjs-hidden'); } player.on('loadstart', vjs.bind(this, function(){ - if (player.tech['volumeControl'] === false) { + if (player.tech['volumeControlFeature'] === false) { this.addClass('vjs-hidden'); } else { this.removeClass('vjs-hidden'); diff --git a/src/js/control-bar/playback-rate-menu-button.js b/src/js/control-bar/playback-rate-menu-button.js index 1fd3c11d97..17c6a9c52b 100644 --- a/src/js/control-bar/playback-rate-menu-button.js +++ b/src/js/control-bar/playback-rate-menu-button.js @@ -72,7 +72,7 @@ vjs.PlaybackRateMenuButton.prototype.onClick = function(){ vjs.PlaybackRateMenuButton.prototype.playbackRateSupported = function(){ return this.player().tech - && this.player().tech['playbackRate'] + && this.player().tech['playbackRateFeature'] && this.player().options()['playbackRates'] && this.player().options()['playbackRates'].length > 0 ; diff --git a/src/js/control-bar/volume-control.js b/src/js/control-bar/volume-control.js index 36c77a2262..b551332ad6 100644 --- a/src/js/control-bar/volume-control.js +++ b/src/js/control-bar/volume-control.js @@ -11,11 +11,11 @@ vjs.VolumeControl = vjs.Component.extend({ vjs.Component.call(this, player, options); // hide volume controls when they're not supported by the current tech - if (player.tech && player.tech['volumeControl'] === false) { + if (player.tech && player.tech['volumeControlFeature'] === false) { this.addClass('vjs-hidden'); } player.on('loadstart', vjs.bind(this, function(){ - if (player.tech['volumeControl'] === false) { + if (player.tech['volumeControlFeature'] === false) { this.addClass('vjs-hidden'); } else { this.removeClass('vjs-hidden'); diff --git a/src/js/control-bar/volume-menu-button.js b/src/js/control-bar/volume-menu-button.js index 05f6262644..2a74049282 100644 --- a/src/js/control-bar/volume-menu-button.js +++ b/src/js/control-bar/volume-menu-button.js @@ -11,11 +11,11 @@ vjs.VolumeMenuButton = vjs.MenuButton.extend({ 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.volumeControl === false) { + if (player.tech && player.tech['volumeControlFeature'] === false) { this.addClass('vjs-hidden'); } player.on('loadstart', vjs.bind(this, function(){ - if (player.tech.volumeControl === false) { + if (player.tech['volumeControlFeature'] === false) { this.addClass('vjs-hidden'); } else { this.removeClass('vjs-hidden'); diff --git a/src/js/exports.js b/src/js/exports.js index bc6e15f2c4..fafbc5e07c 100644 --- a/src/js/exports.js +++ b/src/js/exports.js @@ -121,10 +121,11 @@ goog.exportSymbol('videojs.CaptionsButton', vjs.CaptionsButton); goog.exportSymbol('videojs.ChaptersButton', vjs.ChaptersButton); goog.exportSymbol('videojs.MediaTechController', vjs.MediaTechController); -goog.exportProperty(vjs.MediaTechController.prototype, 'volumeControl', vjs.MediaTechController.prototype.volumeControl); -goog.exportProperty(vjs.MediaTechController.prototype, 'fullscreenResize', vjs.MediaTechController.prototype.fullscreenResize); -goog.exportProperty(vjs.MediaTechController.prototype, 'progressEvents', vjs.MediaTechController.prototype.progressEvents); -goog.exportProperty(vjs.MediaTechController.prototype, 'timeupdateEvents', vjs.MediaTechController.prototype.timeupdateEvents); +goog.exportProperty(vjs.MediaTechController.prototype, 'volumeControlFeature', vjs.MediaTechController.prototype.volumeControlFeature); +goog.exportProperty(vjs.MediaTechController.prototype, 'fullscreenResizeFeature', vjs.MediaTechController.prototype.fullscreenResizeFeature); +goog.exportProperty(vjs.MediaTechController.prototype, 'playbackRateFeature', vjs.MediaTechController.prototype.playbackRateFeature); +goog.exportProperty(vjs.MediaTechController.prototype, 'progressEventsFeature', vjs.MediaTechController.prototype.progressEventsFeature); +goog.exportProperty(vjs.MediaTechController.prototype, 'timeupdateEventsFeature', vjs.MediaTechController.prototype.timeupdateEventsFeature); goog.exportProperty(vjs.MediaTechController.prototype, 'setPoster', vjs.MediaTechController.prototype.setPoster); diff --git a/src/js/media/html5.js b/src/js/media/html5.js index 5c47e99ffc..6add04d651 100644 --- a/src/js/media/html5.js +++ b/src/js/media/html5.js @@ -13,16 +13,16 @@ vjs.Html5 = vjs.MediaTechController.extend({ /** @constructor */ init: function(player, options, ready){ // volume cannot be changed from 1 on iOS - this['volumeControl'] = vjs.Html5.canControlVolume(); + this['volumeControlFeature'] = vjs.Html5.canControlVolume(); // just in case; or is it excessively... - this['playbackRate'] = vjs.Html5.canControlPlaybackRate(); + this['playbackRateFeature'] = vjs.Html5.canControlPlaybackRate(); // In iOS, if you move a video element in the DOM, it breaks video playback. this['movingMediaElementInDOM'] = !vjs.IS_IOS; // HTML video is able to automatically resize when going to fullscreen - this['fullscreenResize'] = true; + this['fullscreenResizeFeature'] = true; vjs.MediaTechController.call(this, player, options, ready); this.setupTriggers(); diff --git a/src/js/media/media.js b/src/js/media/media.js index 2781a28fe0..6f9fee608d 100644 --- a/src/js/media/media.js +++ b/src/js/media/media.js @@ -13,7 +13,6 @@ vjs.MediaTechController = vjs.Component.extend({ /** @constructor */ init: function(player, options, ready){ options = options || {}; - // we don't want the tech to report user activity automatically. // This is done manually in addControlsListeners options.reportTouchActivity = false; @@ -162,15 +161,15 @@ vjs.MediaTechController.prototype.onTap = function(){ */ vjs.MediaTechController.prototype.setPoster = function(){}; -vjs.MediaTechController.prototype[ 'volumeControl' ] = true; +vjs.MediaTechController.prototype['volumeControlFeature'] = true; // Resizing plugins using request fullscreen reloads the plugin -vjs.MediaTechController.prototype[ 'fullscreenResize' ] = false; -vjs.MediaTechController.prototype[ 'playbackRate' ] = false; +vjs.MediaTechController.prototype['fullscreenResizeFeature'] = false; +vjs.MediaTechController.prototype['playbackRateFeature'] = false; // Optional events that we can manually mimic with timers // currently not triggered by video-js-swf -vjs.MediaTechController.prototype[ 'progressEvents' ] = false; -vjs.MediaTechController.prototype[ 'timeupdateEvents' ] = false; +vjs.MediaTechController.prototype['progressEventsFeature'] = false; +vjs.MediaTechController.prototype['timeupdateEventsFeature'] = false; vjs.media = {}; diff --git a/src/js/player.js b/src/js/player.js index 1071514a76..c63c3dac55 100644 --- a/src/js/player.js +++ b/src/js/player.js @@ -313,12 +313,12 @@ vjs.Player.prototype.loadTech = function(techName, source){ this.player_.triggerReady(); // Manually track progress in cases where the browser/flash player doesn't report it. - if (!this['progressEvents']) { + if (!this['progressEventsFeature']) { this.player_.manualProgressOn(); } // Manually track timeudpates in cases where the browser/flash player doesn't report it. - if (!this['timeupdateEvents']) { + if (!this['timeupdateEventsFeature']) { this.player_.manualTimeUpdatesOn(); } }; @@ -386,7 +386,7 @@ vjs.Player.prototype.manualProgressOn = function(){ this.tech.one('progress', function(){ // Update known progress support for this playback technology - this['progressEvents'] = true; + this['progressEventsFeature'] = true; // Turn off manual progress tracking this.player_.manualProgressOff(); @@ -431,7 +431,7 @@ vjs.Player.prototype.manualTimeUpdatesOn = function(){ if (this.tech) { this.tech.one('timeupdate', function(){ // Update known progress support for this playback technology - this['timeupdateEvents'] = true; + this['timeupdateEventsFeature'] = true; // Turn off manual progress tracking this.player_.manualTimeUpdatesOff(); }); @@ -1641,7 +1641,7 @@ vjs.Player.prototype.playbackRate = function(rate) { return this; } - if (this.tech && this.tech['playbackRate']) { + if (this.tech && this.tech['playbackRateFeature']) { return this.techGet('playbackRate'); } else { return 1.0; diff --git a/test/unit/controls.js b/test/unit/controls.js index 9c99ebecef..b5a81c7763 100644 --- a/test/unit/controls.js +++ b/test/unit/controls.js @@ -12,9 +12,7 @@ test('should hide volume control if it\'s not supported', function(){ language: noop, languages: noop, tech: { - features: { - 'volumeControl': false - } + 'volumeControlFeature': false }, volume: function(){}, muted: function(){}, @@ -47,9 +45,7 @@ test('should test and toggle volume control on `loadstart`', function(){ return false; }, tech: { - features: { - 'volumeControl': true - } + 'volumeControlFeature': true }, reportUserActivity: function(){} }; @@ -62,7 +58,7 @@ test('should test and toggle volume control on `loadstart`', function(){ ok(muteToggle.el().className.indexOf('vjs-hidden') < 0, 'muteToggle is hidden initially'); - player.tech.features['volumeControl'] = false; + player.tech['volumeControlFeature'] = false; for (i = 0; i < listeners.length; i++) { listeners[i](); } @@ -72,7 +68,7 @@ test('should test and toggle volume control on `loadstart`', function(){ ok(muteToggle.el().className.indexOf('vjs-hidden') >= 0, 'muteToggle does not hide itself'); - player.tech.features['volumeControl'] = true; + player.tech['volumeControlFeature'] = true; for (i = 0; i < listeners.length; i++) { listeners[i](); } diff --git a/test/unit/mediafaker.js b/test/unit/mediafaker.js index 222a9c10e1..907bca62f9 100644 --- a/test/unit/mediafaker.js +++ b/test/unit/mediafaker.js @@ -42,7 +42,6 @@ vjs.MediaFaker.prototype.muted = function(){ return false; }; vjs.MediaFaker.prototype.pause = function(){ return false; }; vjs.MediaFaker.prototype.paused = function(){ return true; }; vjs.MediaFaker.prototype.supportsFullScreen = function(){ return false; }; -vjs.MediaFaker.prototype.features = {}; vjs.MediaFaker.prototype.buffered = function(){ return {}; }; vjs.MediaFaker.prototype.duration = function(){ return {}; };