mirror of
https://github.com/videojs/video.js.git
synced 2025-02-04 11:43:27 +02:00
Created activateControl method for applying behaviors
Added rEvtContext for creating removable event listeners with context. Switch to top/left form holygrail for load bar positioning. Switched to relative/absolute for contorlsBelow instead of JS calculating heights. Started testing maps integration.
This commit is contained in:
parent
6a682af82c
commit
31f6fcdbd6
13
test/map/coords.srt
Executable file
13
test/map/coords.srt
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
1
|
||||||
|
00:00:02,400 --> 00:00:05,200
|
||||||
|
41.586688,-100.112915
|
||||||
|
|
||||||
|
2
|
||||||
|
00:00:15,712 --> 00:00:17,399
|
||||||
|
46.920255,3.010254
|
||||||
|
|
||||||
|
3
|
||||||
|
00:00:25,712 --> 00:00:30,399
|
||||||
|
-36.208823,-67.192383
|
||||||
|
|
||||||
|
|
91
test/map/map.html
Normal file
91
test/map/map.html
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>HTML5 Video Player</title>
|
||||||
|
|
||||||
|
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
|
||||||
|
|
||||||
|
<!-- Include the VideoJS Library -->
|
||||||
|
<script src="../../video.js" type="text/javascript" charset="utf-8"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
VideoJS.DOMReady(function(){
|
||||||
|
var myPlayer = VideoJS.setup("example_video_1", { controlsHiding: false });
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript"
|
||||||
|
src="http://maps.google.com/maps/api/js?sensor=false">
|
||||||
|
</script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
function initialize() {
|
||||||
|
var latlng = new google.maps.LatLng(-34.397, 150.644);
|
||||||
|
var myOptions = {
|
||||||
|
zoom: 8,
|
||||||
|
center: latlng,
|
||||||
|
disableDefaultUI: true,
|
||||||
|
mapTypeId: google.maps.MapTypeId.ROADMAP
|
||||||
|
};
|
||||||
|
var map = new google.maps.Map(document.getElementById("map_canvas"),
|
||||||
|
myOptions);
|
||||||
|
|
||||||
|
setTimeout(function() { map.panTo(new google.maps.LatLng(37.4419, -122.1419), 13) }, 2000)
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
html { height: 100% }
|
||||||
|
body { height: 100%; margin: 0px; padding: 0px }
|
||||||
|
#map_canvas { height: 100%; position: absolute; top: 0; left: 0; }
|
||||||
|
|
||||||
|
.video-js-box { position: absolute; top: 50%; left: 50%; z-index: 1; margin: -132px 0 0 -320px; }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style type="text/css" media="screen">
|
||||||
|
#attributes { width: 300px; float: left; }
|
||||||
|
#events { width: 300px; height: 500px; float: left; }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- Include the VideoJS Stylesheet -->
|
||||||
|
<link rel="stylesheet" href="../../video-js.css" type="text/css" media="screen" title="Video JS">
|
||||||
|
<link rel="stylesheet" href="../skins/tube.css" type="text/css" media="screen" title="Video JS">
|
||||||
|
<link rel="stylesheet" href="../skins/hu.css" type="text/css" media="screen" title="Video JS">
|
||||||
|
<link rel="stylesheet" href="../skins/vim.css" type="text/css" media="screen" title="Video JS">
|
||||||
|
</head>
|
||||||
|
<body onload="initialize()">
|
||||||
|
|
||||||
|
<!-- Begin VideoJS -->
|
||||||
|
<div class="video-js-box">
|
||||||
|
<!-- Using the Video for Everybody Embed Code http://camendesign.com/code/video_for_everybody -->
|
||||||
|
<video data-subtitles="../demo-subtitles.srt" id="example_video_1" class="video-js" width="640" height="264" controls="controls" preload="auto" poster="http://video-js.zencoder.com/oceans-clip.png">
|
||||||
|
<source src="http://video-js.zencoder.com/oceans-clip.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' />
|
||||||
|
<source src="http://video-js.zencoder.com/oceans-clip.webm" type='video/webm; codecs="vp8, vorbis"' />
|
||||||
|
<source src="http://video-js.zencoder.com/oceans-clip.ogv" type='video/ogg; codecs="theora, vorbis"' />
|
||||||
|
<!-- Flash Fallback. Use any flash video player here. Make sure to keep the vjs-flash-fallback class. -->
|
||||||
|
<object id="flash_fallback_1" class="vjs-flash-fallback" width="640" height="264" type="application/x-shockwave-flash"
|
||||||
|
data="http://releases.flowplayer.org/swf/flowplayer-3.2.1.swf">
|
||||||
|
<param name="movie" value="http://releases.flowplayer.org/swf/flowplayer-3.2.1.swf" />
|
||||||
|
<param name="allowfullscreen" value="true" />
|
||||||
|
<param name="flashvars" value='config={"playlist":["http://video-js.zencoder.com/oceans-clip.png", {"url": "http://video-js.zencoder.com/oceans-clip.mp4","autoPlay":false,"autoBuffering":true}]}' />
|
||||||
|
<!-- Image Fallback. Typically the same as the poster image. -->
|
||||||
|
<img src="http://video-js.zencoder.com/oceans-clip.png" width="640" height="264" alt="Poster Image"
|
||||||
|
title="No video playback capabilities." />
|
||||||
|
</object>
|
||||||
|
</video>
|
||||||
|
<!-- Download links provided for devices that can't play video in the browser. -->
|
||||||
|
<p class="vjs-no-video"><strong>Download Video:</strong>
|
||||||
|
<a href="http://video-js.zencoder.com/oceans-clip.mp4">MP4</a>,
|
||||||
|
<a href="http://video-js.zencoder.com/oceans-clip.webm">WebM</a>,
|
||||||
|
<a href="http://video-js.zencoder.com/oceans-clip.ogv">Ogg</a><br>
|
||||||
|
<!-- Support VideoJS by keeping this link. -->
|
||||||
|
<a href="http://videojs.com">HTML5 Video Player</a> by VideoJS
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<!-- End VideoJS -->
|
||||||
|
|
||||||
|
<div id="map_canvas" style="width:100%; height:100%"></div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -4,13 +4,12 @@
|
|||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<title>HTML5 Video Player</title>
|
<title>HTML5 Video Player</title>
|
||||||
|
|
||||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
|
|
||||||
|
|
||||||
<!-- Include the VideoJS Library -->
|
<!-- Include the VideoJS Library -->
|
||||||
<script src="../video.js" type="text/javascript" charset="utf-8"></script>
|
<script src="../video.js" type="text/javascript" charset="utf-8"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
VideoJS.DOMReady(function(){
|
VideoJS.DOMReady(function(){
|
||||||
var myPlayer = VideoJS.setup("example_video_1", { controlsHiding: false });
|
var myPlayer = VideoJS.setup("example_video_1", { controlsHiding: false, controlsBelow: true, showControlsAtStart: true });
|
||||||
|
myPlayer.activateControl(document.getElementById("scrub"), "loadProgressBar");
|
||||||
var vid = document.getElementById("example_video_1"),
|
var vid = document.getElementById("example_video_1"),
|
||||||
attrTable = document.getElementById("attributes"),
|
attrTable = document.getElementById("attributes"),
|
||||||
attrNames = ["error", "networkState", "readyState", "preload", "buffered",
|
attrNames = ["error", "networkState", "readyState", "preload", "buffered",
|
||||||
@ -66,6 +65,7 @@
|
|||||||
<body>
|
<body>
|
||||||
|
|
||||||
<!-- Begin VideoJS -->
|
<!-- Begin VideoJS -->
|
||||||
|
<div id="scrub" style="background: #000; height: 10px;"></div>
|
||||||
<div class="video-js-box">
|
<div class="video-js-box">
|
||||||
<!-- Using the Video for Everybody Embed Code http://camendesign.com/code/video_for_everybody -->
|
<!-- Using the Video for Everybody Embed Code http://camendesign.com/code/video_for_everybody -->
|
||||||
<video data-subtitles="../demo-subtitles.srt" id="example_video_1" class="video-js" width="640" height="264" controls="controls" preload="auto" poster="http://video-js.zencoder.com/oceans-clip.png">
|
<video data-subtitles="../demo-subtitles.srt" id="example_video_1" class="video-js" width="640" height="264" controls="controls" preload="auto" poster="http://video-js.zencoder.com/oceans-clip.png">
|
||||||
|
18
video-js.css
18
video-js.css
@ -10,7 +10,7 @@ REQUIRED STYLES (be careful overriding)
|
|||||||
.video-js-box { text-align: left; position: relative; vertical-align: bottom; } /* Will be set to the width of the video element */
|
.video-js-box { text-align: left; position: relative; vertical-align: bottom; } /* Will be set to the width of the video element */
|
||||||
|
|
||||||
/* Video Element */
|
/* Video Element */
|
||||||
video.video-js { background-color: #000; position: relative; }
|
video.video-js { background-color: #000; position: relative; margin: 0 0 -1px 0; /* Firefox gap */ padding: 0; }
|
||||||
|
|
||||||
/* Poster Style */
|
/* Poster Style */
|
||||||
.video-js-box img.vjs-poster { display: block; position: absolute; left: 0; top: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
|
.video-js-box img.vjs-poster { display: block; position: absolute; left: 0; top: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
|
||||||
@ -19,7 +19,7 @@ video.video-js { background-color: #000; position: relative; }
|
|||||||
|
|
||||||
/* Fullscreen styles for main elements */
|
/* Fullscreen styles for main elements */
|
||||||
.video-js-box.vjs-fullscreen { position: fixed; left: 0; top: 0; right: 0; bottom: 0; overflow: hidden; z-index: 1000; }
|
.video-js-box.vjs-fullscreen { position: fixed; left: 0; top: 0; right: 0; bottom: 0; overflow: hidden; z-index: 1000; }
|
||||||
.video-js-box.vjs-fullscreen video.video-js { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 1000; }
|
.video-js-box.vjs-fullscreen video.video-js { position: relative; top: 0; left: 0; width: 100%; height: 100%; z-index: 1000; }
|
||||||
.video-js-box.vjs-fullscreen img.vjs-poster { z-index: 1001; }
|
.video-js-box.vjs-fullscreen img.vjs-poster { z-index: 1001; }
|
||||||
.video-js-box.vjs-fullscreen .vjs-spinner { z-index: 1001; }
|
.video-js-box.vjs-fullscreen .vjs-spinner { z-index: 1001; }
|
||||||
.video-js-box.vjs-fullscreen .vjs-controls { z-index: 1003; }
|
.video-js-box.vjs-fullscreen .vjs-controls { z-index: 1003; }
|
||||||
@ -36,24 +36,22 @@ Instead of editing this file, I recommend creating your own skin CSS file to be
|
|||||||
so you can upgrade to newer versions easier. */
|
so you can upgrade to newer versions easier. */
|
||||||
|
|
||||||
/* Controls Layout
|
/* Controls Layout
|
||||||
Using a Holy Grail type method to allow the progress bar holder to expand into all available space,
|
Using absolute positioning to position controls */
|
||||||
but using abosolute positioning for individual controls. http://www.alistapart.com/articles/holygrail */
|
|
||||||
.video-js-box .vjs-controls {
|
.video-js-box .vjs-controls {
|
||||||
position: absolute; margin: 0; border: none; opacity: 0.85; color: #fff;
|
position: absolute; margin: 0; border: none; opacity: 0.85; color: #fff;
|
||||||
display: none; /* Start hidden */
|
display: none; /* Start hidden */
|
||||||
left: 0; right: 0; /* 100% width of video-js-box */
|
left: 0; right: 0; /* 100% width of video-js-box */
|
||||||
|
bottom: 5px;
|
||||||
height: 35px; /* Including any margin you want above or below control items */
|
height: 35px; /* Including any margin you want above or below control items */
|
||||||
padding-left: 35px; /* Width of play button + margin */
|
|
||||||
padding-right: 165px; /* Width of all the controls to the right of the progress control + margins */
|
|
||||||
padding-top: 0; padding-bottom: 0;
|
padding-top: 0; padding-bottom: 0;
|
||||||
}
|
}
|
||||||
/* Controls styles when below the video */
|
/* Controls styles when below the video */
|
||||||
.video-js-box.vjs-controls-below .vjs-controls { background-color: #000; }
|
.video-js-box.vjs-controls-below .vjs-controls { position: relative; opacity: 1; background-color: #000; }
|
||||||
|
|
||||||
.video-js-box .vjs-controls > div { /* Direct div children of control bar */
|
.video-js-box .vjs-controls > div { /* Direct div children of control bar */
|
||||||
position: absolute; float: left; padding: 0; text-align: center;
|
position: absolute; padding: 0; text-align: center;
|
||||||
height: 25px; /* Default height of individual controls */
|
height: 25px; /* Default height of individual controls */
|
||||||
margin: 5px 0 0 0; /* Top margin to put space between video and controls when controls are below */
|
margin: 0; top: 5px; /* Top margin to put space between video and controls when controls are below */
|
||||||
|
|
||||||
/* CSS Background Gradients */
|
/* CSS Background Gradients */
|
||||||
/* Default */ background-color: #0B151A;
|
/* Default */ background-color: #0B151A;
|
||||||
@ -69,7 +67,7 @@ so you can upgrade to newer versions easier. */
|
|||||||
|
|
||||||
/* Placement of Control Items */
|
/* Placement of Control Items */
|
||||||
.vjs-controls > div.vjs-play-control { width: 25px; left: 5px; }
|
.vjs-controls > div.vjs-play-control { width: 25px; left: 5px; }
|
||||||
.vjs-controls > div.vjs-progress-control { width: 100%; position: relative; }
|
.vjs-controls > div.vjs-progress-control { left: 35px; right: 165px; } /* Using left & right so it expands with the width of the video */
|
||||||
.vjs-controls > div.vjs-time-control { width: 75px; right: 90px; } /* Time control and progress bar are combined to look like one */
|
.vjs-controls > div.vjs-time-control { width: 75px; right: 90px; } /* Time control and progress bar are combined to look like one */
|
||||||
.vjs-controls > div.vjs-volume-control { width: 50px; right: 35px; }
|
.vjs-controls > div.vjs-volume-control { width: 50px; right: 35px; }
|
||||||
.vjs-controls > div.vjs-fullscreen-control { width: 25px; right: 5px; }
|
.vjs-controls > div.vjs-fullscreen-control { width: 25px; right: 5px; }
|
||||||
|
483
video.js
483
video.js
@ -21,8 +21,12 @@ along with VideoJS. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
// Using jresig's Class implementation http://ejohn.org/blog/simple-javascript-inheritance/
|
// Using jresig's Class implementation http://ejohn.org/blog/simple-javascript-inheritance/
|
||||||
(function(){var initializing=false, fnTest=/xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/; this.JRClass = function(){}; JRClass.extend = function(prop) { var _super = this.prototype; initializing = true; var prototype = new this(); initializing = false; for (var name in prop) { prototype[name] = typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name]) ? (function(name, fn){ return function() { var tmp = this._super; this._super = _super[name]; var ret = fn.apply(this, arguments); this._super = tmp; return ret; }; })(name, prop[name]) : prop[name]; } function JRClass() { if ( !initializing && this.init ) this.init.apply(this, arguments); } JRClass.prototype = prototype; JRClass.constructor = JRClass; JRClass.extend = arguments.callee; return JRClass;};})();
|
(function(){var initializing=false, fnTest=/xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/; this.JRClass = function(){}; JRClass.extend = function(prop) { var _super = this.prototype; initializing = true; var prototype = new this(); initializing = false; for (var name in prop) { prototype[name] = typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name]) ? (function(name, fn){ return function() { var tmp = this._super; this._super = _super[name]; var ret = fn.apply(this, arguments); this._super = tmp; return ret; }; })(name, prop[name]) : prop[name]; } function JRClass() { if ( !initializing && this.init ) this.init.apply(this, arguments); } JRClass.prototype = prototype; JRClass.constructor = JRClass; JRClass.extend = arguments.callee; return JRClass;};})();
|
||||||
|
|
||||||
|
// Self-executing function to prevent global vars and help with minification
|
||||||
|
(function(window, undefined){
|
||||||
|
var document = window.document;
|
||||||
|
|
||||||
// Video JS Player Class
|
// Video JS Player Class
|
||||||
var VideoJS = JRClass.extend({
|
var VideoJS = _V_ = JRClass.extend({
|
||||||
|
|
||||||
// Initialize the player for the supplied video tag element
|
// Initialize the player for the supplied video tag element
|
||||||
// element: video tag
|
// element: video tag
|
||||||
@ -73,7 +77,8 @@ var VideoJS = JRClass.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
html5Init: function(){
|
html5Init: function(){
|
||||||
this.fixPreloading();
|
this.fixPreloading(); // Support old browsers that used autobuffer
|
||||||
|
this.percentLoaded = 0; // Store amount of video loaded
|
||||||
|
|
||||||
if (VideoJS.isIOS()) {
|
if (VideoJS.isIOS()) {
|
||||||
this.options.useBuiltInControls = true;
|
this.options.useBuiltInControls = true;
|
||||||
@ -90,7 +95,6 @@ var VideoJS = JRClass.extend({
|
|||||||
this.video.controls = false;
|
this.video.controls = false;
|
||||||
|
|
||||||
if (this.options.controlsBelow) { _V_.addClass(this.box, "vjs-controls-below"); }
|
if (this.options.controlsBelow) { _V_.addClass(this.box, "vjs-controls-below"); }
|
||||||
this.percentLoaded = 0; // Store amount of video loaded
|
|
||||||
|
|
||||||
// Build Interface
|
// Build Interface
|
||||||
this.buildStylesCheckDiv(); // Used to check if style are loaded
|
this.buildStylesCheckDiv(); // Used to check if style are loaded
|
||||||
@ -107,12 +111,6 @@ var VideoJS = JRClass.extend({
|
|||||||
// They are also temporary, which means they need to be removed.
|
// They are also temporary, which means they need to be removed.
|
||||||
// They also need context (this) so they can call functions on their specific player.
|
// They also need context (this) so they can call functions on their specific player.
|
||||||
// Adding context on initialization allows us to store a reference to them and remove them later.
|
// Adding context on initialization allows us to store a reference to them and remove them later.
|
||||||
this.onEscKey = this.onEscKey.context(this);
|
|
||||||
this.onWindowResize = this.onWindowResize.context(this);
|
|
||||||
this.onProgressMouseMove = this.onProgressMouseMove.context(this);
|
|
||||||
this.onProgressMouseUp = this.onProgressMouseUp.context(this);
|
|
||||||
this.onVolumeMouseMove = this.onVolumeMouseMove.context(this);
|
|
||||||
this.onVolumeMouseUp = this.onVolumeMouseUp.context(this);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -164,7 +162,7 @@ var VideoJS = JRClass.extend({
|
|||||||
// Don't want to create an endless loop either.
|
// Don't want to create an endless loop either.
|
||||||
if (!this.positionRetries) { this.positionRetries = 1; }
|
if (!this.positionRetries) { this.positionRetries = 1; }
|
||||||
if (this.positionRetries++ < 100) {
|
if (this.positionRetries++ < 100) {
|
||||||
setTimeout(this.loadInterface.context(this),0);
|
setTimeout(this.loadInterface.context(this),10);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -194,7 +192,7 @@ var VideoJS = JRClass.extend({
|
|||||||
this.box.style.width = this.video.offsetWidth + "px";
|
this.box.style.width = this.video.offsetWidth + "px";
|
||||||
if (this.options.controlsBelow) {
|
if (this.options.controlsBelow) {
|
||||||
this.video.style.height = "";
|
this.video.style.height = "";
|
||||||
this.box.style.height = this.video.offsetHeight + this.controls.offsetHeight + "px";
|
// this.box.style.height = this.video.offsetHeight + this.controls.offsetHeight + "px";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -287,6 +285,7 @@ var VideoJS = JRClass.extend({
|
|||||||
|
|
||||||
this.activateControls();
|
this.activateControls();
|
||||||
},
|
},
|
||||||
|
|
||||||
// Set up Event Listeners
|
// Set up Event Listeners
|
||||||
activateControls: function(){
|
activateControls: function(){
|
||||||
/* Activate Errors
|
/* Activate Errors
|
||||||
@ -302,16 +301,14 @@ var VideoJS = JRClass.extend({
|
|||||||
// Listen for when the video ends
|
// Listen for when the video ends
|
||||||
this.video.addEventListener("ended", this.onEnded.context(this), false);
|
this.video.addEventListener("ended", this.onEnded.context(this), false);
|
||||||
// Listen for clicks on the play/pause button
|
// Listen for clicks on the play/pause button
|
||||||
this.activateAsPlayPauseButton(this.playControl);
|
this.activateControl(this.playControl, "playToggle");
|
||||||
// Make a click on the video act like a click on the play button.
|
// Make a click on the video act like a click on the play button.
|
||||||
this.activateAsPlayPauseButton(this.video);
|
this.activateControl(this.video, "playToggle");
|
||||||
|
|
||||||
/* Activate Play Progress
|
/* Activate Play Progress
|
||||||
================================================================================ */
|
================================================================================ */
|
||||||
// Listen for drags on the progress bar
|
// Listen for drags on the progress bar
|
||||||
this.progressHolder.addEventListener("mousedown", this.onProgressHolderMouseDown.context(this), false);
|
this.activateControl(this.progressHolder, "timelineScrubber");
|
||||||
// Listen for a release on the progress bar
|
|
||||||
this.progressHolder.addEventListener("mouseup", this.onProgressHolderMouseUp.context(this), false);
|
|
||||||
|
|
||||||
/* Activate Buffering Progress
|
/* Activate Buffering Progress
|
||||||
================================================================================ */
|
================================================================================ */
|
||||||
@ -319,6 +316,8 @@ var VideoJS = JRClass.extend({
|
|||||||
this.video.addEventListener('progress', this.onProgress.context(this), false);
|
this.video.addEventListener('progress', this.onProgress.context(this), false);
|
||||||
// Set interval for load progress using buffer watching method
|
// Set interval for load progress using buffer watching method
|
||||||
this.watchBuffer = setInterval(this.updateBufferedTotal.context(this), 33);
|
this.watchBuffer = setInterval(this.updateBufferedTotal.context(this), 33);
|
||||||
|
this.activateControl(this.loadProgress, "loadProgressBar");
|
||||||
|
|
||||||
|
|
||||||
/* Activate Volume
|
/* Activate Volume
|
||||||
================================================================================ */
|
================================================================================ */
|
||||||
@ -328,15 +327,12 @@ var VideoJS = JRClass.extend({
|
|||||||
this.updateVolumeDisplay();
|
this.updateVolumeDisplay();
|
||||||
// Listen for a volume change
|
// Listen for a volume change
|
||||||
this.video.addEventListener('volumechange',this.onVolumeChange.context(this),false);
|
this.video.addEventListener('volumechange',this.onVolumeChange.context(this),false);
|
||||||
// Listen for a drag on the volume control
|
this.activateControl(this.volumeControl, "volumeScrubber");
|
||||||
this.volumeControl.addEventListener("mousedown", this.onVolumeControlMouseDown.context(this), false);
|
|
||||||
// Listen for a release on the volume control
|
|
||||||
this.volumeControl.addEventListener("mouseup", this.onVolumeControlMouseUp.context(this), false);
|
|
||||||
|
|
||||||
/* Activate Fullscreen
|
/* Activate Fullscreen
|
||||||
================================================================================ */
|
================================================================================ */
|
||||||
// Listen for clicks on the button
|
// Listen for clicks on the button
|
||||||
this.fullscreenControl.addEventListener("click", this.onFullscreenControlClick.context(this), false);
|
this.activateControl(this.fullscreenControl, "fullscreenToggle")
|
||||||
|
|
||||||
/* Activate Controls Movement
|
/* Activate Controls Movement
|
||||||
================================================================================ */
|
================================================================================ */
|
||||||
@ -359,11 +355,11 @@ var VideoJS = JRClass.extend({
|
|||||||
// Make sure the controls are visible
|
// Make sure the controls are visible
|
||||||
if (this.controls.style.display == 'none') { return; }
|
if (this.controls.style.display == 'none') { return; }
|
||||||
|
|
||||||
if (this.options.controlsBelow) {
|
// if (this.options.controlsBelow) {
|
||||||
this.controls.style.top = this.video.offsetHeight + "px";
|
// this.controls.style.top = this.video.offsetHeight + "px";
|
||||||
} else {
|
// } else {
|
||||||
this.controls.style.top = (this.video.offsetHeight - this.controls.offsetHeight) + "px";
|
// this.controls.style.top = (this.video.offsetHeight - this.controls.offsetHeight) + "px";
|
||||||
}
|
// }
|
||||||
this.updatePlayProgress();
|
this.updatePlayProgress();
|
||||||
this.updateLoadProgress();
|
this.updateLoadProgress();
|
||||||
},
|
},
|
||||||
@ -382,7 +378,7 @@ var VideoJS = JRClass.extend({
|
|||||||
onVideoMouseMove: function(){
|
onVideoMouseMove: function(){
|
||||||
this.showControlBar();
|
this.showControlBar();
|
||||||
clearInterval(this.mouseMoveTimeout);
|
clearInterval(this.mouseMoveTimeout);
|
||||||
this.mouseMoveTimeout = setTimeout(function(){ this.hideControlBar(); }.context(this), 4000);
|
this.mouseMoveTimeout = setTimeout(this.hideControlBar.context(this), 4000);
|
||||||
},
|
},
|
||||||
onVideoMouseOut: function(event){
|
onVideoMouseOut: function(event){
|
||||||
// Prevent flicker by making sure mouse hasn't left the video
|
// Prevent flicker by making sure mouse hasn't left the video
|
||||||
@ -407,12 +403,35 @@ var VideoJS = JRClass.extend({
|
|||||||
|
|
||||||
/* Play/Pause
|
/* Play/Pause
|
||||||
================================================================================ */
|
================================================================================ */
|
||||||
activateAsPlayPauseButton: function(element){
|
behaviors: {
|
||||||
|
playToggle: function(element){
|
||||||
element.addEventListener("click", this.onPlayControlClick.context(this), false);
|
element.addEventListener("click", this.onPlayControlClick.context(this), false);
|
||||||
},
|
},
|
||||||
activateAsPlayButton: function(element){
|
playButton: function(element){
|
||||||
element.addEventListener("click", this.onPlayButtonClick.context(this), false);
|
element.addEventListener("click", this.onPlayButtonClick.context(this), false);
|
||||||
},
|
},
|
||||||
|
pauseButton: function(element){
|
||||||
|
element.addEventListener("click", this.onPauseButtonClick.context(this), false);
|
||||||
|
},
|
||||||
|
timelineScrubber: function(element){
|
||||||
|
var player = this;
|
||||||
|
element.addEventListener("mousedown", this.onTimelineScrubberMouseDown.rEvtContext(this), false);
|
||||||
|
},
|
||||||
|
volumeScrubber: function(element){
|
||||||
|
element.addEventListener("mousedown", this.onVolumeScrubberMouseDown.rEvtContext(this), false);
|
||||||
|
},
|
||||||
|
fullscreenToggle: function(element){
|
||||||
|
element.addEventListener("click", this.onFullscreenToggleClick.context(this), false);
|
||||||
|
},
|
||||||
|
loadProgressBar: function(element){
|
||||||
|
if (!this.loadProgressBars) { this.loadProgressBars = []; }
|
||||||
|
this.loadProgressBars.push(element);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
activateControl: function(element, behavior){
|
||||||
|
this.behaviors[behavior].call(this, element);
|
||||||
|
},
|
||||||
|
|
||||||
// React to clicks on the play/pause button
|
// React to clicks on the play/pause button
|
||||||
onPlayControlClick: function(event){
|
onPlayControlClick: function(event){
|
||||||
@ -448,7 +467,7 @@ var VideoJS = JRClass.extend({
|
|||||||
// Track & display the current play progress
|
// Track & display the current play progress
|
||||||
trackPlayProgress: function(){
|
trackPlayProgress: function(){
|
||||||
if(this.playProgressInterval) { clearInterval(this.playProgressInterval); }
|
if(this.playProgressInterval) { clearInterval(this.playProgressInterval); }
|
||||||
this.playProgressInterval = setInterval(function(){ this.updatePlayProgress(); }.context(this), 33);
|
this.playProgressInterval = setInterval(this.updatePlayProgress.context(this), 33);
|
||||||
},
|
},
|
||||||
// Turn off play progress tracking (when paused)
|
// Turn off play progress tracking (when paused)
|
||||||
stopTrackingPlayProgress: function(){ clearInterval(this.playProgressInterval); },
|
stopTrackingPlayProgress: function(){ clearInterval(this.playProgressInterval); },
|
||||||
@ -469,50 +488,37 @@ var VideoJS = JRClass.extend({
|
|||||||
// currentTime changed, reset subtitles
|
// currentTime changed, reset subtitles
|
||||||
if (!this.subtitles) { this.currentSubtitlePosition = 0; }
|
if (!this.subtitles) { this.currentSubtitlePosition = 0; }
|
||||||
},
|
},
|
||||||
setPlayProgressWithEvent: function(event){
|
setPlayProgressWithScrubber: function(event){
|
||||||
var newProgress = _V_.getRelativePosition(event.pageX, this.progressHolder);
|
var newProgress = _V_.getRelativePosition(event.pageX, this.currentScrubber);
|
||||||
this.setPlayProgress(newProgress);
|
this.setPlayProgress(newProgress);
|
||||||
},
|
},
|
||||||
// Adjust the play position when the user drags on the progress bar
|
// Adjust the play position when the user drags on the progress bar
|
||||||
onProgressHolderMouseDown: function(event){
|
onTimelineScrubberMouseDown: function(event, scrubber){
|
||||||
|
event.preventDefault();
|
||||||
|
this.currentScrubber = scrubber;
|
||||||
|
|
||||||
this.stopTrackingPlayProgress();
|
this.stopTrackingPlayProgress();
|
||||||
|
|
||||||
if (this.video.paused) {
|
this.videoWasPlaying = !this.video.paused;
|
||||||
this.videoWasPlaying = false;
|
|
||||||
} else {
|
|
||||||
this.videoWasPlaying = true;
|
|
||||||
this.video.pause();
|
this.video.pause();
|
||||||
}
|
|
||||||
_V_.blockTextSelection();
|
_V_.blockTextSelection();
|
||||||
this.setPlayProgressWithEvent(event);
|
this.setPlayProgressWithScrubber(event);
|
||||||
document.addEventListener("mousemove", this.onProgressMouseMove, false);
|
document.addEventListener("mousemove", this.onTimelineScrubberMouseMove.rEvtContext(this), false);
|
||||||
document.addEventListener("mouseup", this.onProgressMouseUp, false);
|
document.addEventListener("mouseup", this.onTimelineScrubberMouseUp.rEvtContext(this), false);
|
||||||
},
|
},
|
||||||
onProgressMouseMove: function(event){ // Removeable
|
onTimelineScrubberMouseMove: function(event){ // Removeable
|
||||||
this.setPlayProgressWithEvent(event);
|
this.setPlayProgressWithScrubber(event);
|
||||||
},
|
},
|
||||||
onProgressMouseUp: function(event){ // Removeable
|
onTimelineScrubberMouseUp: function(event){ // Removeable
|
||||||
_V_.unblockTextSelection();
|
_V_.unblockTextSelection();
|
||||||
document.removeEventListener("mousemove", this.onProgressMouseMove, false);
|
document.removeEventListener("mousemove", this.onTimelineScrubberMouseMove, false);
|
||||||
document.removeEventListener("mouseup", this.onProgressMouseUp, false);
|
document.removeEventListener("mouseup", this.onTimelineScrubberMouseUp, false);
|
||||||
if (this.videoWasPlaying) {
|
if (this.videoWasPlaying) {
|
||||||
this.video.play();
|
this.video.play();
|
||||||
this.trackPlayProgress();
|
this.trackPlayProgress();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// When the user stops dragging on the progress bar, update play position
|
|
||||||
// Backup for when the user only clicks and doesn't drag
|
|
||||||
onProgressHolderMouseUp: function(event){
|
|
||||||
// Removed. Chrome breaks (shows poster, plays audio) if you set currentTime rapidly.
|
|
||||||
// this.setPlayProgressWithEvent(event);
|
|
||||||
|
|
||||||
// Fix for a play button state issue.
|
|
||||||
if (this.video.paused) {
|
|
||||||
this.onPause();
|
|
||||||
} else {
|
|
||||||
this.onPlay();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Update the displayed time (00:00)
|
// Update the displayed time (00:00)
|
||||||
updateTimeDisplay: function(){
|
updateTimeDisplay: function(){
|
||||||
@ -550,33 +556,34 @@ var VideoJS = JRClass.extend({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
updateLoadProgress: function(){
|
updateLoadProgress: function(){
|
||||||
if (this.controls.style.display == 'none') { return; }
|
for (var i=0,bars=this.loadProgressBars,j=bars.length; i<j; i++) {
|
||||||
this.loadProgress.style.width = (this.percentLoaded * (_V_.getComputedStyleValue(this.progressHolder, "width").replace("px", ""))) + "px";
|
if (bars[i].style) { bars[i].style.width = parseInt(this.percentLoaded * 100) + "%"; }
|
||||||
|
}
|
||||||
|
// this.loadProgress.style.width = (this.percentLoaded * (_V_.getComputedStyleValue(this.progressHolder, "width").replace("px", ""))) + "px";
|
||||||
},
|
},
|
||||||
|
|
||||||
/* Volume
|
/* Volume
|
||||||
================================================================================ */
|
================================================================================ */
|
||||||
onVolumeChange: function(event){ this.updateVolumeDisplay(); },
|
onVolumeChange: function(event){ this.updateVolumeDisplay(); },
|
||||||
// Adjust the volume when the user drags on the volume control
|
// Adjust the volume when the user drags on the volume control
|
||||||
onVolumeControlMouseDown: function(event){
|
onVolumeScrubberMouseDown: function(event, scrubber){
|
||||||
|
event.preventDefault();
|
||||||
|
this.currentScrubber = scrubber;
|
||||||
_V_.blockTextSelection();
|
_V_.blockTextSelection();
|
||||||
this.setVolumeWithEvent(event);
|
this.setVolumeWithScrubber(event);
|
||||||
document.addEventListener("mousemove", this.onVolumeMouseMove, false);
|
document.addEventListener("mousemove", this.onVolumeScrubberMouseMove.rEvtContext(this), false);
|
||||||
document.addEventListener("mouseup", this.onVolumeMouseUp, false);
|
document.addEventListener("mouseup", this.onVolumeScrubberMouseUp.rEvtContext(this), false);
|
||||||
},
|
},
|
||||||
onVolumeMouseMove: function(event){
|
onVolumeScrubberMouseMove: function(event){ this.setVolumeWithScrubber(event); },
|
||||||
this.setVolumeWithEvent(event);
|
onVolumeScrubberMouseUp: function(event){
|
||||||
},
|
|
||||||
onVolumeMouseUp: function(event){
|
|
||||||
_V_.unblockTextSelection();
|
_V_.unblockTextSelection();
|
||||||
document.removeEventListener("mousemove", this.onVolumeMouseMove, false);
|
document.removeEventListener("mousemove", this.onVolumeScrubberMouseMove, false);
|
||||||
document.removeEventListener("mouseup", this.onVolumeMouseUp, false);
|
document.removeEventListener("mouseup", this.onVolumeScrubberMouseUp, false);
|
||||||
|
this.setVolumeWithScrubber(event);
|
||||||
},
|
},
|
||||||
// When the user stops dragging, set a new volume
|
// When the user stops dragging, set a new volume
|
||||||
// Backup for when the user only clicks and doesn't drag
|
// Backup for when the user only clicks and doesn't drag
|
||||||
onVolumeControlMouseUp: function(event){
|
// onVolumeControlMouseUp: function(event){ this.setVolumeWithScrubber(event); },
|
||||||
this.setVolumeWithEvent(event);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Set a new volume based on where the user clicked on the volume control
|
// Set a new volume based on where the user clicked on the volume control
|
||||||
setVolume: function(newVol){
|
setVolume: function(newVol){
|
||||||
@ -584,8 +591,8 @@ var VideoJS = JRClass.extend({
|
|||||||
this.setLocalStorage("volume", this.video.volume);
|
this.setLocalStorage("volume", this.video.volume);
|
||||||
},
|
},
|
||||||
|
|
||||||
setVolumeWithEvent: function(event){
|
setVolumeWithScrubber: function(event){
|
||||||
var newVol = _V_.getRelativePosition(event.pageX, this.volumeControl.children[0]);
|
var newVol = _V_.getRelativePosition(event.pageX, this.currentScrubber);
|
||||||
this.setVolume(newVol);
|
this.setVolume(newVol);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -605,7 +612,7 @@ var VideoJS = JRClass.extend({
|
|||||||
/* Fullscreen / Full-window
|
/* Fullscreen / Full-window
|
||||||
================================================================================ */
|
================================================================================ */
|
||||||
// When the user clicks on the fullscreen button, update fullscreen setting
|
// When the user clicks on the fullscreen button, update fullscreen setting
|
||||||
onFullscreenControlClick: function(event){
|
onFullscreenToggleClick: function(event){
|
||||||
if (!this.videoIsFullScreen) {
|
if (!this.videoIsFullScreen) {
|
||||||
this.fullscreenOn();
|
this.fullscreenOn();
|
||||||
} else {
|
} else {
|
||||||
@ -620,9 +627,9 @@ var VideoJS = JRClass.extend({
|
|||||||
// Storing original doc overflow value to return to when fullscreen is off
|
// Storing original doc overflow value to return to when fullscreen is off
|
||||||
this.docOrigOverflow = document.documentElement.style.overflow;
|
this.docOrigOverflow = document.documentElement.style.overflow;
|
||||||
// Add listener for esc key to exit fullscreen
|
// Add listener for esc key to exit fullscreen
|
||||||
document.addEventListener("keydown", this.onEscKey, false);
|
document.addEventListener("keydown", this.onEscKey.rEvtContext(this), false);
|
||||||
// Add listener for a window resize
|
// Add listener for a window resize
|
||||||
window.addEventListener("resize", this.onWindowResize, false);
|
window.addEventListener("resize", this.onWindowResize.rEvtContext(this), false);
|
||||||
// Hide any scroll bars
|
// Hide any scroll bars
|
||||||
document.documentElement.style.overflow = 'hidden';
|
document.documentElement.style.overflow = 'hidden';
|
||||||
// Apply fullscreen styles
|
// Apply fullscreen styles
|
||||||
@ -684,7 +691,7 @@ var VideoJS = JRClass.extend({
|
|||||||
this.video.parentNode.appendChild(this.bigPlayButton);
|
this.video.parentNode.appendChild(this.bigPlayButton);
|
||||||
},
|
},
|
||||||
activateBigPlayButton: function(){
|
activateBigPlayButton: function(){
|
||||||
this.activateAsPlayPauseButton(this.bigPlayButton);
|
this.activateControl(this.bigPlayButton, "playToggle");
|
||||||
this.video.addEventListener("play", this.bigPlayButtonOnPlay.context(this), false);
|
this.video.addEventListener("play", this.bigPlayButtonOnPlay.context(this), false);
|
||||||
this.video.addEventListener("ended", this.bigPlayButtonOnEnded.context(this), false);
|
this.video.addEventListener("ended", this.bigPlayButtonOnEnded.context(this), false);
|
||||||
},
|
},
|
||||||
@ -719,7 +726,7 @@ var VideoJS = JRClass.extend({
|
|||||||
showSpinner: function(){
|
showSpinner: function(){
|
||||||
this.spinner.style.display = "block";
|
this.spinner.style.display = "block";
|
||||||
clearInterval(this.spinnerInterval);
|
clearInterval(this.spinnerInterval);
|
||||||
this.spinnerInterval = setInterval(function(){ this.rotateSpinner(); }.context(this), 100);
|
this.spinnerInterval = setInterval(this.rotateSpinner.context(this), 100);
|
||||||
},
|
},
|
||||||
hideSpinner: function(){
|
hideSpinner: function(){
|
||||||
this.spinner.style.display = "none";
|
this.spinner.style.display = "none";
|
||||||
@ -795,7 +802,7 @@ var VideoJS = JRClass.extend({
|
|||||||
// Listen for the mouse moving out of the poster image. Used to hide the controller.
|
// Listen for the mouse moving out of the poster image. Used to hide the controller.
|
||||||
this.poster.addEventListener("mouseout", this.onVideoMouseOut.context(this), false);
|
this.poster.addEventListener("mouseout", this.onVideoMouseOut.context(this), false);
|
||||||
// Make a click on the poster act like a click on the play button.
|
// Make a click on the poster act like a click on the play button.
|
||||||
this.activateAsPlayButton(this.poster);
|
this.activateControl(this.poster, "playButton");
|
||||||
// Hide/Show poster on video events
|
// Hide/Show poster on video events
|
||||||
this.video.addEventListener("play", this.posterOnPlay.context(this), false);
|
this.video.addEventListener("play", this.posterOnPlay.context(this), false);
|
||||||
this.video.addEventListener("ended", this.posterOnEnded.context(this), false);
|
this.video.addEventListener("ended", this.posterOnEnded.context(this), false);
|
||||||
@ -923,7 +930,6 @@ var VideoJS = JRClass.extend({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
/* Device Fixes
|
/* Device Fixes
|
||||||
================================================================================ */
|
================================================================================ */
|
||||||
// Support older browsers that used "autobuffer"
|
// Support older browsers that used "autobuffer"
|
||||||
@ -1045,145 +1051,6 @@ var VideoJS = JRClass.extend({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Convenience Functions (mini library)
|
|
||||||
// Functions not specific to video or VideoJS and could probably be replaced with a library like jQuery
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
var _V_ = {
|
|
||||||
addClass: function(element, classToAdd){
|
|
||||||
if (element.className.split(/\s+/).lastIndexOf(classToAdd) == -1) { element.className = element.className === "" ? classToAdd : element.className + " " + classToAdd; }
|
|
||||||
},
|
|
||||||
|
|
||||||
removeClass: function(element, classToRemove){
|
|
||||||
if (element.className.indexOf(classToRemove) == -1) { return; }
|
|
||||||
var classNames = element.className.split(/\s+/);
|
|
||||||
classNames.splice(classNames.lastIndexOf(classToRemove),1);
|
|
||||||
element.className = classNames.join(" ");
|
|
||||||
},
|
|
||||||
|
|
||||||
merge: function(obj1, obj2){
|
|
||||||
for(var attrname in obj2){
|
|
||||||
if (obj2.hasOwnProperty(attrname)) {
|
|
||||||
obj1[attrname]=obj2[attrname];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return obj1;
|
|
||||||
},
|
|
||||||
|
|
||||||
createElement: function(tagName, attributes){
|
|
||||||
return _V_.merge(document.createElement(tagName), attributes);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Attempt to block the ability to select text while dragging controls
|
|
||||||
blockTextSelection: function(){
|
|
||||||
document.body.focus();
|
|
||||||
document.onselectstart = function () { return false; };
|
|
||||||
},
|
|
||||||
|
|
||||||
// Turn off text selection blocking
|
|
||||||
unblockTextSelection: function(){
|
|
||||||
document.onselectstart = function () { return true; };
|
|
||||||
},
|
|
||||||
|
|
||||||
// Return seconds as MM:SS
|
|
||||||
formatTime: function(secs) {
|
|
||||||
var seconds = Math.round(secs);
|
|
||||||
var minutes = Math.floor(seconds / 60);
|
|
||||||
minutes = (minutes >= 10) ? minutes : "0" + minutes;
|
|
||||||
seconds = Math.floor(seconds % 60);
|
|
||||||
seconds = (seconds >= 10) ? seconds : "0" + seconds;
|
|
||||||
return minutes + ":" + seconds;
|
|
||||||
},
|
|
||||||
|
|
||||||
// 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));
|
|
||||||
},
|
|
||||||
|
|
||||||
// Get an objects position on the page
|
|
||||||
findPosX: function(obj) {
|
|
||||||
var curleft = obj.offsetLeft;
|
|
||||||
while(obj = obj.offsetParent) {
|
|
||||||
curleft += obj.offsetLeft;
|
|
||||||
}
|
|
||||||
return curleft;
|
|
||||||
},
|
|
||||||
|
|
||||||
getComputedStyleValue: function(element, style){
|
|
||||||
return window.getComputedStyle(element, null).getPropertyValue(style);
|
|
||||||
},
|
|
||||||
|
|
||||||
get: function(url, onSuccess){
|
|
||||||
if (typeof XMLHttpRequest == "undefined") {
|
|
||||||
XMLHttpRequest = function () {
|
|
||||||
try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e) {}
|
|
||||||
try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (f) {}
|
|
||||||
try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (g) {}
|
|
||||||
//Microsoft.XMLHTTP points to Msxml2.XMLHTTP.3.0 and is redundant
|
|
||||||
throw new Error("This browser does not support XMLHttpRequest.");
|
|
||||||
};
|
|
||||||
}
|
|
||||||
var request = new XMLHttpRequest();
|
|
||||||
request.open("GET",url);
|
|
||||||
request.onreadystatechange = function() {
|
|
||||||
if (request.readyState == 4 && request.status == 200) {
|
|
||||||
onSuccess(request.responseText);
|
|
||||||
}
|
|
||||||
}.context(this);
|
|
||||||
request.send();
|
|
||||||
},
|
|
||||||
|
|
||||||
// DOM Ready functionality adapted from jQuery. http://jquery.com/
|
|
||||||
bindDOMReady: function(){
|
|
||||||
if (document.readyState === "complete") {
|
|
||||||
return _V_.DOMReady();
|
|
||||||
}
|
|
||||||
if (document.addEventListener) {
|
|
||||||
document.addEventListener("DOMContentLoaded", _V_.DOMContentLoaded, false);
|
|
||||||
window.addEventListener("load", _V_.DOMReady, false);
|
|
||||||
} else if (document.attachEvent) {
|
|
||||||
document.attachEvent("onreadystatechange", _V_.DOMContentLoaded);
|
|
||||||
window.attachEvent("onload", _V_.DOMReady);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
DOMContentLoaded: function(){
|
|
||||||
if (document.addEventListener) {
|
|
||||||
document.removeEventListener( "DOMContentLoaded", _V_.DOMContentLoaded, false);
|
|
||||||
_V_.DOMReady();
|
|
||||||
} else if ( document.attachEvent ) {
|
|
||||||
if ( document.readyState === "complete" ) {
|
|
||||||
document.detachEvent("onreadystatechange", _V_.DOMContentLoaded);
|
|
||||||
_V_.DOMReady();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Functions to be run once the DOM is loaded
|
|
||||||
DOMReadyList: [],
|
|
||||||
addToDOMReady: function(fn){
|
|
||||||
if (_V_.DOMIsReady) {
|
|
||||||
fn.call(document);
|
|
||||||
} else {
|
|
||||||
_V_.DOMReadyList.push(fn);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
DOMIsReady: false,
|
|
||||||
DOMReady: function(){
|
|
||||||
if (_V_.DOMIsReady) { return; }
|
|
||||||
if (!document.body) { return setTimeout(_V_.DOMReady, 13); }
|
|
||||||
_V_.DOMIsReady = true;
|
|
||||||
if (_V_.DOMReadyList) {
|
|
||||||
for (var i=0; i<_V_.DOMReadyList.length; i++) {
|
|
||||||
_V_.DOMReadyList[i].call(document);
|
|
||||||
}
|
|
||||||
_V_.DOMReadyList = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
_V_.bindDOMReady();
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Class Methods
|
// Class Methods
|
||||||
// Functions that don't apply to individual videos.
|
// Functions that don't apply to individual videos.
|
||||||
@ -1230,7 +1097,7 @@ VideoJS.setupAllWhenReady = function(options){
|
|||||||
|
|
||||||
// Run the supplied function when the DOM is ready
|
// Run the supplied function when the DOM is ready
|
||||||
VideoJS.DOMReady = function(fn){
|
VideoJS.DOMReady = function(fn){
|
||||||
_V_.addToDOMReady(fn);
|
VideoJS.addToDOMReady(fn);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set up a specific video or array of video elements
|
// Set up a specific video or array of video elements
|
||||||
@ -1333,16 +1200,179 @@ VideoJS.warnings = {
|
|||||||
localStorageFull: "Local Storage is Full"
|
localStorageFull: "Local Storage is Full"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Combine Objects
|
||||||
|
// Use "safe" to protect from overwriting existing items
|
||||||
|
VideoJS.merge = function(obj1, obj2, safe){
|
||||||
|
for(var attrname in obj2){
|
||||||
|
if (obj2.hasOwnProperty(attrname) && (!safe || !obj1.hasOwnProperty(attrname))) { obj1[attrname]=obj2[attrname]; }
|
||||||
|
}
|
||||||
|
return obj1;
|
||||||
|
};
|
||||||
|
VideoJS.extend = function(obj){ this.merge(this, obj, true); }
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Convenience Functions (mini library)
|
||||||
|
// Functions not specific to video or VideoJS and could probably be replaced with a library like jQuery
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
VideoJS.extend({
|
||||||
|
|
||||||
|
addClass: function(element, classToAdd){
|
||||||
|
if (element.className.split(/\s+/).lastIndexOf(classToAdd) == -1) { element.className = element.className === "" ? classToAdd : element.className + " " + classToAdd; }
|
||||||
|
},
|
||||||
|
removeClass: function(element, classToRemove){
|
||||||
|
if (element.className.indexOf(classToRemove) == -1) { return; }
|
||||||
|
var classNames = element.className.split(/\s+/);
|
||||||
|
classNames.splice(classNames.lastIndexOf(classToRemove),1);
|
||||||
|
element.className = classNames.join(" ");
|
||||||
|
},
|
||||||
|
createElement: function(tagName, attributes){
|
||||||
|
return this.merge(document.createElement(tagName), attributes);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Attempt to block the ability to select text while dragging controls
|
||||||
|
blockTextSelection: function(){
|
||||||
|
document.body.focus();
|
||||||
|
document.onselectstart = function () { return false; };
|
||||||
|
},
|
||||||
|
// Turn off text selection blocking
|
||||||
|
unblockTextSelection: function(){ document.onselectstart = function () { return true; }; },
|
||||||
|
|
||||||
|
// Return seconds as MM:SS
|
||||||
|
formatTime: function(secs) {
|
||||||
|
var seconds = Math.round(secs);
|
||||||
|
var minutes = Math.floor(seconds / 60);
|
||||||
|
minutes = (minutes >= 10) ? minutes : "0" + minutes;
|
||||||
|
seconds = Math.floor(seconds % 60);
|
||||||
|
seconds = (seconds >= 10) ? seconds : "0" + seconds;
|
||||||
|
return minutes + ":" + seconds;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 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 - this.findPosX(relativeElement)) / relativeElement.offsetWidth));
|
||||||
|
},
|
||||||
|
// Get an objects position on the page
|
||||||
|
findPosX: function(obj) {
|
||||||
|
var curleft = obj.offsetLeft;
|
||||||
|
while(obj = obj.offsetParent) {
|
||||||
|
curleft += obj.offsetLeft;
|
||||||
|
}
|
||||||
|
return curleft;
|
||||||
|
},
|
||||||
|
getComputedStyleValue: function(element, style){
|
||||||
|
return window.getComputedStyle(element, null).getPropertyValue(style);
|
||||||
|
},
|
||||||
|
|
||||||
|
get: function(url, onSuccess){
|
||||||
|
if (typeof XMLHttpRequest == "undefined") {
|
||||||
|
XMLHttpRequest = function () {
|
||||||
|
try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e) {}
|
||||||
|
try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (f) {}
|
||||||
|
try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (g) {}
|
||||||
|
//Microsoft.XMLHTTP points to Msxml2.XMLHTTP.3.0 and is redundant
|
||||||
|
throw new Error("This browser does not support XMLHttpRequest.");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var request = new XMLHttpRequest();
|
||||||
|
request.open("GET",url);
|
||||||
|
request.onreadystatechange = function() {
|
||||||
|
if (request.readyState == 4 && request.status == 200) {
|
||||||
|
onSuccess(request.responseText);
|
||||||
|
}
|
||||||
|
}.context(this);
|
||||||
|
request.send();
|
||||||
|
},
|
||||||
|
|
||||||
|
// DOM Ready functionality adapted from jQuery. http://jquery.com/
|
||||||
|
bindDOMReady: function(){
|
||||||
|
if (document.readyState === "complete") {
|
||||||
|
return VideoJS.onDOMReady();
|
||||||
|
}
|
||||||
|
if (document.addEventListener) {
|
||||||
|
document.addEventListener("DOMContentLoaded", VideoJS.DOMContentLoaded, false);
|
||||||
|
window.addEventListener("load", VideoJS.onDOMReady, false);
|
||||||
|
} else if (document.attachEvent) {
|
||||||
|
document.attachEvent("onreadystatechange", VideoJS.DOMContentLoaded);
|
||||||
|
window.attachEvent("onload", VideoJS.onDOMReady);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
DOMContentLoaded: function(){
|
||||||
|
if (document.addEventListener) {
|
||||||
|
document.removeEventListener( "DOMContentLoaded", VideoJS.DOMContentLoaded, false);
|
||||||
|
VideoJS.onDOMReady();
|
||||||
|
} else if ( document.attachEvent ) {
|
||||||
|
if ( document.readyState === "complete" ) {
|
||||||
|
document.detachEvent("onreadystatechange", VideoJS.DOMContentLoaded);
|
||||||
|
VideoJS.onDOMReady();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Functions to be run once the DOM is loaded
|
||||||
|
DOMReadyList: [],
|
||||||
|
addToDOMReady: function(fn){
|
||||||
|
if (VideoJS.DOMIsReady) {
|
||||||
|
fn.call(document);
|
||||||
|
} else {
|
||||||
|
VideoJS.DOMReadyList.push(fn);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
DOMIsReady: false,
|
||||||
|
onDOMReady: function(){
|
||||||
|
if (VideoJS.DOMIsReady) { return; }
|
||||||
|
if (!document.body) { return setTimeout(VideoJS.onDOMReady, 13); }
|
||||||
|
VideoJS.DOMIsReady = true;
|
||||||
|
if (VideoJS.DOMReadyList) {
|
||||||
|
for (var i=0; i<VideoJS.DOMReadyList.length; i++) {
|
||||||
|
VideoJS.DOMReadyList[i].call(document);
|
||||||
|
}
|
||||||
|
VideoJS.DOMReadyList = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
VideoJS.bindDOMReady();
|
||||||
|
|
||||||
// Allows for binding context to functions
|
// Allows for binding context to functions
|
||||||
// when using in event listeners and timeouts
|
// when using in event listeners and timeouts
|
||||||
Function.prototype.context = function(obj){
|
Function.prototype.context = function(obj){
|
||||||
var method = this, temp;
|
var method = this,
|
||||||
temp = function(){
|
temp = function(){
|
||||||
return method.apply(obj, arguments);
|
return method.apply(obj, arguments);
|
||||||
};
|
};
|
||||||
return temp;
|
return temp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Like context, in that it creates a closure
|
||||||
|
// But insteaad keep "this" intact, and passes the var as the second argument of the function
|
||||||
|
// Need for event listeners where you need to know what called the event
|
||||||
|
Function.prototype.evtContext = function(obj){
|
||||||
|
var method = this,
|
||||||
|
temp = function(){
|
||||||
|
var origContext = this;
|
||||||
|
return method.call(obj, arguments[0], origContext);
|
||||||
|
};
|
||||||
|
return temp;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Removeable Event listener with Context
|
||||||
|
// Replaces the original function with a version that has context
|
||||||
|
// So it can be removed using the original function name.
|
||||||
|
// I have a feeling this one is gonna bite me in the butt some day
|
||||||
|
Function.prototype.rEvtContext = function(obj, funcParent){
|
||||||
|
if (this.hasContext == true) { return this; }
|
||||||
|
if (!funcParent) { funcParent = obj; }
|
||||||
|
for (var attrname in funcParent) {
|
||||||
|
if (funcParent[attrname] == this) {
|
||||||
|
funcParent[attrname] = this.evtContext(obj);
|
||||||
|
funcParent[attrname].hasContext = true;
|
||||||
|
return funcParent[attrname];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Log function not found on object
|
||||||
|
};
|
||||||
|
|
||||||
// Shim to make Video tag valid in IE
|
// Shim to make Video tag valid in IE
|
||||||
if(VideoJS.isIE()) { document.createElement("video"); }
|
if(VideoJS.isIE()) { document.createElement("video"); }
|
||||||
|
|
||||||
@ -1361,4 +1391,9 @@ if (window.jQuery) {
|
|||||||
})(jQuery);
|
})(jQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Expose to global
|
||||||
|
VideoJS.player = VideoJS.prototype;
|
||||||
|
return (window.VideoJS = window._V_ = VideoJS);
|
||||||
|
|
||||||
|
// End self-executing function
|
||||||
|
})(window);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user