Make VideoAlpha out of Alpha.
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
// ====================
|
||||
|
||||
// Video Alpha
|
||||
.xmodule_VideoAlphaModule {
|
||||
.xmodule_VideoModule {
|
||||
|
||||
// display mode
|
||||
&.xmodule_display {
|
||||
|
||||
@@ -10,11 +10,30 @@ div.video {
|
||||
padding: 12px;
|
||||
border-radius: 5px;
|
||||
|
||||
div.tc-wrapper {
|
||||
position: relative;
|
||||
@include clearfix;
|
||||
}
|
||||
|
||||
article.video-wrapper {
|
||||
float: left;
|
||||
margin-right: flex-gutter(9);
|
||||
width: flex-grid(6, 9);
|
||||
|
||||
background-color: black;
|
||||
|
||||
position: relative;
|
||||
|
||||
div.video-player-pre {
|
||||
height: 50px;
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
div.video-player-post {
|
||||
height: 50px;
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
section.video-player {
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
@@ -52,10 +71,19 @@ div.video {
|
||||
border-radius: 0;
|
||||
border-top: 1px solid #000;
|
||||
box-shadow: inset 0 1px 0 #eee, 0 1px 0 #555;
|
||||
height: 7px;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
bottom: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 14px;
|
||||
margin-left: -1px;
|
||||
margin-right: -1px;
|
||||
@include transition(height 2.0s ease-in-out 0s);
|
||||
-webkit-transition: -webkit-transform 0.7s ease-in-out;
|
||||
-moz-transition: -moz-transform 0.7s ease-in-out;
|
||||
-ms-transition: -ms-transform 0.7s ease-in-out;
|
||||
transition: transform 0.7s ease-in-out;
|
||||
@include transform(scaleY(0.5) translate3d(0, 50%, 0));
|
||||
|
||||
div.ui-widget-header {
|
||||
background: #777;
|
||||
@@ -66,14 +94,18 @@ div.video {
|
||||
background: $pink url(../images/slider-handle.png) center center no-repeat;
|
||||
background-size: 50%;
|
||||
border: 1px solid darken($pink, 20%);
|
||||
border-radius: 15px;
|
||||
border-radius: 50%;
|
||||
box-shadow: inset 0 1px 0 lighten($pink, 10%);
|
||||
cursor: pointer;
|
||||
height: 15px;
|
||||
margin-left: -7px;
|
||||
top: -4px;
|
||||
@include transition(height 2.0s ease-in-out 0s, width 2.0s ease-in-out 0s);
|
||||
width: 15px;
|
||||
height: 20px;
|
||||
margin-left: 0;
|
||||
top: 0;
|
||||
-webkit-transition: -webkit-transform 0.7s ease-in-out;
|
||||
-moz-transition: -moz-transform 0.7s ease-in-out;
|
||||
-ms-transition: -ms-transform 0.7s ease-in-out;
|
||||
transition: transform 0.7s ease-in-out;
|
||||
@include transform(scale(.7, 1.3) translate3d(-80%, -15%, 0));
|
||||
width: 20px;
|
||||
|
||||
&:focus, &:hover {
|
||||
background-color: lighten($pink, 10%);
|
||||
@@ -101,7 +133,6 @@ div.video {
|
||||
line-height: 46px;
|
||||
padding: 0 lh(.75);
|
||||
text-indent: -9999px;
|
||||
@include transition(background-color 0.75s linear 0s, opacity 0.75s linear 0s);
|
||||
width: 14px;
|
||||
background: url('../images/vcr.png') 15px 15px no-repeat;
|
||||
outline: 0;
|
||||
@@ -118,7 +149,7 @@ div.video {
|
||||
&.play {
|
||||
background-position: 17px -114px;
|
||||
|
||||
&:hover {
|
||||
&:hover, &:focus {
|
||||
background-color: #444;
|
||||
}
|
||||
}
|
||||
@@ -126,7 +157,7 @@ div.video {
|
||||
&.pause {
|
||||
background-position: 16px -50px;
|
||||
|
||||
&:hover {
|
||||
&:hover, &:focus {
|
||||
background-color: #444;
|
||||
}
|
||||
}
|
||||
@@ -213,7 +244,7 @@ div.video {
|
||||
|
||||
// fix for now
|
||||
ol.video_speeds {
|
||||
box-shadow: inset 1px 0 0 #555, 0 3px 0 #444;
|
||||
box-shadow: inset 1px 0 0 #555, 0 4px 0 #444;
|
||||
@include transition(none);
|
||||
background-color: #444;
|
||||
border: 1px solid #000;
|
||||
@@ -221,7 +252,7 @@ div.video {
|
||||
display: none;
|
||||
opacity: 0.0;
|
||||
position: absolute;
|
||||
width: 133px;
|
||||
width: 131px;
|
||||
z-index: 10;
|
||||
|
||||
li {
|
||||
@@ -268,12 +299,15 @@ div.video {
|
||||
|
||||
&.muted {
|
||||
&>a {
|
||||
background: url('../images/mute.png') 10px center no-repeat;
|
||||
background-image: url('../images/mute.png');
|
||||
}
|
||||
}
|
||||
|
||||
> a {
|
||||
background: url('../images/volume.png') 10px center no-repeat;
|
||||
background-image: url('../images/volume.png');
|
||||
background-position: 10px center;
|
||||
background-repeat: no-repeat;
|
||||
|
||||
border-right: 1px solid #000;
|
||||
box-shadow: 1px 0 0 #555, inset 1px 0 0 #555;
|
||||
@include clearfix();
|
||||
@@ -350,7 +384,7 @@ div.video {
|
||||
@include transition(none);
|
||||
width: 30px;
|
||||
|
||||
&:hover {
|
||||
&:hover, &:active, &:focus {
|
||||
background-color: #444;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
@@ -362,7 +396,7 @@ div.video {
|
||||
border-right: 1px solid #000;
|
||||
box-shadow: 1px 0 0 #555, inset 1px 0 0 #555;
|
||||
color: #797979;
|
||||
display: block;
|
||||
display: none;
|
||||
float: left;
|
||||
line-height: 46px; //height of play pause buttons
|
||||
margin-left: 0;
|
||||
@@ -371,7 +405,7 @@ div.video {
|
||||
@include transition(none);
|
||||
width: 30px;
|
||||
|
||||
&:hover {
|
||||
&:hover, &:focus {
|
||||
background-color: #444;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
@@ -387,8 +421,6 @@ div.video {
|
||||
|
||||
a.hide-subtitles {
|
||||
background: url('../images/cc.png') center no-repeat;
|
||||
color: #797979;
|
||||
display: block;
|
||||
float: left;
|
||||
font-weight: 800;
|
||||
line-height: 46px; //height of play pause buttons
|
||||
@@ -401,7 +433,7 @@ div.video {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
width: 30px;
|
||||
|
||||
&:hover {
|
||||
&:hover, &:focus {
|
||||
background-color: #444;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
@@ -410,6 +442,8 @@ div.video {
|
||||
&.off {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
color: #797979;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -420,15 +454,10 @@ div.video {
|
||||
}
|
||||
|
||||
div.slider {
|
||||
height: 14px;
|
||||
margin-top: -7px;
|
||||
@include transform(scaleY(1) translate3d(0, 0, 0));
|
||||
|
||||
a.ui-slider-handle {
|
||||
border-radius: 20px;
|
||||
height: 20px;
|
||||
margin-left: -10px;
|
||||
top: -4px;
|
||||
width: 20px;
|
||||
@include transform(scale(1) translate3d(-50%, -15%, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -471,22 +500,47 @@ div.video {
|
||||
|
||||
article.video-wrapper {
|
||||
width: flex-grid(9,9);
|
||||
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
article.video-wrapper section.video-controls.html5 {
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
article.video-wrapper div.video-player-pre, article.video-wrapper div.video-player-post {
|
||||
height: 0px;
|
||||
}
|
||||
|
||||
ol.subtitles {
|
||||
width: 0;
|
||||
height: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
ol.subtitles.html5 {
|
||||
background-color: rgba(243, 243, 243, 0.8);
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
width: 275px;
|
||||
padding: 0 20px;
|
||||
z-index: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.fullscreen {
|
||||
&.video-fullscreen {
|
||||
background: rgba(#000, .95);
|
||||
border: 0;
|
||||
bottom: 0;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
@@ -501,12 +555,22 @@ div.video {
|
||||
}
|
||||
}
|
||||
|
||||
article.video-wrapper div.video-player-pre, article.video-wrapper div.video-player-post {
|
||||
height: 0px;
|
||||
}
|
||||
|
||||
article.video-wrapper {
|
||||
position: static;
|
||||
}
|
||||
|
||||
div.tc-wrapper {
|
||||
@include clearfix;
|
||||
display: table;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
position: static;
|
||||
|
||||
article.video-wrapper {
|
||||
width: 100%;
|
||||
display: table-cell;
|
||||
@@ -536,7 +600,7 @@ div.video {
|
||||
background: rgba(#000, .8);
|
||||
bottom: 0;
|
||||
height: 100%;
|
||||
max-height: 100%;
|
||||
max-height: 460px;
|
||||
max-width: flex-grid(3);
|
||||
padding: lh();
|
||||
position: fixed;
|
||||
|
||||
@@ -1,620 +0,0 @@
|
||||
& {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
div.videoalpha {
|
||||
@include clearfix();
|
||||
background: #f3f3f3;
|
||||
display: block;
|
||||
margin: 0 -12px;
|
||||
padding: 12px;
|
||||
border-radius: 5px;
|
||||
|
||||
div.tc-wrapper {
|
||||
position: relative;
|
||||
@include clearfix;
|
||||
}
|
||||
|
||||
article.video-wrapper {
|
||||
float: left;
|
||||
margin-right: flex-gutter(9);
|
||||
width: flex-grid(6, 9);
|
||||
|
||||
background-color: black;
|
||||
|
||||
position: relative;
|
||||
|
||||
div.video-player-pre {
|
||||
height: 50px;
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
div.video-player-post {
|
||||
height: 50px;
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
section.video-player {
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
padding-bottom: 56.25%;
|
||||
position: relative;
|
||||
|
||||
object, iframe {
|
||||
border: none;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
section.video-controls {
|
||||
@include clearfix();
|
||||
background: #333;
|
||||
border: 1px solid #000;
|
||||
border-top: 0;
|
||||
color: #ccc;
|
||||
position: relative;
|
||||
|
||||
&:hover {
|
||||
ul, div {
|
||||
opacity: 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
div.slider {
|
||||
@include clearfix();
|
||||
background: #c2c2c2;
|
||||
border: 1px solid #000;
|
||||
border-radius: 0;
|
||||
border-top: 1px solid #000;
|
||||
box-shadow: inset 0 1px 0 #eee, 0 1px 0 #555;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
bottom: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 14px;
|
||||
margin-left: -1px;
|
||||
margin-right: -1px;
|
||||
-webkit-transition: -webkit-transform 0.7s ease-in-out;
|
||||
-moz-transition: -moz-transform 0.7s ease-in-out;
|
||||
-ms-transition: -ms-transform 0.7s ease-in-out;
|
||||
transition: transform 0.7s ease-in-out;
|
||||
@include transform(scaleY(0.5) translate3d(0, 50%, 0));
|
||||
|
||||
div.ui-widget-header {
|
||||
background: #777;
|
||||
box-shadow: inset 0 1px 0 #999;
|
||||
}
|
||||
|
||||
a.ui-slider-handle {
|
||||
background: $pink url(../images/slider-handle.png) center center no-repeat;
|
||||
background-size: 50%;
|
||||
border: 1px solid darken($pink, 20%);
|
||||
border-radius: 50%;
|
||||
box-shadow: inset 0 1px 0 lighten($pink, 10%);
|
||||
cursor: pointer;
|
||||
height: 20px;
|
||||
margin-left: 0;
|
||||
top: 0;
|
||||
-webkit-transition: -webkit-transform 0.7s ease-in-out;
|
||||
-moz-transition: -moz-transform 0.7s ease-in-out;
|
||||
-ms-transition: -ms-transform 0.7s ease-in-out;
|
||||
transition: transform 0.7s ease-in-out;
|
||||
@include transform(scale(.7, 1.3) translate3d(-80%, -15%, 0));
|
||||
width: 20px;
|
||||
|
||||
&:focus, &:hover {
|
||||
background-color: lighten($pink, 10%);
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ul.vcr {
|
||||
float: left;
|
||||
list-style: none;
|
||||
margin: 0 lh() 0 0;
|
||||
padding: 0;
|
||||
|
||||
li {
|
||||
float: left;
|
||||
margin-bottom: 0;
|
||||
|
||||
a {
|
||||
border-bottom: none;
|
||||
border-right: 1px solid #000;
|
||||
box-shadow: 1px 0 0 #555;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
line-height: 46px;
|
||||
padding: 0 lh(.75);
|
||||
text-indent: -9999px;
|
||||
width: 14px;
|
||||
background: url('../images/vcr.png') 15px 15px no-repeat;
|
||||
outline: 0;
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
&:empty {
|
||||
height: 46px;
|
||||
background: url('../images/vcr.png') 15px 15px no-repeat;
|
||||
}
|
||||
|
||||
&.play {
|
||||
background-position: 17px -114px;
|
||||
|
||||
&:hover, &:focus {
|
||||
background-color: #444;
|
||||
}
|
||||
}
|
||||
|
||||
&.pause {
|
||||
background-position: 16px -50px;
|
||||
|
||||
&:hover, &:focus {
|
||||
background-color: #444;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
div.vidtime {
|
||||
padding-left: lh(.75);
|
||||
font-weight: bold;
|
||||
line-height: 46px; //height of play pause buttons
|
||||
padding-left: lh(.75);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
div.secondary-controls {
|
||||
float: right;
|
||||
|
||||
div.speeds {
|
||||
float: left;
|
||||
position: relative;
|
||||
|
||||
&.open {
|
||||
&>a {
|
||||
background: url('../images/open-arrow.png') 10px center no-repeat;
|
||||
}
|
||||
|
||||
ol.video_speeds {
|
||||
display: block;
|
||||
opacity: 1.0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
}
|
||||
}
|
||||
|
||||
&>a {
|
||||
background: url('../images/closed-arrow.png') 10px center no-repeat;
|
||||
border-left: 1px solid #000;
|
||||
border-right: 1px solid #000;
|
||||
box-shadow: 1px 0 0 #555, inset 1px 0 0 #555;
|
||||
@include clearfix();
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
line-height: 46px; //height of play pause buttons
|
||||
margin-right: 0;
|
||||
padding-left: 15px;
|
||||
position: relative;
|
||||
@include transition(none);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
width: 116px;
|
||||
outline: 0;
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
h3 {
|
||||
color: #999;
|
||||
float: left;
|
||||
font-size: em(14);
|
||||
font-weight: normal;
|
||||
letter-spacing: 1px;
|
||||
padding: 0 lh(.25) 0 lh(.5);
|
||||
line-height: 46px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
p.active {
|
||||
float: left;
|
||||
font-weight: bold;
|
||||
margin-bottom: 0;
|
||||
padding: 0 lh(.5) 0 0;
|
||||
line-height: 46px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&:hover, &:active, &:focus {
|
||||
opacity: 1.0;
|
||||
background-color: #444;
|
||||
}
|
||||
}
|
||||
|
||||
// fix for now
|
||||
ol.video_speeds {
|
||||
box-shadow: inset 1px 0 0 #555, 0 4px 0 #444;
|
||||
@include transition(none);
|
||||
background-color: #444;
|
||||
border: 1px solid #000;
|
||||
bottom: 46px;
|
||||
display: none;
|
||||
opacity: 0.0;
|
||||
position: absolute;
|
||||
width: 131px;
|
||||
z-index: 10;
|
||||
|
||||
li {
|
||||
box-shadow: 0 1px 0 #555;
|
||||
border-bottom: 1px solid #000;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
|
||||
a {
|
||||
border: 0;
|
||||
color: #fff;
|
||||
display: block;
|
||||
padding: lh(.5);
|
||||
|
||||
&:hover {
|
||||
background-color: #666;
|
||||
color: #aaa;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
box-shadow: none;
|
||||
border-bottom: 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
div.volume {
|
||||
float: left;
|
||||
position: relative;
|
||||
|
||||
&.open {
|
||||
.volume-slider-container {
|
||||
display: block;
|
||||
opacity: 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
&.muted {
|
||||
&>a {
|
||||
background-image: url('../images/mute.png');
|
||||
}
|
||||
}
|
||||
|
||||
> a {
|
||||
background-image: url('../images/volume.png');
|
||||
background-position: 10px center;
|
||||
background-repeat: no-repeat;
|
||||
|
||||
border-right: 1px solid #000;
|
||||
box-shadow: 1px 0 0 #555, inset 1px 0 0 #555;
|
||||
@include clearfix();
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
height: 46px;
|
||||
margin-right: 0;
|
||||
padding-left: 15px;
|
||||
position: relative;
|
||||
@include transition(none);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
width: 30px;
|
||||
|
||||
&:hover, &:active, &:focus {
|
||||
background-color: #444;
|
||||
}
|
||||
}
|
||||
|
||||
.volume-slider-container {
|
||||
box-shadow: inset 1px 0 0 #555, 0 3px 0 #444;
|
||||
@include transition(none);
|
||||
background-color: #444;
|
||||
border: 1px solid #000;
|
||||
bottom: 46px;
|
||||
display: none;
|
||||
opacity: 0.0;
|
||||
position: absolute;
|
||||
width: 45px;
|
||||
height: 125px;
|
||||
margin-left: -1px;
|
||||
z-index: 10;
|
||||
|
||||
.volume-slider {
|
||||
height: 100px;
|
||||
border: 0;
|
||||
width: 5px;
|
||||
margin: 14px auto;
|
||||
background: #666;
|
||||
border: 1px solid #000;
|
||||
box-shadow: 0 1px 0 #333;
|
||||
|
||||
a.ui-slider-handle {
|
||||
background: $pink url(../images/slider-handle.png) center center no-repeat;
|
||||
background-size: 50%;
|
||||
border: 1px solid darken($pink, 20%);
|
||||
border-radius: 15px;
|
||||
box-shadow: inset 0 1px 0 lighten($pink, 10%);
|
||||
cursor: pointer;
|
||||
height: 15px;
|
||||
left: -6px;
|
||||
@include transition(height 2.0s ease-in-out 0s, width 2.0s ease-in-out 0s);
|
||||
width: 15px;
|
||||
}
|
||||
|
||||
.ui-slider-range {
|
||||
background: #ddd;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a.add-fullscreen {
|
||||
background: url(../images/fullscreen.png) center no-repeat;
|
||||
border-right: 1px solid #000;
|
||||
box-shadow: 1px 0 0 #555, inset 1px 0 0 #555;
|
||||
color: #797979;
|
||||
display: block;
|
||||
float: left;
|
||||
line-height: 46px; //height of play pause buttons
|
||||
margin-left: 0;
|
||||
padding: 0 lh(.5);
|
||||
text-indent: -9999px;
|
||||
@include transition(none);
|
||||
width: 30px;
|
||||
|
||||
&:hover, &:active, &:focus {
|
||||
background-color: #444;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
a.quality_control {
|
||||
background: url(../images/hd.png) center no-repeat;
|
||||
border-right: 1px solid #000;
|
||||
box-shadow: 1px 0 0 #555, inset 1px 0 0 #555;
|
||||
color: #797979;
|
||||
display: none;
|
||||
float: left;
|
||||
line-height: 46px; //height of play pause buttons
|
||||
margin-left: 0;
|
||||
padding: 0 lh(.5);
|
||||
text-indent: -9999px;
|
||||
@include transition(none);
|
||||
width: 30px;
|
||||
|
||||
&:hover, &:focus {
|
||||
background-color: #444;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: #F44;
|
||||
color: #0ff;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
a.hide-subtitles {
|
||||
background: url('../images/cc.png') center no-repeat;
|
||||
float: left;
|
||||
font-weight: 800;
|
||||
line-height: 46px; //height of play pause buttons
|
||||
margin-left: 0;
|
||||
opacity: 1.0;
|
||||
padding: 0 lh(.5);
|
||||
position: relative;
|
||||
text-indent: -9999px;
|
||||
@include transition(none);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
width: 30px;
|
||||
|
||||
&:hover, &:focus {
|
||||
background-color: #444;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
&.off {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
color: #797979;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover section.video-controls {
|
||||
ul, div {
|
||||
opacity: 1.0;
|
||||
}
|
||||
|
||||
div.slider {
|
||||
@include transform(scaleY(1) translate3d(0, 0, 0));
|
||||
|
||||
a.ui-slider-handle {
|
||||
@include transform(scale(1) translate3d(-50%, -15%, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ol.subtitles {
|
||||
padding-left: 0;
|
||||
float: left;
|
||||
max-height: 460px;
|
||||
overflow: auto;
|
||||
width: flex-grid(3, 9);
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
list-style: none;
|
||||
|
||||
li {
|
||||
border: 0;
|
||||
color: #666;
|
||||
cursor: pointer;
|
||||
margin-bottom: 8px;
|
||||
padding: 0;
|
||||
line-height: lh();
|
||||
|
||||
&.current {
|
||||
color: #333;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: $blue;
|
||||
}
|
||||
|
||||
&:empty {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.closed {
|
||||
|
||||
article.video-wrapper {
|
||||
width: flex-grid(9,9);
|
||||
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
article.video-wrapper section.video-controls.html5 {
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
article.video-wrapper div.video-player-pre, article.video-wrapper div.video-player-post {
|
||||
height: 0px;
|
||||
}
|
||||
|
||||
ol.subtitles {
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
ol.subtitles.html5 {
|
||||
background-color: rgba(243, 243, 243, 0.8);
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
width: 275px;
|
||||
padding: 0 20px;
|
||||
z-index: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.video-fullscreen {
|
||||
background: rgba(#000, .95);
|
||||
border: 0;
|
||||
bottom: 0;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
z-index: 999;
|
||||
vertical-align: middle;
|
||||
|
||||
&.closed {
|
||||
ol.subtitles {
|
||||
right: -(flex-grid(4));
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
article.video-wrapper div.video-player-pre, article.video-wrapper div.video-player-post {
|
||||
height: 0px;
|
||||
}
|
||||
|
||||
article.video-wrapper {
|
||||
position: static;
|
||||
}
|
||||
|
||||
div.tc-wrapper {
|
||||
@include clearfix;
|
||||
display: table;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
position: static;
|
||||
|
||||
article.video-wrapper {
|
||||
width: 100%;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
float: none;
|
||||
}
|
||||
|
||||
object, iframe {
|
||||
bottom: 0;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
overflow: hidden;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
section.video-controls {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
z-index: 9999;
|
||||
}
|
||||
}
|
||||
|
||||
ol.subtitles {
|
||||
background: rgba(#000, .8);
|
||||
bottom: 0;
|
||||
height: 100%;
|
||||
max-height: 460px;
|
||||
max-width: flex-grid(3);
|
||||
padding: lh();
|
||||
position: fixed;
|
||||
right: 0;
|
||||
top: 0;
|
||||
@include transition(none);
|
||||
|
||||
li {
|
||||
color: #aaa;
|
||||
|
||||
&.current {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
<div id="example">
|
||||
<div
|
||||
id="video_id"
|
||||
class="videoalpha"
|
||||
class="video"
|
||||
data-show-captions="true"
|
||||
data-start=""
|
||||
data-end=""
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<div id="example">
|
||||
<div
|
||||
id="video_id"
|
||||
class="videoalpha"
|
||||
class="video"
|
||||
data-show-captions="true"
|
||||
data-start=""
|
||||
data-end=""
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<div id="example">
|
||||
<div
|
||||
id="video_id"
|
||||
class="videoalpha"
|
||||
class="video"
|
||||
data-streams="0.75:7tqY6eQzVhE,1.0:cogebirgzzM"
|
||||
data-show-captions="false"
|
||||
data-start=""
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
(function () {
|
||||
xdescribe('Video', function () {
|
||||
describe('Video', function () {
|
||||
var oldOTBD;
|
||||
|
||||
beforeEach(function () {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
(function () {
|
||||
xdescribe('Video HTML5Video', function () {
|
||||
describe('Video HTML5Video', function () {
|
||||
var state, player, oldOTBD, playbackRates = [0.75, 1.0, 1.25, 1.5];
|
||||
|
||||
function initialize() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
(function() {
|
||||
xdescribe('VideoCaption', function() {
|
||||
describe('VideoCaption', function() {
|
||||
var state, videoPlayer, videoCaption, videoSpeedControl, oldOTBD;
|
||||
|
||||
function initialize() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
(function() {
|
||||
xdescribe('VideoControl', function() {
|
||||
describe('VideoControl', function() {
|
||||
var state, videoControl, oldOTBD;
|
||||
|
||||
function initialize() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
(function() {
|
||||
xdescribe('VideoPlayer', function() {
|
||||
describe('VideoPlayer', function() {
|
||||
var state, videoPlayer, player, videoControl, videoCaption, videoProgressSlider, videoSpeedControl, videoVolumeControl, oldOTBD;
|
||||
|
||||
function initialize(fixture) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
(function() {
|
||||
xdescribe('VideoProgressSlider', function() {
|
||||
describe('VideoProgressSlider', function() {
|
||||
var state, videoPlayer, videoProgressSlider, oldOTBD;
|
||||
|
||||
function initialize() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
(function() {
|
||||
xdescribe('VideoQualityControl', function() {
|
||||
describe('VideoQualityControl', function() {
|
||||
var state, videoControl, videoQualityControl, oldOTBD;
|
||||
|
||||
function initialize() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
(function() {
|
||||
xdescribe('VideoSpeedControl', function() {
|
||||
describe('VideoSpeedControl', function() {
|
||||
var state, videoPlayer, videoControl, videoSpeedControl;
|
||||
|
||||
function initialize() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
(function() {
|
||||
xdescribe('VideoVolumeControl', function() {
|
||||
describe('VideoVolumeControl', function() {
|
||||
var state, videoControl, videoVolumeControl, oldOTBD;
|
||||
|
||||
function initialize() {
|
||||
|
||||
4
common/lib/xmodule/xmodule/js/src/.gitignore
vendored
4
common/lib/xmodule/xmodule/js/src/.gitignore
vendored
@@ -4,5 +4,5 @@
|
||||
*.js
|
||||
|
||||
|
||||
# Videoalpha are written in pure JavaScript.
|
||||
!videoalpha/*.js
|
||||
# Video are written in pure JavaScript.
|
||||
!video/*.js
|
||||
@@ -88,7 +88,7 @@ class @Sequence
|
||||
$.postWithPrefix modx_full_url, position: new_position
|
||||
|
||||
# On Sequence change, fire custom event "sequence:change" on element.
|
||||
# Added for aborting video bufferization, see ../videoalpha/10_main.js
|
||||
# Added for aborting video bufferization, see ../video/10_main.js
|
||||
@el.trigger "sequence:change"
|
||||
@mark_active new_position
|
||||
@$('#seq_content').html @contents.eq(new_position - 1).text()
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
(function (requirejs, require, define) {
|
||||
|
||||
define(
|
||||
'videoalpha/01_initialize.js',
|
||||
['videoalpha/03_video_player.js'],
|
||||
'video/01_initialize.js',
|
||||
['video/03_video_player.js'],
|
||||
function (VideoPlayer) {
|
||||
|
||||
if (typeof(window.gettext) == "undefined") {
|
||||
@@ -25,8 +25,8 @@ function (VideoPlayer) {
|
||||
*
|
||||
* Initialize module exports this function.
|
||||
*
|
||||
* @param {Object} state A place for all properties, and methods of Video Alpha.
|
||||
* @param {DOM element} element Container of the entire Video Alpha DOM element.
|
||||
* @param {Object} state A place for all properties, and methods of Video.
|
||||
* @param {DOM element} element Container of the entire Video DOM element.
|
||||
*/
|
||||
return function (state, element) {
|
||||
_makeFunctionsPublic(state);
|
||||
@@ -44,7 +44,7 @@ function (VideoPlayer) {
|
||||
* Functions which will be accessible via 'state' object. When called, these functions will get the 'state'
|
||||
* object as a context.
|
||||
*
|
||||
* @param {Object} state A place for all properties, and methods of Video Alpha.
|
||||
* @param {Object} state A place for all properties, and methods of Video.
|
||||
*/
|
||||
function _makeFunctionsPublic(state) {
|
||||
state.setSpeed = _.bind(setSpeed, state);
|
||||
@@ -70,7 +70,7 @@ function (VideoPlayer) {
|
||||
state.isFullScreen = false;
|
||||
|
||||
// The parent element of the video, and the ID.
|
||||
state.el = $(element).find('.videoalpha');
|
||||
state.el = $(element).find('.video');
|
||||
state.id = state.el.attr('id').replace(/video_/, '');
|
||||
|
||||
// We store all settings passed to us by the server in one place. These are "read only", so don't
|
||||
@@ -14,7 +14,7 @@
|
||||
(function (requirejs, require, define) {
|
||||
|
||||
define(
|
||||
'videoalpha/02_html5_video.js',
|
||||
'video/02_html5_video.js',
|
||||
[],
|
||||
function () {
|
||||
var HTML5Video = {};
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
// VideoPlayer module.
|
||||
define(
|
||||
'videoalpha/03_video_player.js',
|
||||
['videoalpha/02_html5_video.js'],
|
||||
'video/03_video_player.js',
|
||||
['video/02_html5_video.js'],
|
||||
function (HTML5Video) {
|
||||
|
||||
// VideoPlayer() function - what this module "exports".
|
||||
@@ -359,7 +359,7 @@ function (HTML5Video) {
|
||||
this.videoPlayer.player.setPlaybackRate(this.speed);
|
||||
}
|
||||
|
||||
if (!onTouchBasedDevice() && $('.videoalpha:first').data('autoplay') === 'True') {
|
||||
if (!onTouchBasedDevice() && $('.video:first').data('autoplay') === 'True') {
|
||||
this.videoPlayer.play();
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
// VideoControl module.
|
||||
define(
|
||||
'videoalpha/04_video_control.js',
|
||||
'video/04_video_control.js',
|
||||
[],
|
||||
function () {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
// VideoQualityControl module.
|
||||
define(
|
||||
'videoalpha/05_video_quality_control.js',
|
||||
'video/05_video_quality_control.js',
|
||||
[],
|
||||
function () {
|
||||
|
||||
@@ -9,7 +9,7 @@ mind, or whether to act, and in acting, to live."
|
||||
|
||||
// VideoProgressSlider module.
|
||||
define(
|
||||
'videoalpha/06_video_progress_slider.js',
|
||||
'video/06_video_progress_slider.js',
|
||||
[],
|
||||
function () {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
// VideoVolumeControl module.
|
||||
define(
|
||||
'videoalpha/07_video_volume_control.js',
|
||||
'video/07_video_volume_control.js',
|
||||
[],
|
||||
function () {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
// VideoSpeedControl module.
|
||||
define(
|
||||
'videoalpha/08_video_speed_control.js',
|
||||
'video/08_video_speed_control.js',
|
||||
[],
|
||||
function () {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
// VideoCaption module.
|
||||
define(
|
||||
'videoalpha/09_video_caption.js',
|
||||
'video/09_video_caption.js',
|
||||
[],
|
||||
function () {
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
// Main module.
|
||||
require(
|
||||
[
|
||||
'videoalpha/01_initialize.js',
|
||||
'videoalpha/04_video_control.js',
|
||||
'videoalpha/05_video_quality_control.js',
|
||||
'videoalpha/06_video_progress_slider.js',
|
||||
'videoalpha/07_video_volume_control.js',
|
||||
'videoalpha/08_video_speed_control.js',
|
||||
'videoalpha/09_video_caption.js'
|
||||
'video/01_initialize.js',
|
||||
'video/04_video_control.js',
|
||||
'video/05_video_quality_control.js',
|
||||
'video/06_video_progress_slider.js',
|
||||
'video/07_video_volume_control.js',
|
||||
'video/08_video_speed_control.js',
|
||||
'video/09_video_caption.js'
|
||||
],
|
||||
function (
|
||||
Initialize,
|
||||
@@ -31,7 +31,7 @@ function (
|
||||
// afterwards (expecting the DOM elements to be present) must be stopped by hand.
|
||||
previousState = null;
|
||||
|
||||
window.VideoAlpha = function (element) {
|
||||
window.Video = function (element) {
|
||||
var state;
|
||||
|
||||
// Stop bufferization of previous video on sequence change.
|
||||
@@ -64,7 +64,7 @@ function (
|
||||
|
||||
// Because the 'state' object is only available inside this closure, we will also make
|
||||
// it available to the caller by returning it. This is necessary so that we can test
|
||||
// VideoAlpha with Jasmine.
|
||||
// Video with Jasmine.
|
||||
return state;
|
||||
};
|
||||
});
|
||||
@@ -1,66 +0,0 @@
|
||||
class @Video
|
||||
constructor: (element) ->
|
||||
@el = $(element).find('.video')
|
||||
@id = @el.attr('id').replace(/video_/, '')
|
||||
@start = @el.data('start')
|
||||
@end = @el.data('end')
|
||||
@caption_asset_path = @el.data('caption-asset-path')
|
||||
@show_captions = @el.data('show-captions')
|
||||
window.player = null
|
||||
@el = $("#video_#{@id}")
|
||||
@parseVideos()
|
||||
@fetchMetadata()
|
||||
@parseSpeed()
|
||||
$("#video_#{@id}").data('video', this).addClass('video-load-complete')
|
||||
|
||||
@hide_captions = $.cookie('hide_captions') == 'true' or (not @show_captions)
|
||||
|
||||
if YT.Player
|
||||
@embed()
|
||||
else
|
||||
window.onYouTubePlayerAPIReady = =>
|
||||
@el.each ->
|
||||
$(this).data('video').embed()
|
||||
|
||||
youtubeId: (speed)->
|
||||
@videos[speed || @speed]
|
||||
|
||||
parseVideos: (videos) ->
|
||||
@videos = {}
|
||||
if @el.data('youtube-id-0-75')
|
||||
@videos['0.75'] = @el.data('youtube-id-0-75')
|
||||
if @el.data('youtube-id-1-0')
|
||||
@videos['1.0'] = @el.data('youtube-id-1-0')
|
||||
if @el.data('youtube-id-1-25')
|
||||
@videos['1.25'] = @el.data('youtube-id-1-25')
|
||||
if @el.data('youtube-id-1-5')
|
||||
@videos['1.50'] = @el.data('youtube-id-1-5')
|
||||
|
||||
parseSpeed: ->
|
||||
@setSpeed($.cookie('video_speed'))
|
||||
@speeds = ($.map @videos, (url, speed) -> speed).sort()
|
||||
|
||||
setSpeed: (newSpeed) ->
|
||||
if @videos[newSpeed] != undefined
|
||||
@speed = newSpeed
|
||||
$.cookie('video_speed', "#{newSpeed}", expires: 3650, path: '/')
|
||||
else
|
||||
@speed = '1.0'
|
||||
|
||||
embed: ->
|
||||
@player = new VideoPlayer video: this
|
||||
|
||||
fetchMetadata: (url) ->
|
||||
@metadata = {}
|
||||
$.each @videos, (speed, url) =>
|
||||
$.get "https://gdata.youtube.com/feeds/api/videos/#{url}?v=2&alt=jsonc", ((data) => @metadata[data.data.id] = data.data) , 'jsonp'
|
||||
|
||||
getDuration: ->
|
||||
@metadata[@youtubeId()].duration
|
||||
|
||||
log: (eventName) ->
|
||||
Logger.log eventName,
|
||||
id: @id
|
||||
code: @youtubeId()
|
||||
currentTime: @player.currentTime
|
||||
speed: @speed
|
||||
@@ -1,14 +0,0 @@
|
||||
class @Subview
|
||||
constructor: (options) ->
|
||||
$.each options, (key, value) =>
|
||||
@[key] = value
|
||||
@initialize()
|
||||
@render()
|
||||
@bind()
|
||||
|
||||
$: (selector) ->
|
||||
$(selector, @el)
|
||||
|
||||
initialize: ->
|
||||
render: ->
|
||||
bind: ->
|
||||
@@ -1,155 +0,0 @@
|
||||
class @VideoCaption extends Subview
|
||||
initialize: ->
|
||||
@loaded = false
|
||||
|
||||
bind: ->
|
||||
$(window).bind('resize', @resize)
|
||||
@$('.hide-subtitles').click @toggle
|
||||
@$('.subtitles').mouseenter(@onMouseEnter).mouseleave(@onMouseLeave)
|
||||
.mousemove(@onMovement).bind('mousewheel', @onMovement)
|
||||
.bind('DOMMouseScroll', @onMovement)
|
||||
|
||||
captionURL: ->
|
||||
"#{@captionAssetPath}#{@youtubeId}.srt.sjson"
|
||||
|
||||
render: ->
|
||||
# TODO: make it so you can have a video with no captions.
|
||||
#@$('.video-wrapper').after """
|
||||
# <ol class="subtitles"><li>Attempting to load captions...</li></ol>
|
||||
# """
|
||||
@$('.video-wrapper').after """
|
||||
<ol class="subtitles"></ol>
|
||||
"""
|
||||
@$('.video-controls .secondary-controls').append """
|
||||
<a href="#" class="hide-subtitles" title="Turn off captions">Captions</a>
|
||||
"""#"
|
||||
@$('.subtitles').css maxHeight: @$('.video-wrapper').height() - 5
|
||||
@fetchCaption()
|
||||
|
||||
fetchCaption: ->
|
||||
$.ajaxWithPrefix
|
||||
url: @captionURL()
|
||||
notifyOnError: false
|
||||
success: (captions) =>
|
||||
@captions = captions.text
|
||||
@start = captions.start
|
||||
|
||||
@loaded = true
|
||||
|
||||
if onTouchBasedDevice()
|
||||
$('.subtitles').html "<li>Caption will be displayed when you start playing the video.</li>"
|
||||
else
|
||||
@renderCaption()
|
||||
|
||||
renderCaption: ->
|
||||
container = $('<ol>')
|
||||
|
||||
$.each @captions, (index, text) =>
|
||||
container.append $('<li>').html(text).attr
|
||||
'data-index': index
|
||||
'data-start': @start[index]
|
||||
|
||||
@$('.subtitles').html(container.html())
|
||||
@$('.subtitles li[data-index]').click @seekPlayer
|
||||
|
||||
# prepend and append an empty <li> for cosmetic reason
|
||||
@$('.subtitles').prepend($('<li class="spacing">').height(@topSpacingHeight()))
|
||||
.append($('<li class="spacing">').height(@bottomSpacingHeight()))
|
||||
|
||||
@rendered = true
|
||||
|
||||
search: (time) ->
|
||||
if @loaded
|
||||
min = 0
|
||||
max = @start.length - 1
|
||||
|
||||
while min < max
|
||||
index = Math.ceil((max + min) / 2)
|
||||
if time < @start[index]
|
||||
max = index - 1
|
||||
if time >= @start[index]
|
||||
min = index
|
||||
return min
|
||||
|
||||
play: ->
|
||||
if @loaded
|
||||
@renderCaption() unless @rendered
|
||||
@playing = true
|
||||
|
||||
pause: ->
|
||||
if @loaded
|
||||
@playing = false
|
||||
|
||||
updatePlayTime: (time) ->
|
||||
if @loaded
|
||||
# This 250ms offset is required to match the video speed
|
||||
time = Math.round(Time.convert(time, @currentSpeed, '1.0') * 1000 + 250)
|
||||
newIndex = @search time
|
||||
|
||||
if newIndex != undefined && @currentIndex != newIndex
|
||||
if @currentIndex
|
||||
@$(".subtitles li.current").removeClass('current')
|
||||
@$(".subtitles li[data-index='#{newIndex}']").addClass('current')
|
||||
|
||||
@currentIndex = newIndex
|
||||
@scrollCaption()
|
||||
|
||||
resize: =>
|
||||
@$('.subtitles').css maxHeight: @captionHeight()
|
||||
@$('.subtitles .spacing:first').height(@topSpacingHeight())
|
||||
@$('.subtitles .spacing:last').height(@bottomSpacingHeight())
|
||||
@scrollCaption()
|
||||
|
||||
onMouseEnter: =>
|
||||
clearTimeout @frozen if @frozen
|
||||
@frozen = setTimeout @onMouseLeave, 10000
|
||||
|
||||
onMovement: =>
|
||||
@onMouseEnter()
|
||||
|
||||
onMouseLeave: =>
|
||||
clearTimeout @frozen if @frozen
|
||||
@frozen = null
|
||||
@scrollCaption() if @playing
|
||||
|
||||
scrollCaption: ->
|
||||
if !@frozen && @$('.subtitles .current:first').length
|
||||
@$('.subtitles').scrollTo @$('.subtitles .current:first'),
|
||||
offset: - @calculateOffset(@$('.subtitles .current:first'))
|
||||
|
||||
seekPlayer: (event) =>
|
||||
event.preventDefault()
|
||||
time = Math.round(Time.convert($(event.target).data('start'), '1.0', @currentSpeed) / 1000)
|
||||
$(@).trigger('seek', time)
|
||||
|
||||
calculateOffset: (element) ->
|
||||
@captionHeight() / 2 - element.height() / 2
|
||||
|
||||
topSpacingHeight: ->
|
||||
@calculateOffset(@$('.subtitles li:not(.spacing):first'))
|
||||
|
||||
bottomSpacingHeight: ->
|
||||
@calculateOffset(@$('.subtitles li:not(.spacing):last'))
|
||||
|
||||
toggle: (event) =>
|
||||
event.preventDefault()
|
||||
if @el.hasClass('closed') # Captions are "closed" e.g. turned off
|
||||
@hideCaptions(false)
|
||||
else # Captions are on
|
||||
@hideCaptions(true)
|
||||
|
||||
hideCaptions: (hide_captions) =>
|
||||
if hide_captions
|
||||
@$('.hide-subtitles').attr('title', 'Turn on captions')
|
||||
@el.addClass('closed')
|
||||
else
|
||||
@$('.hide-subtitles').attr('title', 'Turn off captions')
|
||||
@el.removeClass('closed')
|
||||
@scrollCaption()
|
||||
$.cookie('hide_captions', hide_captions, expires: 3650, path: '/')
|
||||
|
||||
captionHeight: ->
|
||||
if @el.hasClass('fullscreen')
|
||||
$(window).height() - @$('.video-controls').height()
|
||||
else
|
||||
@$('.video-wrapper').height()
|
||||
@@ -1,35 +0,0 @@
|
||||
class @VideoControl extends Subview
|
||||
bind: ->
|
||||
@$('.video_control').click @togglePlayback
|
||||
|
||||
render: ->
|
||||
@el.append """
|
||||
<div class="slider"></div>
|
||||
<div>
|
||||
<ul class="vcr">
|
||||
<li><a class="video_control" href="#"></a></li>
|
||||
<li>
|
||||
<div class="vidtime">0:00 / 0:00</div>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="secondary-controls">
|
||||
<a href="#" class="add-fullscreen" title="Fill browser">Fill Browser</a>
|
||||
</div>
|
||||
</div>
|
||||
"""#"
|
||||
|
||||
unless onTouchBasedDevice()
|
||||
@$('.video_control').addClass('play').html('Play')
|
||||
|
||||
play: ->
|
||||
@$('.video_control').removeClass('play').addClass('pause').html('Pause')
|
||||
|
||||
pause: ->
|
||||
@$('.video_control').removeClass('pause').addClass('play').html('Play')
|
||||
|
||||
togglePlayback: (event) =>
|
||||
event.preventDefault()
|
||||
if @$('.video_control').hasClass('play')
|
||||
$(@).trigger('play')
|
||||
else if @$('.video_control').hasClass('pause')
|
||||
$(@).trigger('pause')
|
||||
@@ -1,180 +0,0 @@
|
||||
class @VideoPlayer extends Subview
|
||||
initialize: ->
|
||||
# Define a missing constant of Youtube API
|
||||
YT.PlayerState.UNSTARTED = -1
|
||||
|
||||
@currentTime = 0
|
||||
@el = $("#video_#{@video.id}")
|
||||
|
||||
bind: ->
|
||||
$(@control).bind('play', @play)
|
||||
.bind('pause', @pause)
|
||||
$(@qualityControl).bind('changeQuality', @handlePlaybackQualityChange)
|
||||
$(@caption).bind('seek', @onSeek)
|
||||
$(@speedControl).bind('speedChange', @onSpeedChange)
|
||||
$(@progressSlider).bind('seek', @onSeek)
|
||||
if @volumeControl
|
||||
$(@volumeControl).bind('volumeChange', @onVolumeChange)
|
||||
$(document.documentElement).keyup @bindExitFullScreen
|
||||
|
||||
@$('.add-fullscreen').click @toggleFullScreen
|
||||
@addToolTip() unless onTouchBasedDevice()
|
||||
|
||||
bindExitFullScreen: (event) =>
|
||||
if @el.hasClass('fullscreen') && event.keyCode == 27
|
||||
@toggleFullScreen(event)
|
||||
|
||||
render: ->
|
||||
@control = new VideoControl el: @$('.video-controls')
|
||||
@qualityControl = new VideoQualityControl el: @$('.secondary-controls')
|
||||
@caption = new VideoCaption
|
||||
el: @el
|
||||
youtubeId: @video.youtubeId('1.0')
|
||||
currentSpeed: @currentSpeed()
|
||||
captionAssetPath: @video.caption_asset_path
|
||||
unless onTouchBasedDevice()
|
||||
@volumeControl = new VideoVolumeControl el: @$('.secondary-controls')
|
||||
@speedControl = new VideoSpeedControl el: @$('.secondary-controls'), speeds: @video.speeds, currentSpeed: @currentSpeed()
|
||||
@progressSlider = new VideoProgressSlider el: @$('.slider')
|
||||
@playerVars =
|
||||
controls: 0
|
||||
wmode: 'transparent'
|
||||
rel: 0
|
||||
showinfo: 0
|
||||
enablejsapi: 1
|
||||
modestbranding: 1
|
||||
if @video.start
|
||||
@playerVars.start = @video.start
|
||||
@playerVars.wmode = 'window'
|
||||
if @video.end
|
||||
# work in AS3, not HMLT5. but iframe use AS3
|
||||
@playerVars.end = @video.end
|
||||
|
||||
@player = new YT.Player @video.id,
|
||||
playerVars: @playerVars
|
||||
videoId: @video.youtubeId()
|
||||
events:
|
||||
onReady: @onReady
|
||||
onStateChange: @onStateChange
|
||||
onPlaybackQualityChange: @onPlaybackQualityChange
|
||||
@caption.hideCaptions(@['video'].hide_captions)
|
||||
|
||||
addToolTip: ->
|
||||
@$('.add-fullscreen, .hide-subtitles').qtip
|
||||
position:
|
||||
my: 'top right'
|
||||
at: 'top center'
|
||||
|
||||
onReady: (event) =>
|
||||
unless onTouchBasedDevice() or $('.video:first').data('autoplay') == 'False'
|
||||
$('.video-load-complete:first').data('video').player.play()
|
||||
|
||||
onStateChange: (event) =>
|
||||
switch event.data
|
||||
when YT.PlayerState.UNSTARTED
|
||||
@onUnstarted()
|
||||
when YT.PlayerState.PLAYING
|
||||
@onPlay()
|
||||
when YT.PlayerState.PAUSED
|
||||
@onPause()
|
||||
when YT.PlayerState.ENDED
|
||||
@onEnded()
|
||||
|
||||
onPlaybackQualityChange: (event, value) =>
|
||||
quality = @player.getPlaybackQuality()
|
||||
@qualityControl.onQualityChange(quality)
|
||||
|
||||
handlePlaybackQualityChange: (event, value) =>
|
||||
@player.setPlaybackQuality(value)
|
||||
|
||||
onUnstarted: =>
|
||||
@control.pause()
|
||||
@caption.pause()
|
||||
|
||||
onPlay: =>
|
||||
@video.log 'play_video'
|
||||
window.player.pauseVideo() if window.player && window.player != @player
|
||||
window.player = @player
|
||||
unless @player.interval
|
||||
@player.interval = setInterval(@update, 200)
|
||||
@caption.play()
|
||||
@control.play()
|
||||
@progressSlider.play()
|
||||
|
||||
onPause: =>
|
||||
@video.log 'pause_video'
|
||||
window.player = null if window.player == @player
|
||||
clearInterval(@player.interval)
|
||||
@player.interval = null
|
||||
@caption.pause()
|
||||
@control.pause()
|
||||
|
||||
onEnded: =>
|
||||
@control.pause()
|
||||
@caption.pause()
|
||||
|
||||
onSeek: (event, time) =>
|
||||
@player.seekTo(time, true)
|
||||
if @isPlaying()
|
||||
clearInterval(@player.interval)
|
||||
@player.interval = setInterval(@update, 200)
|
||||
else
|
||||
@currentTime = time
|
||||
@updatePlayTime time
|
||||
|
||||
onSpeedChange: (event, newSpeed) =>
|
||||
@currentTime = Time.convert(@currentTime, parseFloat(@currentSpeed()), newSpeed)
|
||||
newSpeed = parseFloat(newSpeed).toFixed(2).replace /\.00$/, '.0'
|
||||
@video.setSpeed(newSpeed)
|
||||
@caption.currentSpeed = newSpeed
|
||||
|
||||
if @isPlaying()
|
||||
@player.loadVideoById(@video.youtubeId(), @currentTime)
|
||||
else
|
||||
@player.cueVideoById(@video.youtubeId(), @currentTime)
|
||||
@updatePlayTime @currentTime
|
||||
|
||||
onVolumeChange: (event, volume) =>
|
||||
@player.setVolume volume
|
||||
|
||||
update: =>
|
||||
if @currentTime = @player.getCurrentTime()
|
||||
@updatePlayTime @currentTime
|
||||
|
||||
updatePlayTime: (time) ->
|
||||
progress = Time.format(time) + ' / ' + Time.format(@duration())
|
||||
@$(".vidtime").html(progress)
|
||||
@caption.updatePlayTime(time)
|
||||
@progressSlider.updatePlayTime(time, @duration())
|
||||
|
||||
toggleFullScreen: (event) =>
|
||||
event.preventDefault()
|
||||
if @el.hasClass('fullscreen')
|
||||
@$('.add-fullscreen').attr('title', 'Fill browser')
|
||||
@el.removeClass('fullscreen')
|
||||
else
|
||||
@el.addClass('fullscreen')
|
||||
@$('.add-fullscreen').attr('title', 'Exit fill browser')
|
||||
@caption.resize()
|
||||
|
||||
# Delegates
|
||||
play: =>
|
||||
@player.playVideo() if @player.playVideo
|
||||
|
||||
isPlaying: ->
|
||||
@player.getPlayerState() == YT.PlayerState.PLAYING
|
||||
|
||||
pause: =>
|
||||
@player.pauseVideo() if @player.pauseVideo
|
||||
|
||||
duration: ->
|
||||
@video.getDuration()
|
||||
|
||||
currentSpeed: ->
|
||||
@video.speed
|
||||
|
||||
volume: (value) ->
|
||||
if value?
|
||||
@player.setVolume value
|
||||
else
|
||||
@player.getVolume()
|
||||
@@ -1,49 +0,0 @@
|
||||
class @VideoProgressSlider extends Subview
|
||||
initialize: ->
|
||||
@buildSlider() unless onTouchBasedDevice()
|
||||
|
||||
buildSlider: ->
|
||||
@slider = @el.slider
|
||||
range: 'min'
|
||||
change: @onChange
|
||||
slide: @onSlide
|
||||
stop: @onStop
|
||||
@buildHandle()
|
||||
|
||||
buildHandle: ->
|
||||
@handle = @$('.ui-slider-handle')
|
||||
@handle.qtip
|
||||
content: "#{Time.format(@slider.slider('value'))}"
|
||||
position:
|
||||
my: 'bottom center'
|
||||
at: 'top center'
|
||||
container: @handle
|
||||
hide:
|
||||
delay: 700
|
||||
style:
|
||||
classes: 'ui-tooltip-slider'
|
||||
widget: true
|
||||
|
||||
play: =>
|
||||
@buildSlider() unless @slider
|
||||
|
||||
updatePlayTime: (currentTime, duration) ->
|
||||
if @slider && !@frozen
|
||||
@slider.slider('option', 'max', duration)
|
||||
@slider.slider('value', currentTime)
|
||||
|
||||
onSlide: (event, ui) =>
|
||||
@frozen = true
|
||||
@updateTooltip(ui.value)
|
||||
$(@).trigger('seek', ui.value)
|
||||
|
||||
onChange: (event, ui) =>
|
||||
@updateTooltip(ui.value)
|
||||
|
||||
onStop: (event, ui) =>
|
||||
@frozen = true
|
||||
$(@).trigger('seek', ui.value)
|
||||
setTimeout (=> @frozen = false), 200
|
||||
|
||||
updateTooltip: (value)->
|
||||
@handle.qtip('option', 'content.text', "#{Time.format(value)}")
|
||||
@@ -1,26 +0,0 @@
|
||||
class @VideoQualityControl extends Subview
|
||||
initialize: ->
|
||||
@quality = null;
|
||||
|
||||
bind: ->
|
||||
@$('.quality_control').click @toggleQuality
|
||||
|
||||
render: ->
|
||||
@el.append """
|
||||
<a href="#" class="quality_control" title="HD">HD</a>
|
||||
"""#"
|
||||
|
||||
onQualityChange: (value) ->
|
||||
@quality = value
|
||||
if @quality in ['hd720', 'hd1080', 'highres']
|
||||
@el.addClass('active')
|
||||
else
|
||||
@el.removeClass('active')
|
||||
|
||||
toggleQuality: (event) =>
|
||||
event.preventDefault()
|
||||
if @quality in ['hd720', 'hd1080', 'highres']
|
||||
newQuality = 'large'
|
||||
else
|
||||
newQuality = 'hd720'
|
||||
$(@).trigger('changeQuality', newQuality)
|
||||
@@ -1,43 +0,0 @@
|
||||
class @VideoSpeedControl extends Subview
|
||||
bind: ->
|
||||
@$('.video_speeds a').click @changeVideoSpeed
|
||||
if onTouchBasedDevice()
|
||||
@$('.speeds').click (event) ->
|
||||
event.preventDefault()
|
||||
$(this).toggleClass('open')
|
||||
else
|
||||
@$('.speeds').mouseenter ->
|
||||
$(this).addClass('open')
|
||||
@$('.speeds').mouseleave ->
|
||||
$(this).removeClass('open')
|
||||
@$('.speeds').click (event) ->
|
||||
event.preventDefault()
|
||||
$(this).removeClass('open')
|
||||
|
||||
render: ->
|
||||
@el.prepend """
|
||||
<div class="speeds">
|
||||
<a href="#">
|
||||
<h3>Speed</h3>
|
||||
<p class="active"></p>
|
||||
</a>
|
||||
<ol class="video_speeds"></ol>
|
||||
</div>
|
||||
"""
|
||||
|
||||
$.each @speeds, (index, speed) =>
|
||||
link = $('<a>').attr(href: "#").html("#{speed}x")
|
||||
@$('.video_speeds').prepend($('<li>').attr('data-speed', speed).html(link))
|
||||
@setSpeed(@currentSpeed)
|
||||
|
||||
changeVideoSpeed: (event) =>
|
||||
event.preventDefault()
|
||||
unless $(event.target).parent().hasClass('active')
|
||||
@currentSpeed = $(event.target).parent().data('speed')
|
||||
$(@).trigger 'speedChange', $(event.target).parent().data('speed')
|
||||
@setSpeed(parseFloat(@currentSpeed).toFixed(2).replace /\.00$/, '.0')
|
||||
|
||||
setSpeed: (speed) ->
|
||||
@$('.video_speeds li').removeClass('active')
|
||||
@$(".video_speeds li[data-speed='#{speed}']").addClass('active')
|
||||
@$('.speeds p.active').html("#{speed}x")
|
||||
@@ -1,40 +0,0 @@
|
||||
class @VideoVolumeControl extends Subview
|
||||
initialize: ->
|
||||
@currentVolume = 100
|
||||
|
||||
bind: ->
|
||||
@$('.volume').mouseenter ->
|
||||
$(this).addClass('open')
|
||||
@$('.volume').mouseleave ->
|
||||
$(this).removeClass('open')
|
||||
@$('.volume>a').click(@toggleMute)
|
||||
|
||||
render: ->
|
||||
@el.prepend """
|
||||
<div class="volume">
|
||||
<a href="#"></a>
|
||||
<div class="volume-slider-container">
|
||||
<div class="volume-slider"></div>
|
||||
</div>
|
||||
</div>
|
||||
"""#"
|
||||
@slider = @$('.volume-slider').slider
|
||||
orientation: "vertical"
|
||||
range: "min"
|
||||
min: 0
|
||||
max: 100
|
||||
value: 100
|
||||
change: @onChange
|
||||
slide: @onChange
|
||||
|
||||
onChange: (event, ui) =>
|
||||
@currentVolume = ui.value
|
||||
$(@).trigger 'volumeChange', @currentVolume
|
||||
@$('.volume').toggleClass 'muted', @currentVolume == 0
|
||||
|
||||
toggleMute: =>
|
||||
if @currentVolume > 0
|
||||
@previousVolume = @currentVolume
|
||||
@slider.slider 'option', 'value', 0
|
||||
else
|
||||
@slider.slider 'option', 'value', @previousVolume
|
||||
@@ -1,56 +1,86 @@
|
||||
<%! from django.utils.translation import ugettext as _ %>
|
||||
|
||||
% if display_name is not UNDEFINED and display_name is not None:
|
||||
<h2> ${display_name} </h2>
|
||||
<h2>${display_name}</h2>
|
||||
% endif
|
||||
|
||||
%if settings.MITX_FEATURES.get('USE_YOUTUBE_OBJECT_API') and normal_speed_video_id:
|
||||
<object width="640" height="390">
|
||||
<param name="movie"
|
||||
% if not settings.MITX_FEATURES['STUB_VIDEO_FOR_TESTING']:
|
||||
value="https://www.youtube.com/v/${normal_speed_video_id}?version=3&autoplay=1&rel=0">
|
||||
% endif
|
||||
</param>
|
||||
<param name="allowScriptAccess" value="always"></param>
|
||||
<embed
|
||||
% if not settings.MITX_FEATURES['STUB_VIDEO_FOR_TESTING']:
|
||||
src="https://www.youtube.com/v/${normal_speed_video_id}?version=3&autoplay=1&rel=0"
|
||||
% endif
|
||||
type="application/x-shockwave-flash"
|
||||
allowscriptaccess="always"
|
||||
width="640" height="390"></embed>
|
||||
</object>
|
||||
%else:
|
||||
<div id="video_${id}"
|
||||
class="video"
|
||||
data-youtube-id-0-75="${youtube_id_0_75}"
|
||||
data-youtube-id-1-0="${youtube_id_1_0}"
|
||||
data-youtube-id-1-25="${youtube_id_1_25}"
|
||||
data-youtube-id-1-5="${youtube_id_1_5}"
|
||||
data-show-captions="${show_captions}"
|
||||
data-start="${start}"
|
||||
data-end="${end}"
|
||||
data-caption-asset-path="${caption_asset_path}"
|
||||
data-autoplay="${settings.MITX_FEATURES['AUTOPLAY_VIDEOS']}">
|
||||
<div class="tc-wrapper">
|
||||
<article class="video-wrapper">
|
||||
<section class="video-player">
|
||||
<div id="${id}"></div>
|
||||
</section>
|
||||
<section class="video-controls"></section>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
%endif
|
||||
<div
|
||||
id="video_${id}"
|
||||
class="video"
|
||||
|
||||
% if source:
|
||||
<div class="video-sources">
|
||||
<p>${_('Download video <a href="%s">here</a>.') % source}</p>
|
||||
% if not settings.MITX_FEATURES['STUB_VIDEO_FOR_TESTING']:
|
||||
data-streams="${youtube_streams}"
|
||||
% endif
|
||||
|
||||
${'data-sub="{}"'.format(sub) if sub else ''}
|
||||
${'data-autoplay="{}"'.format(autoplay) if autoplay else ''}
|
||||
|
||||
% if not settings.MITX_FEATURES['STUB_VIDEO_FOR_TESTING']:
|
||||
${'data-mp4-source="{}"'.format(sources.get('mp4')) if sources.get('mp4') else ''}
|
||||
${'data-webm-source="{}"'.format(sources.get('webm')) if sources.get('webm') else ''}
|
||||
${'data-ogg-source="{}"'.format(sources.get('ogv')) if sources.get('ogv') else ''}
|
||||
% endif
|
||||
|
||||
data-caption-data-dir="${data_dir}"
|
||||
data-show-captions="${show_captions}"
|
||||
data-start="${start}"
|
||||
data-end="${end}"
|
||||
data-caption-asset-path="${caption_asset_path}"
|
||||
data-autoplay="${autoplay}"
|
||||
>
|
||||
<div class="tc-wrapper">
|
||||
<article class="video-wrapper">
|
||||
<div class="video-player-pre"></div>
|
||||
|
||||
<section class="video-player">
|
||||
<div id="${id}"></div>
|
||||
</section>
|
||||
|
||||
<div class="video-player-post"></div>
|
||||
|
||||
<section class="video-controls">
|
||||
<div class="slider" tabindex="0" title="Video position"></div>
|
||||
|
||||
<div>
|
||||
<ul class="vcr">
|
||||
<li><a class="video_control" href="#" tabindex="0" title="${_('Play')}"></a></li>
|
||||
<li><div class="vidtime">0:00 / 0:00</div></li>
|
||||
</ul>
|
||||
<div class="secondary-controls">
|
||||
<div class="speeds">
|
||||
<a href="#" tabindex="0" title="Speeds">
|
||||
<h3 tabindex="-1">${_('Speed')}</h3>
|
||||
<p tabindex="-1" class="active"></p>
|
||||
</a>
|
||||
<ol tabindex="-1" class="video_speeds"></ol>
|
||||
</div>
|
||||
<div class="volume">
|
||||
<a href="#" tabindex="0" title="Volume"></a>
|
||||
<div tabindex="-1" class="volume-slider-container">
|
||||
<div tabindex="-1" class="volume-slider"></div>
|
||||
</div>
|
||||
</div>
|
||||
<a href="#" class="add-fullscreen" tabindex="0" title="${_('Fill browser')}">${_('Fill browser')}</a>
|
||||
<a href="#" class="quality_control" tabindex="0" title="${_('HD')}">${_('HD')}</a>
|
||||
|
||||
<a href="#" class="hide-subtitles" title="${_('Turn off captions')}">${_('Captions')}</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</article>
|
||||
|
||||
<ol class="subtitles" tabindex="0" title="Captions"><li></li></ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
% if sources.get('main'):
|
||||
<div class="video-sources">
|
||||
<p>${(_('Download video') + ' <a href="%s">' + _('here') + '</a>.') % sources.get('main')}</p>
|
||||
</div>
|
||||
% endif
|
||||
|
||||
% if track:
|
||||
<div class="video-tracks">
|
||||
<p>${_('Download subtitles <a href="%s">here</a>.') % track}</p>
|
||||
</div>
|
||||
<div class="video-tracks">
|
||||
<p>${(_('Download subtitles') + ' <a href="%s">' + _('here') + '</a>.') % track}</p>
|
||||
</div>
|
||||
% endif
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
<%! from django.utils.translation import ugettext as _ %>
|
||||
|
||||
% if display_name is not UNDEFINED and display_name is not None:
|
||||
<h2>${display_name}</h2>
|
||||
% endif
|
||||
|
||||
<div
|
||||
id="video_${id}"
|
||||
class="videoalpha"
|
||||
|
||||
% if not settings.MITX_FEATURES['STUB_VIDEO_FOR_TESTING']:
|
||||
data-streams="${youtube_streams}"
|
||||
% endif
|
||||
|
||||
${'data-sub="{}"'.format(sub) if sub else ''}
|
||||
${'data-autoplay="{}"'.format(autoplay) if autoplay else ''}
|
||||
|
||||
% if not settings.MITX_FEATURES['STUB_VIDEO_FOR_TESTING']:
|
||||
${'data-mp4-source="{}"'.format(sources.get('mp4')) if sources.get('mp4') else ''}
|
||||
${'data-webm-source="{}"'.format(sources.get('webm')) if sources.get('webm') else ''}
|
||||
${'data-ogg-source="{}"'.format(sources.get('ogv')) if sources.get('ogv') else ''}
|
||||
% endif
|
||||
|
||||
data-caption-data-dir="${data_dir}"
|
||||
data-show-captions="${show_captions}"
|
||||
data-start="${start}"
|
||||
data-end="${end}"
|
||||
data-caption-asset-path="${caption_asset_path}"
|
||||
data-autoplay="${autoplay}"
|
||||
>
|
||||
<div class="tc-wrapper">
|
||||
<article class="video-wrapper">
|
||||
<div class="video-player-pre"></div>
|
||||
|
||||
<section class="video-player">
|
||||
<div id="${id}"></div>
|
||||
</section>
|
||||
|
||||
<div class="video-player-post"></div>
|
||||
|
||||
<section class="video-controls">
|
||||
<div class="slider" tabindex="0" title="Video position"></div>
|
||||
|
||||
<div>
|
||||
<ul class="vcr">
|
||||
<li><a class="video_control" href="#" tabindex="0" title="${_('Play')}"></a></li>
|
||||
<li><div class="vidtime">0:00 / 0:00</div></li>
|
||||
</ul>
|
||||
<div class="secondary-controls">
|
||||
<div class="speeds">
|
||||
<a href="#" tabindex="0" title="Speeds">
|
||||
<h3 tabindex="-1">${_('Speed')}</h3>
|
||||
<p tabindex="-1" class="active"></p>
|
||||
</a>
|
||||
<ol tabindex="-1" class="video_speeds"></ol>
|
||||
</div>
|
||||
<div class="volume">
|
||||
<a href="#" tabindex="0" title="Volume"></a>
|
||||
<div tabindex="-1" class="volume-slider-container">
|
||||
<div tabindex="-1" class="volume-slider"></div>
|
||||
</div>
|
||||
</div>
|
||||
<a href="#" class="add-fullscreen" tabindex="0" title="${_('Fill browser')}">${_('Fill browser')}</a>
|
||||
<a href="#" class="quality_control" tabindex="0" title="${_('HD')}">${_('HD')}</a>
|
||||
|
||||
<a href="#" class="hide-subtitles" title="${_('Turn off captions')}">${_('Captions')}</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</article>
|
||||
|
||||
<ol class="subtitles" tabindex="0" title="Captions"><li></li></ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
% if sources.get('main'):
|
||||
<div class="video-sources">
|
||||
<p>${(_('Download video') + ' <a href="%s">' + _('here') + '</a>.') % sources.get('main')}</p>
|
||||
</div>
|
||||
% endif
|
||||
|
||||
% if track:
|
||||
<div class="video-tracks">
|
||||
<p>${(_('Download subtitles') + ' <a href="%s">' + _('here') + '</a>.') % track}</p>
|
||||
</div>
|
||||
% endif
|
||||
Reference in New Issue
Block a user