mirror of
https://github.com/videojs/video.js.git
synced 2024-11-24 08:42:25 +02:00
Continued updating all library pieces to support closure compiler.
Renamed internal lib var to vjs instead of _V_.
This commit is contained in:
parent
e125ee878e
commit
428203c466
@ -17,7 +17,7 @@ cp dev.html.example dev.html
|
||||
You can use dev.html to test new code. It's simple HTML doc that includes all the source files. Send a pull request for any updates.
|
||||
|
||||
---
|
||||
BETA NOTES
|
||||
BETA NOTES
|
||||
Version 3 is almost a complete rewrite of the previous versions of VideoJS. New features includes:
|
||||
|
||||
- HTML/CSS Controls and API now work for both the HTML5 and Flash versions.
|
||||
@ -27,3 +27,10 @@ Version 3 is almost a complete rewrite of the previous versions of VideoJS. New
|
||||
- No more embedding of Flash fallback within the video tag HTML.
|
||||
|
||||
---
|
||||
|
||||
TESTING FLASH LOCALLY IN CHROME
|
||||
-------------------------------
|
||||
Chrome 21+ (as of 2013/01/01) doens't run Flash files that are local and loaded into a locally accessed page (file:///). To get around this you need to [disable the version of Flash](http://helpx.adobe.com/flash-player/kb/flash-player-google-chrome.html#How_can_I_run_debugger_or_alternate_versions_of_Flash_Player_in_Google_Chrome) included with Chrome and enable a system-wide version of Flash.
|
||||
|
||||
|
||||
|
||||
|
18
Rakefile
18
Rakefile
@ -4,6 +4,16 @@ require 'httparty'
|
||||
|
||||
namespace :build do
|
||||
|
||||
desc "Compile"
|
||||
task :compiled do
|
||||
Rake::Shell['java -jar build/compiler/compiler.jar --compilation_level ADVANCED_OPTIMIZATIONS --js=src/goog.base.js --js=src/core.js --js=src/lib.js --js=src/events.js --js=src/component.js --js=src/player.js --js=src/media.js --js=src/media.html5.js --js=src/media.flash.js --js=src/controls.js --js=src/tracks.js --js=src/setup.js --js=src/json.js --js=src/exports.js --formatting=pretty_print --js_output_file=closure-test/video.compiled.js --create_source_map closure-test/video.compiled.js.map --source_map_format=V3 --externs src/media.flash.externs.js --externs closure-test/qunit-externs.js --output_wrapper "(function() {%output%})();//@ sourceMappingURL=video.compiled.js.map"']
|
||||
end
|
||||
|
||||
desc "Compile with test"
|
||||
task :compiled_tests do
|
||||
Rake::Shell['java -jar build/compiler/compiler.jar --compilation_level ADVANCED_OPTIMIZATIONS --js=src/goog.base.js --js=src/core.js --js=src/lib.js --js=src/events.js --js=src/component.js --js=src/player.js --js=src/media.js --js=src/media.html5.js --js=src/media.flash.js --js=src/controls.js --js=src/tracks.js --js=src/setup.js --js=src/json.js --js=src/exports.js --js=closure-test/unit/component.js --js=closure-test/unit/lib.js --js=closure-test/unit/events.js --js=closure-test/unit/player.js --formatting=pretty_print --js_output_file=closure-test/video.test.compiled.js --create_source_map closure-test/video.test.compiled.js.map --source_map_format=V3 --externs src/media.flash.externs.js --externs closure-test/qunit-externs.js --output_wrapper "(function() {%output%})();//@ sourceMappingURL=video.test.compiled.js.map"']
|
||||
end
|
||||
|
||||
desc "Build version for current '/c/' CDN copy and locked in version"
|
||||
task :current do
|
||||
Rake::Task["build:source"].execute
|
||||
@ -118,7 +128,7 @@ namespace :build do
|
||||
file.puts "var vjsSourceList = [];"
|
||||
|
||||
src_array = ["src/core", "src/lib"]
|
||||
last = ["src/setup"] # "flash/swfobject",
|
||||
last = ["src/setup"] # "flash/swfobject",
|
||||
exclude = [".", "..", ".DS_Store", "_end.js", "_begin.js"]
|
||||
|
||||
Dir.foreach('src') do |item|
|
||||
@ -141,7 +151,7 @@ namespace :build do
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
desc "Build list of source files for easy inclusion in projects"
|
||||
task :source_html do
|
||||
|
||||
@ -149,7 +159,7 @@ namespace :build do
|
||||
file.puts "<!-- Video.js Source Files -->"
|
||||
|
||||
src_array = ["src/core", "src/lib"]
|
||||
last = ["src/setup"] # "flash/swfobject",
|
||||
last = ["src/setup"] # "flash/swfobject",
|
||||
exclude = [".", "..", ".DS_Store", "_end.js", "_begin.js"]
|
||||
|
||||
Dir.foreach('src') do |item|
|
||||
@ -169,7 +179,7 @@ namespace :build do
|
||||
end
|
||||
# file.puts "vjsSourceList.push('src/#{item.sub(".js", "")}')"
|
||||
# file.puts "vjsSourceList.push('flash/swfobject.js')"
|
||||
|
||||
|
||||
file.puts "<!-- END Video.js Source Files -->"
|
||||
|
||||
end
|
||||
|
@ -23,14 +23,14 @@
|
||||
|
||||
<script src="tech/html5/html5.js"></script>
|
||||
<script src="tech/flash/flash.js"></script>
|
||||
|
||||
|
||||
<script src="src/setup.js"></script>
|
||||
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
// Easy access to test Flash over HTML5. Add ?flash to URL
|
||||
if (window.location.href.indexOf("?flash") !== -1) {
|
||||
_V_.options.techOrder = ["flash"];
|
||||
_V_.options.flash.swf = "tech/flash/video-js.swf";
|
||||
_V_.options.Flash.swf = "tech/flash/video-js.swf";
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -6,7 +6,7 @@ Video.js is pretty easy to set up. It can take a matter of seconds to get the pl
|
||||
Step 1: Include the Video.js Javascript and CSS files in the head of your page.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
You can download the Video.js source and host it on your own servers, or use the free CDN hosted version. It's often recommended now to put JavaScript before the end body tag (</body>) instead of the head (<head>), but Video.js includes an 'HTML5 Shiv', which needs to be in the head for older IE versions to respect the video tag as a valid element.
|
||||
You can download the Video.js source and host it on your own servers, or use the free CDN hosted version. It's often recommended now to put JavaScript before the end body tag (</body>) instead of the head (<head>), but Video.js includes an 'HTML5 Shiv', which needs to be in the head for older IE versions to respect the video tag as a valid element.
|
||||
|
||||
> NOTE: If you're already using an HTML5 shiv like [Modernizr](http://modernizr.com/) you can include the Video.js JavaScript anywhere, however make sure your version of Modernizr includes the shiv for video.
|
||||
|
||||
@ -22,7 +22,7 @@ With the self hosted option you'll also want to update the location of the video
|
||||
<link href="http://example.com/path/to/video-js.css" rel="stylesheet">
|
||||
<script src="http://example.com/path/to/video.js"></script>
|
||||
<script>
|
||||
_V_.options.flash.swf = "http://example.com/path/to/video-js.swf"
|
||||
_V_.options.Flash.swf = "http://example.com/path/to/video-js.swf"
|
||||
</script>
|
||||
```
|
||||
|
||||
@ -42,13 +42,13 @@ With Video.js you just use an HTML5 video tag to embed a video. Video.js will th
|
||||
Otherwise include/exclude attributes, settings, sources, and tracks exactly as you would for HTML5 video.
|
||||
|
||||
```html
|
||||
<video id="example_video_1" class="video-js vjs-default-skin"
|
||||
controls preload="auto" width="640" height="264"
|
||||
poster="http://video-js.zencoder.com/oceans-clip.png"
|
||||
data-setup='{"example_option":true}'>
|
||||
<source src="http://video-js.zencoder.com/oceans-clip.mp4" type='video/mp4' />
|
||||
<source src="http://video-js.zencoder.com/oceans-clip.webm" type='video/webm' />
|
||||
<source src="http://video-js.zencoder.com/oceans-clip.ogv" type='video/ogg' />
|
||||
<video id="example_video_1" class="video-js vjs-default-skin"
|
||||
controls preload="auto" width="640" height="264"
|
||||
poster="http://video-js.zencoder.com/oceans-clip.png"
|
||||
data-setup='{"example_option":true}'>
|
||||
<source src="http://video-js.zencoder.com/oceans-clip.mp4" type='video/mp4' />
|
||||
<source src="http://video-js.zencoder.com/oceans-clip.webm" type='video/webm' />
|
||||
<source src="http://video-js.zencoder.com/oceans-clip.ogv" type='video/ogg' />
|
||||
</video>
|
||||
```
|
||||
|
||||
@ -62,9 +62,9 @@ _V_("example_video_1", {}, function(){
|
||||
});
|
||||
```
|
||||
|
||||
The first argument in the \_V_ function is the ID of your video tag. Replace it with your own.
|
||||
The first argument in the \_V_ function is the ID of your video tag. Replace it with your own.
|
||||
|
||||
The second argument is an options object. It allows you to set additional options like you can with the data-setup attribute.
|
||||
The second argument is an options object. It allows you to set additional options like you can with the data-setup attribute.
|
||||
|
||||
The third argument is a 'ready' callback. Once Video.js has initialized it will call this function.
|
||||
|
||||
|
@ -1,24 +0,0 @@
|
||||
/*!
|
||||
Video.js - HTML5 Video Player
|
||||
Version GENERATED_AT_BUILD
|
||||
|
||||
LGPL v3 LICENSE INFO
|
||||
This file is part of Video.js. Copyright 2011 Zencoder, Inc.
|
||||
|
||||
Video.js is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Video.js is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with Video.js. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Self-executing function to prevent global vars and help with minification
|
||||
;(function(window, undefined){
|
||||
var document = window.document;
|
@ -1,6 +0,0 @@
|
||||
|
||||
// Expose to global
|
||||
window.VideoJS = window._V_ = VideoJS;
|
||||
|
||||
// End self-executing function
|
||||
})(window);
|
174
src/component.js
174
src/component.js
@ -2,9 +2,9 @@
|
||||
* Player Component - Base class for all UI objects
|
||||
*/
|
||||
|
||||
goog.provide('_V_.Component');
|
||||
goog.provide('vjs.Component');
|
||||
|
||||
goog.require('_V_');
|
||||
goog.require('vjs');
|
||||
|
||||
/**
|
||||
* Base UI Component class
|
||||
@ -12,20 +12,24 @@ goog.require('_V_');
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
_V_.Component = function(player, options, ready){
|
||||
vjs.Component = function(player, options, ready){
|
||||
this.player = player;
|
||||
|
||||
// // Allow for overridding default component options
|
||||
options = this.options = _V_.merge(this.options || {}, options);
|
||||
options = this.options = vjs.merge(this.options || {}, options);
|
||||
|
||||
// Get ID from options, element, or create using player ID and unique ID
|
||||
this.id_ = options.id || ((options.el && options.el.id) ? options.el.id : player.id + "_component_" + _V_.guid++);
|
||||
this.id_ = options.id || ((options.el && options.el.id) ? options.el.id : player.id + "_component_" + vjs.guid++);
|
||||
|
||||
this.name_ = options.name || null;
|
||||
|
||||
// Create element if one wasn't provided in potions
|
||||
this.el_ = (options.el) ? options.el : this.createEl();
|
||||
|
||||
this.children_ = [];
|
||||
this.childIndex_ = {};
|
||||
this.childNameIndex_ = {};
|
||||
|
||||
// Add any child components in options
|
||||
this.initChildren();
|
||||
|
||||
@ -37,7 +41,7 @@ _V_.Component = function(player, options, ready){
|
||||
/**
|
||||
* Dispose of the component and all child components.
|
||||
*/
|
||||
_V_.Component.prototype.dispose = function(){
|
||||
vjs.Component.prototype.dispose = function(){
|
||||
// Dispose all children.
|
||||
if (this.children_) {
|
||||
for (var i = this.children_.length - 1; i >= 0; i--) {
|
||||
@ -58,7 +62,7 @@ _V_.Component.prototype.dispose = function(){
|
||||
this.el_.parentNode.removeChild(this.el_);
|
||||
}
|
||||
|
||||
_V_.removeData(this.el_);
|
||||
vjs.removeData(this.el_);
|
||||
this.el_ = null;
|
||||
};
|
||||
|
||||
@ -67,14 +71,14 @@ _V_.Component.prototype.dispose = function(){
|
||||
* @type {Object}
|
||||
* @private
|
||||
*/
|
||||
_V_.Component.prototype.options;
|
||||
vjs.Component.prototype.options;
|
||||
|
||||
/**
|
||||
* The DOM element for the component.
|
||||
* @type {Element}
|
||||
* @private
|
||||
*/
|
||||
_V_.Component.prototype.el_;
|
||||
vjs.Component.prototype.el_;
|
||||
|
||||
/**
|
||||
* Create the component's DOM element.
|
||||
@ -82,15 +86,15 @@ _V_.Component.prototype.el_;
|
||||
* @param {Object=} attributes An object of element attributes that should be set on the element.
|
||||
* @return {Element}
|
||||
*/
|
||||
_V_.Component.prototype.createEl = function(tagName, attributes){
|
||||
return _V_.createEl(tagName, attributes);
|
||||
vjs.Component.prototype.createEl = function(tagName, attributes){
|
||||
return vjs.createEl(tagName, attributes);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the component's DOM element.
|
||||
* @return {Element}
|
||||
*/
|
||||
_V_.Component.prototype.getEl = function(){
|
||||
vjs.Component.prototype.getEl = function(){
|
||||
return this.el_;
|
||||
};
|
||||
|
||||
@ -99,13 +103,13 @@ _V_.Component.prototype.getEl = function(){
|
||||
* @type {String}
|
||||
* @private
|
||||
*/
|
||||
_V_.Component.prototype.id_;
|
||||
vjs.Component.prototype.id_;
|
||||
|
||||
/**
|
||||
* Return the component's ID.
|
||||
* @return {String}
|
||||
*/
|
||||
_V_.Component.prototype.getId = function(){
|
||||
vjs.Component.prototype.getId = function(){
|
||||
return this.id_;
|
||||
};
|
||||
|
||||
@ -114,13 +118,13 @@ _V_.Component.prototype.getId = function(){
|
||||
* @type {String}
|
||||
* @private
|
||||
*/
|
||||
_V_.Component.prototype.name_;
|
||||
vjs.Component.prototype.name_;
|
||||
|
||||
/**
|
||||
* Return the component's ID.
|
||||
* @return {String}
|
||||
*/
|
||||
_V_.Component.prototype.getName = function(){
|
||||
vjs.Component.prototype.getName = function(){
|
||||
return this.name_;
|
||||
};
|
||||
|
||||
@ -129,13 +133,13 @@ _V_.Component.prototype.getName = function(){
|
||||
* @type {Array}
|
||||
* @private
|
||||
*/
|
||||
_V_.Component.prototype.children_;
|
||||
vjs.Component.prototype.children_;
|
||||
|
||||
/**
|
||||
* Returns array of all child components.
|
||||
* @return {Array}
|
||||
*/
|
||||
_V_.Component.prototype.getChildren = function(){
|
||||
vjs.Component.prototype.getChildren = function(){
|
||||
return this.children_;
|
||||
}
|
||||
|
||||
@ -144,13 +148,13 @@ _V_.Component.prototype.getChildren = function(){
|
||||
* @type {Object}
|
||||
* @private
|
||||
*/
|
||||
_V_.Component.prototype.childIndex_;
|
||||
vjs.Component.prototype.childIndex_;
|
||||
|
||||
/**
|
||||
* Returns a child component with the provided ID.
|
||||
* @return {Array}
|
||||
*/
|
||||
_V_.Component.prototype.getChildById = function(id){
|
||||
vjs.Component.prototype.getChildById = function(id){
|
||||
return this.childIndex_[id];
|
||||
}
|
||||
|
||||
@ -159,25 +163,25 @@ _V_.Component.prototype.getChildById = function(id){
|
||||
* @type {Object}
|
||||
* @private
|
||||
*/
|
||||
_V_.Component.prototype.childNameIndex_;
|
||||
vjs.Component.prototype.childNameIndex_;
|
||||
|
||||
/**
|
||||
* Returns a child component with the provided ID.
|
||||
* @return {Array}
|
||||
*/
|
||||
_V_.Component.prototype.getChild = function(name){
|
||||
vjs.Component.prototype.getChild = function(name){
|
||||
return this.childNameIndex_[name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a child component inside this component.
|
||||
* @param {String|_V_.Component} child The class name or instance of a child to add.
|
||||
* @param {String|vjs.Component} child The class name or instance of a child to add.
|
||||
* @param {Object=} options Optional options, including options to be passed to
|
||||
* children of the child.
|
||||
* @return {_V_.Component} The child component, because it might be created in this process.
|
||||
* @return {vjs.Component} The child component, because it might be created in this process.
|
||||
* @suppress {accessControls|checkRegExp|checkTypes|checkVars|const|constantProperty|deprecated|duplicate|es5Strict|fileoverviewTags|globalThis|invalidCasts|missingProperties|nonStandardJsDocs|strictModuleDepCheck|undefinedNames|undefinedVars|unknownDefines|uselessCode|visibility}
|
||||
*/
|
||||
_V_.Component.prototype.addChild = function(child, options){
|
||||
vjs.Component.prototype.addChild = function(child, options){
|
||||
var component, componentClass, componentName, componentId;
|
||||
|
||||
// If string, create new component with options
|
||||
@ -189,16 +193,16 @@ _V_.Component.prototype.addChild = function(child, options){
|
||||
options = options || {};
|
||||
|
||||
// Assume name of set is a lowercased name of the UI Class (PlayButton, etc.)
|
||||
componentClass = options.componentClass || _V_.capitalize(componentName);
|
||||
componentClass = options.componentClass || vjs.capitalize(componentName);
|
||||
|
||||
// Set name through options
|
||||
options.name = componentName;
|
||||
|
||||
// Create a new object & element for this controls set
|
||||
// If there's no .player, this is a player
|
||||
// Closure Compiler throws an 'incomplete alias' warning if we use the _V_ variable directly.
|
||||
// Closure Compiler throws an 'incomplete alias' warning if we use the vjs variable directly.
|
||||
// Every class should be exported, so this should never be a problem here.
|
||||
component = new window['_V_'][componentClass](this.player || this, options);
|
||||
component = new window['videojs'][componentClass](this.player || this, options);
|
||||
|
||||
// child is a component instance
|
||||
} else {
|
||||
@ -208,10 +212,6 @@ _V_.Component.prototype.addChild = function(child, options){
|
||||
componentName = component.getName();
|
||||
componentId = component.getId();
|
||||
|
||||
this.children_ = this.children_ || [];
|
||||
this.childIndex_ = this.childNameIndex_ || {};
|
||||
this.childNameIndex_ = this.childNameIndex_ || {};
|
||||
|
||||
this.children_.push(component);
|
||||
|
||||
if (componentId) {
|
||||
@ -229,7 +229,7 @@ _V_.Component.prototype.addChild = function(child, options){
|
||||
return component;
|
||||
};
|
||||
|
||||
_V_.Component.prototype.removeChild = function(component){
|
||||
vjs.Component.prototype.removeChild = function(component){
|
||||
if (typeof component === 'string') {
|
||||
component = this.getChild(component);
|
||||
}
|
||||
@ -259,17 +259,17 @@ _V_.Component.prototype.removeChild = function(component){
|
||||
/**
|
||||
* Initialize default child components from options
|
||||
*/
|
||||
_V_.Component.prototype.initChildren = function(){
|
||||
vjs.Component.prototype.initChildren = function(){
|
||||
var options = this.options;
|
||||
|
||||
if (options && options.children) {
|
||||
var self = this;
|
||||
|
||||
// Loop through components and add them to the player
|
||||
_V_.eachProp(options.children, function(name, opts){
|
||||
vjs.eachProp(options.children, function(name, opts){
|
||||
|
||||
// Allow for disabling default components
|
||||
// e.g. _V_.options.components.posterImage = false
|
||||
// e.g. vjs.options.components.posterImage = false
|
||||
if (opts === false) return;
|
||||
|
||||
// Allow waiting to add components until a specific event is called
|
||||
@ -287,7 +287,7 @@ _V_.Component.prototype.initChildren = function(){
|
||||
}
|
||||
};
|
||||
|
||||
_V_.Component.prototype.buildCSSClass = function(){
|
||||
vjs.Component.prototype.buildCSSClass = function(){
|
||||
// Child classes can include a function that does:
|
||||
// return "CLASS NAME" + this._super();
|
||||
return "";
|
||||
@ -300,10 +300,10 @@ _V_.Component.prototype.buildCSSClass = function(){
|
||||
* Add an event listener to this component's element. Context will be the component.
|
||||
* @param {String} type Event type e.g. 'click'
|
||||
* @param {Function} fn Event listener
|
||||
* @return {_V_.Component}
|
||||
* @return {vjs.Component}
|
||||
*/
|
||||
_V_.Component.prototype.on = function(type, fn){
|
||||
_V_.on(this.el_, type, _V_.bind(this, fn));
|
||||
vjs.Component.prototype.on = function(type, fn){
|
||||
vjs.on(this.el_, type, vjs.bind(this, fn));
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -311,10 +311,10 @@ _V_.Component.prototype.on = function(type, fn){
|
||||
* Remove an event listener from the component's element
|
||||
* @param {String=} type Optional event type. Without type it will remove all listeners.
|
||||
* @param {Function=} fn Optional event listener. Without fn it will remove all listeners for a type.
|
||||
* @return {_V_.Component}
|
||||
* @return {vjs.Component}
|
||||
*/
|
||||
_V_.Component.prototype.off = function(type, fn){
|
||||
_V_.off(this.el_, type, fn);
|
||||
vjs.Component.prototype.off = function(type, fn){
|
||||
vjs.off(this.el_, type, fn);
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -322,10 +322,10 @@ _V_.Component.prototype.off = function(type, fn){
|
||||
* Add an event listener to be triggered only once and then removed
|
||||
* @param {String} type Event type
|
||||
* @param {Function} fn Event listener
|
||||
* @return {_V_.Component}
|
||||
* @return {vjs.Component}
|
||||
*/
|
||||
_V_.Component.prototype.one = function(type, fn) {
|
||||
_V_.one(this.el_, type, _V_.bind(this, fn));
|
||||
vjs.Component.prototype.one = function(type, fn) {
|
||||
vjs.one(this.el_, type, vjs.bind(this, fn));
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -333,10 +333,10 @@ _V_.Component.prototype.one = function(type, fn) {
|
||||
* Trigger an event on an element
|
||||
* @param {String} type Event type to trigger
|
||||
* @param {Event|Object} event Event object to be passed to the listener
|
||||
* @return {_V_.Component}
|
||||
* @return {vjs.Component}
|
||||
*/
|
||||
_V_.Component.prototype.trigger = function(type, event){
|
||||
_V_.trigger(this.el_, type, event);
|
||||
vjs.Component.prototype.trigger = function(type, event){
|
||||
vjs.trigger(this.el_, type, event);
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -347,7 +347,7 @@ _V_.Component.prototype.trigger = function(type, event){
|
||||
* @type {Boolean}
|
||||
* @private
|
||||
*/
|
||||
_V_.Component.prototype.isReady_;
|
||||
vjs.Component.prototype.isReady_;
|
||||
|
||||
/**
|
||||
* Trigger ready as soon as initialization is finished.
|
||||
@ -357,23 +357,23 @@ _V_.Component.prototype.isReady_;
|
||||
* @type {Boolean}
|
||||
* @private
|
||||
*/
|
||||
_V_.Component.prototype.isReadyOnInitFinish_ = true;
|
||||
vjs.Component.prototype.isReadyOnInitFinish_ = true;
|
||||
|
||||
/**
|
||||
* List of ready listeners
|
||||
* @type {Array}
|
||||
* @private
|
||||
*/
|
||||
_V_.Component.prototype.readyQueue_;
|
||||
vjs.Component.prototype.readyQueue_;
|
||||
|
||||
/**
|
||||
* Bind a listener to the component's ready state.
|
||||
* Different from event listeners in that if the ready event has already happend
|
||||
* it will trigger the function immediately.
|
||||
* @param {Function} fn Ready listener
|
||||
* @return {_V_.Component}
|
||||
* @return {vjs.Component}
|
||||
*/
|
||||
_V_.Component.prototype.ready = function(fn){
|
||||
vjs.Component.prototype.ready = function(fn){
|
||||
if (fn) {
|
||||
if (this.isReady_) {
|
||||
fn.call(this);
|
||||
@ -389,9 +389,9 @@ _V_.Component.prototype.ready = function(fn){
|
||||
|
||||
/**
|
||||
* Trigger the ready listeners
|
||||
* @return {_V_.Component}
|
||||
* @return {vjs.Component}
|
||||
*/
|
||||
_V_.Component.prototype.triggerReady = function(){
|
||||
vjs.Component.prototype.triggerReady = function(){
|
||||
this.isReady_ = true;
|
||||
|
||||
var readyQueue = this.readyQueue_;
|
||||
@ -416,46 +416,46 @@ _V_.Component.prototype.triggerReady = function(){
|
||||
/**
|
||||
* Add a CSS class name to the component's element
|
||||
* @param {String} classToAdd Classname to add
|
||||
* @return {_V_.Component}
|
||||
* @return {vjs.Component}
|
||||
*/
|
||||
_V_.Component.prototype.addClass = function(classToAdd){
|
||||
_V_.addClass(this.el_, classToAdd);
|
||||
vjs.Component.prototype.addClass = function(classToAdd){
|
||||
vjs.addClass(this.el_, classToAdd);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove a CSS class name from the component's element
|
||||
* @param {String} classToRemove Classname to remove
|
||||
* @return {_V_.Component}
|
||||
* @return {vjs.Component}
|
||||
*/
|
||||
_V_.Component.prototype.removeClass = function(classToRemove){
|
||||
_V_.removeClass(this.el_, classToRemove);
|
||||
vjs.Component.prototype.removeClass = function(classToRemove){
|
||||
vjs.removeClass(this.el_, classToRemove);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Show the component element if hidden
|
||||
* @return {_V_.Component}
|
||||
* @return {vjs.Component}
|
||||
*/
|
||||
_V_.Component.prototype.show = function(){
|
||||
vjs.Component.prototype.show = function(){
|
||||
this.el_.style.display = "block";
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Hide the component element if hidden
|
||||
* @return {_V_.Component}
|
||||
* @return {vjs.Component}
|
||||
*/
|
||||
_V_.Component.prototype.hide = function(){
|
||||
vjs.Component.prototype.hide = function(){
|
||||
this.el_.style.display = "none";
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fade a component in using CSS
|
||||
* @return {_V_.Component}
|
||||
* @return {vjs.Component}
|
||||
*/
|
||||
_V_.Component.prototype.fadeIn = function(){
|
||||
vjs.Component.prototype.fadeIn = function(){
|
||||
this.removeClass("vjs-fade-out");
|
||||
this.addClass("vjs-fade-in");
|
||||
return this;
|
||||
@ -463,9 +463,9 @@ _V_.Component.prototype.fadeIn = function(){
|
||||
|
||||
/**
|
||||
* Fade a component out using CSS
|
||||
* @return {_V_.Component}
|
||||
* @return {vjs.Component}
|
||||
*/
|
||||
_V_.Component.prototype.fadeOut = function(){
|
||||
vjs.Component.prototype.fadeOut = function(){
|
||||
this.removeClass("vjs-fade-in");
|
||||
this.addClass("vjs-fade-out");
|
||||
return this;
|
||||
@ -473,9 +473,9 @@ _V_.Component.prototype.fadeOut = function(){
|
||||
|
||||
/**
|
||||
* Lock an item in its visible state. To be used with fadeIn/fadeOut.
|
||||
* @return {_V_.Component}
|
||||
* @return {vjs.Component}
|
||||
*/
|
||||
_V_.Component.prototype.lockShowing = function(){
|
||||
vjs.Component.prototype.lockShowing = function(){
|
||||
var style = this.el_.style;
|
||||
style.display = "block";
|
||||
style.opacity = 1;
|
||||
@ -485,9 +485,9 @@ _V_.Component.prototype.lockShowing = function(){
|
||||
|
||||
/**
|
||||
* Unlock an item to be hidden. To be used with fadeIn/fadeOut.
|
||||
* @return {_V_.Component}
|
||||
* @return {vjs.Component}
|
||||
*/
|
||||
_V_.Component.prototype.unlockShowing = function(){
|
||||
vjs.Component.prototype.unlockShowing = function(){
|
||||
var style = this.el.style;
|
||||
style.display = "";
|
||||
style.opacity = "";
|
||||
@ -503,10 +503,10 @@ _V_.Component.prototype.unlockShowing = function(){
|
||||
* But allowing limited percents use. e.g. width() will return number+%, not computed width
|
||||
* @param {Number|String=} num Optional width number
|
||||
* @param {[type]} skipListeners Skip the 'resize' event trigger
|
||||
* @return {_V_.Component|Number|String} Returns 'this' if dimension was set.
|
||||
* @return {vjs.Component|Number|String} Returns 'this' if dimension was set.
|
||||
* Otherwise it returns the dimension.
|
||||
*/
|
||||
_V_.Component.prototype.width = function(num, skipListeners){
|
||||
vjs.Component.prototype.width = function(num, skipListeners){
|
||||
return this.dimension("width", num, skipListeners);
|
||||
};
|
||||
|
||||
@ -514,9 +514,9 @@ _V_.Component.prototype.width = function(num, skipListeners){
|
||||
* Get or set the height of the player
|
||||
* @param {Number|String=} num Optional new player height
|
||||
* @param {Boolean=} skipListeners Optional skip resize event trigger
|
||||
* @return {_V_.Component|Number|String} The player, or the dimension
|
||||
* @return {vjs.Component|Number|String} The player, or the dimension
|
||||
*/
|
||||
_V_.Component.prototype.height = function(num, skipListeners){
|
||||
vjs.Component.prototype.height = function(num, skipListeners){
|
||||
return this.dimension("height", num, skipListeners);
|
||||
};
|
||||
|
||||
@ -524,9 +524,9 @@ _V_.Component.prototype.height = function(num, skipListeners){
|
||||
* Set both width and height at the same time.
|
||||
* @param {Number|String} width
|
||||
* @param {Number|String} height
|
||||
* @return {_V_.Component} The player.
|
||||
* @return {vjs.Component} The player.
|
||||
*/
|
||||
_V_.Component.prototype.dimensions = function(width, height){
|
||||
vjs.Component.prototype.dimensions = function(width, height){
|
||||
// Skip resize listeners on width for optimization
|
||||
return this.width(width, true).height(height);
|
||||
};
|
||||
@ -545,7 +545,7 @@ _V_.Component.prototype.dimensions = function(width, height){
|
||||
* @return {vjs.Component|Number|String} Return the player if setting a dimension.
|
||||
* Otherwise it returns the dimension.
|
||||
*/
|
||||
_V_.Component.prototype.dimension = function(widthOrHeight, num, skipListeners){
|
||||
vjs.Component.prototype.dimension = function(widthOrHeight, num, skipListeners){
|
||||
if (num !== undefined) {
|
||||
|
||||
// Check if using css width/height (% or px) and adjust
|
||||
@ -578,13 +578,13 @@ _V_.Component.prototype.dimension = function(widthOrHeight, num, skipListeners){
|
||||
// TODO: handle display:none and no dimension style using px
|
||||
} else {
|
||||
|
||||
return parseInt(this.el_['offset'+_V_.capitalize(widthOrHeight)], 10);
|
||||
return parseInt(this.el_['offset'+vjs.capitalize(widthOrHeight)], 10);
|
||||
|
||||
// ComputedStyle version.
|
||||
// Only difference is if the element is hidden it will return
|
||||
// the percent value (e.g. '100%'')
|
||||
// instead of zero like offsetWidth returns.
|
||||
// var val = _V_.getComputedStyleValue(this.el_, widthOrHeight);
|
||||
// var val = vjs.getComputedStyleValue(this.el_, widthOrHeight);
|
||||
// var pxIndex = val.indexOf("px");
|
||||
|
||||
// if (pxIndex !== -1) {
|
||||
@ -597,11 +597,11 @@ _V_.Component.prototype.dimension = function(widthOrHeight, num, skipListeners){
|
||||
|
||||
// /* Utility
|
||||
// ================================================================================ */
|
||||
// _V_.Component.prototype.each = function(arr, fn){ _V_.each.call(this, arr, fn); };
|
||||
// vjs.Component.prototype.each = function(arr, fn){ vjs.each.call(this, arr, fn); };
|
||||
|
||||
// _V_.Component.prototype.eachProp = function(obj, fn){ _V_.eachProp.call(this, obj, fn); };
|
||||
// vjs.Component.prototype.eachProp = function(obj, fn){ vjs.eachProp.call(this, obj, fn); };
|
||||
|
||||
// _V_.Component.prototype.extend = function(obj){ _V_.merge(this, obj) };
|
||||
// vjs.Component.prototype.extend = function(obj){ vjs.merge(this, obj) };
|
||||
|
||||
// // More easily attach 'this' to functions
|
||||
// _V_.Component.prototype.proxy = function(fn, uid){ return _V_.proxy(this, fn, uid); };
|
||||
// vjs.Component.prototype.proxy = function(fn, uid){ return vjs.proxy(this, fn, uid); };
|
||||
|
680
src/controls.js
vendored
680
src/controls.js
vendored
File diff suppressed because it is too large
Load Diff
51
src/core.js
51
src/core.js
@ -1,10 +1,18 @@
|
||||
// HTML5 Shiv. Must be in <head> to support older browsers.
|
||||
document.createElement("video");document.createElement("audio");
|
||||
|
||||
goog.provide('_V_');
|
||||
goog.provide('VideoJS');
|
||||
goog.provide('vjs');
|
||||
|
||||
var VideoJS = function(id, options, ready){
|
||||
/**
|
||||
* Doubles as the main function for users to create a player instance and also
|
||||
* the main library object.
|
||||
*
|
||||
* @param {String|Element} id Video element or video element ID
|
||||
* @param {Object=} options Optional options object for config/settings
|
||||
* @param {Function=} ready Optional ready callback
|
||||
* @return {vjs.Player} A player instance
|
||||
*/
|
||||
vjs = function(id, options, ready){
|
||||
var tag; // Element of ID
|
||||
|
||||
// Allow for element or ID to be passed in
|
||||
@ -17,12 +25,12 @@ var VideoJS = function(id, options, ready){
|
||||
}
|
||||
|
||||
// If a player instance has already been created for this ID return it.
|
||||
if (_V_.players[id]) {
|
||||
return _V_.players[id];
|
||||
if (vjs.players[id]) {
|
||||
return vjs.players[id];
|
||||
|
||||
// Otherwise get element for ID
|
||||
} else {
|
||||
tag = _V_.el(id)
|
||||
tag = vjs.el(id)
|
||||
}
|
||||
|
||||
// ID is a media element
|
||||
@ -32,16 +40,17 @@ var VideoJS = function(id, options, ready){
|
||||
|
||||
// Check for a useable element
|
||||
if (!tag || !tag.nodeName) { // re: nodeName, could be a box div also
|
||||
throw new TypeError("The element or ID supplied is not valid. (VideoJS)"); // Returns
|
||||
throw new TypeError("The element or ID supplied is not valid. (videojs)"); // Returns
|
||||
}
|
||||
|
||||
// Element may have a player attr referring to an already created player instance.
|
||||
// If not, set up a new player and return the instance.
|
||||
return tag.player || new _V_.Player(tag, options, ready);
|
||||
return tag.player || new vjs.Player(tag, options, ready);
|
||||
};
|
||||
|
||||
// Shortcut
|
||||
// VideoJS = _V_;
|
||||
var videojs = vjs;
|
||||
// videojs = vjs;
|
||||
|
||||
// CDN Version. Used to target right flash swf.
|
||||
CDN_VERSION = "GENERATED_CDN_VSN";
|
||||
@ -50,27 +59,29 @@ CDN_VERSION = "GENERATED_CDN_VSN";
|
||||
* Global Player instance options
|
||||
* @type {Object}
|
||||
*/
|
||||
_V_.options = {
|
||||
// var vjs = videojs;
|
||||
|
||||
vjs.options = {
|
||||
// Default order of fallback technology
|
||||
techOrder: ["html5","flash"],
|
||||
'techOrder': ["html5","flash"],
|
||||
// techOrder: ["flash","html5"],
|
||||
|
||||
html5: {},
|
||||
flash: { swf: "http://vjs.zencdn.net/c/video-js.swf" },
|
||||
'html5': {},
|
||||
'flash': { swf: "http://vjs.zencdn.net/c/video-js.swf" },
|
||||
|
||||
// Default of web browser is 300x150. Should rely on source width/height.
|
||||
width: 300,
|
||||
height: 150,
|
||||
'width': 300,
|
||||
'height': 150,
|
||||
|
||||
// defaultVolume: 0.85,
|
||||
defaultVolume: 0.00, // The freakin seaguls are driving me crazy!
|
||||
'defaultVolume': 0.00, // The freakin seaguls are driving me crazy!
|
||||
|
||||
// Included control sets
|
||||
// TODO: just use uppercase Class name
|
||||
children: {
|
||||
'children': {
|
||||
"mediaLoader": {},
|
||||
"posterImage": {},
|
||||
// // "textTrackDisplay": {},
|
||||
// "textTrackDisplay": {},
|
||||
"loadingSpinner": {},
|
||||
"bigPlayButton": {},
|
||||
"controlBar": {}
|
||||
@ -81,10 +92,10 @@ _V_.options = {
|
||||
* Global player list
|
||||
* @type {Object}
|
||||
*/
|
||||
_V_.players = {};
|
||||
vjs.players = {};
|
||||
|
||||
|
||||
// Set CDN Version of swf
|
||||
if (CDN_VERSION != "GENERATED_CDN_VSN") {
|
||||
_V_.options.flash.swf = "http://vjs.zencdn.net/"+CDN_VERSION+"/video-js.swf"
|
||||
vjs.options.Flash.swf = "http://vjs.zencdn.net/"+CDN_VERSION+"/video-js.swf"
|
||||
}
|
||||
|
@ -13,15 +13,15 @@
|
||||
* @param {String} type Type of event to bind to.
|
||||
* @param {Function} fn Event listener.
|
||||
*/
|
||||
_V_.on = function(elem, type, fn){
|
||||
var data = _V_.getData(elem);
|
||||
vjs.on = function(elem, type, fn){
|
||||
var data = vjs.getData(elem);
|
||||
|
||||
// We need a place to store all our handler data
|
||||
if (!data.handlers) data.handlers = {};
|
||||
|
||||
if (!data.handlers[type]) data.handlers[type] = [];
|
||||
|
||||
if (!fn.guid) fn.guid = _V_.guid++;
|
||||
if (!fn.guid) fn.guid = vjs.guid++;
|
||||
|
||||
data.handlers[type].push(fn);
|
||||
|
||||
@ -31,7 +31,7 @@ _V_.on = function(elem, type, fn){
|
||||
data.dispatcher = function (event){
|
||||
|
||||
if (data.disabled) return;
|
||||
event = _V_.fixEvent(event);
|
||||
event = vjs.fixEvent(event);
|
||||
|
||||
var handlers = data.handlers[event.type];
|
||||
|
||||
@ -67,11 +67,11 @@ _V_.on = function(elem, type, fn){
|
||||
* @param {String=} type Type of listener to remove. Don't include to remove all events from element.
|
||||
* @param {Function} fn Specific listener to remove. Don't incldue to remove listeners for an event type.
|
||||
*/
|
||||
_V_.off = function(elem, type, fn) {
|
||||
vjs.off = function(elem, type, fn) {
|
||||
// Don't want to add a cache object through getData if not needed
|
||||
if (!_V_.hasData(elem)) return;
|
||||
if (!vjs.hasData(elem)) return;
|
||||
|
||||
var data = _V_.getData(elem);
|
||||
var data = vjs.getData(elem);
|
||||
|
||||
// If no events exist, nothing to unbind
|
||||
if (!data.handlers) { return; }
|
||||
@ -79,7 +79,7 @@ _V_.off = function(elem, type, fn) {
|
||||
// Utility function
|
||||
var removeType = function(t){
|
||||
data.handlers[t] = [];
|
||||
_V_.cleanUpEvents(elem,t);
|
||||
vjs.cleanUpEvents(elem,t);
|
||||
};
|
||||
|
||||
// Are we removing all bound events?
|
||||
@ -108,7 +108,7 @@ _V_.off = function(elem, type, fn) {
|
||||
}
|
||||
}
|
||||
|
||||
_V_.cleanUpEvents(elem, type);
|
||||
vjs.cleanUpEvents(elem, type);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -116,8 +116,8 @@ _V_.off = function(elem, type, fn) {
|
||||
* @param {Element|Object} elem Element to clean up
|
||||
* @param {String} type Type of event to clean up
|
||||
*/
|
||||
_V_.cleanUpEvents = function(elem, type) {
|
||||
var data = _V_.getData(elem);
|
||||
vjs.cleanUpEvents = function(elem, type) {
|
||||
var data = vjs.getData(elem);
|
||||
|
||||
// Remove the events of a particular type if there are none left
|
||||
if (data.handlers[type].length === 0) {
|
||||
@ -134,7 +134,7 @@ _V_.cleanUpEvents = function(elem, type) {
|
||||
}
|
||||
|
||||
// Remove the events object if there are no types left
|
||||
if (_V_.isEmpty(data.handlers)) {
|
||||
if (vjs.isEmpty(data.handlers)) {
|
||||
delete data.handlers;
|
||||
delete data.dispatcher;
|
||||
delete data.disabled;
|
||||
@ -145,8 +145,8 @@ _V_.cleanUpEvents = function(elem, type) {
|
||||
}
|
||||
|
||||
// Finally remove the expando if there is no data left
|
||||
if (_V_.isEmpty(data)) {
|
||||
_V_.removeData(elem);
|
||||
if (vjs.isEmpty(data)) {
|
||||
vjs.removeData(elem);
|
||||
}
|
||||
};
|
||||
|
||||
@ -155,7 +155,7 @@ _V_.cleanUpEvents = function(elem, type) {
|
||||
* @param {Object} event Event object to fix
|
||||
* @return {Object}
|
||||
*/
|
||||
_V_.fixEvent = function(event) {
|
||||
vjs.fixEvent = function(event) {
|
||||
|
||||
function returnTrue() { return true; }
|
||||
function returnFalse() { return false; }
|
||||
@ -240,11 +240,11 @@ _V_.fixEvent = function(event) {
|
||||
* @param {Element|Object} elem Element to trigger an event on
|
||||
* @param {String} event Type of event to trigger
|
||||
*/
|
||||
_V_.trigger = function(elem, event) {
|
||||
vjs.trigger = function(elem, event) {
|
||||
// Fetches element data and a reference to the parent (for bubbling).
|
||||
// Don't want to add a data object to cache for every parent,
|
||||
// so checking hasData first.
|
||||
var elemData = (_V_.hasData(elem)) ? _V_.getData(elem) : {};
|
||||
var elemData = (vjs.hasData(elem)) ? vjs.getData(elem) : {};
|
||||
var parent = elem.parentNode || elem.ownerDocument;
|
||||
// type = event.type || event,
|
||||
// handler;
|
||||
@ -254,7 +254,7 @@ _V_.trigger = function(elem, event) {
|
||||
event = { type:event, target:elem };
|
||||
}
|
||||
// Normalizes the event properties.
|
||||
event = _V_.fixEvent(event);
|
||||
event = vjs.fixEvent(event);
|
||||
|
||||
// If the passed element has a dispatcher, executes the established handlers.
|
||||
if (elemData.dispatcher) {
|
||||
@ -263,11 +263,11 @@ _V_.trigger = function(elem, event) {
|
||||
|
||||
// Unless explicitly stopped, recursively calls this function to bubble the event up the DOM.
|
||||
if (parent && !event.isPropagationStopped()) {
|
||||
_V_.trigger(parent, event);
|
||||
vjs.trigger(parent, event);
|
||||
|
||||
// If at the top of the DOM, triggers the default action unless disabled.
|
||||
} else if (!parent && !event.isDefaultPrevented()) {
|
||||
var targetData = _V_.getData(event.target);
|
||||
var targetData = vjs.getData(event.target);
|
||||
|
||||
// Checks if the target has a default action for this event.
|
||||
if (event.target[event.type]) {
|
||||
@ -287,10 +287,10 @@ _V_.trigger = function(elem, event) {
|
||||
*/
|
||||
// // Added in attion to book. Book code was broke.
|
||||
// event = typeof event === "object" ?
|
||||
// event[_V_.expando] ?
|
||||
// event[vjs.expando] ?
|
||||
// event :
|
||||
// new _V_.Event(type, event) :
|
||||
// new _V_.Event(type);
|
||||
// new vjs.Event(type, event) :
|
||||
// new vjs.Event(type);
|
||||
|
||||
// event.type = type;
|
||||
// if (handler) {
|
||||
@ -309,9 +309,9 @@ _V_.trigger = function(elem, event) {
|
||||
* @param {Function} fn [description]
|
||||
* @return {[type]}
|
||||
*/
|
||||
_V_.one = function(elem, type, fn) {
|
||||
_V_.on(elem, type, function(){
|
||||
_V_.off(elem, type, arguments.callee)
|
||||
vjs.one = function(elem, type, fn) {
|
||||
vjs.on(elem, type, function(){
|
||||
vjs.off(elem, type, arguments.callee)
|
||||
fn.apply(this, arguments);
|
||||
});
|
||||
}
|
||||
|
172
src/exports.js
172
src/exports.js
@ -1,79 +1,117 @@
|
||||
goog.require('_V_');
|
||||
goog.require('_V_.Component');
|
||||
goog.require('_V_.Player');
|
||||
/**
|
||||
* @fileoverview Exports for Video.js.
|
||||
* Exports are publically available variables.
|
||||
* All other variables (including function names) will probably
|
||||
* be renamed by closure compiler.
|
||||
*/
|
||||
|
||||
goog.exportSymbol('VideoJS', VideoJS);
|
||||
/**
|
||||
* vjs (internal only) = videojs = _V_ (external only)
|
||||
*
|
||||
* vjs is the same as the goog var in Closure Library. It holds all variables
|
||||
* used in Video.js development. Closure compiler will rename all variables,
|
||||
* including class prototype functions, except those specifcally
|
||||
* exported (eports.js). Don't assume any function you can use in Video.js
|
||||
* development will be available on window.videojs for use with other js.
|
||||
*
|
||||
* For example, vjs.trim is an internal function and will be renamed by compiler
|
||||
* to something like 'a.b', or actually more likely 'a' removing it from
|
||||
* a parent object.
|
||||
*
|
||||
* videojs is a var that helps bridge bewteen internal and external development.
|
||||
* Avoid using it over vjs when developing the Video.js core.
|
||||
*
|
||||
* _V_ is only external. It's just cute and short(er). Like jQuery === $.
|
||||
* Also because it's nice having a different var for internal (vjs) vs.
|
||||
* external (_V_) because it makes it clearer what context we're in.
|
||||
*/
|
||||
goog.exportSymbol('videojs', vjs);
|
||||
goog.exportSymbol('_V_', vjs);
|
||||
|
||||
goog.exportSymbol('_V_.Component', _V_.Component);
|
||||
goog.exportProperty(_V_.Component.prototype, "dispose", _V_.Component.prototype.dispose);
|
||||
goog.exportProperty(_V_.Component.prototype, "createEl", _V_.Component.prototype.createEl);
|
||||
goog.exportProperty(_V_.Component.prototype, "getEl", _V_.Component.prototype.getEl);
|
||||
goog.exportProperty(_V_.Component.prototype, "addChild", _V_.Component.prototype.addChild);
|
||||
goog.exportProperty(_V_.Component.prototype, "getChildren", _V_.Component.prototype.getChildren);
|
||||
goog.exportProperty(_V_.Component.prototype, "on", _V_.Component.prototype.on);
|
||||
goog.exportProperty(_V_.Component.prototype, "off", _V_.Component.prototype.off);
|
||||
goog.exportProperty(_V_.Component.prototype, "one", _V_.Component.prototype.one);
|
||||
goog.exportProperty(_V_.Component.prototype, "trigger", _V_.Component.prototype.trigger);
|
||||
goog.exportProperty(_V_.Component.prototype, "show", _V_.Component.prototype.show);
|
||||
goog.exportProperty(_V_.Component.prototype, "hide", _V_.Component.prototype.hide);
|
||||
goog.exportProperty(_V_.Component.prototype, "width", _V_.Component.prototype.width);
|
||||
goog.exportProperty(_V_.Component.prototype, "height", _V_.Component.prototype.height);
|
||||
goog.exportProperty(_V_.Component.prototype, "dimensions", _V_.Component.prototype.dimensions);
|
||||
goog.exportSymbol('videojs.options', vjs.options);
|
||||
|
||||
goog.exportSymbol('_V_.Player', _V_.Player);
|
||||
// Allow external components to use global cache
|
||||
goog.exportSymbol('videojs.cache', vjs.cache);
|
||||
|
||||
goog.exportSymbol('_V_.MediaLoader', _V_.MediaLoader);
|
||||
goog.exportSymbol('_V_.PosterImage', _V_.PosterImage);
|
||||
goog.exportSymbol('_V_.LoadingSpinner', _V_.LoadingSpinner);
|
||||
goog.exportSymbol('_V_.BigPlayButton', _V_.BigPlayButton);
|
||||
goog.exportSymbol('_V_.ControlBar', _V_.ControlBar);
|
||||
goog.exportSymbol('_V_.TextTrackDisplay', _V_.TextTrackDisplay);
|
||||
goog.exportSymbol('videojs.Component', vjs.Component);
|
||||
goog.exportProperty(vjs.Component.prototype, "dispose", vjs.Component.prototype.dispose);
|
||||
goog.exportProperty(vjs.Component.prototype, "createEl", vjs.Component.prototype.createEl);
|
||||
goog.exportProperty(vjs.Component.prototype, "getEl", vjs.Component.prototype.getEl);
|
||||
goog.exportProperty(vjs.Component.prototype, "addChild", vjs.Component.prototype.addChild);
|
||||
goog.exportProperty(vjs.Component.prototype, "getChildren", vjs.Component.prototype.getChildren);
|
||||
goog.exportProperty(vjs.Component.prototype, "on", vjs.Component.prototype.on);
|
||||
goog.exportProperty(vjs.Component.prototype, "off", vjs.Component.prototype.off);
|
||||
goog.exportProperty(vjs.Component.prototype, "one", vjs.Component.prototype.one);
|
||||
goog.exportProperty(vjs.Component.prototype, "trigger", vjs.Component.prototype.trigger);
|
||||
goog.exportProperty(vjs.Component.prototype, "show", vjs.Component.prototype.show);
|
||||
goog.exportProperty(vjs.Component.prototype, "hide", vjs.Component.prototype.hide);
|
||||
goog.exportProperty(vjs.Component.prototype, "width", vjs.Component.prototype.width);
|
||||
goog.exportProperty(vjs.Component.prototype, "height", vjs.Component.prototype.height);
|
||||
goog.exportProperty(vjs.Component.prototype, "dimensions", vjs.Component.prototype.dimensions);
|
||||
|
||||
goog.exportSymbol('_V_.Control', _V_.Control);
|
||||
goog.exportSymbol('_V_.ControlBar', _V_.ControlBar);
|
||||
goog.exportSymbol('_V_.Button', _V_.Button);
|
||||
goog.exportSymbol('_V_.PlayButton', _V_.PlayButton);
|
||||
goog.exportSymbol('_V_.PauseButton', _V_.PauseButton);
|
||||
goog.exportSymbol('_V_.PlayToggle', _V_.PlayToggle);
|
||||
goog.exportSymbol('_V_.FullscreenToggle', _V_.FullscreenToggle);
|
||||
goog.exportSymbol('_V_.BigPlayButton', _V_.BigPlayButton);
|
||||
goog.exportSymbol('_V_.LoadingSpinner', _V_.LoadingSpinner);
|
||||
goog.exportSymbol('_V_.CurrentTimeDisplay', _V_.CurrentTimeDisplay);
|
||||
goog.exportSymbol('_V_.DurationDisplay', _V_.DurationDisplay);
|
||||
goog.exportSymbol('_V_.TimeDivider', _V_.TimeDivider);
|
||||
goog.exportSymbol('_V_.RemainingTimeDisplay', _V_.RemainingTimeDisplay);
|
||||
goog.exportSymbol('_V_.Slider', _V_.Slider);
|
||||
goog.exportSymbol('_V_.ProgressControl', _V_.ProgressControl);
|
||||
goog.exportSymbol('_V_.SeekBar', _V_.SeekBar);
|
||||
goog.exportSymbol('_V_.LoadProgressBar', _V_.LoadProgressBar);
|
||||
goog.exportSymbol('_V_.PlayProgressBar', _V_.PlayProgressBar);
|
||||
goog.exportSymbol('_V_.SeekHandle', _V_.SeekHandle);
|
||||
goog.exportSymbol('_V_.VolumeControl', _V_.VolumeControl);
|
||||
goog.exportSymbol('_V_.VolumeBar', _V_.VolumeBar);
|
||||
goog.exportSymbol('_V_.VolumeLevel', _V_.VolumeLevel);
|
||||
goog.exportSymbol('_V_.VolumeHandle', _V_.VolumeHandle);
|
||||
goog.exportSymbol('_V_.MuteToggle', _V_.MuteToggle);
|
||||
goog.exportSymbol('_V_.PosterImage', _V_.PosterImage);
|
||||
goog.exportSymbol('_V_.Menu', _V_.Menu);
|
||||
goog.exportSymbol('_V_.MenuItem', _V_.MenuItem);
|
||||
goog.exportSymbol('videojs.Player', vjs.Player);
|
||||
|
||||
goog.exportSymbol('_V_.MediaTechController', _V_.MediaTechController);
|
||||
goog.exportSymbol('videojs.MediaLoader', vjs.MediaLoader);
|
||||
goog.exportSymbol('videojs.PosterImage', vjs.PosterImage);
|
||||
goog.exportSymbol('videojs.LoadingSpinner', vjs.LoadingSpinner);
|
||||
goog.exportSymbol('videojs.BigPlayButton', vjs.BigPlayButton);
|
||||
goog.exportSymbol('videojs.ControlBar', vjs.ControlBar);
|
||||
goog.exportSymbol('videojs.TextTrackDisplay', vjs.TextTrackDisplay);
|
||||
|
||||
goog.exportSymbol('_V_.Html5', _V_.Html5);
|
||||
goog.exportProperty(_V_.Html5, "Supports", _V_.Html5.Supports);
|
||||
goog.exportProperty(_V_.Html5, "Events", _V_.Html5.Events);
|
||||
goog.exportProperty(_V_.Html5, "isSupported", _V_.Html5.isSupported);
|
||||
goog.exportProperty(_V_.Html5, "canPlaySource", _V_.Html5.canPlaySource);
|
||||
goog.exportSymbol('videojs.Control', vjs.Control);
|
||||
goog.exportSymbol('videojs.ControlBar', vjs.ControlBar);
|
||||
goog.exportSymbol('videojs.Button', vjs.Button);
|
||||
goog.exportSymbol('videojs.PlayButton', vjs.PlayButton);
|
||||
goog.exportSymbol('videojs.PauseButton', vjs.PauseButton);
|
||||
goog.exportSymbol('videojs.PlayToggle', vjs.PlayToggle);
|
||||
goog.exportSymbol('videojs.FullscreenToggle', vjs.FullscreenToggle);
|
||||
goog.exportSymbol('videojs.BigPlayButton', vjs.BigPlayButton);
|
||||
goog.exportSymbol('videojs.LoadingSpinner', vjs.LoadingSpinner);
|
||||
goog.exportSymbol('videojs.CurrentTimeDisplay', vjs.CurrentTimeDisplay);
|
||||
goog.exportSymbol('videojs.DurationDisplay', vjs.DurationDisplay);
|
||||
goog.exportSymbol('videojs.TimeDivider', vjs.TimeDivider);
|
||||
goog.exportSymbol('videojs.RemainingTimeDisplay', vjs.RemainingTimeDisplay);
|
||||
goog.exportSymbol('videojs.Slider', vjs.Slider);
|
||||
goog.exportSymbol('videojs.ProgressControl', vjs.ProgressControl);
|
||||
goog.exportSymbol('videojs.SeekBar', vjs.SeekBar);
|
||||
goog.exportSymbol('videojs.LoadProgressBar', vjs.LoadProgressBar);
|
||||
goog.exportSymbol('videojs.PlayProgressBar', vjs.PlayProgressBar);
|
||||
goog.exportSymbol('videojs.SeekHandle', vjs.SeekHandle);
|
||||
goog.exportSymbol('videojs.VolumeControl', vjs.VolumeControl);
|
||||
goog.exportSymbol('videojs.VolumeBar', vjs.VolumeBar);
|
||||
goog.exportSymbol('videojs.VolumeLevel', vjs.VolumeLevel);
|
||||
goog.exportSymbol('videojs.VolumeHandle', vjs.VolumeHandle);
|
||||
goog.exportSymbol('videojs.MuteToggle', vjs.MuteToggle);
|
||||
goog.exportSymbol('videojs.PosterImage', vjs.PosterImage);
|
||||
goog.exportSymbol('videojs.Menu', vjs.Menu);
|
||||
goog.exportSymbol('videojs.MenuItem', vjs.MenuItem);
|
||||
|
||||
goog.exportSymbol('videojs.SubtitlesButton', vjs.SubtitlesButton);
|
||||
goog.exportSymbol('videojs.CaptionsButton', vjs.CaptionsButton);
|
||||
goog.exportSymbol('videojs.ChaptersButton', vjs.ChaptersButton);
|
||||
|
||||
goog.exportSymbol('videojs.MediaTechController', vjs.MediaTechController);
|
||||
|
||||
goog.exportSymbol('videojs.Html5', vjs.Html5);
|
||||
goog.exportProperty(vjs.Html5, "Events", vjs.Html5.Events);
|
||||
goog.exportProperty(vjs.Html5, "isSupported", vjs.Html5.isSupported);
|
||||
goog.exportProperty(vjs.Html5, "canPlaySource", vjs.Html5.canPlaySource);
|
||||
|
||||
// Export non-standard HTML5 video API methods.
|
||||
// Standard method names already protected by default externs.
|
||||
goog.exportProperty(_V_.Html5.prototype, "setCurrentTime", _V_.Html5.prototype.setCurrentTime);
|
||||
goog.exportProperty(_V_.Html5.prototype, "setVolume", _V_.Html5.prototype.setVolume);
|
||||
goog.exportProperty(_V_.Html5.prototype, "setMuted", _V_.Html5.prototype.setMuted);
|
||||
goog.exportProperty(_V_.Html5.prototype, "setPreload", _V_.Html5.prototype.setPreload);
|
||||
goog.exportProperty(_V_.Html5.prototype, "setAutoplay", _V_.Html5.prototype.setAutoplay);
|
||||
goog.exportProperty(_V_.Html5.prototype, "setLoop", _V_.Html5.prototype.setLoop);
|
||||
goog.exportProperty(vjs.Html5.prototype, "setCurrentTime", vjs.Html5.prototype.setCurrentTime);
|
||||
goog.exportProperty(vjs.Html5.prototype, "setVolume", vjs.Html5.prototype.setVolume);
|
||||
goog.exportProperty(vjs.Html5.prototype, "setMuted", vjs.Html5.prototype.setMuted);
|
||||
goog.exportProperty(vjs.Html5.prototype, "setPreload", vjs.Html5.prototype.setPreload);
|
||||
goog.exportProperty(vjs.Html5.prototype, "setAutoplay", vjs.Html5.prototype.setAutoplay);
|
||||
goog.exportProperty(vjs.Html5.prototype, "setLoop", vjs.Html5.prototype.setLoop);
|
||||
|
||||
goog.exportSymbol('videojs.Flash', vjs.Flash);
|
||||
goog.exportProperty(vjs.Flash, "Events", vjs.Flash.Events);
|
||||
goog.exportProperty(vjs.Flash, "isSupported", vjs.Flash.isSupported);
|
||||
goog.exportProperty(vjs.Flash, "canPlaySource", vjs.Flash.canPlaySource);
|
||||
goog.exportProperty(vjs.Flash, "onReady", vjs.Flash['onReady']);
|
||||
|
||||
// Allow external components to use global cache
|
||||
goog.exportSymbol('_V_.cache', _V_.cache);
|
||||
goog.exportSymbol('videojs.CaptionsTrack', vjs.CaptionsTrack);
|
||||
goog.exportSymbol('videojs.SubtitlesTrack', vjs.SubtitlesTrack);
|
||||
goog.exportSymbol('videojs.ChaptersTrack', vjs.ChaptersTrack);
|
||||
|
81
src/json.js
81
src/json.js
@ -2,53 +2,58 @@
|
||||
// (Parse Method Only)
|
||||
// https://github.com/douglascrockford/JSON-js/blob/master/json2.js
|
||||
|
||||
var JSON;
|
||||
if (!JSON) { JSON = {}; }
|
||||
/**
|
||||
* JSON shim. Only using for parse method when parsing data-setup attribute JSON.
|
||||
*/
|
||||
vjs.JSON;
|
||||
|
||||
if (JSON && JSON.parse === 'function') {
|
||||
vjs.JSON = JSON;
|
||||
|
||||
} else {
|
||||
vjs.JSON = {};
|
||||
|
||||
(function(){
|
||||
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
|
||||
|
||||
if (typeof JSON.parse !== 'function') {
|
||||
JSON.parse = function (text, reviver) {
|
||||
var j;
|
||||
vjs.JSON.parse = function (text, reviver) {
|
||||
var j;
|
||||
|
||||
function walk(holder, key) {
|
||||
var k, v, value = holder[key];
|
||||
if (value && typeof value === 'object') {
|
||||
for (k in value) {
|
||||
if (Object.prototype.hasOwnProperty.call(value, k)) {
|
||||
v = walk(value, k);
|
||||
if (v !== undefined) {
|
||||
value[k] = v;
|
||||
} else {
|
||||
delete value[k];
|
||||
}
|
||||
function walk(holder, key) {
|
||||
var k, v, value = holder[key];
|
||||
if (value && typeof value === 'object') {
|
||||
for (k in value) {
|
||||
if (Object.prototype.hasOwnProperty.call(value, k)) {
|
||||
v = walk(value, k);
|
||||
if (v !== undefined) {
|
||||
value[k] = v;
|
||||
} else {
|
||||
delete value[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
return reviver.call(holder, key, value);
|
||||
}
|
||||
text = String(text);
|
||||
cx.lastIndex = 0;
|
||||
if (cx.test(text)) {
|
||||
text = text.replace(cx, function (a) {
|
||||
return '\\u' +
|
||||
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
||||
});
|
||||
}
|
||||
return reviver.call(holder, key, value);
|
||||
}
|
||||
text = String(text);
|
||||
cx.lastIndex = 0;
|
||||
if (cx.test(text)) {
|
||||
text = text.replace(cx, function (a) {
|
||||
return '\\u' +
|
||||
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
||||
});
|
||||
}
|
||||
|
||||
if (/^[\],:{}\s]*$/
|
||||
.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
|
||||
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
|
||||
.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
|
||||
if (/^[\],:{}\s]*$/
|
||||
.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
|
||||
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
|
||||
.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
|
||||
|
||||
j = eval('(' + text + ')');
|
||||
j = eval('(' + text + ')');
|
||||
|
||||
return typeof reviver === 'function' ?
|
||||
walk({'': j}, '') : j;
|
||||
}
|
||||
return typeof reviver === 'function' ?
|
||||
walk({'': j}, '') : j;
|
||||
}
|
||||
|
||||
throw new SyntaxError('JSON.parse');
|
||||
};
|
||||
}
|
||||
}());
|
||||
throw new SyntaxError('JSON.parse');
|
||||
};
|
||||
}
|
||||
|
150
src/lib.js
150
src/lib.js
@ -4,7 +4,7 @@
|
||||
* @param {Object=} properties Element properties to be applied.
|
||||
* @return {Element}
|
||||
*/
|
||||
_V_.createEl = function(tagName, properties){
|
||||
vjs.createEl = function(tagName, properties){
|
||||
var el = document.createElement(tagName || 'div');
|
||||
|
||||
for (var propName in properties){
|
||||
@ -27,7 +27,7 @@ _V_.createEl = function(tagName, properties){
|
||||
* @param {String} string String to be uppercased
|
||||
* @return {String}
|
||||
*/
|
||||
_V_.capitalize = function(string){
|
||||
vjs.capitalize = function(string){
|
||||
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||
};
|
||||
|
||||
@ -38,7 +38,7 @@ _V_.capitalize = function(string){
|
||||
* @param {Function} fn Function to be called on each property.
|
||||
* @this {*}
|
||||
*/
|
||||
_V_.eachProp = function(obj, fn){
|
||||
vjs.eachProp = function(obj, fn){
|
||||
if (!obj) { return; }
|
||||
for (var name in obj) {
|
||||
if (obj.hasOwnProperty(name)) {
|
||||
@ -54,7 +54,7 @@ _V_.eachProp = function(obj, fn){
|
||||
* @param {[type]} safe [description]
|
||||
* @return {[type]}
|
||||
*/
|
||||
_V_.merge = function(obj1, obj2, safe){
|
||||
vjs.merge = function(obj1, obj2, safe){
|
||||
// Make sure second object exists
|
||||
if (!obj2) { return obj1; }
|
||||
|
||||
@ -63,7 +63,7 @@ _V_.merge = function(obj1, obj2, safe){
|
||||
}
|
||||
return obj1;
|
||||
};
|
||||
// _V_.extend = function(obj){ this.merge(this, obj, true); };
|
||||
// vjs.extend = function(obj){ this.merge(this, obj, true); };
|
||||
|
||||
/**
|
||||
* Bind (a.k.a proxy or Context). A simple method for changing the context of a function
|
||||
@ -73,9 +73,9 @@ _V_.merge = function(obj1, obj2, safe){
|
||||
* @param {Number=} uid An optional unique ID for the function to be set
|
||||
* @return {Function}
|
||||
*/
|
||||
_V_.bind = function(context, fn, uid) {
|
||||
vjs.bind = function(context, fn, uid) {
|
||||
// Make sure the function has a unique ID
|
||||
if (!fn.guid) { fn.guid = _V_.guid++; }
|
||||
if (!fn.guid) { fn.guid = vjs.guid++; }
|
||||
|
||||
// Create the new function that changes the context
|
||||
var ret = function() {
|
||||
@ -107,7 +107,7 @@ _V_.bind = function(context, fn, uid) {
|
||||
* @return {!Function} A partially-applied form of the function bind() was
|
||||
* invoked as a method of.
|
||||
*/
|
||||
_V_.partial = function(fn, var_args) {
|
||||
vjs.partial = function(fn, var_args) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
return function() {
|
||||
// Prepend the bound arguments to the current arguments.
|
||||
@ -123,33 +123,33 @@ _V_.partial = function(fn, var_args) {
|
||||
* (also from jsninja.com, slightly modified and updated for closure compiler)
|
||||
* @type {Object}
|
||||
*/
|
||||
_V_.cache = {};
|
||||
vjs.cache = {};
|
||||
|
||||
/**
|
||||
* Unique ID for an element or function
|
||||
* @type {Number}
|
||||
*/
|
||||
_V_.guid = 1;
|
||||
vjs.guid = 1;
|
||||
|
||||
/**
|
||||
* Unique attribute name to store an element's guid in
|
||||
* @type {String}
|
||||
* @constant
|
||||
*/
|
||||
_V_.expando = "vdata" + (new Date).getTime();
|
||||
vjs.expando = "vdata" + (new Date).getTime();
|
||||
|
||||
/**
|
||||
* Returns the cache object where data for an element is stored
|
||||
* @param {Element} el Element to store data for.
|
||||
* @return {Object}
|
||||
*/
|
||||
_V_.getData = function(el){
|
||||
var id = el[_V_.expando];
|
||||
vjs.getData = function(el){
|
||||
var id = el[vjs.expando];
|
||||
if (!id) {
|
||||
id = el[_V_.expando] = _V_.guid++;
|
||||
_V_.cache[id] = {};
|
||||
id = el[vjs.expando] = vjs.guid++;
|
||||
vjs.cache[id] = {};
|
||||
}
|
||||
return _V_.cache[id];
|
||||
return vjs.cache[id];
|
||||
};
|
||||
|
||||
/**
|
||||
@ -157,38 +157,38 @@ _V_.getData = function(el){
|
||||
* @param {Element} el Element to store data for.
|
||||
* @return {Object}
|
||||
*/
|
||||
_V_.hasData = function(el){
|
||||
var id = el[_V_.expando];
|
||||
return !(!id || _V_.isEmpty(_V_.cache[id]));
|
||||
vjs.hasData = function(el){
|
||||
var id = el[vjs.expando];
|
||||
return !(!id || vjs.isEmpty(vjs.cache[id]));
|
||||
};
|
||||
|
||||
/**
|
||||
* Delete data for the element from the cache and the guid attr from getElementById
|
||||
* @param {Element} el Remove data for an element
|
||||
*/
|
||||
_V_.removeData = function(el){
|
||||
var id = el[_V_.expando];
|
||||
vjs.removeData = function(el){
|
||||
var id = el[vjs.expando];
|
||||
if (!id) { return; }
|
||||
// Remove all stored data
|
||||
// Changed to = null
|
||||
// http://coding.smashingmagazine.com/2012/11/05/writing-fast-memory-efficient-javascript/
|
||||
// _V_.cache[id] = null;
|
||||
delete _V_.cache[id];
|
||||
// vjs.cache[id] = null;
|
||||
delete vjs.cache[id];
|
||||
|
||||
// Remove the expando property from the DOM node
|
||||
try {
|
||||
delete el[_V_.expando];
|
||||
delete el[vjs.expando];
|
||||
} catch(e) {
|
||||
if (el.removeAttribute) {
|
||||
el.removeAttribute(_V_.expando);
|
||||
el.removeAttribute(vjs.expando);
|
||||
} else {
|
||||
// IE doesn't appear to support removeAttribute on the document element
|
||||
el[_V_.expando] = null;
|
||||
el[vjs.expando] = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_V_.isEmpty = function(obj) {
|
||||
vjs.isEmpty = function(obj) {
|
||||
for (var prop in obj) {
|
||||
// Inlude null properties as empty.
|
||||
if (obj[prop] !== null) {
|
||||
@ -203,7 +203,7 @@ _V_.isEmpty = function(obj) {
|
||||
* @param {Element} element Element to add class name to
|
||||
* @param {String} classToAdd Classname to add
|
||||
*/
|
||||
_V_.addClass = function(element, classToAdd){
|
||||
vjs.addClass = function(element, classToAdd){
|
||||
if ((" "+element.className+" ").indexOf(" "+classToAdd+" ") == -1) {
|
||||
element.className = element.className === "" ? classToAdd : element.className + " " + classToAdd;
|
||||
}
|
||||
@ -214,7 +214,7 @@ _V_.addClass = function(element, classToAdd){
|
||||
* @param {Element} element Element to remove from class name
|
||||
* @param {String} classToAdd Classname to remove
|
||||
*/
|
||||
_V_.removeClass = function(element, classToRemove){
|
||||
vjs.removeClass = function(element, classToRemove){
|
||||
if (element.className.indexOf(classToRemove) == -1) { return; }
|
||||
var classNames = element.className.split(" ");
|
||||
classNames.splice(classNames.indexOf(classToRemove),1);
|
||||
@ -226,32 +226,32 @@ _V_.removeClass = function(element, classToRemove){
|
||||
* @type {Element}
|
||||
* @constant
|
||||
*/
|
||||
_V_.TEST_VID = document.createElement("video");
|
||||
vjs.TEST_VID = document.createElement("video");
|
||||
|
||||
/**
|
||||
* Useragent for browser testing.
|
||||
* @type {String}
|
||||
* @constant
|
||||
*/
|
||||
_V_.UA = navigator.userAgent;
|
||||
vjs.USER_AGENT = navigator.userAgent;
|
||||
|
||||
/**
|
||||
* Device is an iPhone
|
||||
* @type {Boolean}
|
||||
* @constant
|
||||
*/
|
||||
_V_.IS_IPHONE = !!navigator.userAgent.match(/iPad/i);
|
||||
_V_.IS_IPAD = !!navigator.userAgent.match(/iPhone/i);
|
||||
_V_.IS_IPOD = !!navigator.userAgent.match(/iPod/i);
|
||||
_V_.IS_IOS = _V_.IS_IPHONE || _V_.IS_IPAD || _V_.IS_IPOD;
|
||||
vjs.IS_IPHONE = !!navigator.userAgent.match(/iPad/i);
|
||||
vjs.IS_IPAD = !!navigator.userAgent.match(/iPhone/i);
|
||||
vjs.IS_IPOD = !!navigator.userAgent.match(/iPod/i);
|
||||
vjs.IS_IOS = vjs.IS_IPHONE || vjs.IS_IPAD || vjs.IS_IPOD;
|
||||
|
||||
_V_.IOS_VERSION = (function(){
|
||||
vjs.IOS_VERSION = (function(){
|
||||
var match = navigator.userAgent.match(/OS (\d+)_/i);
|
||||
if (match && match[1]) { return match[1]; }
|
||||
})();
|
||||
|
||||
_V_.IS_ANDROID = !!navigator.userAgent.match(/Android.*AppleWebKit/i);
|
||||
_V_.ANDROID_VERSION = (function() {
|
||||
vjs.IS_ANDROID = !!navigator.userAgent.match(/Android.*AppleWebKit/i);
|
||||
vjs.ANDROID_VERSION = (function() {
|
||||
var match = navigator.userAgent.match(/Android (\d+)\./i);
|
||||
if (match && match[1]) {
|
||||
return match[1];
|
||||
@ -259,6 +259,13 @@ _V_.ANDROID_VERSION = (function() {
|
||||
return null;
|
||||
})();
|
||||
|
||||
// http://webreflection.blogspot.com/2009/01/32-bytes-to-know-if-your-browser-is-ie.html
|
||||
// IE9+ returns false
|
||||
vjs.IS_IE6to8 = function(){ return !+"\v1"; };
|
||||
|
||||
vjs.IS_FIREFOX = function(){ return !!vjs.USER_AGENT.match("Firefox") };
|
||||
|
||||
|
||||
/**
|
||||
* Get an element's attribute values, as defined on the HTML tag
|
||||
* Attributs are not the same as properties. They're defined on the tag
|
||||
@ -267,7 +274,7 @@ _V_.ANDROID_VERSION = (function() {
|
||||
* @param {Element} tag Element from which to get tag attributes
|
||||
* @return {Object}
|
||||
*/
|
||||
_V_.getAttributeValues = function(tag){
|
||||
vjs.getAttributeValues = function(tag){
|
||||
var obj = {};
|
||||
|
||||
// Known boolean attributes
|
||||
@ -307,7 +314,7 @@ _V_.getAttributeValues = function(tag){
|
||||
* @param {String} strCssRule Style name
|
||||
* @return {String} Style value
|
||||
*/
|
||||
_V_.getComputedStyleValue = function(el, strCssRule){
|
||||
vjs.getComputedStyleValue = function(el, strCssRule){
|
||||
var strValue = "";
|
||||
if(document.defaultView && document.defaultView.getComputedStyle){
|
||||
strValue = document.defaultView.getComputedStyle(el, "").getPropertyValue(strCssRule);
|
||||
@ -326,7 +333,7 @@ _V_.getComputedStyleValue = function(el, strCssRule){
|
||||
* @param {Element} child Element to insert
|
||||
* @param {[type]} parent Element to insert child into
|
||||
*/
|
||||
_V_.insertFirst = function(child, parent){
|
||||
vjs.insertFirst = function(child, parent){
|
||||
if (parent.firstChild) {
|
||||
parent.insertBefore(child, parent.firstChild);
|
||||
} else {
|
||||
@ -338,7 +345,7 @@ _V_.insertFirst = function(child, parent){
|
||||
* Object to hold browser support information
|
||||
* @type {Object}
|
||||
*/
|
||||
_V_.support = {};
|
||||
vjs.support = {};
|
||||
|
||||
/**
|
||||
* Shorthand for document.getElementById()
|
||||
@ -346,7 +353,7 @@ _V_.support = {};
|
||||
* @param {String} id Element ID
|
||||
* @return {Element} Element with supplied ID
|
||||
*/
|
||||
_V_.el = function(id){
|
||||
vjs.el = function(id){
|
||||
if (id.indexOf("#") === 0) {
|
||||
id = id.slice(1);
|
||||
}
|
||||
@ -362,7 +369,7 @@ _V_.el = function(id){
|
||||
* @param {Number} guide Number (in seconds) to model the string after
|
||||
* @return {String} Time formatted as H:MM:SS or M:SS
|
||||
*/
|
||||
_V_.formatTime = function(seconds, guide) {
|
||||
vjs.formatTime = function(seconds, guide) {
|
||||
guide = guide || seconds; // Default to using seconds as guide
|
||||
var s = Math.floor(seconds % 60),
|
||||
m = Math.floor(seconds / 60 % 60),
|
||||
@ -384,19 +391,19 @@ _V_.formatTime = function(seconds, guide) {
|
||||
};
|
||||
|
||||
// Attempt to block the ability to select text while dragging controls
|
||||
_V_.blockTextSelection = function(){
|
||||
vjs.blockTextSelection = function(){
|
||||
document.body.focus();
|
||||
document.onselectstart = function () { return false; };
|
||||
};
|
||||
// Turn off text selection blocking
|
||||
_V_.unblockTextSelection = function(){ document.onselectstart = function () { return true; }; };
|
||||
vjs.unblockTextSelection = function(){ document.onselectstart = function () { return true; }; };
|
||||
|
||||
/**
|
||||
* Trim whitespace from the ends of a string.
|
||||
* @param {String} string String to trim
|
||||
* @return {String} Trimmed string
|
||||
*/
|
||||
_V_.trim = function(string){
|
||||
vjs.trim = function(string){
|
||||
return string.toString().replace(/^\s+/, "").replace(/\s+$/, "");
|
||||
};
|
||||
|
||||
@ -406,7 +413,7 @@ _V_.trim = function(string){
|
||||
* @param {Number} dec Number of decimal places to round to
|
||||
* @return {Number} Rounded number
|
||||
*/
|
||||
_V_.round = function(num, dec) {
|
||||
vjs.round = function(num, dec) {
|
||||
if (!dec) { dec = 0; }
|
||||
return Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);
|
||||
};
|
||||
@ -420,7 +427,7 @@ _V_.round = function(num, dec) {
|
||||
* @param {Number} end End time in seconds
|
||||
* @return {Object} Fake TimeRange object
|
||||
*/
|
||||
_V_.createTimeRange = function(start, end){
|
||||
vjs.createTimeRange = function(start, end){
|
||||
return {
|
||||
length: 1,
|
||||
start: function() { return start; },
|
||||
@ -428,10 +435,7 @@ _V_.createTimeRange = function(start, end){
|
||||
};
|
||||
};
|
||||
|
||||
// _V_.extend({
|
||||
// // Device Checks
|
||||
// isIE: function(){ return !+"\v1"; },
|
||||
// isFF: function(){ return !!_V_.ua.match("Firefox") },
|
||||
// vjs.extend({
|
||||
|
||||
// each: function(arr, fn){
|
||||
// if (!arr || arr.length === 0) { return; }
|
||||
@ -442,7 +446,7 @@ _V_.createTimeRange = function(start, end){
|
||||
|
||||
// // Return the relative horizonal position of an event as a value from 0-1
|
||||
// getRelativePosition: function(x, relativeElement){
|
||||
// return Math.max(0, Math.min(1, (x - _V_.findPosX(relativeElement)) / relativeElement.offsetWidth));
|
||||
// return Math.max(0, Math.min(1, (x - vjs.findPosX(relativeElement)) / relativeElement.offsetWidth));
|
||||
// },
|
||||
|
||||
// get: function(url, onSuccess, onError){
|
||||
@ -466,12 +470,12 @@ _V_.createTimeRange = function(start, end){
|
||||
// try {
|
||||
// request.open("GET", url);
|
||||
// } catch(e) {
|
||||
// _V_.log("VideoJS XMLHttpRequest (open)", e);
|
||||
// vjs.log("VideoJS XMLHttpRequest (open)", e);
|
||||
// // onError(e);
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// request.onreadystatechange = _V_.proxy(this, function() {
|
||||
// request.onreadystatechange = vjs.proxy(this, function() {
|
||||
// if (request.readyState == 4) {
|
||||
// if (request.status == 200 || local && request.status == 0) {
|
||||
// onSuccess(request.responseText);
|
||||
@ -486,7 +490,7 @@ _V_.createTimeRange = function(start, end){
|
||||
// try {
|
||||
// request.send();
|
||||
// } catch(e) {
|
||||
// _V_.log("VideoJS XMLHttpRequest (send)", e);
|
||||
// vjs.log("VideoJS XMLHttpRequest (send)", e);
|
||||
// if (onError) {
|
||||
// onError(e);
|
||||
// }
|
||||
@ -495,7 +499,7 @@ _V_.createTimeRange = function(start, end){
|
||||
|
||||
/* Local Storage
|
||||
================================================================================ */
|
||||
_V_.setLocalStorage = function(key, value){
|
||||
vjs.setLocalStorage = function(key, value){
|
||||
// IE was throwing errors referencing the var anywhere without this
|
||||
var localStorage = window.localStorage || false;
|
||||
if (!localStorage) { return; }
|
||||
@ -503,9 +507,9 @@ _V_.setLocalStorage = function(key, value){
|
||||
localStorage[key] = value;
|
||||
} catch(e) {
|
||||
if (e.code == 22 || e.code == 1014) { // Webkit == 22 / Firefox == 1014
|
||||
_V_.log("LocalStorage Full (VideoJS)", e);
|
||||
vjs.log("LocalStorage Full (VideoJS)", e);
|
||||
} else {
|
||||
_V_.log("LocalStorage Error (VideoJS)", e);
|
||||
vjs.log("LocalStorage Error (VideoJS)", e);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -516,12 +520,12 @@ _V_.setLocalStorage = function(key, value){
|
||||
* @param {String} url URL to make absolute
|
||||
* @return {String} Absolute URL
|
||||
*/
|
||||
_V_.getAbsoluteURL = function(url){
|
||||
vjs.getAbsoluteURL = function(url){
|
||||
|
||||
// Check if absolute URL
|
||||
if (!url.match(/^https?:\/\//)) {
|
||||
// Convert to absolute URL. Flash hosted off-site needs an absolute URL.
|
||||
url = _V_.createEl('div', {
|
||||
url = vjs.createEl('div', {
|
||||
innerHTML: '<a href="'+url+'">x</a>'
|
||||
}).firstChild.href;
|
||||
}
|
||||
@ -529,17 +533,15 @@ _V_.getAbsoluteURL = function(url){
|
||||
return url;
|
||||
};
|
||||
|
||||
// });
|
||||
|
||||
// usage: log('inside coolFunc', this, arguments);
|
||||
// paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
|
||||
_V_.log = function(){
|
||||
_V_.log.history = _V_.log.history || [];// store logs to an array for reference
|
||||
_V_.log.history.push(arguments);
|
||||
vjs.log = function(){
|
||||
vjs.log.history = vjs.log.history || [];// store logs to an array for reference
|
||||
vjs.log.history.push(arguments);
|
||||
if(window.console) {
|
||||
arguments.callee = arguments.callee.caller;
|
||||
var newarr = [].slice.call(arguments);
|
||||
(typeof console.log === 'object' ? _V_.log.apply.call(console.log, console, newarr) : console.log.apply(console, newarr));
|
||||
(typeof console.log === 'object' ? vjs.log.apply.call(console.log, console, newarr) : console.log.apply(console, newarr));
|
||||
}
|
||||
};
|
||||
|
||||
@ -550,7 +552,7 @@ _V_.log = function(){
|
||||
// Offset Left
|
||||
// getBoundingClientRect technique from John Resig http://ejohn.org/blog/getboundingclientrect-is-awesome/
|
||||
if ("getBoundingClientRect" in document.documentElement) {
|
||||
_V_.findPosX = function(el) {
|
||||
vjs.findPosX = function(el) {
|
||||
var box;
|
||||
|
||||
try {
|
||||
@ -568,14 +570,14 @@ if ("getBoundingClientRect" in document.documentElement) {
|
||||
return left;
|
||||
};
|
||||
} else {
|
||||
_V_.findPosX = function(el) {
|
||||
vjs.findPosX = function(el) {
|
||||
var curleft = el.offsetLeft;
|
||||
// _V_.log(obj.className, obj.offsetLeft)
|
||||
// vjs.log(obj.className, obj.offsetLeft)
|
||||
while(el = obj.offsetParent) {
|
||||
if (el.className.indexOf("video-js") == -1) {
|
||||
// _V_.log(el.offsetParent, "OFFSETLEFT", el.offsetLeft)
|
||||
// _V_.log("-webkit-full-screen", el.webkitMatchesSelector("-webkit-full-screen"));
|
||||
// _V_.log("-webkit-full-screen", el.querySelectorAll(".video-js:-webkit-full-screen"));
|
||||
// vjs.log(el.offsetParent, "OFFSETLEFT", el.offsetLeft)
|
||||
// vjs.log("-webkit-full-screen", el.webkitMatchesSelector("-webkit-full-screen"));
|
||||
// vjs.log("-webkit-full-screen", el.querySelectorAll(".video-js:-webkit-full-screen"));
|
||||
} else {
|
||||
}
|
||||
curleft += el.offsetLeft;
|
||||
|
27
src/media.flash.externs.js
Normal file
27
src/media.flash.externs.js
Normal file
@ -0,0 +1,27 @@
|
||||
/**
|
||||
* @fileoverview Externs for video-js.swf. Externs are functions
|
||||
* that the compiler shouldn't obfuscate.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
*/
|
||||
HTMLObjectElement.prototype.vjs_getProperty = function(name) {};
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @param {string|number} value
|
||||
*/
|
||||
HTMLObjectElement.prototype.vjs_setProperty = function(name, value) {}
|
||||
|
||||
/**
|
||||
* Control methods
|
||||
*/
|
||||
HTMLObjectElement.prototype.vjs_play = function() {}
|
||||
HTMLObjectElement.prototype.vjs_pause = function() {}
|
||||
HTMLObjectElement.prototype.vjs_load = function() {}
|
||||
|
||||
/**
|
||||
* @param {string} src
|
||||
*/
|
||||
HTMLObjectElement.prototype.vjs_src = function(src) {}
|
@ -1,18 +1,19 @@
|
||||
goog.provide('_V_.Flash');
|
||||
goog.provide('_V_.media.flash');
|
||||
goog.provide('vjs.Flash');
|
||||
goog.provide('vjs.media.flash');
|
||||
|
||||
goog.require('_V_.MediaTechController');
|
||||
goog.require('vjs.MediaTechController');
|
||||
|
||||
/* VideoJS-SWF - Custom Flash Player with HTML5-ish API - https://github.com/zencoder/video-js-swf
|
||||
Not using setupTriggers. Using global onEvent func to distribute events
|
||||
================================================================================ */
|
||||
/**
|
||||
* HTML5 Media Controller - Wrapper for HTML5 Media API
|
||||
* @param {_V_.Player|Object} player
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @param {Function=} ready
|
||||
* @constructor
|
||||
*/
|
||||
_V_.Flash = function(player, options, ready){
|
||||
vjs.Flash = function(player, options, ready){
|
||||
goog.base(this, player, options, ready);
|
||||
|
||||
var source = options.source,
|
||||
@ -21,51 +22,53 @@ _V_.Flash = function(player, options, ready){
|
||||
parentEl = options.parentEl,
|
||||
|
||||
// Create a temporary element to be replaced by swf object
|
||||
placeHolder = this.el = _V_.createElement("div", { id: parentEl.id + "_temp_flash" }),
|
||||
placeHolder = this.el_ = vjs.createEl("div", { id: player.getId() + "_temp_flash" }),
|
||||
|
||||
// Generate ID for swf object
|
||||
objId = player.el.id+"_flash_api",
|
||||
objId = player.getId()+"_flash_api",
|
||||
|
||||
// Store player options in local var for optimization
|
||||
// TODO: switch to using player methods instead of options
|
||||
// e.g. player.autoplay();
|
||||
playerOptions = player.options,
|
||||
|
||||
// Merge default flashvars with ones passed in to init
|
||||
flashVars = _V_.merge({
|
||||
flashVars = vjs.merge({
|
||||
|
||||
// SWF Callback Functions
|
||||
readyFunction: "_V_.Flash.onReady",
|
||||
eventProxyFunction: "_V_.Flash.onEvent",
|
||||
errorEventProxyFunction: "_V_.Flash.onError",
|
||||
'readyFunction': "videojs.Flash.onReady",
|
||||
'eventProxyFunction': "videojs.Flash.onEvent",
|
||||
'errorEventProxyFunction': "videojs.Flash.onError",
|
||||
|
||||
// Player Settings
|
||||
autoplay: playerOptions.autoplay,
|
||||
preload: playerOptions.preload,
|
||||
loop: playerOptions.loop,
|
||||
muted: playerOptions.muted
|
||||
'autoplay': playerOptions.autoplay,
|
||||
'preload': playerOptions.preload,
|
||||
'loop': playerOptions.loop,
|
||||
'muted': playerOptions.muted
|
||||
|
||||
}, options.flashVars),
|
||||
}, options['flashVars']),
|
||||
|
||||
// Merge default parames with ones passed in
|
||||
params = _V_.merge({
|
||||
wmode: "opaque", // Opaque is needed to overlay controls, but can affect playback performance
|
||||
bgcolor: "#000000" // Using bgcolor prevents a white flash when the object is loading
|
||||
}, options.params),
|
||||
params = vjs.merge({
|
||||
'wmode': "opaque", // Opaque is needed to overlay controls, but can affect playback performance
|
||||
'bgcolor': "#000000" // Using bgcolor prevents a white flash when the object is loading
|
||||
}, options['params']),
|
||||
|
||||
// Merge default attributes with ones passed in
|
||||
attributes = _V_.merge({
|
||||
id: objId,
|
||||
name: objId, // Both ID and Name needed or swf to identifty itself
|
||||
attributes = vjs.merge({
|
||||
'id': objId,
|
||||
'name': objId, // Both ID and Name needed or swf to identifty itself
|
||||
'class': 'vjs-tech'
|
||||
}, options.attributes)
|
||||
}, options['attributes'])
|
||||
;
|
||||
|
||||
// If source was supplied pass as a flash var.
|
||||
if (source) {
|
||||
flashVars.src = encodeURIComponent(_V_.getAbsoluteURL(source.src));
|
||||
flashVars['src'] = encodeURIComponent(vjs.getAbsoluteURL(source.src));
|
||||
}
|
||||
|
||||
// Add placeholder to player div
|
||||
_V_.insertFirst(placeHolder, parentEl);
|
||||
vjs.insertFirst(placeHolder, parentEl);
|
||||
|
||||
// Having issues with Flash reloading on certain page actions (hide/resize/fullscreen) in certain browsers
|
||||
// This allows resetting the playhead when we catch the reload
|
||||
@ -97,43 +100,43 @@ _V_.Flash = function(player, options, ready){
|
||||
// Not sure why that even works, but it causes the browser to look like it's continuously trying to load the page.
|
||||
// Firefox 3.6 keeps calling the iframe onload function anytime I write to it, causing an endless loop.
|
||||
|
||||
if (options.iFrameMode === true && !_V_.isFF) {
|
||||
if (options.iFrameMode === true && !vjs.IS_FIREFOX) {
|
||||
|
||||
// Create iFrame with vjs-tech class so it's 100% width/height
|
||||
var iFrm = _V_.createElement("iframe", {
|
||||
id: objId + "_iframe",
|
||||
name: objId + "_iframe",
|
||||
className: "vjs-tech",
|
||||
scrolling: "no",
|
||||
marginWidth: 0,
|
||||
marginHeight: 0,
|
||||
frameBorder: 0
|
||||
var iFrm = vjs.createEl("iframe", {
|
||||
'id': objId + "_iframe",
|
||||
'name': objId + "_iframe",
|
||||
'className': "vjs-tech",
|
||||
'scrolling': "no",
|
||||
'marginWidth': 0,
|
||||
'marginHeight': 0,
|
||||
'frameBorder': 0
|
||||
});
|
||||
|
||||
// Update ready function names in flash vars for iframe window
|
||||
flashVars.readyFunction = "ready";
|
||||
flashVars.eventProxyFunction = "events";
|
||||
flashVars.errorEventProxyFunction = "errors";
|
||||
flashVars['readyFunction'] = "ready";
|
||||
flashVars['eventProxyFunction'] = "events";
|
||||
flashVars['errorEventProxyFunction'] = "errors";
|
||||
|
||||
// Tried multiple methods to get this to work in all browsers
|
||||
|
||||
// Tried embedding the flash object in the page first, and then adding a place holder to the iframe, then replacing the placeholder with the page object.
|
||||
// The goal here was to try to load the swf URL in the parent page first and hope that got around the firefox security error
|
||||
// var newObj = _V_.Flash.embed(options.swf, placeHolder, flashVars, params, attributes);
|
||||
// var newObj = vjs.Flash.embed(options.swf, placeHolder, flashVars, params, attributes);
|
||||
// (in onload)
|
||||
// var temp = _V_.createElement("a", { id:"asdf", innerHTML: "asdf" } );
|
||||
// var temp = vjs.createEl("a", { id:"asdf", innerHTML: "asdf" } );
|
||||
// iDoc.body.appendChild(temp);
|
||||
|
||||
// Tried embedding the flash object through javascript in the iframe source.
|
||||
// This works in webkit but still triggers the firefox security error
|
||||
// iFrm.src = "javascript: document.write('"+_V_.Flash.getEmbedCode(options.swf, flashVars, params, attributes)+"');";
|
||||
// iFrm.src = "javascript: document.write('"+vjs.Flash.getEmbedCode(options.swf, flashVars, params, attributes)+"');";
|
||||
|
||||
// Tried an actual local iframe just to make sure that works, but it kills the easiness of the CDN version if you require the user to host an iframe
|
||||
// We should add an option to host the iframe locally though, because it could help a lot of issues.
|
||||
// iFrm.src = "iframe.html";
|
||||
|
||||
// Wait until iFrame has loaded to write into it.
|
||||
_V_.addEvent(iFrm, "load", _V_.proxy(this, function(){
|
||||
vjs.on(iFrm, "load", vjs.bind(this, function(){
|
||||
|
||||
var iDoc, objTag, swfLoc,
|
||||
iWin = iFrm.contentWindow,
|
||||
@ -145,7 +148,7 @@ _V_.Flash = function(player, options, ready){
|
||||
// I did find a hack where if I call the iframe's window.location.href="", it would get around the security error
|
||||
// However, the main page would look like it was loading indefinitely (URL bar loading spinner would never stop)
|
||||
// Plus Firefox 3.6 didn't work no matter what I tried.
|
||||
// if (_V_.ua.match("Firefox")) {
|
||||
// if (vjs.USER_AGENT.match("Firefox")) {
|
||||
// iWin.location.href = "";
|
||||
// }
|
||||
|
||||
@ -166,14 +169,14 @@ _V_.Flash = function(player, options, ready){
|
||||
// Using document.write actually got around the security error that browsers were throwing.
|
||||
// Again, it's a dynamically generated (same domain) iframe, loading an external Flash swf.
|
||||
// Not sure why that's a security issue, but apparently it is.
|
||||
iDoc.write(_V_.Flash.getEmbedCode(options.swf, flashVars, params, attributes));
|
||||
iDoc.write(vjs.Flash.getEmbedCode(options['swf'], flashVars, params, attributes));
|
||||
|
||||
// Setting variables on the window needs to come after the doc write because otherwise they can get reset in some browsers
|
||||
// So far no issues with swf ready event being called before it's set on the window.
|
||||
iWin.player = this.player;
|
||||
|
||||
// Create swf ready function for iFrame window
|
||||
iWin.ready = _V_.proxy(this.player, function(currSwf){
|
||||
iWin.ready = vjs.bind(this.player, function(currSwf){
|
||||
var el = iDoc.getElementById(currSwf),
|
||||
player = this,
|
||||
tech = player.tech;
|
||||
@ -182,23 +185,23 @@ _V_.Flash = function(player, options, ready){
|
||||
tech.el = el;
|
||||
|
||||
// Now that the element is ready, make a click on the swf play the video
|
||||
_V_.addEvent(el, "click", tech.proxy(tech.onClick));
|
||||
vjs.on(el, "click", tech.bind(tech.onClick));
|
||||
|
||||
// Make sure swf is actually ready. Sometimes the API isn't actually yet.
|
||||
_V_.Flash.checkReady(tech);
|
||||
vjs.Flash.checkReady(tech);
|
||||
});
|
||||
|
||||
// Create event listener for all swf events
|
||||
iWin.events = _V_.proxy(this.player, function(swfID, eventName, other){
|
||||
iWin.events = vjs.bind(this.player, function(swfID, eventName, other){
|
||||
var player = this;
|
||||
if (player && player.techName == "flash") {
|
||||
player.triggerEvent(eventName);
|
||||
player.trigger(eventName);
|
||||
}
|
||||
});
|
||||
|
||||
// Create error listener for all swf errors
|
||||
iWin.errors = _V_.proxy(this.player, function(swfID, eventName){
|
||||
_V_.log("Flash Error", eventName);
|
||||
iWin.errors = vjs.bind(this.player, function(swfID, eventName){
|
||||
vjs.log("Flash Error", eventName);
|
||||
});
|
||||
|
||||
}));
|
||||
@ -208,98 +211,105 @@ _V_.Flash = function(player, options, ready){
|
||||
|
||||
// If not using iFrame mode, embed as normal object
|
||||
} else {
|
||||
_V_.Flash.embed(options.swf, placeHolder, flashVars, params, attributes);
|
||||
vjs.Flash.embed(options['swf'], placeHolder, flashVars, params, attributes);
|
||||
}
|
||||
|
||||
};
|
||||
goog.inherits(_V_.Flash, _V_.MediaTechController);
|
||||
goog.inherits(vjs.Flash, vjs.MediaTechController);
|
||||
|
||||
_V_.Flash = _V_.PlaybackTech.extend({
|
||||
vjs.Flash.prototype.dispose = function(){
|
||||
goog.base(this, 'dispose');
|
||||
};
|
||||
|
||||
init: function(player, options){
|
||||
|
||||
},
|
||||
vjs.Flash.prototype.play = function(){
|
||||
this.el_.vjs_play();
|
||||
}
|
||||
|
||||
destroy: function(){
|
||||
this.el.parentNode.removeChild(this.el);
|
||||
},
|
||||
vjs.Flash.prototype.pause = function(){
|
||||
this.el_.vjs_pause();
|
||||
}
|
||||
|
||||
// setupTriggers: function(){}, // Using global onEvent func to distribute events
|
||||
vjs.Flash.prototype.src = function(src){
|
||||
// Make sure source URL is abosolute.
|
||||
src = vjs.getAbsoluteURL(src);
|
||||
|
||||
play: function(){ this.el.vjs_play(); },
|
||||
pause: function(){ this.el.vjs_pause(); },
|
||||
src: function(src){
|
||||
// Make sure source URL is abosolute.
|
||||
src = _V_.getAbsoluteURL(src);
|
||||
this.el_.vjs_src(src);
|
||||
|
||||
this.el.vjs_src(src);
|
||||
|
||||
// Currently the SWF doesn't autoplay if you load a source later.
|
||||
// e.g. Load player w/ no source, wait 2s, set src.
|
||||
if (this.player.autoplay()) {
|
||||
var tech = this;
|
||||
setTimeout(function(){ tech.play(); }, 0);
|
||||
}
|
||||
},
|
||||
load: function(){ this.el.vjs_load(); },
|
||||
poster: function(){ this.el.vjs_getProperty("poster"); },
|
||||
|
||||
buffered: function(){
|
||||
return _V_.createTimeRange(0, this.el.vjs_getProperty("buffered"));
|
||||
},
|
||||
|
||||
supportsFullScreen: function(){
|
||||
return false; // Flash does not allow fullscreen through javascript
|
||||
},
|
||||
enterFullScreen: function(){
|
||||
return false;
|
||||
// Currently the SWF doesn't autoplay if you load a source later.
|
||||
// e.g. Load player w/ no source, wait 2s, set src.
|
||||
if (this.player.autoplay()) {
|
||||
var tech = this;
|
||||
setTimeout(function(){ tech.play(); }, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
vjs.Flash.prototype.load = function(){
|
||||
this.el_.vjs_load();
|
||||
}
|
||||
|
||||
vjs.Flash.prototype.poster = function(){
|
||||
this.el_.vjs_getProperty("poster");
|
||||
}
|
||||
|
||||
vjs.Flash.prototype.buffered = function(){
|
||||
return vjs.createTimeRange(0, this.el_.vjs_getProperty("buffered"));
|
||||
}
|
||||
|
||||
vjs.Flash.prototype.supportsFullScreen = function(){
|
||||
return false; // Flash does not allow fullscreen through javascript
|
||||
}
|
||||
|
||||
vjs.Flash.prototype.enterFullScreen = function(){
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Create setters and getters for attributes
|
||||
(function(){
|
||||
var api = vjs.Flash.prototype,
|
||||
readWrite = "preload,currentTime,defaultPlaybackRate,playbackRate,autoplay,loop,mediaGroup,controller,controls,volume,muted,defaultMuted".split(","),
|
||||
readOnly = "error,currentSrc,networkState,readyState,seeking,initialTime,duration,startOffsetTime,paused,played,seekable,ended,videoTracks,audioTracks,videoWidth,videoHeight,textTracks".split(","),
|
||||
callOnly = "load,play,pause".split(",");
|
||||
// Overridden: buffered
|
||||
|
||||
var api = _V_.Flash.prototype,
|
||||
readWrite = "preload,currentTime,defaultPlaybackRate,playbackRate,autoplay,loop,mediaGroup,controller,controls,volume,muted,defaultMuted".split(","),
|
||||
readOnly = "error,currentSrc,networkState,readyState,seeking,initialTime,duration,startOffsetTime,paused,played,seekable,ended,videoTracks,audioTracks,videoWidth,videoHeight,textTracks".split(","),
|
||||
callOnly = "load,play,pause".split(",");
|
||||
// Overridden: buffered
|
||||
/**
|
||||
* @this {*}
|
||||
*/
|
||||
createSetter = function(attr){
|
||||
var attrUpper = attr.charAt(0).toUpperCase() + attr.slice(1);
|
||||
api["set"+attrUpper] = function(val){ return this.el_.vjs_setProperty(attr, val); };
|
||||
},
|
||||
|
||||
createSetter = function(attr){
|
||||
var attrUpper = attr.charAt(0).toUpperCase() + attr.slice(1);
|
||||
api["set"+attrUpper] = function(val){ return this.el.vjs_setProperty(attr, val); };
|
||||
},
|
||||
/**
|
||||
* @this {*}
|
||||
*/
|
||||
createGetter = function(attr){
|
||||
api[attr] = function(){ return this.el_.vjs_getProperty(attr); };
|
||||
}
|
||||
;
|
||||
|
||||
createGetter = function(attr){
|
||||
api[attr] = function(){ return this.el.vjs_getProperty(attr); };
|
||||
}
|
||||
;
|
||||
// Create getter and setters for all read/write attributes
|
||||
for (var i = 0; i < readWrite.length; i++) {
|
||||
createGetter(readWrite[i]);
|
||||
createSetter(readWrite[i]);
|
||||
};
|
||||
|
||||
// Create getter and setters for all read/write attributes
|
||||
_V_.each(readWrite, function(attr){
|
||||
createGetter(attr);
|
||||
createSetter(attr);
|
||||
});
|
||||
|
||||
// Create getters for read-only attributes
|
||||
_V_.each(readOnly, function(attr){
|
||||
createGetter(attr);
|
||||
});
|
||||
|
||||
})();
|
||||
// Create getters for read-only attributes
|
||||
for (var i = 0; i < readOnly.length; i++) {
|
||||
createGetter(readOnly[i]);
|
||||
};
|
||||
|
||||
/* Flash Support Testing -------------------------------------------------------- */
|
||||
|
||||
_V_.Flash.isSupported = function(){
|
||||
return _V_.Flash.version()[0] >= 10;
|
||||
vjs.Flash.isSupported = function(){
|
||||
return vjs.Flash.version()[0] >= 10;
|
||||
// return swfobject.hasFlashPlayerVersion("10");
|
||||
};
|
||||
|
||||
_V_.Flash.canPlaySource = function(srcObj){
|
||||
if (srcObj.type in _V_.Flash.prototype.support.formats) { return "maybe"; }
|
||||
vjs.Flash.canPlaySource = function(srcObj){
|
||||
if (srcObj.type in vjs.Flash.prototype.features.formats) { return "maybe"; }
|
||||
};
|
||||
|
||||
_V_.Flash.prototype.support = {
|
||||
vjs.Flash.prototype.features = {
|
||||
formats: {
|
||||
"video/flv": "FLV",
|
||||
"video/x-flv": "FLV",
|
||||
@ -308,19 +318,19 @@ _V_.Flash.prototype.support = {
|
||||
},
|
||||
|
||||
// Optional events that we can manually mimic with timers
|
||||
progressEvent: false,
|
||||
timeupdateEvent: false,
|
||||
// currently not triggered by video-js-swf
|
||||
progressEvents: false,
|
||||
timeupdateEvents: false,
|
||||
|
||||
// Resizing plugins using request fullscreen reloads the plugin
|
||||
fullscreenResize: false,
|
||||
|
||||
// Resizing plugins in Firefox always reloads the plugin (e.g. full window mode)
|
||||
parentResize: !(_V_.ua.match("Firefox"))
|
||||
parentResize: !(vjs.USER_AGENT.match("Firefox"))
|
||||
};
|
||||
|
||||
_V_.Flash.onReady = function(currSwf){
|
||||
|
||||
var el = _V_.el(currSwf);
|
||||
vjs.Flash['onReady'] = function(currSwf){
|
||||
var el = vjs.el(currSwf);
|
||||
|
||||
// Get player from box
|
||||
// On firefox reloads, el might already have a player
|
||||
@ -331,20 +341,20 @@ _V_.Flash.onReady = function(currSwf){
|
||||
el.player = player;
|
||||
|
||||
// Update reference to playback technology element
|
||||
tech.el = el;
|
||||
tech.el_ = el;
|
||||
|
||||
// Now that the element is ready, make a click on the swf play the video
|
||||
tech.addEvent("click", tech.onClick);
|
||||
tech.on("click", tech.onClick);
|
||||
|
||||
_V_.Flash.checkReady(tech);
|
||||
vjs.Flash.checkReady(tech);
|
||||
};
|
||||
|
||||
// The SWF isn't alwasy ready when it says it is. Sometimes the API functions still need to be added to the object.
|
||||
// If it's not ready, we set a timeout to check again shortly.
|
||||
_V_.Flash.checkReady = function(tech){
|
||||
vjs.Flash.checkReady = function(tech){
|
||||
|
||||
// Check if API property exists
|
||||
if (tech.el.vjs_getProperty) {
|
||||
if (tech.getEl().vjs_getProperty) {
|
||||
|
||||
// If so, tell tech it's ready
|
||||
tech.triggerReady();
|
||||
@ -353,27 +363,27 @@ _V_.Flash.checkReady = function(tech){
|
||||
} else {
|
||||
|
||||
setTimeout(function(){
|
||||
_V_.Flash.checkReady(tech);
|
||||
vjs.Flash.checkReady(tech);
|
||||
}, 50);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
// Trigger events from the swf on the player
|
||||
_V_.Flash.onEvent = function(swfID, eventName){
|
||||
var player = _V_.el(swfID).player;
|
||||
player.triggerEvent(eventName);
|
||||
vjs.Flash['onEvent'] = function(swfID, eventName){
|
||||
var player = vjs.el(swfID).player;
|
||||
player.trigger(eventName);
|
||||
};
|
||||
|
||||
// Log errors from the swf
|
||||
_V_.Flash.onError = function(swfID, err){
|
||||
var player = _V_.el(swfID).player;
|
||||
player.triggerEvent("error");
|
||||
_V_.log("Flash Error", err, swfID);
|
||||
vjs.Flash['onError'] = function(swfID, err){
|
||||
var player = vjs.el(swfID).player;
|
||||
player.trigger("error");
|
||||
vjs.log("Flash Error", err, swfID);
|
||||
};
|
||||
|
||||
// Flash Version Check
|
||||
_V_.Flash.version = function(){
|
||||
vjs.Flash.version = function(){
|
||||
var version = '0,0,0';
|
||||
|
||||
// IE
|
||||
@ -392,11 +402,11 @@ _V_.Flash.version = function(){
|
||||
};
|
||||
|
||||
// Flash embedding method. Only used in non-iframe mode
|
||||
_V_.Flash.embed = function(swf, placeHolder, flashVars, params, attributes){
|
||||
var code = _V_.Flash.getEmbedCode(swf, flashVars, params, attributes),
|
||||
vjs.Flash.embed = function(swf, placeHolder, flashVars, params, attributes){
|
||||
var code = vjs.Flash.getEmbedCode(swf, flashVars, params, attributes),
|
||||
|
||||
// Get element by embedding code and retrieving created element
|
||||
obj = _V_.createElement("div", { innerHTML: code }).childNodes[0],
|
||||
obj = vjs.createEl("div", { innerHTML: code }).childNodes[0],
|
||||
|
||||
par = placeHolder.parentNode
|
||||
;
|
||||
@ -405,7 +415,7 @@ _V_.Flash.embed = function(swf, placeHolder, flashVars, params, attributes){
|
||||
|
||||
// IE6 seems to have an issue where it won't initialize the swf object after injecting it.
|
||||
// This is a dumb temporary fix
|
||||
if (_V_.isIE()) {
|
||||
if (vjs.IS_IE6to8()) {
|
||||
var newObj = par.childNodes[0];
|
||||
setTimeout(function(){
|
||||
newObj.style.display = "block";
|
||||
@ -416,7 +426,7 @@ _V_.Flash.embed = function(swf, placeHolder, flashVars, params, attributes){
|
||||
|
||||
};
|
||||
|
||||
_V_.Flash.getEmbedCode = function(swf, flashVars, params, attributes){
|
||||
vjs.Flash.getEmbedCode = function(swf, flashVars, params, attributes){
|
||||
|
||||
var objTag = '<object type="application/x-shockwave-flash"',
|
||||
flashVarsString = '',
|
||||
@ -425,36 +435,36 @@ _V_.Flash.getEmbedCode = function(swf, flashVars, params, attributes){
|
||||
|
||||
// Convert flash vars to string
|
||||
if (flashVars) {
|
||||
_V_.eachProp(flashVars, function(key, val){
|
||||
vjs.eachProp(flashVars, function(key, val){
|
||||
flashVarsString += (key + "=" + val + "&");
|
||||
});
|
||||
}
|
||||
|
||||
// Add swf, flashVars, and other default params
|
||||
params = _V_.merge({
|
||||
movie: swf,
|
||||
flashvars: flashVarsString,
|
||||
allowScriptAccess: "always", // Required to talk to swf
|
||||
allowNetworking: "all" // All should be default, but having security issues.
|
||||
params = vjs.merge({
|
||||
'movie': swf,
|
||||
'flashvars': flashVarsString,
|
||||
'allowScriptAccess': "always", // Required to talk to swf
|
||||
'allowNetworking': "all" // All should be default, but having security issues.
|
||||
}, params);
|
||||
|
||||
// Create param tags string
|
||||
_V_.eachProp(params, function(key, val){
|
||||
vjs.eachProp(params, function(key, val){
|
||||
paramsString += '<param name="'+key+'" value="'+val+'" />';
|
||||
});
|
||||
|
||||
attributes = _V_.merge({
|
||||
attributes = vjs.merge({
|
||||
// Add swf to attributes (need both for IE and Others to work)
|
||||
data: swf,
|
||||
'data': swf,
|
||||
|
||||
// Default to 100% width/height
|
||||
width: "100%",
|
||||
height: "100%"
|
||||
'width': "100%",
|
||||
'height': "100%"
|
||||
|
||||
}, attributes);
|
||||
|
||||
// Create Attributes string
|
||||
_V_.eachProp(attributes, function(key, val){
|
||||
vjs.eachProp(attributes, function(key, val){
|
||||
attrsString += (key + '="' + val + '" ');
|
||||
});
|
||||
|
||||
|
@ -1,22 +1,21 @@
|
||||
goog.provide('_V_.Html5');
|
||||
goog.provide('_V_.media.html5');
|
||||
goog.provide('_V_.Html5.Supports');
|
||||
goog.provide('_V_.Html5.Events');
|
||||
goog.provide('_V_.Html5.isSupported');
|
||||
goog.provide('_V_.Html5.canPlaySource');
|
||||
goog.provide('vjs.Html5');
|
||||
goog.provide('vjs.media.html5');
|
||||
goog.provide('vjs.Html5.Events');
|
||||
goog.provide('vjs.Html5.isSupported');
|
||||
goog.provide('vjs.Html5.canPlaySource');
|
||||
|
||||
goog.require('_V_.MediaTechController');
|
||||
goog.require('vjs.MediaTechController');
|
||||
|
||||
/* HTML5 Media Controller - Wrapper for HTML5 Media API
|
||||
================================================================================ */
|
||||
============================================================================= */
|
||||
/**
|
||||
* HTML5 Media Controller - Wrapper for HTML5 Media API
|
||||
* @param {_V_.Player|Object} player
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @param {Function=} ready
|
||||
* @constructor
|
||||
*/
|
||||
_V_.Html5 = function(player, options, ready){
|
||||
vjs.Html5 = function(player, options, ready){
|
||||
goog.base(this, player, options, ready);
|
||||
|
||||
var source = options.source;
|
||||
@ -48,16 +47,16 @@ _V_.Html5 = function(player, options, ready){
|
||||
|
||||
this.triggerReady();
|
||||
};
|
||||
goog.inherits(_V_.Html5, _V_.MediaTechController);
|
||||
goog.inherits(vjs.Html5, vjs.MediaTechController);
|
||||
|
||||
_V_.Html5.prototype.dispose = function(){
|
||||
vjs.Html5.prototype.dispose = function(){
|
||||
// this.player.tag = false;
|
||||
this.removeTriggers();
|
||||
|
||||
goog.base(this, 'dispose');
|
||||
};
|
||||
|
||||
_V_.Html5.prototype.createEl = function(){
|
||||
vjs.Html5.prototype.createEl = function(){
|
||||
var player = this.player,
|
||||
// If possible, reuse original tag for HTML5 playback technology element
|
||||
el = player.tag,
|
||||
@ -66,20 +65,20 @@ _V_.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 || _V_.Html5.Supports.movingElementInDOM === false) {
|
||||
if (!el || this.features.movingMediaElementInDOM === false) {
|
||||
|
||||
// If the original tag is still there, remove it.
|
||||
if (el) {
|
||||
player.getEl().removeChild(el);
|
||||
}
|
||||
|
||||
newEl = _V_.createElement("video", {
|
||||
newEl = vjs.createElement("video", {
|
||||
id: el.id || player.id + "_html5_api",
|
||||
className: el.className || "vjs-tech"
|
||||
});
|
||||
|
||||
el = newEl;
|
||||
_V_.insertFirst(el, player.el);
|
||||
vjs.insertFirst(el, player.el);
|
||||
}
|
||||
|
||||
// Update specific tag settings, in case they were overridden
|
||||
@ -97,50 +96,50 @@ _V_.Html5.prototype.createEl = function(){
|
||||
|
||||
// Make video events trigger player events
|
||||
// May seem verbose here, but makes other APIs possible.
|
||||
_V_.Html5.prototype.setupTriggers = function(){
|
||||
for (var i = _V_.Html5.Events.length - 1; i >= 0; i--) {
|
||||
_V_.on(this.el_, _V_.Html5.Events[i], _V_.bind(this.player, this.eventHandler));
|
||||
vjs.Html5.prototype.setupTriggers = function(){
|
||||
for (var i = vjs.Html5.Events.length - 1; i >= 0; i--) {
|
||||
vjs.on(this.el_, vjs.Html5.Events[i], vjs.bind(this.player, this.eventHandler));
|
||||
};
|
||||
};
|
||||
_V_.Html5.prototype.removeTriggers = function(){
|
||||
for (var i = _V_.Html5.Events.length - 1; i >= 0; i--) {
|
||||
_V_.off(this.el_, _V_.Html5.Events[i], _V_.bind(this.player, this.eventHandler));
|
||||
vjs.Html5.prototype.removeTriggers = function(){
|
||||
for (var i = vjs.Html5.Events.length - 1; i >= 0; i--) {
|
||||
vjs.off(this.el_, vjs.Html5.Events[i], vjs.bind(this.player, this.eventHandler));
|
||||
};
|
||||
// console.log("removeTriggers", _V_.getData(this.el_));
|
||||
// console.log("removeTriggers", vjs.getData(this.el_));
|
||||
};
|
||||
_V_.Html5.prototype.eventHandler = function(e){
|
||||
vjs.Html5.prototype.eventHandler = function(e){
|
||||
// console.log('eventHandler', e.type, e, this.el_)
|
||||
this.trigger(e);
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
|
||||
_V_.Html5.prototype.play = function(){ this.el_.play(); };
|
||||
_V_.Html5.prototype.pause = function(){ this.el_.pause(); };
|
||||
_V_.Html5.prototype.paused = function(){ return this.el_.paused; };
|
||||
vjs.Html5.prototype.play = function(){ this.el_.play(); };
|
||||
vjs.Html5.prototype.pause = function(){ this.el_.pause(); };
|
||||
vjs.Html5.prototype.paused = function(){ return this.el_.paused; };
|
||||
|
||||
_V_.Html5.prototype.currentTime = function(){ return this.el_.currentTime; };
|
||||
_V_.Html5.prototype.setCurrentTime = function(seconds){
|
||||
vjs.Html5.prototype.currentTime = function(){ return this.el_.currentTime; };
|
||||
vjs.Html5.prototype.setCurrentTime = function(seconds){
|
||||
try {
|
||||
this.el_.currentTime = seconds;
|
||||
} catch(e) {
|
||||
_V_.log(e, "Video isn't ready. (Video.js)");
|
||||
vjs.log(e, "Video isn't ready. (Video.js)");
|
||||
// this.warning(VideoJS.warnings.videoNotReady);
|
||||
}
|
||||
};
|
||||
|
||||
_V_.Html5.prototype.duration = function(){ return this.el_.duration || 0; };
|
||||
_V_.Html5.prototype.buffered = function(){ return this.el_.buffered; };
|
||||
vjs.Html5.prototype.duration = function(){ return this.el_.duration || 0; };
|
||||
vjs.Html5.prototype.buffered = function(){ return this.el_.buffered; };
|
||||
|
||||
_V_.Html5.prototype.volume = function(){ return this.el_.volume; };
|
||||
_V_.Html5.prototype.setVolume = function(percentAsDecimal){ this.el_.volume = percentAsDecimal; };
|
||||
_V_.Html5.prototype.muted = function(){ return this.el_.muted; };
|
||||
_V_.Html5.prototype.setMuted = function(muted){ this.el_.muted = muted; };
|
||||
vjs.Html5.prototype.volume = function(){ return this.el_.volume; };
|
||||
vjs.Html5.prototype.setVolume = function(percentAsDecimal){ this.el_.volume = percentAsDecimal; };
|
||||
vjs.Html5.prototype.muted = function(){ return this.el_.muted; };
|
||||
vjs.Html5.prototype.setMuted = function(muted){ this.el_.muted = muted; };
|
||||
|
||||
_V_.Html5.prototype.width = function(){ return this.el_.offsetWidth; };
|
||||
_V_.Html5.prototype.height = function(){ return this.el_.offsetHeight; };
|
||||
vjs.Html5.prototype.width = function(){ return this.el_.offsetWidth; };
|
||||
vjs.Html5.prototype.height = function(){ return this.el_.offsetHeight; };
|
||||
|
||||
_V_.Html5.prototype.supportsFullScreen = function(){
|
||||
vjs.Html5.prototype.supportsFullScreen = function(){
|
||||
if (typeof this.el_.webkitEnterFullScreen == 'function') {
|
||||
|
||||
// Seems to be broken in Chromium/Chrome && Safari in Leopard
|
||||
@ -151,46 +150,46 @@ _V_.Html5.prototype.supportsFullScreen = function(){
|
||||
return false;
|
||||
};
|
||||
|
||||
_V_.Html5.prototype.enterFullScreen = function(){
|
||||
vjs.Html5.prototype.enterFullScreen = function(){
|
||||
try {
|
||||
this.el_.webkitEnterFullScreen();
|
||||
} catch (e) {
|
||||
if (e.code == 11) {
|
||||
// this.warning(VideoJS.warnings.videoNotReady);
|
||||
_V_.log("Video.js: Video not ready.");
|
||||
vjs.log("Video.js: Video not ready.");
|
||||
}
|
||||
}
|
||||
};
|
||||
_V_.Html5.prototype.exitFullScreen = function(){
|
||||
vjs.Html5.prototype.exitFullScreen = function(){
|
||||
try {
|
||||
this.el_.webkitExitFullScreen();
|
||||
} catch (e) {
|
||||
if (e.code == 11) {
|
||||
// this.warning(VideoJS.warnings.videoNotReady);
|
||||
_V_.log("Video.js: Video not ready.");
|
||||
vjs.log("Video.js: Video not ready.");
|
||||
}
|
||||
}
|
||||
};
|
||||
_V_.Html5.prototype.src = function(src){ this.el_.src = src; };
|
||||
_V_.Html5.prototype.load = function(){ this.el_.load(); };
|
||||
_V_.Html5.prototype.currentSrc = function(){ return this.el_.currentSrc; };
|
||||
vjs.Html5.prototype.src = function(src){ this.el_.src = src; };
|
||||
vjs.Html5.prototype.load = function(){ this.el_.load(); };
|
||||
vjs.Html5.prototype.currentSrc = function(){ return this.el_.currentSrc; };
|
||||
|
||||
_V_.Html5.prototype.preload = function(){ return this.el_.preload; };
|
||||
_V_.Html5.prototype.setPreload = function(val){ this.el_.preload = val; };
|
||||
_V_.Html5.prototype.autoplay = function(){ return this.el_.autoplay; };
|
||||
_V_.Html5.prototype.setAutoplay = function(val){ this.el_.autoplay = val; };
|
||||
_V_.Html5.prototype.loop = function(){ return this.el_.loop; };
|
||||
_V_.Html5.prototype.setLoop = function(val){ this.el_.loop = val; };
|
||||
vjs.Html5.prototype.preload = function(){ return this.el_.preload; };
|
||||
vjs.Html5.prototype.setPreload = function(val){ this.el_.preload = val; };
|
||||
vjs.Html5.prototype.autoplay = function(){ return this.el_.autoplay; };
|
||||
vjs.Html5.prototype.setAutoplay = function(val){ this.el_.autoplay = val; };
|
||||
vjs.Html5.prototype.loop = function(){ return this.el_.loop; };
|
||||
vjs.Html5.prototype.setLoop = function(val){ this.el_.loop = val; };
|
||||
|
||||
_V_.Html5.prototype.error = function(){ return this.el_.error; };
|
||||
vjs.Html5.prototype.error = function(){ return this.el_.error; };
|
||||
// networkState: function(){ return this.el_.networkState; },
|
||||
// readyState: function(){ return this.el_.readyState; },
|
||||
_V_.Html5.prototype.seeking = function(){ return this.el_.seeking; };
|
||||
vjs.Html5.prototype.seeking = function(){ return this.el_.seeking; };
|
||||
// initialTime: function(){ return this.el_.initialTime; },
|
||||
// startOffsetTime: function(){ return this.el_.startOffsetTime; },
|
||||
// played: function(){ return this.el_.played; },
|
||||
// seekable: function(){ return this.el_.seekable; },
|
||||
_V_.Html5.prototype.ended = function(){ return this.el_.ended; };
|
||||
vjs.Html5.prototype.ended = function(){ return this.el_.ended; };
|
||||
// videoTracks: function(){ return this.el_.videoTracks; },
|
||||
// audioTracks: function(){ return this.el_.audioTracks; },
|
||||
// videoWidth: function(){ return this.el_.videoWidth; },
|
||||
@ -200,16 +199,16 @@ _V_.Html5.prototype.ended = function(){ return this.el_.ended; };
|
||||
// playbackRate: function(){ return this.el_.playbackRate; },
|
||||
// mediaGroup: function(){ return this.el_.mediaGroup; },
|
||||
// controller: function(){ return this.el_.controller; },
|
||||
_V_.Html5.prototype.controls = function(){ return this.player.options.controls; };
|
||||
_V_.Html5.prototype.defaultMuted = function(){ return this.el_.defaultMuted; };
|
||||
vjs.Html5.prototype.controls = function(){ return this.player.options.controls; };
|
||||
vjs.Html5.prototype.defaultMuted = function(){ return this.el_.defaultMuted; };
|
||||
|
||||
/* HTML5 Support Testing -------------------------------------------------------- */
|
||||
/* HTML5 Support Testing ---------------------------------------------------- */
|
||||
|
||||
_V_.Html5.isSupported = function(){
|
||||
vjs.Html5.isSupported = function(){
|
||||
return !!document.createElement("video").canPlayType;
|
||||
};
|
||||
|
||||
_V_.Html5.canPlaySource = function(srcObj){
|
||||
vjs.Html5.canPlaySource = function(srcObj){
|
||||
return !!document.createElement("video").canPlayType(srcObj.type);
|
||||
// TODO: Check Type
|
||||
// If no Type, check ext
|
||||
@ -217,28 +216,31 @@ _V_.Html5.canPlaySource = function(srcObj){
|
||||
};
|
||||
|
||||
// List of all HTML5 events (various uses).
|
||||
_V_.Html5.Events = "loadstart,suspend,abort,error,emptied,stalled,loadedmetadata,loadeddata,canplay,canplaythrough,playing,waiting,seeking,seeked,ended,durationchange,timeupdate,progress,play,pause,ratechange,volumechange".split(",");
|
||||
vjs.Html5.Events = "loadstart,suspend,abort,error,emptied,stalled,loadedmetadata,loadeddata,canplay,canplaythrough,playing,waiting,seeking,seeked,ended,durationchange,timeupdate,progress,play,pause,ratechange,volumechange".split(",");
|
||||
|
||||
|
||||
// HTML5 Device Fixes ---------------------------------------------------------- //
|
||||
|
||||
_V_.Html5.Supports = {
|
||||
// HTML5 Feature detection and Device Fixes --------------------------------- //
|
||||
vjs.Html5.prototype.features = {
|
||||
|
||||
// Support for video element specific full screen. (webkitEnterFullScreen, not requestFullscreen which we use on the player div)
|
||||
// http://developer.apple.com/library/safari/#documentation/AudioVideo/Reference/HTMLVideoElementClassReference/HTMLVideoElement/HTMLVideoElement.html
|
||||
// Seems to be broken in Chromium/Chrome && Safari in Leopard
|
||||
'fullscreen': (_V_.TEST_VID.webkitEnterFullScreen) ? (!_V_.UA.match("Chrome") && !_V_.UA.match("Mac OS X 10.5") ? true : false) : false,
|
||||
fullscreen: (vjs.TEST_VID.webkitEnterFullScreen)
|
||||
? ((!vjs.USER_AGENT.match("Chrome") && !vjs.USER_AGENT.match("Mac OS X 10.5")
|
||||
? true
|
||||
: false))
|
||||
: false,
|
||||
|
||||
// In iOS, if you move a video element in the DOM, it breaks video playback.
|
||||
'movingElementInDOM': !_V_.IS_IOS
|
||||
movingMediaElementInDOM: !vjs.IS_IOS
|
||||
|
||||
};
|
||||
|
||||
// Android
|
||||
if (_V_.IS_ANDROID) {
|
||||
if (vjs.IS_ANDROID) {
|
||||
|
||||
// Override Android 2.2 and less canPlayType method which is broken
|
||||
if (_V_.ANDROID_VERSION < 3) {
|
||||
if (vjs.ANDROID_VERSION < 3) {
|
||||
document.createElement("video").constructor.prototype.canPlayType = function(type){
|
||||
return (type && type.toLowerCase().indexOf("video/mp4") != -1) ? "maybe" : "";
|
||||
};
|
||||
|
22
src/media.js
22
src/media.js
@ -1,18 +1,18 @@
|
||||
goog.provide('_V_.media');
|
||||
goog.provide('_V_.MediaTechController');
|
||||
goog.provide('vjs.media');
|
||||
goog.provide('vjs.MediaTechController');
|
||||
|
||||
goog.require('_V_.Component');
|
||||
goog.require('vjs.Component');
|
||||
|
||||
/* Media Technology Controller - Base class for media playback technologies
|
||||
================================================================================ */
|
||||
|
||||
/**
|
||||
* Base class for media (HTML5 Video, Flash) controllers
|
||||
* @param {_V_.Player|Object} player Central player instance
|
||||
* @param {vjs.Player|Object} player Central player instance
|
||||
* @param {Object=} options Options object
|
||||
* @constructor
|
||||
*/
|
||||
_V_.MediaTechController = function(player, options, ready){
|
||||
vjs.MediaTechController = function(player, options, ready){
|
||||
goog.base(this, player, options, ready);
|
||||
|
||||
// Make playback element clickable
|
||||
@ -20,7 +20,7 @@ _V_.MediaTechController = function(player, options, ready){
|
||||
|
||||
// player.triggerEvent("techready");
|
||||
};
|
||||
goog.inherits(_V_.MediaTechController, _V_.Component);
|
||||
goog.inherits(vjs.MediaTechController, vjs.Component);
|
||||
|
||||
// destroy: function(){},
|
||||
// createElement: function(){},
|
||||
@ -28,7 +28,7 @@ goog.inherits(_V_.MediaTechController, _V_.Component);
|
||||
/**
|
||||
* Handle a click on the media element. By default will play the media.
|
||||
*/
|
||||
_V_.MediaTechController.prototype.onClick = function(){
|
||||
vjs.MediaTechController.prototype.onClick = function(){
|
||||
if (this.player.options.controls) {
|
||||
if (this.player.paused()) {
|
||||
this.player.play();
|
||||
@ -42,13 +42,13 @@ _V_.MediaTechController.prototype.onClick = function(){
|
||||
* List of default API methods for any MediaTechController
|
||||
* @type {String}
|
||||
*/
|
||||
_V_.apiMethods = "play,pause,paused,currentTime,setCurrentTime,duration,buffered,volume,setVolume,muted,setMuted,width,height,supportsFullScreen,enterFullScreen,src,load,currentSrc,preload,setPreload,autoplay,setAutoplay,loop,setLoop,error,networkState,readyState,seeking,initialTime,startOffsetTime,played,seekable,ended,videoTracks,audioTracks,videoWidth,videoHeight,textTracks,defaultPlaybackRate,playbackRate,mediaGroup,controller,controls,defaultMuted".split(",");
|
||||
vjs.media.ApiMethods = "play,pause,paused,currentTime,setCurrentTime,duration,buffered,volume,setVolume,muted,setMuted,width,height,supportsFullScreen,enterFullScreen,src,load,currentSrc,preload,setPreload,autoplay,setAutoplay,loop,setLoop,error,networkState,readyState,seeking,initialTime,startOffsetTime,played,seekable,ended,videoTracks,audioTracks,videoWidth,videoHeight,textTracks,defaultPlaybackRate,playbackRate,mediaGroup,controller,controls,defaultMuted".split(",");
|
||||
|
||||
// Create placeholder methods for each that warn when a method isn't supported by the current playback technology
|
||||
for (var i = _V_.apiMethods.length - 1; i >= 0; i--) {
|
||||
var methodName = _V_.apiMethods[i];
|
||||
for (var i = vjs.media.ApiMethods.length - 1; i >= 0; i--) {
|
||||
var methodName = vjs.media.ApiMethods[i];
|
||||
|
||||
_V_.MediaTechController.prototype[_V_.apiMethods[i]] = (function(methodName){
|
||||
vjs.MediaTechController.prototype[vjs.media.ApiMethods[i]] = (function(methodName){
|
||||
return function(){
|
||||
throw new Error("The '"+methodName+"' method is not available on the playback technology's API");
|
||||
}
|
||||
|
265
src/player.js
265
src/player.js
@ -1,15 +1,15 @@
|
||||
goog.provide('_V_.Player');
|
||||
goog.provide('vjs.Player');
|
||||
|
||||
goog.require('_V_.Component');
|
||||
goog.require('vjs.Component');
|
||||
|
||||
/**
|
||||
* Main player class. Returned by _V_(id);
|
||||
* Main player class. Returned by vjs(id);
|
||||
* @param {Element} tag The original video tag used for configuring options
|
||||
* @param {Object=} options Player options
|
||||
* @param {Function=} ready Ready callback function
|
||||
* @constructor
|
||||
*/
|
||||
_V_.Player = function(tag, options, ready){
|
||||
vjs.Player = function(tag, options, ready){
|
||||
this.tag = tag; // Store the original tag used to set options
|
||||
|
||||
// Set Options
|
||||
@ -18,17 +18,25 @@ _V_.Player = function(tag, options, ready){
|
||||
// This latter part coincides with the load order
|
||||
// (tag must exist before Player)
|
||||
var opts = {};
|
||||
_V_.merge(opts, _V_.options); // Copy Global Defaults
|
||||
_V_.merge(opts, this.getTagSettings(tag)); // Override with Video Tag Options
|
||||
_V_.merge(opts, options); // Override/extend with options from setup call
|
||||
vjs.merge(opts, vjs.options); // Copy Global Defaults
|
||||
vjs.merge(opts, this.getTagSettings(tag)); // Override with Video Tag Options
|
||||
vjs.merge(opts, options); // Override/extend with options from setup call
|
||||
|
||||
// Cache for video property values.
|
||||
this.cache_ = {};
|
||||
|
||||
// Tracks defined in tracks.js
|
||||
this.textTracks = [];
|
||||
// this.ready(function() {
|
||||
// if (opts.tracks && opts.tracks.length > 0) {
|
||||
// this.addTextTracks(opts.tracks);
|
||||
// }
|
||||
// });
|
||||
|
||||
// Run base component initializing with new options.
|
||||
// Builds the element through createEl()
|
||||
// Inits and embeds any child components in opts
|
||||
_V_.Component.call(this, this, opts, ready);
|
||||
vjs.Component.call(this, this, opts, ready);
|
||||
|
||||
this.on("ended", this.onEnded);
|
||||
this.on("play", this.onPlay);
|
||||
@ -37,22 +45,16 @@ _V_.Player = function(tag, options, ready){
|
||||
this.on("durationchange", this.onDurationChange);
|
||||
this.on("error", this.onError);
|
||||
|
||||
// Tracks defined in tracks.js
|
||||
// this.textTracks = [];
|
||||
// if (opts.tracks && opts.tracks.length > 0) {
|
||||
// this.addTextTracks(opts.tracks);
|
||||
// }
|
||||
|
||||
// Make player easily findable by ID
|
||||
_V_.players[this.id] = this;
|
||||
vjs.players[this.id] = this;
|
||||
};
|
||||
goog.inherits(_V_.Player, _V_.Component);
|
||||
goog.inherits(vjs.Player, vjs.Component);
|
||||
|
||||
_V_.Player.prototype.dispose = function(){
|
||||
vjs.Player.prototype.dispose = function(){
|
||||
// this.isReady_ = false;
|
||||
|
||||
// Kill reference to this player
|
||||
_V_.players[this.id] = null;
|
||||
vjs.players[this.id] = null;
|
||||
if (this.tag && this.tag.player) { this.tag.player = null; }
|
||||
if (this.el_ && this.el_.player) { this.el_.player = null; }
|
||||
|
||||
@ -66,13 +68,13 @@ _V_.Player.prototype.dispose = function(){
|
||||
goog.base(this, 'dispose');
|
||||
};
|
||||
|
||||
_V_.Player.prototype.getTagSettings = function(tag){
|
||||
vjs.Player.prototype.getTagSettings = function(tag){
|
||||
var options = {
|
||||
sources: [],
|
||||
tracks: []
|
||||
};
|
||||
|
||||
_V_.merge(options, _V_.getAttributeValues(tag));
|
||||
vjs.merge(options, vjs.getAttributeValues(tag));
|
||||
|
||||
// Get tag children settings
|
||||
if (tag.hasChildNodes()) {
|
||||
@ -87,10 +89,10 @@ _V_.Player.prototype.getTagSettings = function(tag){
|
||||
childName = child.nodeName.toLowerCase();
|
||||
|
||||
if (childName === "source") {
|
||||
options.sources.push(_V_.getAttributeValues(child));
|
||||
options.sources.push(vjs.getAttributeValues(child));
|
||||
|
||||
} else if (childName === "track") {
|
||||
options.tracks.push(_V_.getAttributeValues(child));
|
||||
options.tracks.push(vjs.getAttributeValues(child));
|
||||
|
||||
}
|
||||
}
|
||||
@ -98,7 +100,7 @@ _V_.Player.prototype.getTagSettings = function(tag){
|
||||
return options;
|
||||
};
|
||||
|
||||
_V_.Player.prototype.createEl = function(){
|
||||
vjs.Player.prototype.createEl = function(){
|
||||
var el = this.el_ = goog.base(this, 'createEl', 'div');
|
||||
var tag = this.tag;
|
||||
|
||||
@ -124,7 +126,7 @@ _V_.Player.prototype.createEl = function(){
|
||||
}
|
||||
|
||||
// Make sure tag ID exists
|
||||
tag.id = tag.id || "vjs_video_" + _V_.guid++;
|
||||
tag.id = tag.id || "vjs_video_" + vjs.guid++;
|
||||
|
||||
// Give video tag ID and class to player div
|
||||
// ID will now reference player box, not the video tag
|
||||
@ -152,7 +154,7 @@ _V_.Player.prototype.createEl = function(){
|
||||
if (tag.parentNode) {
|
||||
tag.parentNode.insertBefore(el, tag);
|
||||
}
|
||||
_V_.insertFirst(tag, el); // Breaks iPhone, fixed in HTML5 setup.
|
||||
vjs.insertFirst(tag, el); // Breaks iPhone, fixed in HTML5 setup.
|
||||
|
||||
return el;
|
||||
}
|
||||
@ -161,7 +163,7 @@ _V_.Player.prototype.createEl = function(){
|
||||
// ================================================================================ */
|
||||
// Load/Create an instance of playback technlogy including element and API methods
|
||||
// And append playback element in player div.
|
||||
_V_.Player.prototype.loadTech = function(techName, source){
|
||||
vjs.Player.prototype.loadTech = function(techName, source){
|
||||
|
||||
// Pause and remove current playback technology
|
||||
if (this.tech) {
|
||||
@ -183,18 +185,18 @@ _V_.Player.prototype.loadTech = function(techName, source){
|
||||
this.player.triggerReady();
|
||||
|
||||
// Manually track progress in cases where the browser/flash player doesn't report it.
|
||||
if (!window['_V_'][techName]['Supports']['progressEvent']) {
|
||||
if (!this.features.progressEvents) {
|
||||
this.player.manualProgressOn();
|
||||
}
|
||||
|
||||
// Manually track timeudpates in cases where the browser/flash player doesn't report it.
|
||||
if (!window['_V_'][techName]['Supports']['timeupdateEvent']) {
|
||||
if (!this.features.timeupdateEvents) {
|
||||
this.player.manualTimeUpdatesOn();
|
||||
}
|
||||
}
|
||||
|
||||
// Grab tech-specific options from player options and add source and parent element to use.
|
||||
var techOptions = _V_.merge({ source: source, parentEl: this.el_ }, this.options[techName])
|
||||
var techOptions = vjs.merge({ source: source, parentEl: this.el_ }, this.options[techName.toLowerCase()])
|
||||
|
||||
if (source) {
|
||||
if (source.src == this.cache_.src && this.cache_.currentTime > 0) {
|
||||
@ -205,11 +207,12 @@ _V_.Player.prototype.loadTech = function(techName, source){
|
||||
}
|
||||
|
||||
// Initialize tech instance
|
||||
this.tech = new window['_V_'][techName](this, techOptions);
|
||||
this.tech = new window['videojs'][techName](this, techOptions);
|
||||
|
||||
this.tech.ready(techReady);
|
||||
};
|
||||
|
||||
// _V_.Player.prototype.unloadTech = function(){
|
||||
// vjs.Player.prototype.unloadTech = function(){
|
||||
// this.tech.destroy();
|
||||
|
||||
// // Turn off any manual progress or timeupdate tracking
|
||||
@ -225,20 +228,20 @@ _V_.Player.prototype.loadTech = function(techName, source){
|
||||
// Then with the new fullscreen API, Mozilla and webkit browsers will reload the flash object after going to fullscreen.
|
||||
// To get around this, we're unloading the tech, caching source and currentTime values, and reloading the tech once the plugin is resized.
|
||||
// reloadTech: function(betweenFn){
|
||||
// _V_.log("unloadingTech")
|
||||
// vjs.log("unloadingTech")
|
||||
// this.unloadTech();
|
||||
// _V_.log("unloadedTech")
|
||||
// vjs.log("unloadedTech")
|
||||
// if (betweenFn) { betweenFn.call(); }
|
||||
// _V_.log("LoadingTech")
|
||||
// vjs.log("LoadingTech")
|
||||
// this.loadTech(this.techName, { src: this.cache_.src })
|
||||
// _V_.log("loadedTech")
|
||||
// vjs.log("loadedTech")
|
||||
// },
|
||||
|
||||
/* Fallbacks for unsupported event types
|
||||
================================================================================ */
|
||||
// Manually trigger progress events based on changes to the buffered amount
|
||||
// Many flash players and older HTML5 browsers don't send progress or progress-like events
|
||||
_V_.Player.prototype.manualProgressOn = function(){
|
||||
vjs.Player.prototype.manualProgressOn = function(){
|
||||
this.manualProgress = true;
|
||||
|
||||
// Trigger progress watching when a source begins loading
|
||||
@ -253,21 +256,21 @@ _V_.Player.prototype.manualProgressOn = function(){
|
||||
this.tech.one("progress", function(){
|
||||
|
||||
// Update known progress support for this playback technology
|
||||
window['_V_'][techName]['Supports']['progressEvent'] = true;
|
||||
this.features.progressEvents = true;
|
||||
|
||||
// Turn off manual progress tracking
|
||||
this.player.manualProgressOff();
|
||||
});
|
||||
};
|
||||
|
||||
_V_.Player.prototype.manualProgressOff = function(){
|
||||
vjs.Player.prototype.manualProgressOff = function(){
|
||||
this.manualProgress = false;
|
||||
this.stopTrackingProgress();
|
||||
};
|
||||
|
||||
_V_.Player.prototype.trackProgress = function(){
|
||||
vjs.Player.prototype.trackProgress = function(){
|
||||
|
||||
this.progressInterval = setInterval(_V_.bind(this, function(){
|
||||
this.progressInterval = setInterval(vjs.bind(this, function(){
|
||||
// Don't trigger unless buffered amount is greater than last time
|
||||
// log(this.cache_.bufferEnd, this.buffered().end(0), this.duration())
|
||||
/* TODO: update for multiple buffered regions */
|
||||
@ -279,69 +282,62 @@ _V_.Player.prototype.trackProgress = function(){
|
||||
}
|
||||
}), 500);
|
||||
};
|
||||
_V_.Player.prototype.stopTrackingProgress = function(){ clearInterval(this.progressInterval); };
|
||||
vjs.Player.prototype.stopTrackingProgress = function(){ clearInterval(this.progressInterval); };
|
||||
|
||||
/* Time Tracking -------------------------------------------------------------- */
|
||||
_V_.Player.prototype.manualTimeUpdatesOn = function(){
|
||||
vjs.Player.prototype.manualTimeUpdatesOn = function(){
|
||||
this.manualTimeUpdates = true;
|
||||
|
||||
this.on("play", this.trackCurrentTime);
|
||||
this.on("pause", this.stopTrackingCurrentTime);
|
||||
// timeupdate is also called by .currentTime whenever current time is set
|
||||
|
||||
var techName = this.techName;
|
||||
|
||||
// Watch for native timeupdate event
|
||||
this.tech.on("timeupdate", function(){
|
||||
|
||||
// Remove this listener from the element
|
||||
this.off("timeupdate", arguments.callee);
|
||||
|
||||
this.tech.one("timeupdate", function(){
|
||||
// Update known progress support for this playback technology
|
||||
window['_V_'][techName]['Supports']['timeupdateEvent'] = true;
|
||||
|
||||
this.features.timeupdateEvents = true;
|
||||
// Turn off manual progress tracking
|
||||
this.player.manualTimeUpdatesOff();
|
||||
});
|
||||
};
|
||||
|
||||
_V_.Player.prototype.manualTimeUpdatesOff = function(){
|
||||
vjs.Player.prototype.manualTimeUpdatesOff = function(){
|
||||
this.manualTimeUpdates = false;
|
||||
this.stopTrackingCurrentTime();
|
||||
this.off("play", this.trackCurrentTime);
|
||||
this.off("pause", this.stopTrackingCurrentTime);
|
||||
};
|
||||
|
||||
_V_.Player.prototype.trackCurrentTime = function(){
|
||||
vjs.Player.prototype.trackCurrentTime = function(){
|
||||
if (this.currentTimeInterval) { this.stopTrackingCurrentTime(); }
|
||||
this.currentTimeInterval = setInterval(_V_.bind(this, function(){
|
||||
this.currentTimeInterval = setInterval(vjs.bind(this, function(){
|
||||
this.trigger("timeupdate");
|
||||
}), 250); // 42 = 24 fps // 250 is what Webkit uses // FF uses 15
|
||||
};
|
||||
|
||||
// Turn off play progress tracking (when paused or dragging)
|
||||
_V_.Player.prototype.stopTrackingCurrentTime = function(){ clearInterval(this.currentTimeInterval); };
|
||||
vjs.Player.prototype.stopTrackingCurrentTime = function(){ clearInterval(this.currentTimeInterval); };
|
||||
|
||||
// /* Player event handlers (how the player reacts to certain events)
|
||||
// ================================================================================ */
|
||||
_V_.Player.prototype.onEnded = function(){
|
||||
vjs.Player.prototype.onEnded = function(){
|
||||
if (this.options.loop) {
|
||||
this.currentTime(0);
|
||||
this.play();
|
||||
}
|
||||
};
|
||||
|
||||
_V_.Player.prototype.onPlay = function(){
|
||||
_V_.removeClass(this.el_, "vjs-paused");
|
||||
_V_.addClass(this.el_, "vjs-playing");
|
||||
vjs.Player.prototype.onPlay = function(){
|
||||
vjs.removeClass(this.el_, "vjs-paused");
|
||||
vjs.addClass(this.el_, "vjs-playing");
|
||||
};
|
||||
|
||||
_V_.Player.prototype.onPause = function(){
|
||||
_V_.removeClass(this.el_, "vjs-playing");
|
||||
_V_.addClass(this.el_, "vjs-paused");
|
||||
vjs.Player.prototype.onPause = function(){
|
||||
vjs.removeClass(this.el_, "vjs-playing");
|
||||
vjs.addClass(this.el_, "vjs-paused");
|
||||
};
|
||||
|
||||
_V_.Player.prototype.onProgress = function(){
|
||||
vjs.Player.prototype.onProgress = function(){
|
||||
// Add custom event for when source is finished downloading.
|
||||
if (this.bufferedPercent() == 1) {
|
||||
this.trigger("loadedalldata");
|
||||
@ -350,12 +346,12 @@ _V_.Player.prototype.onProgress = function(){
|
||||
|
||||
// Update duration with durationchange event
|
||||
// Allows for cacheing value instead of asking player each time.
|
||||
_V_.Player.prototype.onDurationChange = function(){
|
||||
vjs.Player.prototype.onDurationChange = function(){
|
||||
this.duration(this.techGet("duration"));
|
||||
};
|
||||
|
||||
_V_.Player.prototype.onError = function(e) {
|
||||
_V_.log("Video Error", e);
|
||||
vjs.Player.prototype.onError = function(e) {
|
||||
vjs.log("Video Error", e);
|
||||
};
|
||||
|
||||
// /* Player API
|
||||
@ -365,15 +361,14 @@ _V_.Player.prototype.onError = function(e) {
|
||||
* Object for cached values.
|
||||
* @private
|
||||
*/
|
||||
_V_.Player.prototype.cache_;
|
||||
vjs.Player.prototype.cache_;
|
||||
|
||||
_V_.Player.prototype.getCache = function(){
|
||||
vjs.Player.prototype.getCache = function(){
|
||||
return this.cache_;
|
||||
};
|
||||
|
||||
// Pass values to the playback tech
|
||||
_V_.Player.prototype.techCall = function(method, arg){
|
||||
|
||||
vjs.Player.prototype.techCall = function(method, arg){
|
||||
// If it's not ready yet, call method when it is
|
||||
if (!this.tech.isReady_) {
|
||||
this.tech.ready(function(){
|
||||
@ -385,13 +380,13 @@ _V_.Player.prototype.techCall = function(method, arg){
|
||||
try {
|
||||
this.tech[method](arg);
|
||||
} catch(e) {
|
||||
_V_.log(e);
|
||||
vjs.log(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Get calls can't wait for the tech, and sometimes don't need to.
|
||||
_V_.Player.prototype.techGet = function(method){
|
||||
vjs.Player.prototype.techGet = function(method){
|
||||
|
||||
// Make sure tech is ready
|
||||
if (this.tech.isReady_) {
|
||||
@ -405,18 +400,18 @@ _V_.Player.prototype.techGet = function(method){
|
||||
|
||||
// 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);
|
||||
vjs.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") {
|
||||
window['e'] = e
|
||||
_V_.log("Video.js: " + method + " unavailable on "+this.techName+" playback technology element.", e);
|
||||
vjs.log("Video.js: " + method + " unavailable on "+this.techName+" playback technology element.", e);
|
||||
this.tech.isReady_ = false;
|
||||
throw e;
|
||||
} else {
|
||||
_V_.log(e);
|
||||
vjs.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -426,25 +421,25 @@ _V_.Player.prototype.techGet = function(method){
|
||||
};
|
||||
|
||||
// http://dev.w3.org/html5/spec/video.html#dom-media-play
|
||||
_V_.Player.prototype.play = function(){
|
||||
vjs.Player.prototype.play = function(){
|
||||
this.techCall("play");
|
||||
return this;
|
||||
};
|
||||
|
||||
// http://dev.w3.org/html5/spec/video.html#dom-media-pause
|
||||
_V_.Player.prototype.pause = function(){
|
||||
vjs.Player.prototype.pause = function(){
|
||||
this.techCall("pause");
|
||||
return this;
|
||||
};
|
||||
|
||||
// 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)
|
||||
_V_.Player.prototype.paused = function(){
|
||||
vjs.Player.prototype.paused = function(){
|
||||
return (this.techGet("paused") === false) ? false : true;
|
||||
};
|
||||
|
||||
// http://dev.w3.org/html5/spec/video.html#dom-media-currenttime
|
||||
_V_.Player.prototype.currentTime = function(seconds){
|
||||
vjs.Player.prototype.currentTime = function(seconds){
|
||||
if (seconds !== undefined) {
|
||||
|
||||
// Cache the last set value for smoother scrubbing.
|
||||
@ -465,7 +460,7 @@ _V_.Player.prototype.currentTime = function(seconds){
|
||||
|
||||
// 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.
|
||||
_V_.Player.prototype.duration = function(seconds){
|
||||
vjs.Player.prototype.duration = function(seconds){
|
||||
if (seconds !== undefined) {
|
||||
|
||||
// Cache the last set value for optimiized scrubbing (esp. Flash)
|
||||
@ -478,14 +473,14 @@ _V_.Player.prototype.duration = function(seconds){
|
||||
};
|
||||
|
||||
// Calculates how much time is left. Not in spec, but useful.
|
||||
_V_.Player.prototype.remainingTime = function(){
|
||||
vjs.Player.prototype.remainingTime = function(){
|
||||
return this.duration() - this.currentTime();
|
||||
};
|
||||
|
||||
// http://dev.w3.org/html5/spec/video.html#dom-media-buffered
|
||||
// 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)
|
||||
_V_.Player.prototype.buffered = function(){
|
||||
vjs.Player.prototype.buffered = function(){
|
||||
var buffered = this.techGet("buffered"),
|
||||
start = 0,
|
||||
end = this.cache_.bufferEnd = this.cache_.bufferEnd || 0, // Default end to 0 and store in values
|
||||
@ -497,23 +492,23 @@ _V_.Player.prototype.buffered = function(){
|
||||
this.cache_.bufferEnd = end;
|
||||
}
|
||||
|
||||
return _V_.createTimeRange(start, end);
|
||||
return vjs.createTimeRange(start, end);
|
||||
};
|
||||
|
||||
// Calculates amount of buffer is full. Not in spec but useful.
|
||||
_V_.Player.prototype.bufferedPercent = function(){
|
||||
vjs.Player.prototype.bufferedPercent = function(){
|
||||
return (this.duration()) ? this.buffered().end(0) / this.duration() : 0;
|
||||
};
|
||||
|
||||
// http://dev.w3.org/html5/spec/video.html#dom-media-volume
|
||||
_V_.Player.prototype.volume = function(percentAsDecimal){
|
||||
vjs.Player.prototype.volume = function(percentAsDecimal){
|
||||
var vol;
|
||||
|
||||
if (percentAsDecimal !== undefined) {
|
||||
vol = Math.max(0, Math.min(1, parseFloat(percentAsDecimal))); // Force value to between 0 and 1
|
||||
this.cache_.volume = vol;
|
||||
this.techCall("setVolume", vol);
|
||||
_V_.setLocalStorage("volume", vol);
|
||||
vjs.setLocalStorage("volume", vol);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -523,7 +518,7 @@ _V_.Player.prototype.volume = function(percentAsDecimal){
|
||||
};
|
||||
|
||||
// http://dev.w3.org/html5/spec/video.html#attr-media-muted
|
||||
_V_.Player.prototype.muted = function(muted){
|
||||
vjs.Player.prototype.muted = function(muted){
|
||||
if (muted !== undefined) {
|
||||
this.techCall("setMuted", muted);
|
||||
return this;
|
||||
@ -532,11 +527,11 @@ _V_.Player.prototype.muted = function(muted){
|
||||
};
|
||||
|
||||
// Check if current tech can support native fullscreen (e.g. with built in controls lik iOS, so not our flash swf)
|
||||
_V_.Player.prototype.supportsFullScreen = function(){ return this.techGet("supportsFullScreen") || false; };
|
||||
vjs.Player.prototype.supportsFullScreen = function(){ return this.techGet("supportsFullScreen") || false; };
|
||||
|
||||
// Turn on fullscreen (or window) mode
|
||||
_V_.Player.prototype.requestFullScreen = function(){
|
||||
var requestFullScreen = _V_.support.requestFullScreen;
|
||||
vjs.Player.prototype.requestFullScreen = function(){
|
||||
var requestFullScreen = vjs.support.requestFullScreen;
|
||||
|
||||
this.isFullScreen = true;
|
||||
|
||||
@ -544,12 +539,12 @@ _V_.Player.prototype.requestFullScreen = function(){
|
||||
if (requestFullScreen) {
|
||||
|
||||
// Trigger fullscreenchange event after change
|
||||
_V_.on(document, requestFullScreen.eventName, _V_.bind(this, function(){
|
||||
vjs.on(document, requestFullScreen.eventName, vjs.bind(this, function(){
|
||||
this.isFullScreen = document[requestFullScreen.isFullScreen];
|
||||
|
||||
// If cancelling fullscreen, remove event listener.
|
||||
if (this.isFullScreen == false) {
|
||||
_V_.off(document, requestFullScreen.eventName, arguments.callee);
|
||||
vjs.off(document, requestFullScreen.eventName, arguments.callee);
|
||||
}
|
||||
|
||||
this.trigger("fullscreenchange");
|
||||
@ -557,13 +552,13 @@ _V_.Player.prototype.requestFullScreen = function(){
|
||||
|
||||
// Flash and other plugins get reloaded when you take their parent to fullscreen.
|
||||
// To fix that we'll remove the tech, and reload it after the resize has finished.
|
||||
if (window['_V_'][this.techName]['Supports']['fullscreenResize'] === false && this.options.flash.iFrameMode != true) {
|
||||
if (this.tech.features.fullscreenResize === false && this.options.Flash.iFrameMode != true) {
|
||||
|
||||
this.pause();
|
||||
this.unloadTech();
|
||||
|
||||
_V_.on(document, requestFullScreen.eventName, _V_.bind(this, function(){
|
||||
_V_.off(document, requestFullScreen.eventName, arguments.callee);
|
||||
vjs.on(document, requestFullScreen.eventName, vjs.bind(this, function(){
|
||||
vjs.off(document, requestFullScreen.eventName, arguments.callee);
|
||||
this.loadTech(this.techName, { src: this.cache_.src });
|
||||
}));
|
||||
|
||||
@ -585,8 +580,8 @@ _V_.Player.prototype.requestFullScreen = function(){
|
||||
return this;
|
||||
};
|
||||
|
||||
_V_.Player.prototype.cancelFullScreen = function(){
|
||||
var requestFullScreen = _V_.support.requestFullScreen;
|
||||
vjs.Player.prototype.cancelFullScreen = function(){
|
||||
var requestFullScreen = vjs.support.requestFullScreen;
|
||||
|
||||
this.isFullScreen = false;
|
||||
|
||||
@ -595,13 +590,13 @@ _V_.Player.prototype.cancelFullScreen = function(){
|
||||
|
||||
// Flash and other plugins get reloaded when you take their parent to fullscreen.
|
||||
// To fix that we'll remove the tech, and reload it after the resize has finished.
|
||||
if (window['_V_'][this.techName]['Supports']['fullscreenResize'] === false && this.options.flash.iFrameMode != true) {
|
||||
if (this.tech.features.fullscreenResize === false && this.options.Flash.iFrameMode != true) {
|
||||
|
||||
this.pause();
|
||||
this.unloadTech();
|
||||
|
||||
_V_.on(document, requestFullScreen.eventName, _V_.bind(this, function(){
|
||||
_V_.off(document, requestFullScreen.eventName, arguments.callee);
|
||||
vjs.on(document, requestFullScreen.eventName, vjs.bind(this, function(){
|
||||
vjs.off(document, requestFullScreen.eventName, arguments.callee);
|
||||
this.loadTech(this.techName, { src: this.cache_.src })
|
||||
}));
|
||||
|
||||
@ -624,25 +619,25 @@ _V_.Player.prototype.cancelFullScreen = function(){
|
||||
};
|
||||
|
||||
// When fullscreen isn't supported we can stretch the video container to as wide as the browser will let us.
|
||||
_V_.Player.prototype.enterFullWindow = function(){
|
||||
vjs.Player.prototype.enterFullWindow = function(){
|
||||
this.isFullWindow = true;
|
||||
|
||||
// Storing original doc overflow value to return to when fullscreen is off
|
||||
this.docOrigOverflow = document.documentElement.style.overflow;
|
||||
|
||||
// Add listener for esc key to exit fullscreen
|
||||
_V_.on(document, "keydown", _V_.bind(this, this.fullWindowOnEscKey));
|
||||
vjs.on(document, "keydown", vjs.bind(this, this.fullWindowOnEscKey));
|
||||
|
||||
// Hide any scroll bars
|
||||
document.documentElement.style.overflow = 'hidden';
|
||||
|
||||
// Apply fullscreen styles
|
||||
_V_.addClass(document.body, "vjs-full-window");
|
||||
_V_.addClass(this.el_, "vjs-fullscreen");
|
||||
vjs.addClass(document.body, "vjs-full-window");
|
||||
vjs.addClass(this.el_, "vjs-fullscreen");
|
||||
|
||||
this.trigger("enterFullWindow");
|
||||
};
|
||||
_V_.Player.prototype.fullWindowOnEscKey = function(event){
|
||||
vjs.Player.prototype.fullWindowOnEscKey = function(event){
|
||||
if (event.keyCode == 27) {
|
||||
if (this.isFullScreen == true) {
|
||||
this.cancelFullScreen();
|
||||
@ -652,30 +647,28 @@ _V_.Player.prototype.fullWindowOnEscKey = function(event){
|
||||
}
|
||||
};
|
||||
|
||||
_V_.Player.prototype.exitFullWindow = function(){
|
||||
vjs.Player.prototype.exitFullWindow = function(){
|
||||
this.isFullWindow = false;
|
||||
_V_.off(document, "keydown", this.fullWindowOnEscKey);
|
||||
vjs.off(document, "keydown", this.fullWindowOnEscKey);
|
||||
|
||||
// Unhide scroll bars.
|
||||
document.documentElement.style.overflow = this.docOrigOverflow;
|
||||
|
||||
// Remove fullscreen styles
|
||||
_V_.removeClass(document.body, "vjs-full-window");
|
||||
_V_.removeClass(this.el_, "vjs-fullscreen");
|
||||
vjs.removeClass(document.body, "vjs-full-window");
|
||||
vjs.removeClass(this.el_, "vjs-fullscreen");
|
||||
|
||||
// Resize the box, controller, and poster to original sizes
|
||||
// this.positionAll();
|
||||
this.trigger("exitFullWindow");
|
||||
};
|
||||
|
||||
_V_.Player.prototype.selectSource = function(sources){
|
||||
vjs.Player.prototype.selectSource = function(sources){
|
||||
|
||||
// Loop through each playback technology in the options order
|
||||
for (var i=0,j=this.options.techOrder;i<j.length;i++) {
|
||||
var techName = _V_.capitalize(j[i]),
|
||||
tech = window['_V_'][techName];
|
||||
|
||||
var techInfo = window['_V_'][j[i]];
|
||||
for (var i=0,j=this.options['techOrder'];i<j.length;i++) {
|
||||
var techName = vjs.capitalize(j[i]),
|
||||
tech = window['videojs'][techName];
|
||||
|
||||
// Check if the browser supports this technology
|
||||
if (tech.isSupported()) {
|
||||
@ -699,7 +692,7 @@ _V_.Player.prototype.selectSource = function(sources){
|
||||
// If the new source requires a new playback technology, it will switch to that.
|
||||
// If you pass it an object, it will set the source to object.src
|
||||
// If you pass it anything else (url string) it will set the video source to that
|
||||
_V_.Player.prototype.src = function(source){
|
||||
vjs.Player.prototype.src = function(source){
|
||||
// Case: Array of source objects to choose from and pick the best to play
|
||||
if (source instanceof Array) {
|
||||
|
||||
@ -719,13 +712,13 @@ _V_.Player.prototype.src = function(source){
|
||||
this.loadTech(techName, source);
|
||||
}
|
||||
} else {
|
||||
_V_.log("No compatible source and media technology were found.")
|
||||
vjs.log("No compatible source and media technology were found.")
|
||||
}
|
||||
|
||||
// Case: Source object { src: "", type: "" ... }
|
||||
} else if (source instanceof Object) {
|
||||
|
||||
if (window['_V_'][this.techName]['canPlaySource'](source)) {
|
||||
if (window['videojs'][this.techName]['canPlaySource'](source)) {
|
||||
this.src(source.src);
|
||||
} else {
|
||||
// Send through tech loop to check for a compatible technology.
|
||||
@ -756,18 +749,18 @@ _V_.Player.prototype.src = function(source){
|
||||
|
||||
// Begin loading the src data
|
||||
// http://dev.w3.org/html5/spec/video.html#dom-media-load
|
||||
_V_.Player.prototype.load = function(){
|
||||
vjs.Player.prototype.load = function(){
|
||||
this.techCall("load");
|
||||
return this;
|
||||
};
|
||||
|
||||
// http://dev.w3.org/html5/spec/video.html#dom-media-currentsrc
|
||||
_V_.Player.prototype.currentSrc = function(){
|
||||
vjs.Player.prototype.currentSrc = function(){
|
||||
return this.techGet("currentSrc") || this.cache_.src || "";
|
||||
};
|
||||
|
||||
// Attributes/Options
|
||||
_V_.Player.prototype.preload = function(value){
|
||||
vjs.Player.prototype.preload = function(value){
|
||||
if (value !== undefined) {
|
||||
this.techCall("setPreload", value);
|
||||
this.options.preload = value;
|
||||
@ -775,7 +768,7 @@ _V_.Player.prototype.preload = function(value){
|
||||
}
|
||||
return this.techGet("preload");
|
||||
};
|
||||
_V_.Player.prototype.autoplay = function(value){
|
||||
vjs.Player.prototype.autoplay = function(value){
|
||||
if (value !== undefined) {
|
||||
this.techCall("setAutoplay", value);
|
||||
this.options.autoplay = value;
|
||||
@ -783,7 +776,7 @@ _V_.Player.prototype.autoplay = function(value){
|
||||
}
|
||||
return this.techGet("autoplay", value);
|
||||
};
|
||||
_V_.Player.prototype.loop = function(value){
|
||||
vjs.Player.prototype.loop = function(value){
|
||||
if (value !== undefined) {
|
||||
this.techCall("setLoop", value);
|
||||
this.options.loop = value;
|
||||
@ -792,10 +785,10 @@ _V_.Player.prototype.loop = function(value){
|
||||
return this.techGet("loop");
|
||||
};
|
||||
|
||||
_V_.Player.prototype.controls = function(){ return this.options.controls; };
|
||||
_V_.Player.prototype.poster = function(){ return this.techGet("poster"); };
|
||||
_V_.Player.prototype.error = function(){ return this.techGet("error"); };
|
||||
_V_.Player.prototype.ended = function(){ return this.techGet("ended"); };
|
||||
vjs.Player.prototype.controls = function(){ return this.options.controls; };
|
||||
vjs.Player.prototype.poster = function(){ return this.techGet("poster"); };
|
||||
vjs.Player.prototype.error = function(){ return this.techGet("error"); };
|
||||
vjs.Player.prototype.ended = function(){ return this.techGet("ended"); };
|
||||
|
||||
// Methods to add support for
|
||||
// networkState: function(){ return this.techCall("networkState"); },
|
||||
@ -825,7 +818,7 @@ _V_.Player.prototype.ended = function(){ return this.techGet("ended"); };
|
||||
cancelFn,
|
||||
eventName,
|
||||
isFullScreen,
|
||||
playerProto = _V_.Player.prototype;
|
||||
playerProto = vjs.Player.prototype;
|
||||
|
||||
// Current W3C Spec
|
||||
// http://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html#api
|
||||
@ -863,7 +856,7 @@ _V_.Player.prototype.ended = function(){ return this.techGet("ended"); };
|
||||
}
|
||||
|
||||
if (requestFn) {
|
||||
_V_.support.requestFullScreen = {
|
||||
vjs.support.requestFullScreen = {
|
||||
requestFn: requestFn,
|
||||
cancelFn: cancelFn,
|
||||
eventName: eventName,
|
||||
@ -876,17 +869,15 @@ _V_.Player.prototype.ended = function(){ return this.techGet("ended"); };
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
_V_.MediaLoader = function(player, options, ready){
|
||||
_V_.Component.call(this, player, options, ready);
|
||||
vjs.MediaLoader = function(player, options, ready){
|
||||
vjs.Component.call(this, player, options, ready);
|
||||
|
||||
// If there are no sources when the player is initialized,
|
||||
// load the first supported playback technology.
|
||||
if (!player.options.sources || player.options.sources.length == 0) {
|
||||
for (var i=0,j=player.options.techOrder; i<j.length; i++) {
|
||||
var techName = _V_.capitalize(j[i]),
|
||||
tech = window['_V_'][techName];
|
||||
|
||||
var techInfo = window['_V_'][j[i]];
|
||||
for (var i=0,j=player.options['techOrder']; i<j.length; i++) {
|
||||
var techName = vjs.capitalize(j[i]),
|
||||
tech = window['videojs'][techName];
|
||||
|
||||
// Check if the browser supports this technology
|
||||
if (tech && tech.isSupported()) {
|
||||
@ -902,6 +893,6 @@ _V_.MediaLoader = function(player, options, ready){
|
||||
player.src(player.options.sources);
|
||||
}
|
||||
};
|
||||
goog.inherits(_V_.MediaLoader, _V_.Component);
|
||||
goog.inherits(vjs.MediaLoader, vjs.Component);
|
||||
|
||||
|
||||
|
24
src/setup.js
24
src/setup.js
@ -1,5 +1,5 @@
|
||||
// Automatically set up any tags that have a data-setup attribute
|
||||
_V_.autoSetup = function(){
|
||||
vjs.autoSetup = function(){
|
||||
var options, vid, player,
|
||||
vids = document.getElementsByTagName("video");
|
||||
|
||||
@ -17,40 +17,40 @@ _V_.autoSetup = function(){
|
||||
if (vid.player === undefined) {
|
||||
options = vid.getAttribute("data-setup");
|
||||
|
||||
// Check if data-setup attr exists.
|
||||
// Check if data-setup attr exists.
|
||||
// We only auto-setup if they've added the data-setup attr.
|
||||
if (options !== null) {
|
||||
|
||||
// Parse options JSON
|
||||
// If empty string, make it a parsable json object.
|
||||
options = JSON.parse(options || "{}");
|
||||
options = vjs.JSON.parse(options || "{}");
|
||||
|
||||
// Create new video.js instance.
|
||||
player = _V_(vid, options);
|
||||
player = videojs(vid, options);
|
||||
}
|
||||
}
|
||||
|
||||
// If getAttribute isn't defined, we need to wait for the DOM.
|
||||
} else {
|
||||
_V_.autoSetupTimeout(1);
|
||||
vjs.autoSetupTimeout(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// No videos were found, so keep looping unless page is finisehd loading.
|
||||
} else if (!_V_.windowLoaded) {
|
||||
_V_.autoSetupTimeout(1);
|
||||
} else if (!vjs.windowLoaded) {
|
||||
vjs.autoSetupTimeout(1);
|
||||
}
|
||||
};
|
||||
|
||||
// Pause to let the DOM keep processing
|
||||
_V_.autoSetupTimeout = function(wait){
|
||||
setTimeout(_V_.autoSetup, wait);
|
||||
vjs.autoSetupTimeout = function(wait){
|
||||
setTimeout(vjs.autoSetup, wait);
|
||||
};
|
||||
|
||||
_V_.addEvent(window, "load", function(){
|
||||
_V_.windowLoaded = true;
|
||||
vjs.one(window, "load", function(){
|
||||
vjs.windowLoaded = true;
|
||||
});
|
||||
|
||||
// Run Auto-load players
|
||||
_V_.autoSetup();
|
||||
vjs.autoSetup();
|
||||
|
258
src/tracks.js
258
src/tracks.js
@ -9,17 +9,19 @@
|
||||
|
||||
// Add an array of text tracks. captions, subtitles, chapters, descriptions
|
||||
// Track objects will be stored in the player.textTracks array
|
||||
_V_.Player.prototype.addTextTracks = function(trackObjects){
|
||||
var tracks = this.textTracks = (this.textTracks) ? this.textTracks : [],
|
||||
i = 0, j = trackObjects.length, track, Kind;
|
||||
vjs.Player.prototype.addTextTracks = function(trackObjects){
|
||||
var track, Kind,
|
||||
tracks = this.textTracks = this.textTracks || [],
|
||||
i = 0,
|
||||
j = trackObjects.length;
|
||||
|
||||
for (;i<j;i++) {
|
||||
// HTML5 Spec says default to subtitles.
|
||||
// Uppercase (uc) first letter to match class names
|
||||
Kind = _V_.capitalize(trackObjects[i].kind || "subtitles");
|
||||
Kind = vjs.capitalize(trackObjects[i].kind || "subtitles");
|
||||
|
||||
// Create correct texttrack class. CaptionsTrack, etc.
|
||||
track = new _V_[Kind + "Track"](this, trackObjects[i]);
|
||||
track = new window['videojs'][Kind + "Track"](this, trackObjects[i]);
|
||||
|
||||
tracks.push(track);
|
||||
|
||||
@ -28,7 +30,7 @@ _V_.Player.prototype.addTextTracks = function(trackObjects){
|
||||
// Incase there are mulitple defaulted tracks of the same kind
|
||||
// Or the user has a set preference of a specific language that should override the default
|
||||
if (track['default']) {
|
||||
this.ready(_V_.bind(track, track.show));
|
||||
this.ready(vjs.bind(track, track.show));
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,7 +40,7 @@ _V_.Player.prototype.addTextTracks = function(trackObjects){
|
||||
|
||||
// Show a text track
|
||||
// disableSameKind: disable all other tracks of the same kind. Value should be a track kind (captions, etc.)
|
||||
_V_.Player.prototype.showTextTrack = function(id, disableSameKind){
|
||||
vjs.Player.prototype.showTextTrack = function(id, disableSameKind){
|
||||
var tracks = this.textTracks,
|
||||
i = 0,
|
||||
j = tracks.length,
|
||||
@ -71,18 +73,18 @@ _V_.Player.prototype.showTextTrack = function(id, disableSameKind){
|
||||
/**
|
||||
* Track Class
|
||||
* Contains track methods for loading, showing, parsing cues of tracks
|
||||
* @param {_V_.Player|Object} player
|
||||
* @param {vjs.Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*/
|
||||
_V_.Track = function(player, options){
|
||||
vjs.Track = function(player, options){
|
||||
goog.base(this, player, options);
|
||||
|
||||
// Apply track info to track object
|
||||
// Options will often be a track element
|
||||
_V_.merge(this, {
|
||||
vjs.merge(this, {
|
||||
// Build ID if one doesn't exist
|
||||
id: options.id || ("vjs_" + options.kind + "_" + options.language + "_" + _V_.guid++),
|
||||
id: options.id || ("vjs_" + options.kind + "_" + options.language + "_" + vjs.guid++),
|
||||
|
||||
src: options.src,
|
||||
|
||||
@ -122,10 +124,10 @@ _V_.Track = function(player, options){
|
||||
mode: 0
|
||||
});
|
||||
};
|
||||
goog.inherits(_V_.Track, _V_.Component);
|
||||
goog.inherits(vjs.Track, vjs.Component);
|
||||
|
||||
// Create basic div to hold cue text
|
||||
_V_.Track.prototype.createEl = function(){
|
||||
vjs.Track.prototype.createEl = function(){
|
||||
return goog.base(this, 'createEl', "div", {
|
||||
className: "vjs-" + this.kind + " vjs-text-track"
|
||||
});
|
||||
@ -139,7 +141,7 @@ _V_.Track.prototype.createEl = function(){
|
||||
// and for text tracks whose kind is chapters, the user agent is making available to the user a mechanism by which the user can navigate to any point in the media resource by selecting a cue.
|
||||
// The showing by default state is used in conjunction with the default attribute on track elements to indicate that the text track was enabled due to that attribute.
|
||||
// This allows the user agent to override the state if a later track is discovered that is more appropriate per the user's preferences.
|
||||
_V_.Track.prototype.show = function(){
|
||||
vjs.Track.prototype.show = function(){
|
||||
this.activate();
|
||||
|
||||
this.mode = 2;
|
||||
@ -152,7 +154,7 @@ _V_.Track.prototype.show = function(){
|
||||
// Indicates that the text track is active, but that the user agent is not actively displaying the cues.
|
||||
// If no attempt has yet been made to obtain the track's cues, the user agent will perform such an attempt momentarily.
|
||||
// The user agent is maintaining a list of which cues are active, and events are being fired accordingly.
|
||||
_V_.Track.prototype.hide = function(){
|
||||
vjs.Track.prototype.hide = function(){
|
||||
// When hidden, cues are still triggered. Disable to stop triggering.
|
||||
this.activate();
|
||||
|
||||
@ -165,7 +167,7 @@ _V_.Track.prototype.hide = function(){
|
||||
// Disable: Mode Off/Disable (0)
|
||||
// Indicates that the text track is not active. Other than for the purposes of exposing the track in the DOM, the user agent is ignoring the text track.
|
||||
// No cues are active, no events are fired, and the user agent will not attempt to obtain the track's cues.
|
||||
_V_.Track.prototype.disable = function(){
|
||||
vjs.Track.prototype.disable = function(){
|
||||
// If showing, hide.
|
||||
if (this.mode == 2) { this.hide(); }
|
||||
|
||||
@ -177,7 +179,7 @@ _V_.Track.prototype.disable = function(){
|
||||
};
|
||||
|
||||
// Turn on cue tracking. Tracks that are showing OR hidden are active.
|
||||
_V_.Track.prototype.activate = function(){
|
||||
vjs.Track.prototype.activate = function(){
|
||||
// Load text file if it hasn't been yet.
|
||||
if (this.readyState == 0) { this.load(); }
|
||||
|
||||
@ -185,23 +187,26 @@ _V_.Track.prototype.activate = function(){
|
||||
if (this.mode == 0) {
|
||||
// Update current cue on timeupdate
|
||||
// Using unique ID for bind function so other tracks don't remove listener
|
||||
this.player.on("timeupdate", _V_.bind(this, this.update, this.id));
|
||||
this.player.on("timeupdate", vjs.bind(this, this.update, this.id));
|
||||
|
||||
// Reset cue time on media end
|
||||
this.player.on("ended", _V_.bind(this, this.reset, this.id));
|
||||
this.player.on("ended", vjs.bind(this, this.reset, this.id));
|
||||
|
||||
// Add to display
|
||||
if (this.kind == "captions" || this.kind == "subtitles") {
|
||||
|
||||
console.log('adsf', this.player.childNameIndex_);
|
||||
|
||||
this.player.textTrackDisplay.addChild(this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Turn off cue tracking.
|
||||
_V_.Track.prototype.deactivate = function(){
|
||||
vjs.Track.prototype.deactivate = function(){
|
||||
// Using unique ID for bind function so other tracks don't remove listener
|
||||
this.player.off("timeupdate", _V_.bind(this, this.update, this.id));
|
||||
this.player.off("ended", _V_.bind(this, this.reset, this.id));
|
||||
this.player.off("timeupdate", vjs.bind(this, this.update, this.id));
|
||||
this.player.off("ended", vjs.bind(this, this.reset, this.id));
|
||||
this.reset(); // Reset
|
||||
|
||||
// Remove from display
|
||||
@ -222,17 +227,18 @@ _V_.Track.prototype.deactivate = function(){
|
||||
//
|
||||
// Failed to load
|
||||
// Indicates that the text track was enabled, but when the user agent attempted to obtain it, this failed in some way (e.g. URL could not be resolved, network error, unknown text track format). Some or all of the cues are likely missing and will not be obtained.
|
||||
_V_.Track.prototype.load = function(){
|
||||
vjs.Track.prototype.load = function(){
|
||||
|
||||
// Only load if not loaded yet.
|
||||
if (this.readyState == 0) {
|
||||
this.readyState = 1;
|
||||
_V_.get(this.src, _V_.bind(this, this.parseCues), _V_.bind(this, this.onError));
|
||||
console.log('track get method not supported yet')
|
||||
// vjs.get(this.src, vjs.bind(this, this.parseCues), vjs.bind(this, this.onError));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
_V_.Track.prototype.onError = function(err){
|
||||
vjs.Track.prototype.onError = function(err){
|
||||
this.error = err;
|
||||
this.readyState = 3;
|
||||
this.trigger("error");
|
||||
@ -240,7 +246,7 @@ _V_.Track.prototype.onError = function(err){
|
||||
|
||||
// Parse the WebVTT text format for cue times.
|
||||
// TODO: Separate parser into own class so alternative timed text formats can be used. (TTML, DFXP)
|
||||
_V_.Track.prototype.parseCues = function(srcContent) {
|
||||
vjs.Track.prototype.parseCues = function(srcContent) {
|
||||
var cue, time, text,
|
||||
lines = srcContent.split("\n"),
|
||||
line = "", id;
|
||||
@ -248,7 +254,7 @@ _V_.Track.prototype.parseCues = function(srcContent) {
|
||||
for (var i=1, j=lines.length; i<j; i++) {
|
||||
// Line 0 should be 'WEBVTT', so skipping i=0
|
||||
|
||||
line = _V_.trim(lines[i]); // Trim whitespace and linebreaks
|
||||
line = vjs.trim(lines[i]); // Trim whitespace and linebreaks
|
||||
|
||||
if (line) { // Loop until a line with content
|
||||
|
||||
@ -257,7 +263,7 @@ _V_.Track.prototype.parseCues = function(srcContent) {
|
||||
if (line.indexOf("-->") == -1) {
|
||||
id = line;
|
||||
// Advance to next line for timing.
|
||||
line = _V_.trim(lines[++i]);
|
||||
line = vjs.trim(lines[++i]);
|
||||
} else {
|
||||
id = this.cues.length;
|
||||
}
|
||||
@ -278,7 +284,7 @@ _V_.Track.prototype.parseCues = function(srcContent) {
|
||||
|
||||
// Loop until a blank line or end of lines
|
||||
// Assumeing trim("") returns false for blank lines
|
||||
while (lines[++i] && (line = _V_.trim(lines[i]))) {
|
||||
while (lines[++i] && (line = vjs.trim(lines[i]))) {
|
||||
text.push(line);
|
||||
}
|
||||
|
||||
@ -294,7 +300,7 @@ _V_.Track.prototype.parseCues = function(srcContent) {
|
||||
};
|
||||
|
||||
|
||||
_V_.Track.prototype.parseCueTime = function(timeText) {
|
||||
vjs.Track.prototype.parseCueTime = function(timeText) {
|
||||
var parts = timeText.split(':'),
|
||||
time = 0,
|
||||
hours, minutes, other, seconds, ms, flags;
|
||||
@ -335,7 +341,7 @@ _V_.Track.prototype.parseCueTime = function(timeText) {
|
||||
};
|
||||
|
||||
// Update active cues whenever timeupdate events are triggered on the player.
|
||||
_V_.Track.prototype.update = function(){
|
||||
vjs.Track.prototype.update = function(){
|
||||
if (this.cues.length > 0) {
|
||||
|
||||
// Get curent player time
|
||||
@ -445,7 +451,7 @@ _V_.Track.prototype.update = function(){
|
||||
};
|
||||
|
||||
// Add cue HTML to display
|
||||
_V_.Track.prototype.updateDisplay = function(){
|
||||
vjs.Track.prototype.updateDisplay = function(){
|
||||
var cues = this.activeCues,
|
||||
html = "",
|
||||
i=0,j=cues.length;
|
||||
@ -458,7 +464,7 @@ _V_.Track.prototype.updateDisplay = function(){
|
||||
};
|
||||
|
||||
// Set all loop helper values back
|
||||
_V_.Track.prototype.reset = function(){
|
||||
vjs.Track.prototype.reset = function(){
|
||||
this.nextChange = 0;
|
||||
this.prevChange = this.player.duration();
|
||||
this.firstActiveIndex = 0;
|
||||
@ -469,36 +475,54 @@ _V_.Track.prototype.reset = function(){
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
_V_.CaptionsTrack = function(){};
|
||||
goog.inherits(_V_.CaptionsTrack, _V_.Track);
|
||||
_V_.CaptionsTrack.prototype.kind = "captions";
|
||||
vjs.CaptionsTrack = function(player, options, ready){
|
||||
goog.base(this, player, options, ready);
|
||||
};
|
||||
goog.inherits(vjs.CaptionsTrack, vjs.Track);
|
||||
vjs.CaptionsTrack.prototype.kind = "captions";
|
||||
// Exporting here because Track creation requires the track kind
|
||||
// to be available on global object. e.g. new window['videojs'][Kind + 'Track']
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
_V_.SubtitlesTrack = function(){};
|
||||
goog.inherits(_V_.SubtitlesTrack, _V_.Track);
|
||||
_V_.SubtitlesTrack.prototype.kind = "subtitles";
|
||||
vjs.SubtitlesTrack = function(player, options, ready){
|
||||
goog.base(this, player, options, ready);
|
||||
};
|
||||
goog.inherits(vjs.SubtitlesTrack, vjs.Track);
|
||||
vjs.SubtitlesTrack.prototype.kind = "subtitles";
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
_V_.ChaptersTrack = function(){};
|
||||
goog.inherits(_V_.ChaptersTrack, _V_.Track);
|
||||
_V_.ChaptersTrack.prototype.kind = "chapters";
|
||||
vjs.ChaptersTrack = function(player, options, ready){
|
||||
goog.base(this, player, options, ready);
|
||||
};
|
||||
goog.inherits(vjs.ChaptersTrack, vjs.Track);
|
||||
vjs.ChaptersTrack.prototype.kind = "chapters";
|
||||
|
||||
|
||||
/* Text Track Display
|
||||
================================================================================ */
|
||||
============================================================================= */
|
||||
// Global container for both subtitle and captions text. Simple div container.
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
_V_.TextTrackDisplay = function()}{};
|
||||
goog.inherits(_V_.TextTrackDisplay, _V_.Component);
|
||||
vjs.TextTrackDisplay = function(player, options, ready){
|
||||
goog.base(this, player, options, ready);
|
||||
|
||||
_V_.TextTrackDisplay.prototype.createEl = function(){
|
||||
// This used to be called during player init, but was causing an error
|
||||
// if a track should show by default and the display hadn't loaded yet.
|
||||
// Should probably be moved to an external track loader when we support
|
||||
// tracks that don't need a display.
|
||||
if (player.options.tracks && player.options.tracks.length > 0) {
|
||||
this.player.addTextTracks(options.tracks);
|
||||
}
|
||||
};
|
||||
goog.inherits(vjs.TextTrackDisplay, vjs.Component);
|
||||
|
||||
vjs.TextTrackDisplay.prototype.createEl = function(){
|
||||
return goog.base(this, 'createEl', "div", {
|
||||
className: "vjs-text-track-display"
|
||||
});
|
||||
@ -506,11 +530,11 @@ _V_.TextTrackDisplay.prototype.createEl = function(){
|
||||
|
||||
|
||||
/* Text Track Menu Items
|
||||
================================================================================ */
|
||||
============================================================================= */
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
_V_.TextTrackMenuItem = function(player, options){
|
||||
vjs.TextTrackMenuItem = function(player, options){
|
||||
var track = this.track = options.track;
|
||||
|
||||
// Modify options for parent MenuItem class's init.
|
||||
@ -518,16 +542,16 @@ _V_.TextTrackMenuItem = function(player, options){
|
||||
options.selected = track["default"];
|
||||
goog.base(this, player, options);
|
||||
|
||||
this.player.on(track.kind + "trackchange", _V_.bind(this, this.update));
|
||||
this.player.on(track.kind + "trackchange", vjs.bind(this, this.update));
|
||||
};
|
||||
goog.inherits(_V_.TextTrackMenuItem, _V_.MenuItem);
|
||||
goog.inherits(vjs.TextTrackMenuItem, vjs.MenuItem);
|
||||
|
||||
_V_.TextTrackMenuItem.prototype.onClick = function(){
|
||||
vjs.TextTrackMenuItem.prototype.onClick = function(){
|
||||
goog.base(this, 'onClick');
|
||||
this.player.showTextTrack(this.track.id, this.track.kind);
|
||||
};
|
||||
|
||||
_V_.TextTrackMenuItem.prototype.update = function(){
|
||||
vjs.TextTrackMenuItem.prototype.update = function(){
|
||||
if (this.track.mode == 2) {
|
||||
this.selected(true);
|
||||
} else {
|
||||
@ -538,20 +562,20 @@ _V_.TextTrackMenuItem.prototype.update = function(){
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
_V_.OffTextTrackMenuItem = function(player, options){
|
||||
vjs.OffTextTrackMenuItem = function(player, options){
|
||||
// Create pseudo track info
|
||||
// Requires options.kind
|
||||
options.track = { kind: options.kind, player: player, label: "Off" }
|
||||
goog.base(this, player, options);
|
||||
};
|
||||
goog.inherits(_V_.OffTextTrackMenuItem, _V_.TextTrackMenuItem);
|
||||
goog.inherits(vjs.OffTextTrackMenuItem, vjs.TextTrackMenuItem);
|
||||
|
||||
_V_.OffTextTrackMenuItem.prototype.onClick = function(){
|
||||
vjs.OffTextTrackMenuItem.prototype.onClick = function(){
|
||||
goog.base(this, 'onClick');
|
||||
this.player.showTextTrack(this.track.id, this.track.kind);
|
||||
};
|
||||
|
||||
_V_.OffTextTrackMenuItem.prototype.update = function(){
|
||||
vjs.OffTextTrackMenuItem.prototype.update = function(){
|
||||
var tracks = this.player.textTracks,
|
||||
i=0, j=tracks.length, track,
|
||||
off = true;
|
||||
@ -575,7 +599,7 @@ _V_.OffTextTrackMenuItem.prototype.update = function(){
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
_V_.TextTrackButton = function(player, options){
|
||||
vjs.TextTrackButton = function(player, options){
|
||||
goog.base(this, player, options);
|
||||
|
||||
this.menu = this.createMenu();
|
||||
@ -584,26 +608,26 @@ _V_.TextTrackButton = function(player, options){
|
||||
this.hide();
|
||||
}
|
||||
};
|
||||
goog.inherits(_V_.TextTrackButton, _V_.Button);
|
||||
goog.inherits(vjs.TextTrackButton, vjs.Button);
|
||||
|
||||
_V_.TextTrackButton.prototype.createMenu = function(){
|
||||
var menu = new _V_.Menu(this.player);
|
||||
vjs.TextTrackButton.prototype.createMenu = function(){
|
||||
var menu = new vjs.Menu(this.player);
|
||||
|
||||
// Add a title list item to the top
|
||||
menu.el.appendChild(_V_.createElement("li", {
|
||||
menu.el_.appendChild(vjs.createEl("li", {
|
||||
className: "vjs-menu-title",
|
||||
innerHTML: _V_.capitalize(this.kind)
|
||||
innerHTML: vjs.capitalize(this.kind)
|
||||
}));
|
||||
|
||||
// Add an OFF menu item to turn all tracks off
|
||||
menu.addItem(new _V_.OffTextTrackMenuItem(this.player, { kind: this.kind }))
|
||||
menu.addItem(new vjs.OffTextTrackMenuItem(this.player, { kind: this.kind }))
|
||||
|
||||
this.items = this.createItems();
|
||||
|
||||
// Add menu items to the menu
|
||||
this.each(this.items, function(item){
|
||||
menu.addItem(item);
|
||||
});
|
||||
for (var i = 0; i < this.items.length; i++) {
|
||||
menu.addItem(this.items[i]);
|
||||
};
|
||||
|
||||
// Add list to element
|
||||
this.addChild(menu);
|
||||
@ -612,41 +636,44 @@ _V_.TextTrackButton.prototype.createMenu = function(){
|
||||
};
|
||||
|
||||
// Create a menu item for each text track
|
||||
_V_.TextTrackButton.prototype.createItems = function(){
|
||||
var items = [];
|
||||
this.each(this.player.textTracks, function(track){
|
||||
vjs.TextTrackButton.prototype.createItems = function(){
|
||||
var items = [], track;
|
||||
|
||||
for (var i = 0; i < this.player.textTracks.length; i++) {
|
||||
track = this.player.textTracks[i];
|
||||
if (track.kind === this.kind) {
|
||||
items.push(new _V_.TextTrackMenuItem(this.player, {
|
||||
items.push(new vjs.TextTrackMenuItem(this.player, {
|
||||
track: track
|
||||
}));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return items;
|
||||
};
|
||||
|
||||
_V_.TextTrackButton.prototype.buildCSSClass = function(){
|
||||
vjs.TextTrackButton.prototype.buildCSSClass = function(){
|
||||
return this.className + " vjs-menu-button " + goog.base(this, 'buildCSSClass');
|
||||
};
|
||||
|
||||
// Focus - Add keyboard functionality to element
|
||||
_V_.TextTrackButton.prototype.onFocus = function(){
|
||||
vjs.TextTrackButton.prototype.onFocus = function(){
|
||||
// Show the menu, and keep showing when the menu items are in focus
|
||||
this.menu.lockShowing();
|
||||
// this.menu.el.style.display = "block";
|
||||
// this.menu.el_.style.display = "block";
|
||||
|
||||
// When tabbing through, the menu should hide when focus goes from the last menu item to the next tabbed element.
|
||||
_V_.one(this.menu.el.childNodes[this.menu.el.childNodes.length - 1], "blur", _V_.bind(this, function(){
|
||||
vjs.one(this.menu.el_.childNodes[this.menu.el_.childNodes.length - 1], "blur", vjs.bind(this, function(){
|
||||
this.menu.unlockShowing();
|
||||
}));
|
||||
};
|
||||
// Can't turn off list display that we turned on with focus, because list would go away.
|
||||
_V_.TextTrackButton.prototype.onBlur = function(){};
|
||||
vjs.TextTrackButton.prototype.onBlur = function(){};
|
||||
|
||||
_V_.TextTrackButton.prototype.onClick = function(){
|
||||
vjs.TextTrackButton.prototype.onClick = function(){
|
||||
// When you click the button it adds focus, which will show the menu indefinitely.
|
||||
// So we'll remove focus when the mouse leaves the button.
|
||||
// Focus is needed for tab navigation.
|
||||
this.one("mouseout", _V_.bind(this, function(){
|
||||
this.one("mouseout", vjs.bind(this, function(){
|
||||
this.menu.unlockShowing();
|
||||
this.el_.blur();
|
||||
}));
|
||||
@ -655,48 +682,55 @@ _V_.TextTrackButton.prototype.onClick = function(){
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
_V_.CaptionsButton = function(){};
|
||||
goog.inherits(_V_.CaptionsButton, _V_.TextTrackButton);
|
||||
_V_.CaptionsButton.prototype.kind = "captions";
|
||||
_V_.CaptionsButton.prototype.buttonText = "Captions";
|
||||
_V_.CaptionsButton.prototype.className = "vjs-captions-button";
|
||||
vjs.CaptionsButton = function(player, options, ready){
|
||||
goog.base(this, player, options, ready)
|
||||
};
|
||||
goog.inherits(vjs.CaptionsButton, vjs.TextTrackButton);
|
||||
vjs.CaptionsButton.prototype.kind = "captions";
|
||||
vjs.CaptionsButton.prototype.buttonText = "Captions";
|
||||
vjs.CaptionsButton.prototype.className = "vjs-captions-button";
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
_V_.SubtitlesButton = function(){};
|
||||
goog.inherits(_V_.SubtitlesButton, _V_.TextTrackButton);
|
||||
_V_.SubtitlesButton.prototype.kind = "subtitles";
|
||||
_V_.SubtitlesButton.prototype.buttonText = "Subtitles";
|
||||
_V_.SubtitlesButton.prototype.className = "vjs-subtitles-button";
|
||||
vjs.SubtitlesButton = function(player, options, ready){
|
||||
goog.base(this, player, options, ready);
|
||||
};
|
||||
goog.inherits(vjs.SubtitlesButton, vjs.TextTrackButton);
|
||||
vjs.SubtitlesButton.prototype.kind = "subtitles";
|
||||
vjs.SubtitlesButton.prototype.buttonText = "Subtitles";
|
||||
vjs.SubtitlesButton.prototype.className = "vjs-subtitles-button";
|
||||
|
||||
// Chapters act much differently than other text tracks
|
||||
// Cues are navigation vs. other tracks of alternative languages
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
_V_.ChaptersButton = function(){};
|
||||
goog.inherits(_V_.ChaptersButton, _V_.TextTrackButton);
|
||||
_V_.ChaptersButton.prototype.kind = "chapters";
|
||||
_V_.ChaptersButton.prototype.buttonText = "Chapters";
|
||||
_V_.ChaptersButton.prototype.className = "vjs-chapters-button";
|
||||
vjs.ChaptersButton = function(player, options, ready){
|
||||
goog.base(this, player, options, ready);
|
||||
};
|
||||
goog.inherits(vjs.ChaptersButton, vjs.TextTrackButton);
|
||||
vjs.ChaptersButton.prototype.kind = "chapters";
|
||||
vjs.ChaptersButton.prototype.buttonText = "Chapters";
|
||||
vjs.ChaptersButton.prototype.className = "vjs-chapters-button";
|
||||
|
||||
// Create a menu item for each text track
|
||||
_V_.ChaptersButton.prototype.createItems = function(chaptersTrack){
|
||||
var items = [];
|
||||
vjs.ChaptersButton.prototype.createItems = function(chaptersTrack){
|
||||
var items = [], track;
|
||||
|
||||
this.each(this.player.textTracks, function(track){
|
||||
for (var i = 0; i < this.player.textTracks.length; i++) {;
|
||||
track = this.player.textTracks[i];
|
||||
if (track.kind === this.kind) {
|
||||
items.push(new _V_.TextTrackMenuItem(this.player, {
|
||||
items.push(new vjs.TextTrackMenuItem(this.player, {
|
||||
track: track
|
||||
}));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return items;
|
||||
};
|
||||
|
||||
_V_.ChaptersButton.prototype.createMenu = function(){
|
||||
vjs.ChaptersButton.prototype.createMenu = function(){
|
||||
var tracks = this.player.textTracks,
|
||||
i = 0,
|
||||
j = tracks.length,
|
||||
@ -708,7 +742,7 @@ _V_.ChaptersButton.prototype.createMenu = function(){
|
||||
if (track.kind == this.kind && track["default"]) {
|
||||
if (track.readyState < 2) {
|
||||
this.chaptersTrack = track;
|
||||
track.on("loaded", _V_.bind(this, this.createMenu));
|
||||
track.on("loaded", vjs.bind(this, this.createMenu));
|
||||
return;
|
||||
} else {
|
||||
chaptersTrack = track;
|
||||
@ -717,11 +751,11 @@ _V_.ChaptersButton.prototype.createMenu = function(){
|
||||
}
|
||||
}
|
||||
|
||||
var menu = this.menu = new _V_.Menu(this.player);
|
||||
var menu = this.menu = new vjs.Menu(this.player);
|
||||
|
||||
menu.el.appendChild(_V_.createElement("li", {
|
||||
menu.el_.appendChild(vjs.createEl("li", {
|
||||
className: "vjs-menu-title",
|
||||
innerHTML: _V_.capitalize(this.kind)
|
||||
innerHTML: vjs.capitalize(this.kind)
|
||||
}));
|
||||
|
||||
if (chaptersTrack) {
|
||||
@ -731,7 +765,7 @@ _V_.ChaptersButton.prototype.createMenu = function(){
|
||||
for (;i<j;i++) {
|
||||
cue = cues[i];
|
||||
|
||||
mi = new _V_.ChaptersTrackMenuItem(this.player, {
|
||||
mi = new vjs.ChaptersTrackMenuItem(this.player, {
|
||||
track: chaptersTrack,
|
||||
cue: cue
|
||||
});
|
||||
@ -756,7 +790,7 @@ _V_.ChaptersButton.prototype.createMenu = function(){
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
_V_.ChaptersTrackMenuItem = function(player, options){
|
||||
vjs.ChaptersTrackMenuItem = function(player, options){
|
||||
var track = this.track = options.track,
|
||||
cue = this.cue = options.cue,
|
||||
currentTime = player.currentTime();
|
||||
@ -766,21 +800,21 @@ _V_.ChaptersTrackMenuItem = function(player, options){
|
||||
options.selected = (cue.startTime <= currentTime && currentTime < cue.endTime);
|
||||
goog.base(this, player, options);
|
||||
|
||||
track.on("cuechange", _V_.bind(this, this.update));
|
||||
track.on("cuechange", vjs.bind(this, this.update));
|
||||
};
|
||||
goog.inherits(_V_.ChaptersTrackMenuItem, _V_.MenuItem);
|
||||
goog.inherits(vjs.ChaptersTrackMenuItem, vjs.MenuItem);
|
||||
|
||||
_V_.ChaptersTrackMenuItem.prototype.onClick = function(){
|
||||
vjs.ChaptersTrackMenuItem.prototype.onClick = function(){
|
||||
goog.base(this, 'onClick');
|
||||
this.player.currentTime(this.cue.startTime);
|
||||
this.update(this.cue.startTime);
|
||||
};
|
||||
|
||||
_V_.ChaptersTrackMenuItem.prototype.update = function(time){
|
||||
vjs.ChaptersTrackMenuItem.prototype.update = function(time){
|
||||
var cue = this.cue,
|
||||
currentTime = this.player.currentTime();
|
||||
|
||||
// _V_.log(currentTime, cue.startTime);
|
||||
// vjs.log(currentTime, cue.startTime);
|
||||
if (cue.startTime <= currentTime && currentTime < cue.endTime) {
|
||||
this.selected(true);
|
||||
} else {
|
||||
@ -789,13 +823,13 @@ _V_.ChaptersTrackMenuItem.prototype.update = function(time){
|
||||
};
|
||||
|
||||
// Add Buttons to controlBar
|
||||
_V_.merge(_V_.ControlBar.prototype.options.children, {
|
||||
vjs.merge(vjs.ControlBar.prototype.options.children, {
|
||||
"subtitlesButton": {},
|
||||
"captionsButton": {},
|
||||
"chaptersButton": {}
|
||||
});
|
||||
|
||||
// _V_.Cue = _V_.Component.extend({
|
||||
// vjs.Cue = vjs.Component.extend({
|
||||
// init: function(player, options){
|
||||
// goog.base(this, player, options);
|
||||
// }
|
||||
|
@ -87,7 +87,7 @@ _V_.flash = _V_.PlaybackTech.extend({
|
||||
// Not sure why that even works, but it causes the browser to look like it's continuously trying to load the page.
|
||||
// Firefox 3.6 keeps calling the iframe onload function anytime I write to it, causing an endless loop.
|
||||
|
||||
if (options.iFrameMode === true && !_V_.isFF) {
|
||||
if (options.iFrameMode === true && !_V_.IS_FIREFOX) {
|
||||
|
||||
// Create iFrame with vjs-tech class so it's 100% width/height
|
||||
var iFrm = _V_.createElement("iframe", {
|
||||
@ -290,8 +290,8 @@ _V_.flash.prototype.support = {
|
||||
},
|
||||
|
||||
// Optional events that we can manually mimic with timers
|
||||
progressEvent: false,
|
||||
timeupdateEvent: false,
|
||||
progressEvents: false,
|
||||
timeupdateEvents: false,
|
||||
|
||||
// Resizing plugins using request fullscreen reloads the plugin
|
||||
fullscreenResize: false,
|
||||
@ -387,7 +387,7 @@ _V_.flash.embed = function(swf, placeHolder, flashVars, params, attributes){
|
||||
|
||||
// IE6 seems to have an issue where it won't initialize the swf object after injecting it.
|
||||
// This is a dumb temporary fix
|
||||
if (_V_.isIE()) {
|
||||
if (_V_.IS_IE6to8()) {
|
||||
var newObj = par.childNodes[0];
|
||||
setTimeout(function(){
|
||||
newObj.style.display = "block";
|
||||
|
@ -253,7 +253,7 @@ _V_.vimeo.onFinish = function(id) {
|
||||
player.vimeoInfo.state = VimeoState.ENDED;
|
||||
player.triggerEvent("ended");
|
||||
_V_.vimeo.hideOverlay(player);
|
||||
|
||||
|
||||
// Vimeo looping doesn't seem to play well with VideoJS, so we need to
|
||||
// implement it manually here
|
||||
if (player.apiArgs.loop) {
|
||||
@ -300,8 +300,8 @@ _V_.vimeo.prototype.support = {
|
||||
},
|
||||
|
||||
// Optional events that we can manually mimic with timers
|
||||
progressEvent: true,
|
||||
timeupdateEvent: true,
|
||||
progressEvents: true,
|
||||
timeupdateEvents: true,
|
||||
|
||||
//fullscreen: true,
|
||||
// In iOS, if you move a video element in the DOM, it breaks video playback.
|
||||
|
@ -104,7 +104,7 @@ _V_.youtube = _V_.PlaybackTech.extend({
|
||||
|
||||
src: function(src){
|
||||
delete this.player.error;
|
||||
|
||||
|
||||
// FIXME: Does this work or do we have to set the iFrame src again?
|
||||
var videoId = this.getVideoId(src);
|
||||
this.youtube.loadVideoById(videoId);
|
||||
@ -227,7 +227,7 @@ _V_.youtube.onReady = function(e){
|
||||
player.tech.triggerReady();
|
||||
player.triggerReady();
|
||||
player.triggerEvent("durationchange");
|
||||
|
||||
|
||||
_V_.youtube.hideOverlay(player);
|
||||
};
|
||||
|
||||
@ -247,7 +247,7 @@ _V_.youtube.onStateChange = function(e){
|
||||
case YT.PlayerState.ENDED:
|
||||
player.triggerEvent("ended");
|
||||
_V_.youtube.hideOverlay(player);
|
||||
|
||||
|
||||
// YouTube looping doesn't seem to play well with VideoJS, so we need to
|
||||
// implement it manually here
|
||||
if (player.apiArgs.playerVars.loop) {
|
||||
@ -347,8 +347,8 @@ _V_.youtube.prototype.support = {
|
||||
},
|
||||
|
||||
// Optional events that we can manually mimic with timers
|
||||
progressEvent: false,
|
||||
timeupdateEvent: false,
|
||||
progressEvents: false,
|
||||
timeupdateEvents: false,
|
||||
|
||||
//fullscreen: true,
|
||||
// In iOS, if you move a video element in the DOM, it breaks video playback.
|
||||
|
Loading…
Reference in New Issue
Block a user