1
0
mirror of https://github.com/videojs/video.js.git synced 2025-07-15 01:34:23 +02:00

Updated api and setup docs

This commit is contained in:
Steve Heffernan
2012-01-05 23:25:09 -08:00
parent 9678c7717f
commit 7ef5b15ae2
22 changed files with 477 additions and 601 deletions

View File

@ -1,2 +0,0 @@
Tagging a Release
git tag -a v[version number] [commit]

24
build/Versioning Notes.md Normal file
View File

@ -0,0 +1,24 @@
Version Numbers
---------------
http://en.wikipedia.org/wiki/Software_versioning#Sequence-based_identifiers
### Major Version (Integer, e.g 3.0)
- Any features where we expect it could break plugins, skins, or any major API integration.
### Minor Version (3.1)
- Additional non-breaking features
### Revision Versions
- Beta (3.1-b1)
- Release Candidate (3.1-rc1)
- Release with revisions (3.1-r1)
Notes:
The last level of one revision type (beta/release candidate) should match the first level of the next revision type. 4.0-b10 should match 4.0-rc1, assuming b10 is the last beta version.
Release revisions means bug fixes. The CDN url should not reflect the revision number. 4.0-r2 would still be /4.0/.
Tagging a Release
-----------------
git tag -a v[version number] [commit]

View File

