From a839c89f0bfd8d4a088c6a2701ea51c3386f292c Mon Sep 17 00:00:00 2001 From: Steve Heffernan Date: Thu, 2 Feb 2012 14:56:47 -0800 Subject: [PATCH 1/4] Updated player API to be avialable immediately. Moved auto setup code to setup.js. --- src/component.js | 3 + src/core.js | 52 +---------- src/player.js | 233 ++++++++++++++++++++++++++++++----------------- src/setup.js | 50 ++++++++++ 4 files changed, 201 insertions(+), 137 deletions(-) diff --git a/src/component.js b/src/component.js index c1c64f9521..454dcb7e2b 100644 --- a/src/component.js +++ b/src/component.js @@ -184,6 +184,9 @@ _V_.Component = _V_.Class.extend({ // Reset Ready Queue this.readyQueue = []; + + // Allow for using event listeners also, in case you want to do something everytime a source is ready. + this.triggerEvent("ready"); } }, diff --git a/src/core.js b/src/core.js index dd3ffca7d9..f87f60aab8 100644 --- a/src/core.js +++ b/src/core.js @@ -113,54 +113,4 @@ VideoJS.options = { // Set CDN Version of swf if (CDN_VERSION != "GENERATED_CDN_VSN") { _V_.options.flash.swf = "http://vjs.zencdn.net/"+CDN_VERSION+"/video-js.swf" -} - -// Automatically set up any tags that have a data-setup attribute -_V_.autoSetup = function(){ - var options, vid, player, - vids = document.getElementsByTagName("video"); - - // Check if any media elements exist - if (vids && vids.length > 0) { - - for (var i=0,j=vids.length; i 0 && buffered.end(0) !== end) { @@ -410,34 +436,46 @@ _V_.Player = _V_.Component.extend({ return _V_.createTimeRange(start, end); }, - // Calculates amount of buffer is full + // Calculates amount of buffer is full. Not in spec but useful. bufferedPercent: function(){ return (this.duration()) ? this.buffered().end(0) / this.duration() : 0; }, + // http://dev.w3.org/html5/spec/video.html#dom-media-volume volume: function(percentAsDecimal){ + var vol; + if (percentAsDecimal !== undefined) { - var vol = Math.max(0, Math.min(1, parseFloat(percentAsDecimal))); // Force value to between 0 and 1 + vol = Math.max(0, Math.min(1, parseFloat(percentAsDecimal))); // Force value to between 0 and 1 this.values.volume = vol; - this.apiCall("setVolume", vol); + this.techCall("setVolume", vol); _V_.setLocalStorage("volume", vol); return this; } - // if (this.values.volume) { return this.values.volume; } - return this.apiCall("volume"); + + // Default to 1 when returning current volume. + vol = parseFloat(this.techCall("volume")); + return (isNaN(vol)) ? 1 : vol; }, + + // http://dev.w3.org/html5/spec/video.html#attr-media-muted muted: function(muted){ if (muted !== undefined) { - this.apiCall("setMuted", muted); + this.techCall("setMuted", muted); return this; } - return this.apiCall("muted"); + return this.techCall("muted") || false; // Default to false }, + // http://dev.w3.org/html5/spec/dimension-attributes.html#attr-dim-height + // Video tag width/height only work in pixels. No percents. + // We could potentially allow percents but won't for now until we can do testing around it. width: function(width, skipListeners){ if (width !== undefined) { this.el.width = width; this.el.style.width = width+"px"; + + // skipListeners allows us to avoid triggering the resize event when setting both width and height if (!skipListeners) { this.triggerEvent("resize"); } return this; } @@ -452,12 +490,14 @@ _V_.Player = _V_.Component.extend({ } return parseInt(this.el.getAttribute("height")); }, + // Set both width and height at the same time. size: function(width, height){ // Skip resize listeners on width for optimization return this.width(width, true).height(height); }, - supportsFullScreen: function(){ return this.apiCall("supportsFullScreen"); }, + // Check if current tech can support native fullscreen (e.g. with built in controls lik iOS, so not our flash swf) + supportsFullScreen: function(){ return this.techCall("supportsFullScreen") || false; }, // Turn on fullscreen (or window) mode requestFullScreen: function(){ @@ -492,7 +532,7 @@ _V_.Player = _V_.Component.extend({ })); } else if (this.tech.supportsFullScreen()) { - this.apiCall("enterFullScreen"); + this.techCall("enterFullScreen"); } else { this.enterFullWindow(); @@ -528,7 +568,7 @@ _V_.Player = _V_.Component.extend({ } } else if (this.tech.supportsFullScreen()) { - this.apiCall("exitFullScreen"); + this.techCall("exitFullScreen"); } else { this.exitFullWindow(); @@ -540,6 +580,7 @@ _V_.Player = _V_.Component.extend({ return this; }, + // When fullscreen isn't supported we can stretch the video container to as wide as the browser will let us. enterFullWindow: function(){ this.isFullWindow = true; @@ -558,7 +599,6 @@ _V_.Player = _V_.Component.extend({ this.triggerEvent("enterFullWindow"); }, - fullWindowOnEscKey: function(event){ if (event.keyCode == 27) { if (this.isFullScreen == true) { @@ -585,6 +625,36 @@ _V_.Player = _V_.Component.extend({ this.triggerEvent("exitFullWindow"); }, + selectSource: function(sources){ + + _V_.log(sources) + + // Loop through each playback technology in the options order + for (var i=0,j=this.options.techOrder;i 0) { + + for (var i=0,j=vids.length; i Date: Thu, 2 Feb 2012 19:16:45 -0800 Subject: [PATCH 2/4] Introduced techSet/techCall methods. techCall caches method calls if tech isn't ready. techGet provides defaults. --- src/player.js | 78 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 31 deletions(-) diff --git a/src/player.js b/src/player.js index 63b37785c5..fc5600edbf 100644 --- a/src/player.js +++ b/src/player.js @@ -65,9 +65,6 @@ _V_.Player = _V_.Component.extend({ } } - // Holder for playback tech components - this.techs = {}; - // Cache for video property values. this.values = {}; @@ -99,8 +96,9 @@ _V_.Player = _V_.Component.extend({ } } } else { - // Loop through playback technologies (HTML5, Flash) and check for support - // Then load the best source. + // Loop through playback technologies (HTML5, Flash) and check for support. Then load the best source. + // A few assumptions here: + // All playback technologies respect preload false. this.src(options.sources); } }, @@ -115,9 +113,7 @@ _V_.Player = _V_.Component.extend({ delete _V_.players[this.id] }, - createElement: function(type, options){ - - }, + createElement: function(type, options){}, getVideoTagSettings: function(){ var options = { @@ -352,23 +348,43 @@ _V_.Player = _V_.Component.extend({ /* Player API ================================================================================ */ - // Method for calling methods on the current playback technology + // Pass values to the playback tech techCall: function(method, arg){ + + // If it's not ready yet, call method when it is + if (!this.tech.isReady) { + this.tech.ready(function(){ + this[method](arg); + }); + + // Otherwise call method now + } else { + this.tech[method](arg); + } + }, + + // Get calls can't wait for the tech, and sometimes don't need to. + techGet: function(method){ try { - return this.tech[method](arg); + return this.tech[method](); } catch(e) { _V_.log(e); return; } - // if (this.isReady) { - // - // } else { - // _V_.log("The playback technology API is not ready yet. Use player.ready(myFunction)."+" ["+method+"]", arguments.callee.caller.arguments.callee.caller.arguments.callee.caller) - // return false; - // // throw new Error("The playback technology API is not ready yet. Use player.ready(myFunction)."+" ["+method+"]"); - // } }, + // Method for calling methods on the current playback technology + // techCall: function(method, arg){ + // + // // if (this.isReady) { + // // + // // } else { + // // _V_.log("The playback technology API is not ready yet. Use player.ready(myFunction)."+" ["+method+"]", arguments.callee.caller.arguments.callee.caller.arguments.callee.caller) + // // return false; + // // // throw new Error("The playback technology API is not ready yet. Use player.ready(myFunction)."+" ["+method+"]"); + // // } + // }, + // http://dev.w3.org/html5/spec/video.html#dom-media-play play: function(){ this.techCall("play"); @@ -384,7 +400,7 @@ _V_.Player = _V_.Component.extend({ // http://dev.w3.org/html5/spec/video.html#dom-media-paused // The initial state of paused should be true (in Safari it's actually false) paused: function(){ - return (this.techCall("paused") === false) ? false : true; + return (this.techGet("paused") === false) ? false : true; }, // http://dev.w3.org/html5/spec/video.html#dom-media-currenttime @@ -404,13 +420,13 @@ _V_.Player = _V_.Component.extend({ // Cache last currentTime and return // Default to 0 seconds - return this.values.currentTime = (this.techCall("currentTime") || 0); + return this.values.currentTime = (this.techGet("currentTime") || 0); }, // http://dev.w3.org/html5/spec/video.html#dom-media-duration // Duration should return NaN if not available. ParseFloat will turn false-ish values to NaN. duration: function(){ - return parseFloat(this.techCall("duration")); + return parseFloat(this.techGet("duration")); }, // Calculates how much time is left. Not in spec, but useful. @@ -422,7 +438,7 @@ _V_.Player = _V_.Component.extend({ // Buffered returns a timerange object. Kind of like an array of portions of the video that have been downloaded. // So far no browsers return more than one range (portion) buffered: function(){ - var buffered = this.techCall("buffered"), + var buffered = this.techGet("buffered"), start = 0, end = this.values.bufferEnd = this.values.bufferEnd || 0, // Default end to 0 and store in values timeRange; @@ -454,7 +470,7 @@ _V_.Player = _V_.Component.extend({ } // Default to 1 when returning current volume. - vol = parseFloat(this.techCall("volume")); + vol = parseFloat(this.techGet("volume")); return (isNaN(vol)) ? 1 : vol; }, @@ -464,7 +480,7 @@ _V_.Player = _V_.Component.extend({ this.techCall("setMuted", muted); return this; } - return this.techCall("muted") || false; // Default to false + return this.techGet("muted") || false; // Default to false }, // http://dev.w3.org/html5/spec/dimension-attributes.html#attr-dim-height @@ -497,7 +513,7 @@ _V_.Player = _V_.Component.extend({ }, // Check if current tech can support native fullscreen (e.g. with built in controls lik iOS, so not our flash swf) - supportsFullScreen: function(){ return this.techCall("supportsFullScreen") || false; }, + supportsFullScreen: function(){ return this.techGet("supportsFullScreen") || false; }, // Turn on fullscreen (or window) mode requestFullScreen: function(){ @@ -725,7 +741,7 @@ _V_.Player = _V_.Component.extend({ // http://dev.w3.org/html5/spec/video.html#dom-media-currentsrc currentSrc: function(){ - return this.techCall("currentSrc") || ""; + return this.techGet("currentSrc") || this.values.src || ""; }, textTrackValue: function(kind, value){ @@ -744,7 +760,7 @@ _V_.Player = _V_.Component.extend({ this.options.preload = value; return this; } - return this.techCall("preload", value); + return this.techGet("preload"); }, autoplay: function(value){ if (value !== undefined) { @@ -752,7 +768,7 @@ _V_.Player = _V_.Component.extend({ this.options.autoplay = value; return this; } - return this.techCall("autoplay", value); + return this.techGet("autoplay", value); }, loop: function(value){ if (value !== undefined) { @@ -760,14 +776,14 @@ _V_.Player = _V_.Component.extend({ this.options.loop = value; return this; } - return this.techCall("loop", value); + return this.techGet("loop"); }, controls: function(){ return this.options.controls; }, textTracks: function(){ return this.options.tracks; }, - poster: function(){ return this.techCall("poster"); }, - error: function(){ return this.techCall("error"); }, - ended: function(){ return this.techCall("ended"); } + poster: function(){ return this.techGet("poster"); }, + error: function(){ return this.techGet("error"); }, + ended: function(){ return this.techGet("ended"); } // Methods to add support for // networkState: function(){ return this.techCall("networkState"); }, From 45f519820a1a7c7a5daca03d405472f3f4d9d588 Mon Sep 17 00:00:00 2001 From: Steve Heffernan Date: Fri, 3 Feb 2012 10:28:00 -0800 Subject: [PATCH 3/4] Updated techGet to handle common errors. --- src/player.js | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/src/player.js b/src/player.js index fc5600edbf..cc792bd896 100644 --- a/src/player.js +++ b/src/player.js @@ -359,18 +359,46 @@ _V_.Player = _V_.Component.extend({ // Otherwise call method now } else { - this.tech[method](arg); + try { + this.tech[method](arg); + } catch(e) { + _V_.log(e); + } } }, // Get calls can't wait for the tech, and sometimes don't need to. techGet: function(method){ - try { - return this.tech[method](); - } catch(e) { - _V_.log(e); - return; + + // Make sure tech is ready + if (this.tech.isReady) { + + // Flash likes to die and reload when you hide or reposition it. + // In these cases the object methods go away and we get errors. + // When that happens we'll catch the errors and inform tech that it's not ready any more. + try { + return this.tech[method](); + } catch(e) { + + // When building additional tech libs, an expected method may not be defined yet + if (this.tech[method] === undefined) { + _V_.log("Video.js: " + method + " method not defined for "+this.techName+" playback technology.", e); + + } else { + + // When a method isn't available on the object it throws a TypeError + if (e.name == "TypeError") { + _V_.log("Video.js: " + method + " unavailable on "+this.techName+" playback technology element.", e); + this.tech.isReady = false; + + } else { + _V_.log(e); + } + } + } } + + return; }, // Method for calling methods on the current playback technology @@ -643,8 +671,6 @@ _V_.Player = _V_.Component.extend({ selectSource: function(sources){ - _V_.log(sources) - // Loop through each playback technology in the options order for (var i=0,j=this.options.techOrder;i Date: Fri, 3 Feb 2012 10:51:38 -0800 Subject: [PATCH 4/4] Adding line to CHANGELOG: Refactored API to be more immediately available. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 83d77e8e74..790cac6bad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,4 @@ +* Refactored API to be more immediately available. -------------------------------------------------------------------------------- ^ ADD NEW CHANGES ABOVE ^ --------------------------------------------------------------------------------