@ -1,4 +1,5 @@
_V_.options.flash.swf = "../flash/video-js.swf"; _V_.options.flash.swf = "../flash/video-js.swf";
_V_.options.flash.swf = "http://andylemay.com/dev/videojs/VideoJS.swf";
$(function(){ $(function(){
var tech, i, tname, player, var tech, i, tname, player,

View File

@ -1,369 +0,0 @@
/*
VideoJS YouTube Skin (http://videojs.com)
Version 3.0
REQUIRED STYLES (be careful overriding)
================================================================================ */
/* When loading the player, the video tag is replaced with a DIV,
that will hold the video tag or object tag for other playback methods.
The div contains the video playback element (Flash or HTML5) and controls, and sets the width and height of the video.
** If you want to add some kind of border/padding (e.g. a frame), or special positioning, use another containing element.
Otherwise you risk messing up control positioning and full window mode. **
*/
.video-js {
background-color: #000; position: relative; padding: 0;
/* Start with 10px for base font size so other dimensions can be em based and easily calculable. */
font-size: 10px;
}
/* Playback technology elements expand to the width/height of the containing div. <video> or <object> */
.video-js .vjs-tech { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
/* Fullscreen Styles */
body.vjs-full-window {
padding: 0; margin: 0;
height: 100%; overflow-y: auto; /* Fix for IE6 full-window. http://www.cssplay.co.uk/layouts/fixed.html */
}
.video-js.vjs-fullscreen {
position: fixed; overflow: hidden; z-index: 1000; left: 0; top: 0; bottom: 0; right: 0; width: 100% !important; height: 100% !important;
_position: absolute; /* IE6 Full-window (underscore hack) */
}
.video-js:-webkit-full-screen {
width: 100% !important; height: 100% !important;
}
.video-js:-moz-full-screen {
width: 100% !important; height: 100% !important;
}
/* Subtiles Style */
.video-js .vjs-subtitles { color: #fff; font-size: 20px; text-align: center; position: absolute; bottom: 40px; left: 0; right: 0; }
/* The default control bar. Created by bar.js */
.tubecss .vjs-controls {
position: absolute;
bottom: 0; /* Distance from the bottom of the box/video. Keep 0. Use height to add more bottom margin. */
left: 0; right: 0; /* 100% width of div */
opacity: 0.85; display: block; /* Start hidden */
margin: 0; padding: 0; /* Controls are absolutely position, so no padding necessary */
height: 2.6em; /* Including any margin you want above or below control items */
color: #fff; border-top: 1px solid #404040;
/* CSS Gradient */
/* Can use the Ultimate CSS Gradient Generator: http://www.colorzilla.com/gradient-editor/ */
background: -moz-linear-gradient(top, rgba(51,51,51,0.8) 0%, rgba(0,0,0,1) 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(51,51,51,0.8)), color-stop(100%,rgba(0,0,0,1))); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, rgba(51,51,51,0.8) 0%,rgba(0,0,0,1) 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, rgba(51,51,51,0.8) 0%,rgba(0,0,0,1) 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, rgba(51,51,51,0.8) 0%,rgba(0,0,0,1) 100%); /* IE10+ */
background: linear-gradient(top, rgba(51,51,51,0.8) 0%,rgba(0,0,0,1) 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#cc333333', endColorstr='#000000',GradientType=0 ); /* IE6-9 */
/* Fade-in using CSS Transitions */
/* -webkit-transition: opacity 0.3s linear;
-moz-transition: opacity 0.3s linear;
-o-transition: opacity 0.3s linear;
-ms-transition: opacity 0.3s linear;
transition: opacity 0.3s linear;*/
}
/* General styles for individual controls. */
.tubecss .vjs-control {
position: relative; float: left;
text-align: center; margin: 0; padding: 0;
height: 2.6em; width: 2.6em;
}
.tubecss .vjs-control:focus {
outline: 0;
}
/* Hide control text visually, but have it available for screenreaders: h5bp.com/v */
.tubecss .vjs-control-text { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; }
/* Play/Pause
-------------------------------------------------------------------------------- */
.tubecss .vjs-play-control { width: 5em; cursor: pointer !important; border-left: 1px solid #333; border-right: 1px solid #222; }
/* Play Icon */
.tubecss.vjs-paused .vjs-play-control div { width: 15px; height: 17px; background: url('tubesprite.png'); margin: 0.5em auto 0; }
.tubecss.vjs-paused .vjs-play-control div:hover {background: url('tubesprite.png') 0 -75px;}
.tubecss.vjs-playing .vjs-play-control div { width: 15px; height: 17px; background: url('tubesprite.png') -25px 0; margin: 0.5em auto 0; }
.tubecss.vjs-playing .vjs-play-control div:hover {background: url('tubesprite.png') -25px -75px;}
/* Rewind
-------------------------------------------------------------------------------- */
.tubecss .vjs-rewind-control { width: 5em; cursor: pointer !important; }
.tubecss .vjs-rewind-control div { width: 19px; height: 16px; background: url('tubesprite.png'); margin: 0.5em auto 0; }
/* Volume/Mute
-------------------------------------------------------------------------------- */
.tubecss .vjs-mute-control { width: 3.8em; cursor: pointer !important; float: left; border-left: 1px solid #333;}
.tubecss .vjs-mute-control div { width: 22px; height: 16px; background: url('tubesprite.png') -75px -25px; margin: 0.5em auto 0; }
.tubecss .vjs-mute-control.vjs-vol-0 div { background: url('tubesprite.png') 0 -25px; }
.tubecss .vjs-mute-control.vjs-vol-1 div { background: url('tubesprite.png') -25px -25px; }
.tubecss .vjs-mute-control.vjs-vol-2 div { background: url('tubesprite.png') -50px -25px; }
.tubecss .vjs-mute-control div:hover {background: url('tubesprite.png') -75px -100px; }
.tubecss .vjs-mute-control.vjs-vol-0 div:hover { background: url('tubesprite.png') 0 -100px; }
.tubecss .vjs-mute-control.vjs-vol-1 div:hover { background: url('tubesprite.png') -25px -100px; }
.tubecss .vjs-mute-control.vjs-vol-2 div:hover { background: url('tubesprite.png') -50px -100px; }
.tubecss .vjs-volume-control { position: absolute; top: -0.1em; left: 9em; width: 6em; padding-right: 8px; border-right: 1px solid #222;}
.tubecss .vjs-volume-bar {
position: relative; border-bottom: 1px solid #333; width: 6em; height: 0.6em; margin: 1em auto 0; cursor: pointer !important;
-moz-border-radius: 0.3em; -webkit-border-radius: 0.3em; border-radius: 0.3em;
background: #111; /* Old browsers */
}
.tubecss .vjs-volume-level {
position: absolute; top: 0; left: 0; height: 0.6em;
-moz-border-radius: 0.3em; -webkit-border-radius: 0.3em; border-radius: 0.3em;
background: #c61003; /* Old browsers */
background: -moz-linear-gradient(top, #c61003 0%, #840400 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#c61003), color-stop(100%,#840400)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #c61003 0%,#840400 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, #c61003 0%,#840400 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, #c61003 0%,#840400 100%); /* IE10+ */
background: linear-gradient(top, #c61003 0%,#840400 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#c61003', endColorstr='#840400',GradientType=0 ); /* IE6-9 */
}
.tubecss .vjs-volume-handle {
position: absolute; top: -0.3em; width: 0.5em; height: 1.2em; background: #696969; left: 0;
border: none;
border-top: 1px solid #888;
-moz-border-radius: 0.3em; -webkit-border-radius: 0.3em; border-radius: 0.3em;
}
/* Progress
-------------------------------------------------------------------------------- */
.tubecss div.vjs-progress-control {
position: absolute;
left: 0em; right: 0em; /* Leave room for time displays. */
height: 1em; width: auto;
top: -1.3em; /* Set above the rest of the controls. And leave room for 2px of borders (progress bottom and controls top). */
border-bottom: 1px solid #1F1F1F;
border-top: 1px solid #222;
/* CSS Gradient */
background: #111;
-moz-opacity: 0.80;
opacity: 0.80;
/* 1px top shadow */
/* -webkit-box-shadow: 0px -1px 0px 0px rgba(0, 0, 0, 0.15); -moz-box-shadow: 0px -1px 0px 0px rgba(0, 0, 0, 0.15); box-shadow: 0px -1px 0px 0px rgba(0, 0, 0, 0.15);*/
}
/* Box containing play and load progresses. Also acts as seek scrubber. */
.tubecss .vjs-progress-holder {
position: relative; cursor: pointer !important; /*overflow: hidden;*/
padding: 0; margin: 0; /* Placement within the progress control item */
height: 1.0em;
-moz-border-radius: 0em; -webkit-border-radius: 0em; border-radius: 0em;
/* CSS Gradient */
background: #000
-moz-opacity: 0.90;
opacity: 0.90;
}
.tubecss .vjs-progress-holder .vjs-play-progress,
.tubecss .vjs-progress-holder .vjs-load-progress { /* Progress Bars */
position: absolute; display: block; height: 1.0em; margin: 0; padding: 0;
left: 0; top: 0; /*Needed for IE6*/
-moz-border-radius: 0em; -webkit-border-radius: 0em; border-radius: 0em;
/*width: 0;*/
}
.tubecss .vjs-play-progress {
background: #ff0505; /* Old browsers */
background: -moz-linear-gradient(top, #ff0505 0%, #9b0000 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ff0505), color-stop(100%,#9b0000)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #ff0505 0%,#9b0000 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, #ff0505 0%,#9b0000 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, #ff0505 0%,#9b0000 100%); /* IE10+ */
background: linear-gradient(top, #ff0505 0%,#9b0000 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ff0505', endColorstr='#9b0000',GradientType=0 ); /* IE6-9 */
}
.tubecss .vjs-load-progress {
background: #999;
}
.tubecss div.vjs-seek-handle {
position: absolute;
width: 16px; height: 16px; /* Match img pixles */
margin-top: -0.3em;
left: 0; top: 0; /*Needed for IE6*/
background: url('tubesprite.png') 0 -50px;
/* CSS Curved Corners. Needed to make shadows curved. */
-moz-border-radius: 0.8em; -webkit-border-radius: 0.8em; border-radius: 0.8em;
/* CSS Shadows */
-webkit-box-shadow: 0 2px 4px 0 #000; -moz-box-shadow: 0 2px 4px 0 #000; box-shadow: 0 2px 4px 0 #000;
}
.tubecss div.vjs-seek-handle:hover {
background: url('tubesprite.png') -188px -50px;
}
/* Time Display
-------------------------------------------------------------------------------- */
.tubecss .vjs-time-controls {
position: absolute;
right: 0;
height: 100%; width: 4em;
top: 0.0em;
border-bottom: none;
border-top: none;
background: transparent;
font-size: 1em; line-height: 1.0em; font-weight: normal; font-family: Helvetica, Arial, sans-serif;
/* 1px top shadow */
/* -webkit-box-shadow: 0px -1px 0px 0px rgba(0, 0, 0, 0.15); -moz-box-shadow: 0px -1px 0px 0px rgba(0, 0, 0, 0.15); box-shadow: 0px -1px 0px 0px rgba(0, 0, 0, 0.15);*/
}
.tubecss .vjs-current-time {line-height: 2.4em; left: 15.9em; border-left: 1px solid #333; }
.tubecss .vjs-duration {line-height: 2.4em; left: 20.2em; display: inline; color: #999; width: 39.5em; text-align: left; padding-left: 2px; border-right: 1px solid #222;}
.tubecss .vjs-remaining-time { right: 0; display: none; }
.vjs-time-divider {line-height: 1.6em; display: inline; position: absolute; left: 19.5em; top: 0.5em; color: #999;}
/* Fullscreen
-------------------------------------------------------------------------------- */
.vjs-secondary-controls { float: right; }
.tubecss .vjs-fullscreen-control { width: 3.8em; cursor: pointer !important; float: right; border-left: 1px solid #333; border-right: 1px solid #222;}
.tubecss .vjs-fullscreen-control div { width: 16px; height: 16px; background: url('tubesprite.png') -50px 0; margin: 0.5em auto 0; }
.tubecss .vjs-fullscreen-control div:hover {background: url('tubesprite.png') -50px -75px; }
.tubecss.vjs-fullscreen .vjs-fullscreen-control div { background: url('tubesprite.png') -75px 0; }
.tubecss.vjs-fullscreen .vjs-fullscreen-control div:hover { background: url('tubesprite.png') -75px -75px; }
/* Big Play Button (at start)
---------------------------------------------------------*/
.tubecss .vjs-big-play-button {
display: block; /* Start hidden */ z-index: 2;
position: absolute; top: 50%; left: 50%; width: 8.0em; height: 8.0em; margin: -43px 0 0 -43px; text-align: center; vertical-align: center; cursor: pointer !important;
border: 0.3em solid #fff; opacity: 0.95;
-webkit-border-radius: 25px; -moz-border-radius: 25px; border-radius: 25px;
background: #454545;
background: -moz-linear-gradient(top, #454545 0%, #232323 50%, #161616 50%, #3f3f3f 100%);
background: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%,#454545), color-stop(50%,#232323), color-stop(50%,#161616), color-stop(100%,#3f3f3f));
background: -webkit-linear-gradient(top, #454545 0%,#232323 50%,#161616 50%,#3f3f3f 100%);
background: -o-linear-gradient(top, #454545 0%,#232323 50%,#161616 50%,#3f3f3f 100%);
background: -ms-linear-gradient(top, #454545 0%,#232323 50%,#161616 50%,#3f3f3f 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#454545', endColorstr='#3f3f3f',GradientType=0 );
background: linear-gradient(top, #454545 0%,#232323 50%,#161616 50%,#3f3f3f 100%);
/* CSS Shadows */
-webkit-box-shadow: 4px 4px 8px #000; -moz-box-shadow: 4px 4px 8px #000; box-shadow: 4px 4px 8px #000;
}
.tubecss div.vjs-big-play-button:hover {
-webkit-box-shadow: 0 0 80px #fff; -moz-box-shadow: 0 0 80px #fff; box-shadow: 0 0 80px #fff;
}
.tubecss div.vjs-big-play-button span {
position: absolute; top: 50%; left: 50%;
display: block; width: 35px; height: 42px;
margin: -20px 0 0 -15px; /* Using negative margin to center image. */
background: url('tubesprite.png') -100px 0;
}
/* Loading Spinner
---------------------------------------------------------*/
.vjs-default-skin div.vjs-loading-spinner-fallback {
display: none;
position: absolute; top: 50%; left: 50%; width: 30px; height: 30px;
margin: -15px 0 0 -15px; /* Using negative margin to center image.*/
background: url('loading.gif');
}
/* Spinner Styles
---------------------------------------------------------*/
/* CSS Spinners by Kilian Valkhof - http://kilianvalkhof.com/2010/css-xhtml/css3-loading-spinners-without-images/ */
.vjs-loading-spinner {
display: hidden;
position: absolute; top: 50%; left: 50%; width: 55px; height: 55px;
margin: -28px 0 0 -28px;
-webkit-animation-name: rotatethis;
-webkit-animation-duration:1s;
-webkit-animation-iteration-count:infinite;
-webkit-animation-timing-function:linear;
-moz-animation-name: rotatethis;
-moz-animation-duration:1s;
-moz-animation-iteration-count:infinite;
-moz-animation-timing-function:linear;
}
@-webkit-keyframes rotatethis {
0% {-webkit-transform:scale(0.6) rotate(0deg);}
12.5% {-webkit-transform:scale(0.6) rotate(0deg);}
12.51% {-webkit-transform:scale(0.6) rotate(45deg);}
25% {-webkit-transform:scale(0.6) rotate(45deg);}
25.01% {-webkit-transform:scale(0.6) rotate(90deg);}
37.5% {-webkit-transform:scale(0.6) rotate(90deg);}
37.51% {-webkit-transform:scale(0.6) rotate(135deg);}
50% {-webkit-transform:scale(0.6) rotate(135deg);}
50.01% {-webkit-transform:scale(0.6) rotate(180deg);}
62.5% {-webkit-transform:scale(0.6) rotate(180deg);}
62.51% {-webkit-transform:scale(0.6) rotate(225deg);}
75% {-webkit-transform:scale(0.6) rotate(225deg);}
75.01% {-webkit-transform:scale(0.6) rotate(270deg);}
87.5% {-webkit-transform:scale(0.6) rotate(270deg);}
87.51% {-webkit-transform:scale(0.6) rotate(315deg);}
100% {-webkit-transform:scale(0.6) rotate(315deg);}
}
@-moz-keyframes rotatethis {
0% {-moz-transform:scale(0.6) rotate(0deg);}
12.5% {-moz-transform:scale(0.6) rotate(0deg);}
12.51% {-moz-transform:scale(0.6) rotate(45deg);}
25% {-moz-transform:scale(0.6) rotate(45deg);}
25.01% {-moz-transform:scale(0.6) rotate(90deg);}
37.5% {-moz-transform:scale(0.6) rotate(90deg);}
37.51% {-moz-transform:scale(0.6) rotate(135deg);}
50% {-moz-transform:scale(0.6) rotate(135deg);}
50.01% {-moz-transform:scale(0.6) rotate(180deg);}
62.5% {-moz-transform:scale(0.6) rotate(180deg);}
62.51% {-moz-transform:scale(0.6) rotate(225deg);}
75% {-moz-transform:scale(0.6) rotate(225deg);}
75.01% {-moz-transform:scale(0.6) rotate(270deg);}
87.5% {-moz-transform:scale(0.6) rotate(270deg);}
87.51% {-moz-transform:scale(0.6) rotate(315deg);}
100% {-moz-transform:scale(0.6) rotate(315deg);}
}
/* Each circle */
div.vjs-loading-spinner .ball1 { opacity: 0.12; position:absolute; left: 20px; top: 0px; width: 13px; height: 13px; background: #fff;
border-radius: 13px; -webkit-border-radius: 13px; -moz-border-radius: 13px; border: 1px solid #ccc; }
div.vjs-loading-spinner .ball2 { opacity: 0.25; position:absolute; left: 34px; top: 6px; width: 13px; height: 13px; background: #fff;
border-radius: 13px; -webkit-border-radius: 13px; -moz-border-radius: 13px; border: 1px solid #ccc; }
div.vjs-loading-spinner .ball3 { opacity: 0.37; position:absolute; left: 40px; top: 20px; width: 13px; height: 13px; background: #fff;
border-radius: 13px; -webkit-border-radius: 13px; -moz-border-radius: 13px; border: 1px solid #ccc; }
div.vjs-loading-spinner .ball4 { opacity: 0.50; position:absolute; left: 34px; top: 34px; width: 13px; height: 13px; background: #fff;
border-radius: 10px; -webkit-border-radius: 10px; -moz-border-radius: 15px; border: 1px solid #ccc; }
div.vjs-loading-spinner .ball5 { opacity: 0.62; position:absolute; left: 20px; top: 40px; width: 13px; height: 13px; background: #fff;
border-radius: 13px; -webkit-border-radius: 13px; -moz-border-radius: 13px; border: 1px solid #ccc; }
div.vjs-loading-spinner .ball6 { opacity: 0.75; position:absolute; left: 6px; top: 34px; width: 13px; height: 13px; background: #fff;
border-radius: 13px; -webkit-border-radius: 13px; -moz-border-radius: 13px; border: 1px solid #ccc; }
div.vjs-loading-spinner .ball7 { opacity: 0.87; position:absolute; left: 0px; top: 20px; width: 13px; height: 13px; background: #fff;
border-radius: 13px; -webkit-border-radius: 13px; -moz-border-radius: 13px; border: 1px solid #ccc; }
div.vjs-loading-spinner .ball8 { opacity: 1.00; position:absolute; left: 6px; top: 6px; width: 13px; height: 13px; background: #fff;
border-radius: 13px; -webkit-border-radius: 13px; -moz-border-radius: 13px; border: 1px solid #ccc; }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

View File

@ -19,7 +19,7 @@ REQUIRED STYLES (be careful overriding)
/* Allow poster to be vertially aligned. */ /* Allow poster to be vertially aligned. */
vertical-align: middle; vertical-align: middle;
display: table-cell; /* display: table-cell; */ /*This works in Safari but not Firefox.*/
} }
/* Playback technology elements expand to the width/height of the containing div. <video> or <object> */ /* Playback technology elements expand to the width/height of the containing div. <video> or <object> */

17
dev/build-source-list.rb Normal file
View File

@ -0,0 +1,17 @@
#! /usr/bin/env ruby
# Create javascript file with list of source files for easy inclusion in other development files.
# puts ARGV[0]
File.open("source-list.js", "w+") do |file|
file.puts "var vjsSourceList = [];"
Dir.foreach('../src') do |item|
next if item == '.' or item == '..' or item == '.DS_Store'
file.puts "vjsSourceList.push('src/#{item}')"
end
end

0
dev/include-sources.js Normal file
View File

13
dev/source-list.js Normal file
View File

@ -0,0 +1,13 @@
var vjsSourceList = [];
vjsSourceList.push('_begin.js')
vjsSourceList.push('_end.js')
vjsSourceList.push('component.js')
vjsSourceList.push('controls.js')
vjsSourceList.push('core.js')
vjsSourceList.push('ecma.js')
vjsSourceList.push('events.js')
vjsSourceList.push('json.js')
vjsSourceList.push('lib.js')
vjsSourceList.push('player.js')
vjsSourceList.push('tech.js')
vjsSourceList.push('tracks.js')

View File

@ -1,17 +1,18 @@
--- ---
layout: docs layout: docs
title: API title: API &mdash; Video.JS &raquo; HTML5 Video Player
description: Video.JS API Docs description: Video.JS API Docs - API settings based on the HTML5 video API
body_id: docs body_id: api
body_class: docs subpage
--- ---
API API
=== ===
The VideoJS API allows you to interact with the video through Javascript, whether the browser is playing the video through HTML5 video or any other supported playback technologies. The Video.js API allows you to interact with the video through Javascript, whether the browser is playing the video through HTML5 video, Flash, or any other supported playback technologies.
Referencing the Player Referencing the Player
---------------------- ----------------------
To use the API functions, you need access to the player object. Luckily this is easy to get. You just need to make sure your video tag has an ID. The example embed code has an ID of "example_video_1". If you have multiple videos on one page, make sure every video tag has a unique ID (example_video_2, example_video_3, etc.). To use the API functions, you need access to the player object. Luckily this is easy to get. You just need to make sure your video tag has an ID. The example embed code has an ID of "example_video_1". If you have multiple videos on one page, make sure every video tag has a unique ID.
{% highlight javascript %} {% highlight javascript %}
@ -19,10 +20,11 @@ To use the API functions, you need access to the player object. Luckily this is
{% endhighlight %} {% endhighlight %}
(If the player hasn't been initialized yet via the data-setup attribute or another method, this will also initialize the player.)
Wait Until the Player is Ready Wait Until the Player is Ready
------------------------------ ------------------------------
The time it takes VideoJS to set up the video and API will vary depending on the playback technology being used (HTML5 will often be much faster to load than Flash). For that reason we want to use the player's 'ready' function to trigger any code that requires the player's API. The time it takes Video.js to set up the video and API will vary depending on the playback technology being used (HTML5 will often be much faster to load than Flash). For that reason we want to use the player's 'ready' function to trigger any code that requires the player's API.
{% highlight javascript %} {% highlight javascript %}
@ -39,122 +41,189 @@ The time it takes VideoJS to set up the video and API will vary depending on the
API Methods API Methods
----------- -----------
Now that you have access to a ready player, you can control the video or react to video events using the following functions. The VideoJS API function names follow the HTML5 media API. The main difference is that attributes which you would get or set on a video element directly ( videoElement.currentTime = "120"; ), you would use a function argument syntax for VideoJS ( myPlayer.currentTime(120); ) Now that you have access to a ready player, you can control the video or respond to video events using the following functions. The Video.js API function names follow the [HTML5 media API](http://www.w3.org/TR/html5/video.html). The main difference is that attributes which you would get or set on a video element using the equals sign ( `myVideoElement.currentTime = "120";` ), you would use a function argument syntax for Video.js ( `myPlayer.currentTime(120);` )
### play() ### play()
Start video playback. Start video playback. Returns the player object.
Returns the player object.
Example: {% highlight javascript %}
myPlayer.play();
{% endhighlight %}
myPlayer.play();
### pause() ### pause()
Pause the video playback. Pause the video playback. Returns: the player object
Returns: the player object
Example:
myPlayer.pause(); {% highlight javascript %}
myPlayer.pause();
{% endhighlight %}
### currentTime() ### currentTime()
Returns the current time of the video in seconds. Returns the current time of the video in seconds.
Example:
var whereYouAt = myPlayer.currentTime(); {% highlight javascript %}
var whereYouAt = myPlayer.currentTime();
{% endhighlight %}
### currentTime(seconds) // Type: Integer or Float ### currentTime(seconds) // Type: Integer or Float
Seek to the supplied time (seconds). Seek to the supplied time (seconds).
Returns the player object. Returns the player object.
Example:
myPlayer.currentTime(120); // 2 minutes into the video {% highlight javascript %}
myPlayer.currentTime(120); // 2 minutes into the video
{% endhighlight %}
### duration() ### duration()
Returns the length in time of the video in seconds. NOTE: The video must have started loading before the duration can be known, and in the case of Flash, may not be known until the video starts playing. Returns the length in time of the video in seconds. NOTE: The video must have started loading before the duration can be known, and in the case of Flash, may not be known until the video starts playing.
Example:
var howLongIsThis = myPlayer.duration();
{% highlight javascript %}
var howLongIsThis = myPlayer.duration();
{% endhighlight %}
### buffered() ### buffered()
Returns a [TimeRange](http://videojs.com/docs/glossary.html#timerange) with sections of the video that have been downloaded. If you just want the percent of the video that's been downloaded, use bufferedPercent. Returns a [TimeRange](http://videojs.com/docs/glossary.html#timerange) with sections of the video that have been downloaded. If you just want the percent of the video that's been downloaded, use bufferedPercent.
Example:
var whatHasBeenBuffered = myPlayer.buffered(); {% highlight javascript %}
var whatHasBeenBuffered = myPlayer.buffered();
{% endhighlight %}
### bufferedPercent() ### bufferedPercent()
Returns the percent (as a decimal) of the video that's been downloaded. Returns the percent (as a decimal) of the video that's been downloaded.
Example:
var howMuchIsDownloaded = myPlayer.bufferedPercent(); {% highlight javascript %}
var howMuchIsDownloaded = myPlayer.bufferedPercent();
{% endhighlight %}
### volume() ### volume()
Returns the current volume of the video as a percent in decimal form. 0 is off (muted), 1.0 is all the way up, 0.5 is half way. Returns the current volume of the video as a percent in decimal form. 0 is off (muted), 1.0 is all the way up, 0.5 is half way.
Example:
var howLoudIsIt = myPlayer.volume(); {% highlight javascript %}
var howLoudIsIt = myPlayer.volume();
{% endhighlight %}
### volume(percentAsDecimal) ### volume(percentAsDecimal)
Set the volume to the supplied percent (as a decimal between 0 and 1). Set the volume to the supplied percent (as a decimal between 0 and 1).
Example:
myPlayer.volume(0.5); // Set volume to half {% highlight javascript %}
myPlayer.volume(0.5); // Set volume to half
{% endhighlight %}
### width() ### width()
Returns the current width of the video in pixels. Returns the current width of the video in pixels.
Example:
{% highlight javascript %}
var howWideIsIt = myPlayer.width(); var howWideIsIt = myPlayer.width();
{% endhighlight %}
### width(pixels) ### width(pixels)
Change the width of the video to the supplied width in pixels. Change the width of the video to the supplied width in pixels.
Returns the player object Returns the player object
Example:
myPlayer.width(640); {% highlight javascript %}
myPlayer.width(640);
{% endhighlight %}
### height() ### height()
Returns the current height of the video in pixels. Returns the current height of the video in pixels.
Example:
var howTallIsIt = myPlayer.height(); {% highlight javascript %}
var howTallIsIt = myPlayer.height();
{% endhighlight %}
### height(pixels) ### height(pixels)
Change the height of the video to the supplied height in pixels. Change the height of the video to the supplied height in pixels.
Returns the player object Returns the player object
myPlayer.height(480); {% highlight javascript %}
myPlayer.height(480);
{% endhighlight %}
### size(width, height) ### size(width, height)
Changes the width and height of the video to the supplied width and height. This is more efficient if you're changing both width and height. Changes the width and height of the video to the supplied width and height. This is more efficient if you're changing both width and height (only triggers the player's resize event once). Returns the player object.
Returns the player object.
myPlayer.size(640,480);
### enterFullScreen() {% highlight javascript %}
Increase the size of the video to full screen. In some browsers, full screen is not supported natively, so it enters full window mode, where the fills the browser window. In browsers that support native full screen, typically the browser's default controls will be shown, and not the VideoJS custom skin. In full window mode, the VideoJS controls and skin will always be used.
myPlayer.size(640,480);
{% endhighlight %}
### requestFullScreen()
Increase the size of the video to full screen. In some browsers, full screen is not supported natively, so it enters full window mode, where the fills the browser window. In browsers that support native full screen, typically the browser's default controls will be shown, and not the Video.js custom skin. In full window mode, the Video.js controls and skin will always be used.
Returns the player object. Returns the player object.
myPlayer.enterFullScreen(); {% highlight javascript %}
### exitFullScreen() myPlayer.enterFullScreen();
{% endhighlight %}
### cancelFullScreen()
Return the video to its normal size after having been in full screen mode. Return the video to its normal size after having been in full screen mode.
Returns the player object. Returns the player object.
myPlayer.exitFullScreen(); {% highlight javascript %}
myPlayer.exitFullScreen();
{% endhighlight %}
Events Events
------ ------
You can attach event listeners to the player similarly to how you would for a video element. You can attach event listeners to the player similarly to how you would for a video element.
var myFunc = function(){ {% highlight javascript %}
// Do something when the event is fired
}; var myFunc = function(){
myPlayer.addEvent("eventName", myFunc); // Do something when the event is fired
};
myPlayer.addEvent("eventName", myFunc);
{% endhighlight %}
You can also remove the listeners later. You can also remove the listeners later.
myPlayer.removeEvent("eventName", myFunc); {% highlight javascript %}
myPlayer.removeEvent("eventName", myFunc);
{% endhighlight %}
### Event Types ### Event Types

View File

@ -1,59 +0,0 @@
---
layout: docs
title: Behvaiors
description: Video.JS Behaviors
body_id: docs
---
DEPRECATED
Behaviors
=========
Behaviors allow you to make an element on your page act as a video control or a display of video information. The easiest example of this is creating a play button. The following code will make a click on your element play the video.
myPlayer.activateElement(myElement, "playButton");
controlBar
The controlBar behavior is what's added to the main control bar to make it show/hide depending on the user's mouse and the set preferences. It can also be added to other elements if the same effect is desired.
playButton
The playButton behavior can be added to an element to make it play the video when clicked. (See also playToggle)
pauseButton
The pauseButton behavior can be added to an element to make it pause the video when clicked.
playToggle
The playToggle behavior can be added to an element to make it toggle between play and pause. When the video is playing it will pause the video, and vice versa. The play button in the default control bar works this way.
The icon in the play button changes to pause (two vertical bars) or play (triangle) depending on the state of the video. This is done through CSS classes. When the video is playing, a class of "vjs-playing" will be added to the playToggle element. When the video is paused, a class of "vjs-paused" will be added to the element. If you are using an image for the icon, set it as a background image of the element (or a sub element) and change the background image accordingly.
#my_play_toggle.vjs-playing { background-image: url("my-pause-icon.png") }
#my_play_toggle.vjs-paused { background-image: url("my-play-icon.png") }
playProgressBar
With the playProgressBar behavior, you can make an element grow like a progress bar as the video plays. The width of the element is set as a percent, and uses the video's current time divided by the video's total duration. For this reason, you may also need a container element to get the desired effect. In this example the width of the playProgressBar will be based on the width of myPlayProgressHolder.
<div id="myPlayProgressHolder">
<div id="myPlayProgressBar"></div>
</div>
loadProgressBar
The loadProgressBar behavior works similarly to the playProgressBar behavior, except that it's based on the amount of video data that's been downloaded to the users machine.
currentTimeDisplay
The currentTimeDisplay behavior will make an element display the video's current playback time in the format of 00:00. It does so by changing the innerHTML of the element to the time.
durationDisplay
The durationDisplay behavior will make an element display the video's duration in the format of 00:00. It does so by changing the innerHTML of the element to the duration.
currentTimeScrubber
The currentTimeScrubber behavior allows you to make an element that controls the current time of the video by clicking and dragging on the element. The current time will be set based on where the user clicks or drags to, in relation to the width of the element.
volumeDisplay
...
volumeScrubber
The volumeScrubber behavior allows you to make an element that controls the volume of the video by clicking and dragging on the element. The volume will be set based on where the user clicks or drags to, in relation to the width of the element.
fullscreenToggle
...
(Note to self: Have a video that is fixed position beside the behavior docs, that all examples are tied to)

View File

@ -2,7 +2,8 @@
layout: docs layout: docs
title: VideoJS Glossary title: VideoJS Glossary
description: Video.JS Glossary description: Video.JS Glossary
body_id: docs body_id: glossary
body_class: docs subpage
--- ---

View File

@ -3,6 +3,27 @@ layout: docs
title: Docs title: Docs
description: Video.JS Docs description: Video.JS Docs
body_id: docs body_id: docs
body_class: docs subpage
--- ---
Intro <h1>Start</h1>
The Video.js documentation is here to help you setup and use the player. These docs can be found and contributed to in the [Video.js library repository](https://github.com/zencoder/video-js/tree/master/docs).
### [Setup](/docs/setup)
Check out the [5 second setup](/#setup) if you're just getting started. The setup documentation gives a deeper view of the additional methods you can use to trigger the player setup.
### [Options](/docs/options/)
There are a number of options that can be used to change how the player behaves, starting with the HTML5 media options like autoplay and preload, and expanding to Video.JS specific options.
### [API](/docs/api/)
The Video.js API allows you to control the video through javascript or trigger event listeners, whether the video is playing through HTML5, flash, or another playback technology.
### [Skins](/docs/skins/)
You can change the look of the player across playback technologies just by editing a CSS file. The skins documentation gives you a intro to how the HTML and CSS of the default skin is put together.
### [Tech](/docs/tech/)
A 'playback technology' is the term we're using to represent HTML5 video, Flash, and other video plugins, as well as other players like the YouTube player. Basically anything that has a unique API to audio or video. Additional playback technologies can be added relatively easily.
### [Glossary](/docs/glossary/)
Some helpful definitions.

View File

@ -2,7 +2,8 @@
layout: docs layout: docs
title: Options title: Options
description: Player Options description: Player Options
body_id: docs body_id: options
body_class: docs subpage
--- ---
Options Options

View File

@ -2,35 +2,51 @@
layout: docs layout: docs
title: Setup title: Setup
description: Setup description: Setup
body_id: docs body_id: setup
body_class: docs subpage
--- ---
Setup Setup
===== =====
Step 1: Include the VideoJS Javascript and CSS files in the head of your page. Video.js is pretty easy to set up. It can take a matter of seconds to get the player up and working on your web page.
------------------------------------------------------------------------------
You can download the VideoJS source and host it on your own servers, or use the free CDN hosted version (thanks to Zencoder).
<script src="http://video-js.zencoder.com/3.0/video.min.js"></script> Step 1: Include the Video.js Javascript and CSS files in the head of your page.
<link href="http://video-js.zencoder.com/3.0/video-js.css" rel="stylesheet"> ------------------------------------------------------------------------------
You can download the Video.js source and host it on your own servers, or use the free CDN hosted version (thanks to Zencoder). It's often recommended now to put JavaScript before the end \</body\> tag instead of the head but Video.js includes an 'HTML5 Shiv', which needs to be in the \<head\> for older IE versions. If you
{% highlight html %}
<script src="http://vjs.zencdn.com/c/video.js"></script>
<link href="http://vjs.zencdn.com/c/video-js.css" rel="stylesheet">
{% endhighlight %}
It's often recommended now to include JavaScript before the end \</body\> tag instead of the \<head\>, but Video.js includes an 'HTML5 Shiv', which needs to be in the \<head\> for older IE versions.
Step 2: Add an HTML5 video tag to your page. Step 2: Add an HTML5 video tag to your page.
-------------------------------------------- --------------------------------------------
Use the video tag as normal, with a few extra pieces for VideoJS: Use the video tag as normal, with a few extra pieces for Video.js:
1. The 'data-setup' Atrribute tells VideoJS to automatically set up the video when the page is ready, and read any options (in JSON format) from the attribute (see ['options'](http://videojs.com/docs/options.html)). 1. The 'data-setup' Atrribute tells Video.js to automatically set up the video when the page is ready, and read any options (in JSON format) from the attribute (see ['options'](http://videojs.com/docs/options.html)).
2. The 'id' Attribute: Should be used and unique for every video on the same page. 2. The 'id' Attribute: Should be used and unique for every video on the same page.
3. The 'class' attribute contains two classes: 3. The 'class' attribute contains two classes:
- 'video-js' applies styles that are required for VideoJS functionality, like fullscreen and subtitles. - 'video-js' applies styles that are required for Video.js functionality, like fullscreen and subtitles.
- 'vjs-default-skin' applies the default skin to the HTML controls, and can be removed or overridden to create your own controls design. - 'vjs-default-skin' applies the default skin to the HTML controls, and can be removed or overridden to create your own controls design.
Otherwise include/exclude attributes, settings, sources, and tracks exactly as you would for HTML5 video (see ['video-tag'](http://videojs.com/docs/video-tag.html)). Otherwise include/exclude attributes, settings, sources, and tracks exactly as you would for HTML5 video (see ['video-tag'](http://videojs.com/docs/video-tag.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" {% highlight html %}
data-setup='{"example_option":true}'>
<source src="http://video-js.zencoder.com/oceans-clip.mp4" type='video/mp4' /> <video id="example_video_1" class="video-js vjs-default-skin"
<source src="http://video-js.zencoder.com/oceans-clip.webm" type='video/webm' /> controls preload="auto" width="640" height="264"
<source src="http://video-js.zencoder.com/oceans-clip.ogv" type='video/ogg' /> poster="http://video-js.zencoder.com/oceans-clip.png"
</video> 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>
{% endhighlight %}

0
docs/skins.md Normal file
View File

View File

@ -2,7 +2,8 @@
layout: docs layout: docs
title: Playback Technology title: Playback Technology
description: Video.JS Playback Technology description: Video.JS Playback Technology
body_id: docs body_id: tech
body_class: docs subpage
--- ---
Playback Technology ("Tech") Playback Technology ("Tech")

View File

@ -138,7 +138,7 @@ _V_.Component = _V_.Class.extend({
/* Ready - Trigger functions when component is ready /* Ready - Trigger functions when component is ready
================================================================================ */ ================================================================================ */
ready: function(fn){ ready: function(fn){
if (!fn) return; if (!fn) return this;
if (this.isReady) { if (this.isReady) {
fn.call(this); fn.call(this);
@ -148,6 +148,8 @@ _V_.Component = _V_.Class.extend({
} }
this.readyQueue.push(fn); this.readyQueue.push(fn);
} }
return this;
}, },
triggerReady: function(){ triggerReady: function(){

10
src/controls.js vendored
View File

@ -28,8 +28,6 @@ _V_.Button = _V_.Control.extend({
role: "button", role: "button",
tabIndex: 0 tabIndex: 0
}, attrs); }, attrs);
_V_.log(attrs)
return this._super(type, attrs); return this._super(type, attrs);
}, },
@ -143,9 +141,9 @@ _V_.FullscreenToggle = _V_.Button.extend({
onClick: function(){ onClick: function(){
if (!this.player.videoIsFullScreen) { if (!this.player.videoIsFullScreen) {
this.player.enterFullScreen(); this.player.requestFullScreen();
} else { } else {
this.player.exitFullScreen(); this.player.cancelFullScreen();
} }
} }
@ -717,6 +715,10 @@ _V_.Poster = _V_.Button.extend({
init: function(player, options){ init: function(player, options){
this._super(player, options); this._super(player, options);
if (!this.player.options.poster) {
this.hide();
}
player.addEvent("play", _V_.proxy(this, this.hide)); player.addEvent("play", _V_.proxy(this, this.hide));
}, },

View File

@ -13,17 +13,6 @@ _V_.extend({
tech: {}, // Holder for playback technology settings tech: {}, // Holder for playback technology settings
controlSets: {}, // Holder for control set definitions controlSets: {}, // Holder for control set definitions
techSupports: function(tech, type, name){
if (_V_[tech].supports[type]) {
return _V_[tech].supports[type][name];
}
return false;
},
updateTechSupport: function(tech, type, name, value){
if (_V_[tech].supports[type] === undefined) { _V_[tech].supports[type] = {}; }
_V_[tech].supports[type][name] = value;
},
// Device Checks // Device Checks
isIE: function(){ return !+"\v1"; }, isIE: function(){ return !+"\v1"; },
isIPad: function(){ return navigator.userAgent.match(/iPad/i) !== null; }, isIPad: function(){ return navigator.userAgent.match(/iPad/i) !== null; },
@ -38,7 +27,10 @@ _V_.extend({
var match = navigator.userAgent.match(/Android (\d+)\./i); var match = navigator.userAgent.match(/Android (\d+)\./i);
if (match && match[1]) { return match[1]; } if (match && match[1]) { return match[1]; }
}, },
//isAndroidBrowser
testVid: document.createElement("video"),
ua: navigator.userAgent,
support: {},
each: function(arr, fn){ each: function(arr, fn){
if (!arr || arr.length === 0) { return; } if (!arr || arr.length === 0) { return; }

View File

@ -168,20 +168,13 @@ _V_.Player = _V_.Component.extend({
// Pause and remove current playback technology // Pause and remove current playback technology
if (this.tech) { if (this.tech) {
this.unloadTech();
this.tech.destroy();
// Turn off any manual progress or timeupdate tracking
if (this.manualProgress) { this.manualProgressOff(); }
if (this.manualTimeUpdates) { this.manualTimeUpdatesOff(); }
this.tech = false;
// If the first time loading, HTML5 tag will exist but won't be initialized // If the first time loading, HTML5 tag will exist but won't be initialized
// So we need to remove it if we're not loading HTML5 // So we need to remove it if we're not loading HTML5
} else if (techName != "html5") { } else if (techName != "html5" && this.tag) {
this.el.removeChild(this.tag); this.el.removeChild(this.tag);
this.tag = false;
} }
this.techName = techName; this.techName = techName;
@ -190,17 +183,15 @@ _V_.Player = _V_.Component.extend({
this.isReady = false; this.isReady = false;
var techReady = function(){ var techReady = function(){
_V_.log("ready")
this.player.triggerReady(); this.player.triggerReady();
// Manually track progress in cases where the browser/flash player doesn't report it. // Manually track progress in cases where the browser/flash player doesn't report it.
if (!_V_.techSupports(this.player.techName, "event", "progress")) { if (!this.support.progressEvent) {
this.player.manualProgressOn(); this.player.manualProgressOn();
} }
// Manually track timeudpates in cases where the browser/flash player doesn't report it. // Manually track timeudpates in cases where the browser/flash player doesn't report it.
if (!_V_.techSupports(this.player.techName, "event", "timeupdate")) { if (!this.support.timeupdateEvent) {
this.player.manualTimeUpdatesOn(); this.player.manualTimeUpdatesOn();
} }
} }
@ -208,11 +199,44 @@ _V_.Player = _V_.Component.extend({
// Grab tech-specific options from player options and add source and parent element to use. // 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 = _V_.merge({ source: source, parentEl: this.el }, this.options[techName])
if (source.src == this.values.src && this.values.currentTime > 0) {
techOptions.startTime = this.values.currentTime;
}
if (source) {
this.values.src = source.src;
}
// Initialize tech instance // Initialize tech instance
this.tech = new _V_[techName](this, techOptions); this.tech = new _V_[techName](this, techOptions);
this.tech.ready(techReady); this.tech.ready(techReady);
}, },
unloadTech: function(){
this.tech.destroy();
// Turn off any manual progress or timeupdate tracking
if (this.manualProgress) { this.manualProgressOff(); }
if (this.manualTimeUpdates) { this.manualTimeUpdatesOff(); }
this.tech = false;
},
// There's many issues around changing the size of a Flash (or other plugin) object.
// First is a plugin reload issue in Firefox that has been around for 11 years: https://bugzilla.mozilla.org/show_bug.cgi?id=90268
// 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")
this.unloadTech();
_V_.log("unloadedTech")
if (betweenFn) { betweenFn.call(); }
_V_.log("LoadingTech")
this.loadTech(this.techName, { src: this.values.src })
_V_.log("loadedTech")
},
/* Fallbacks for unsupported event types /* Fallbacks for unsupported event types
================================================================================ */ ================================================================================ */
// Manually trigger progress events based on changes to the buffered amount // Manually trigger progress events based on changes to the buffered amount
@ -232,7 +256,7 @@ _V_.Player = _V_.Component.extend({
this.removeEvent("progress", arguments.callee); this.removeEvent("progress", arguments.callee);
// Update known progress support for this playback technology // Update known progress support for this playback technology
_V_.updateTechSupport(this.player.techName, "event", "progress", true); this.support.progressEvent = true;
// Turn off manual progress tracking // Turn off manual progress tracking
this.player.manualProgressOff(); this.player.manualProgressOff();
@ -274,7 +298,7 @@ _V_.Player = _V_.Component.extend({
this.removeEvent("timeupdate", arguments.callee); this.removeEvent("timeupdate", arguments.callee);
// Update known progress support for this playback technology // Update known progress support for this playback technology
_V_.updateTechSupport(this.player.techName, "event", "timeupdate", true); this.support.timeupdateEvent = true;
// Turn off manual progress tracking // Turn off manual progress tracking
this.player.manualTimeUpdatesOff(); this.player.manualTimeUpdatesOff();
@ -323,19 +347,16 @@ _V_.Player = _V_.Component.extend({
onError: function(e) { onError: function(e) {
_V_.log("Video Error", e); _V_.log("Video Error", e);
} },
});
/* Player API /* Player API
================================================================================ */ ================================================================================ */
_V_.Player.prototype.extend({
apiCall: function(method, arg){ apiCall: function(method, arg){
if (this.isReady) { if (this.isReady) {
return this.tech[method](arg); return this.tech[method](arg);
} else { } else {
_V_.log("The playback technology API is not ready yet. Use player.ready(myFunction)."+" ["+method+"]") _V_.log("The playback technology API is not ready yet. Use player.ready(myFunction)."+" ["+method+"]", arguments.callee.caller.arguments.callee.caller.arguments.callee.caller)
return false; return false;
// throw new Error("The playback technology API is not ready yet. Use player.ready(myFunction)."+" ["+method+"]"); // throw new Error("The playback technology API is not ready yet. Use player.ready(myFunction)."+" ["+method+"]");
} }
@ -355,7 +376,7 @@ _V_.Player.prototype.extend({
if (seconds !== undefined) { if (seconds !== undefined) {
// Cache the last set value for smoother scrubbing. // Cache the last set value for smoother scrubbing.
this.values.currentTime = seconds; this.values.lastSetCurrentTime = seconds;
this.apiCall("setCurrentTime", seconds); this.apiCall("setCurrentTime", seconds);
@ -364,7 +385,9 @@ _V_.Player.prototype.extend({
} }
return this; return this;
} }
return this.apiCall("currentTime");
// Cache last currentTime and return
return this.values.currentTime = this.apiCall("currentTime");
}, },
duration: function(){ duration: function(){
return this.apiCall("duration"); return this.apiCall("duration");
@ -437,33 +460,81 @@ _V_.Player.prototype.extend({
supportsFullScreen: function(){ return this.apiCall("supportsFullScreen"); }, supportsFullScreen: function(){ return this.apiCall("supportsFullScreen"); },
// Turn on fullscreen (or window) mode // Turn on fullscreen (or window) mode
enterFullScreen: function(){ requestFullScreen: function(){
this.videoIsFullScreen = true; var requestFullScreen = _V_.support.requestFullScreen;
if (typeof this.el.webkitRequestFullScreen == 'function') {
this.el.webkitRequestFullScreen(); // Check for browser element fullscreen support
} else if (typeof this.el.mozRequestFullScreen == 'function') { if (requestFullScreen) {
this.el.mozRequestFullScreen(); // Flash and other plugins get reloaded when you take their parent to fullscreen.
} else if (this.supportsFullScreen()) { // To fix that we'll remove the tech, and reload it after the resize has finished.
this.apiCall("enterFullScreen"); if (this.tech.support.fullscreenResize === false) {
} else {
this.enterFullWindow(); this.pause();
} this.unloadTech();
this.triggerEvent("enterFullScreen");
_V_.addEvent(document, "keydown", _V_.proxy(this, function(e){
_V_.log("asdf", e)
}));
_V_.addEvent(document, requestFullScreen.eventName, this.proxy(function(){
_V_.removeEvent(document, requestFullScreen.eventName, arguments.callee);
this.loadTech(this.techName, { src: this.values.src });
}));
this.el[requestFullScreen.requestFn]();
} else {
this.el[requestFullScreen.requestFn]();
}
} else if (this.tech.supportsFullScreen()) {
this.apiCall("enterFullScreen");
} else {
this.enterFullWindow();
}
this.videoIsFullScreen = true;
this.triggerEvent("fullscreenchange");
return this; return this;
}, },
exitFullScreen: function(){ cancelFullScreen: function(){
this.videoIsFullScreen = false; var requestFullScreen = _V_.support.requestFullScreen;
if (typeof this.el.webkitRequestFullScreen == 'function') {
document.webkitCancelFullScreen(); // Check for browser element fullscreen support
} else if (this.supportsFullScreen()) { if (requestFullScreen) {
document.webkitExitFullScreen();
} else { // Flash and other plugins get reloaded when you take their parent to fullscreen.
this.exitFullWindow(); // To fix that we'll remove the tech, and reload it after the resize has finished.
} if (this.tech.support.fullscreenResize === false) {
this.triggerEvent("exitFullScreen");
this.pause();
this.unloadTech();
_V_.addEvent(document, requestFullScreen.eventName, this.proxy(function(){
_V_.removeEvent(document, requestFullScreen.eventName, arguments.callee);
_V_.log("document fullscreeneventchange")
this.loadTech(this.techName, { src: this.values.src })
}));
document[requestFullScreen.cancelFn]();
} else {
document[requestFullScreen.cancelFn]();
}
} else if (this.tech.supportsFullScreen()) {
this.apiCall("exitFullScreen");
} else {
this.exitFullWindow();
}
this.videoIsFullScreen = false;
this.triggerEvent("fullscreenchange");
// Otherwise Shouldn't be called since native fullscreen uses own controls.
return this; return this;
}, },
@ -488,7 +559,7 @@ _V_.Player.prototype.extend({
fullWindowOnEscKey: function(event){ fullWindowOnEscKey: function(event){
if (event.keyCode == 27) { if (event.keyCode == 27) {
this.exitFullScreen(); this.cancelFullScreen();
} }
}, },
@ -561,6 +632,9 @@ _V_.Player.prototype.extend({
} }
// Case: URL String (http://myvideo...) // Case: URL String (http://myvideo...)
} else { } else {
// Cache for getting last set source
this.values.src = source;
if (!this.isReady) { if (!this.isReady) {
this.ready(function(){ this.ready(function(){
this.src(source); this.src(source);
@ -647,3 +721,44 @@ _V_.Player.prototype.extend({
defaultMuted: function(){ return this.apiCall("defaultMuted"); } defaultMuted: function(){ return this.apiCall("defaultMuted"); }
}); });
// RequestFullscreen API
(function(){
var requestFn,
cancelFn,
playerProto = _V_.Player.prototype;
// Current W3C Spec
// http://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html#api
// Mozilla Draft: https://wiki.mozilla.org/Gecko:FullScreenAPI#fullscreenchange_event
if (document.cancelFullscreen !== undefined) {
requestFn = "requestFullscreen";
cancelFn = "exitFullscreen";
eventName = "fullscreenchange";
// Webkit (Chrome/Safari) and Mozilla (Firefox) have working implementaitons
// that use prefixes and vary slightly from the new W3C spec. Specifically, using 'exit' instead of 'cancel',
// and lowercasing the 'S' in Fullscreen.
// Other browsers don't have any hints of which version they might follow yet, so not going to try to predict by loopeing through all prefixes.
} else {
_V_.each(["moz", "webkit"], function(prefix){
if (document[prefix + "CancelFullScreen"] !== undefined) {
requestFn = prefix + "RequestFullScreen";
cancelFn = prefix + "CancelFullScreen";
eventName = prefix + "fullscreenchange";
}
});
}
if (requestFn) {
_V_.support.requestFullScreen = {
requestFn: requestFn,
cancelFn: cancelFn,
eventName: eventName
};
}
})();

View File

@ -7,10 +7,17 @@ _V_.PlaybackTech = _V_.Component.extend({
// Make playback element clickable // Make playback element clickable
// _V_.addEvent(this.el, "click", _V_.proxy(this, _V_.PlayToggle.prototype.onClick)); // _V_.addEvent(this.el, "click", _V_.proxy(this, _V_.PlayToggle.prototype.onClick));
// this.addEvent("click", this.proxy(this.onClick));
// player.triggerEvent("techready"); // player.triggerEvent("techready");
} },
// destroy: function(){}, // destroy: function(){},
// createElement: function(){}, // createElement: function(){},
onClick: function(){
if (this.player.options.controls) {
_V_.PlayToggle.prototype.onClick.call(this);
}
}
}); });
// Create placeholder methods for each that warn when a method isn't supported by the current playback technology // Create placeholder methods for each that warn when a method isn't supported by the current playback technology
@ -29,7 +36,8 @@ _V_.html5 = _V_.PlaybackTech.extend({
this.player = player; this.player = player;
this.el = this.createElement(); this.el = this.createElement();
this.ready(ready); this.ready(ready);
_V_.addEvent(this.el, "click", _V_.proxy(this, _V_.PlayToggle.prototype.onClick));
this.addEvent("click", this.proxy(this.onClick));
var source = options.source; var source = options.source;
@ -61,6 +69,7 @@ _V_.html5 = _V_.PlaybackTech.extend({
destroy: function(){ destroy: function(){
this.player.tag = false; this.player.tag = false;
this.removeTriggers();
this.el.parentNode.removeChild(this.el); this.el.parentNode.removeChild(this.el);
}, },
@ -75,7 +84,7 @@ _V_.html5 = _V_.PlaybackTech.extend({
// Check if this browser supports moving the element into the box. // Check if this browser supports moving the element into the box.
// On the iPhone video will break if you move the element, // On the iPhone video will break if you move the element,
// So we have to create a brand new element. // So we have to create a brand new element.
if (!el || html5.supports.movingElementInDOM === false) { if (!el || this.support.movingElementInDOM === false) {
// If the original tag is still there, remove it. // If the original tag is still there, remove it.
if (el) { if (el) {
@ -99,21 +108,22 @@ _V_.html5 = _V_.PlaybackTech.extend({
return el; return el;
}, },
// Make video events trigger player events
// May seem verbose here, but makes other APIs possible.
setupTriggers: function(){ setupTriggers: function(){
// Make video events trigger player events _V_.each.call(this, _V_.html5.events, function(type){
// May seem verbose here, but makes other APIs possible. _V_.addEvent(this.el, type, _V_.proxy(this.player, this.eventHandler));
});
// ["play", "playing", "pause", "ended", "volumechange", "error", "progress", "seeking", "timeupdate"] },
var types = _V_.html5.events, removeTriggers: function(){
i; _V_.each.call(this, _V_.html5.events, function(type){
for (i = 0;i<types.length; i++) { _V_.removeEvent(this.el, type, _V_.proxy(this.player, this.eventHandler));
_V_.addEvent(this.el, types[i], _V_.proxy(this.player, function(e){ });
e.stopPropagation(); },
this.triggerEvent(e); eventHandler: function(e){
})); e.stopPropagation();
} this.triggerEvent(e);
}, },
removeTriggers: function(){},
play: function(){ this.el.play(); }, play: function(){ this.el.play(); },
pause: function(){ this.el.pause(); }, pause: function(){ this.el.pause(); },
@ -148,8 +158,9 @@ _V_.html5 = _V_.PlaybackTech.extend({
return true; return true;
} }
} }
return false; return false;
}, },
enterFullScreen: function(){ enterFullScreen: function(){
try { try {
this.el.webkitEnterFullScreen(); this.el.webkitEnterFullScreen();
@ -206,18 +217,22 @@ _V_.html5.canPlaySource = function(srcObj){
// Check Media Type // Check Media Type
}; };
_V_.html5.supports = {};
// List of all HTML5 events (various uses). // 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(","); _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(",");
/* HTML5 Device Fixes ---------------------------------------------------------- */ /* HTML5 Device Fixes ---------------------------------------------------------- */
// iOS _V_.html5.prototype.support = {
if (_V_.isIOS()) {
// If you move a video element in the DOM, it breaks video playback. // Support for tech specific full screen. (webkitEnterFullScreen, not requestFullscreen)
_V_.html5.supports.movingElementInDOM = false; // http://developer.apple.com/library/safari/#documentation/AudioVideo/Reference/HTMLVideoElementClassReference/HTMLVideoElement/HTMLVideoElement.html
} // Seems to be broken in Chromium/Chrome && Safari in Leopard
fullscreen: (typeof _V_.testVid.webkitEnterFullScreen !== undefined) ? (!_V_.ua.match("Chrome") && !_V_.ua.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_.isIOS()
};
// Android // Android
if (_V_.isAndroid()) { if (_V_.isAndroid()) {
@ -285,6 +300,14 @@ _V_.flash = _V_.PlaybackTech.extend({
// Add to box. // Add to box.
_V_.insertFirst(placeHolder, parentEl); _V_.insertFirst(placeHolder, parentEl);
if (options.startTime) {
this.ready(function(){
this.load();
this.play();
this.currentTime(options.startTime);
});
}
swfobject.embedSWF(options.swf, placeHolder.id, "480", "270", "9.0.124", "", flashVars, params, attributes); swfobject.embedSWF(options.swf, placeHolder.id, "480", "270", "9.0.124", "", flashVars, params, attributes);
}, },
@ -310,7 +333,11 @@ _V_.flash = _V_.PlaybackTech.extend({
poster: function(){ this.el.vjs_getProperty("poster"); }, poster: function(){ this.el.vjs_getProperty("poster"); },
buffered: function(){ buffered: function(){
return _V_.createTimeRange(0, this.el.vjs_getProperty("buffered")); try {
return _V_.createTimeRange(0, this.el.vjs_getProperty("buffered"));
} catch(e) {
_V_.log(e, arguments.callee.caller.arguments.callee.caller)
}
}, },
supportsFullScreen: function(){ supportsFullScreen: function(){
@ -353,15 +380,15 @@ _V_.flash = _V_.PlaybackTech.extend({
/* Flash Support Testing -------------------------------------------------------- */ /* Flash Support Testing -------------------------------------------------------- */
_V_.flash.isSupported = function(){ _V_.flash.isSupported = function(){
return swfobject.hasFlashPlayerVersion("9"); return swfobject.hasFlashPlayerVersion("10");
}; };
_V_.flash.canPlaySource = function(srcObj){ _V_.flash.canPlaySource = function(srcObj){
if (srcObj.type in _V_.flash.supports.format) { return "maybe"; } if (srcObj.type in _V_.flash.prototype.support.formats) { return "maybe"; }
}; };
_V_.flash.supports = { _V_.flash.prototype.support = {
format: { formats: {
"video/flv": "FLV", "video/flv": "FLV",
"video/x-flv": "FLV", "video/x-flv": "FLV",
"video/mp4": "MP4", "video/mp4": "MP4",
@ -369,15 +396,19 @@ _V_.flash.supports = {
}, },
// Optional events that we can manually mimic with timers // Optional events that we can manually mimic with timers
event: { progressEvent: false,
progress: false, timeupdateEvent: false,
timeupdate: 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"))
}; };
_V_.flash.onSWFReady = function(currSwf){ _V_.flash.onSWFReady = function(currSwf){
_V_.log(currSwf, "currSwf") _V_.log("swfReady", currSwf)
var el = _V_.el(currSwf); var el = _V_.el(currSwf);
@ -392,8 +423,8 @@ _V_.flash.onSWFReady = function(currSwf){
// Update reference to playback technology element // Update reference to playback technology element
tech.el = el; tech.el = el;
// Make a click on the swf play the video // Now that the element is ready, make a click on the swf play the video
_V_.addEvent(el, "click", _V_.proxy(player, _V_.PlayToggle.prototype.onClick)); tech.addEvent("click", tech.onClick);
_V_.flash.checkReady(tech); _V_.flash.checkReady(tech);
}; };
@ -413,7 +444,7 @@ _V_.flash.checkReady = function(tech){
_V_.flash.onSWFEvent = function(swfID, eventName, other){ _V_.flash.onSWFEvent = function(swfID, eventName, other){
try { try {
var player = _V_.el(swfID).player; var player = _V_.el(swfID).player;
if (player) { if (player && player.techName == "flash") {
player.triggerEvent(eventName); player.triggerEvent(eventName);
} }
} catch(err) { } catch(err) {