Merge pull request #593 from edx/valera/captions_keyboard_access_2
Valera/captions keyboard access 2
This commit is contained in:
@@ -133,7 +133,6 @@ div.videoalpha {
|
||||
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;
|
||||
@@ -150,7 +149,7 @@ div.videoalpha {
|
||||
&.play {
|
||||
background-position: 17px -114px;
|
||||
|
||||
&:hover {
|
||||
&:hover, &:focus {
|
||||
background-color: #444;
|
||||
}
|
||||
}
|
||||
@@ -158,7 +157,7 @@ div.videoalpha {
|
||||
&.pause {
|
||||
background-position: 16px -50px;
|
||||
|
||||
&:hover {
|
||||
&:hover, &:focus {
|
||||
background-color: #444;
|
||||
}
|
||||
}
|
||||
@@ -300,12 +299,15 @@ div.videoalpha {
|
||||
|
||||
&.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();
|
||||
@@ -382,7 +384,7 @@ div.videoalpha {
|
||||
@include transition(none);
|
||||
width: 30px;
|
||||
|
||||
&:hover {
|
||||
&:hover, &:active, &:focus {
|
||||
background-color: #444;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
@@ -403,7 +405,7 @@ div.videoalpha {
|
||||
@include transition(none);
|
||||
width: 30px;
|
||||
|
||||
&:hover {
|
||||
&:hover, &:focus {
|
||||
background-color: #444;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
@@ -419,7 +421,6 @@ div.videoalpha {
|
||||
|
||||
a.hide-subtitles {
|
||||
background: url('../images/cc.png') center no-repeat;
|
||||
display: block;
|
||||
float: left;
|
||||
font-weight: 800;
|
||||
line-height: 46px; //height of play pause buttons
|
||||
@@ -432,7 +433,7 @@ div.videoalpha {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
width: 30px;
|
||||
|
||||
&:hover {
|
||||
&:hover, &:focus {
|
||||
background-color: #444;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
@@ -442,9 +443,7 @@ div.videoalpha {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
background-color: #444;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
color: #797979;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -513,12 +512,6 @@ div.videoalpha {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
article.video-wrapper section.video-controls div.secondary-controls a.hide-subtitles {
|
||||
background-color: inherit;
|
||||
color: #797979;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
article.video-wrapper div.video-player-pre, article.video-wrapper div.video-player-post {
|
||||
height: 0px;
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
<div id="video_example">
|
||||
<div id="example">
|
||||
<div id="video_id" class="video"
|
||||
data-youtube-id-0-75="slowerSpeedYoutubeId"
|
||||
data-youtube-id-1-0="normalSpeedYoutubeId"
|
||||
data-youtube-id-0-75="7tqY6eQzVhE"
|
||||
data-youtube-id-1-0="cogebirgzzM"
|
||||
data-show-captions="true"
|
||||
data-start=""
|
||||
data-end=""
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div
|
||||
id="video_id"
|
||||
class="videoalpha"
|
||||
data-streams="0.75:slowerSpeedYoutubeId,1.0:normalSpeedYoutubeId"
|
||||
data-streams="0.75:7tqY6eQzVhE,1.0:cogebirgzzM"
|
||||
data-show-captions="true"
|
||||
data-start=""
|
||||
data-end=""
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
data-start=""
|
||||
data-end=""
|
||||
data-caption-asset-path="/static/subs/"
|
||||
data-sub="test_name_of_the_subtitles"
|
||||
data-sub="Z5KLxerq05Y"
|
||||
data-mp4-source="test_files/test.mp4"
|
||||
data-webm-source="test_files/test.webm"
|
||||
data-ogg-source="test_files/test.ogv"
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
data-start=""
|
||||
data-end=""
|
||||
data-caption-asset-path="/static/subs/"
|
||||
data-sub="test_name_of_the_subtitles"
|
||||
data-sub="Z5KLxerq05Y"
|
||||
data-mp4-source="test_files/test.mp4"
|
||||
data-webm-source="test_files/test.webm"
|
||||
data-ogg-source="test_files/test.ogv"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div
|
||||
id="video_id"
|
||||
class="videoalpha"
|
||||
data-streams="0.75:slowerSpeedYoutubeId,1.0:normalSpeedYoutubeId"
|
||||
data-streams="0.75:7tqY6eQzVhE,1.0:cogebirgzzM"
|
||||
data-show-captions="false"
|
||||
data-start=""
|
||||
data-end=""
|
||||
|
||||
@@ -12,6 +12,9 @@ window.STATUS = window.YT.PlayerState
|
||||
|
||||
oldAjaxWithPrefix = window.jQuery.ajaxWithPrefix
|
||||
|
||||
window.onTouchBasedDevice = ->
|
||||
navigator.userAgent.match /iPhone|iPod|iPad/i
|
||||
|
||||
jasmine.stubbedCaption =
|
||||
end: [3120, 6270, 8490, 21620, 24920, 25750, 27900, 34380, 35550, 40250]
|
||||
start: [1180, 3120, 6270, 14910, 21620, 24920, 25750, 27900, 34380, 35550]
|
||||
@@ -36,7 +39,7 @@ jasmine.stubbedCaption =
|
||||
#
|
||||
# We will replace it with a function that does:
|
||||
#
|
||||
# 1.) Return a hard coded captions object if the file name contains 'test_name_of_the_subtitles'.
|
||||
# 1.) Return a hard coded captions object if the file name contains 'Z5KLxerq05Y'.
|
||||
# 2.) Behaves the same a as the origianl in all other cases.
|
||||
|
||||
window.jQuery.ajaxWithPrefix = (url, settings) ->
|
||||
@@ -46,7 +49,7 @@ window.jQuery.ajaxWithPrefix = (url, settings) ->
|
||||
success = settings.success
|
||||
data = settings.data
|
||||
|
||||
if url.match(/test_name_of_the_subtitles/g) isnt null or url.match(/slowerSpeedYoutubeId/g) isnt null or url.match(/normalSpeedYoutubeId/g) isnt null
|
||||
if url.match(/Z5KLxerq05Y/g) isnt null or url.match(/7tqY6eQzVhE/g) isnt null or url.match(/cogebirgzzM/g) isnt null
|
||||
if window.jQuery.isFunction(success) is true
|
||||
success jasmine.stubbedCaption
|
||||
else if window.jQuery.isFunction(data) is true
|
||||
@@ -60,11 +63,11 @@ window.WAIT_TIMEOUT = 1000
|
||||
jasmine.getFixtures().fixturesPath = 'xmodule/js/fixtures'
|
||||
|
||||
jasmine.stubbedMetadata =
|
||||
slowerSpeedYoutubeId:
|
||||
id: 'slowerSpeedYoutubeId'
|
||||
'7tqY6eQzVhE':
|
||||
id: '7tqY6eQzVhE'
|
||||
duration: 300
|
||||
normalSpeedYoutubeId:
|
||||
id: 'normalSpeedYoutubeId'
|
||||
'cogebirgzzM':
|
||||
id: 'cogebirgzzM'
|
||||
duration: 200
|
||||
bogus:
|
||||
duration: 100
|
||||
@@ -117,7 +120,7 @@ jasmine.stubVideoPlayer = (context, enableParts, createPlayer=true) ->
|
||||
loadFixtures 'video.html'
|
||||
jasmine.stubRequests()
|
||||
YT.Player = undefined
|
||||
videosDefinition = '0.75:slowerSpeedYoutubeId,1.0:normalSpeedYoutubeId'
|
||||
videosDefinition = '0.75:7tqY6eQzVhE,1.0:cogebirgzzM'
|
||||
context.video = new Video '#example', videosDefinition
|
||||
jasmine.stubYoutubePlayer()
|
||||
if createPlayer
|
||||
@@ -135,7 +138,7 @@ jasmine.stubVideoPlayerAlpha = (context, enableParts, html5=false) ->
|
||||
YT.Player = undefined
|
||||
window.OldVideoPlayerAlpha = undefined
|
||||
jasmine.stubYoutubePlayer()
|
||||
return new VideoAlpha '#example', '.75:slowerSpeedYoutubeId,1.0:normalSpeedYoutubeId'
|
||||
return new VideoAlpha '#example', '.75:7tqY6eQzVhE,1.0:cogebirgzzM'
|
||||
|
||||
|
||||
# Stub jQuery.cookie
|
||||
|
||||
@@ -19,7 +19,7 @@ describe 'VideoCaption', ->
|
||||
@caption = @player.caption
|
||||
|
||||
it 'set the youtube id', ->
|
||||
expect(@caption.youtubeId).toEqual 'normalSpeedYoutubeId'
|
||||
expect(@caption.youtubeId).toEqual 'cogebirgzzM'
|
||||
|
||||
it 'create the caption element', ->
|
||||
expect($('.video')).toContain 'ol.subtitles'
|
||||
|
||||
@@ -35,7 +35,7 @@ describe 'VideoPlayer', ->
|
||||
expect(window.VideoCaption.prototype.initialize).toHaveBeenCalled()
|
||||
expect(@player.caption).toBeDefined()
|
||||
expect(@player.caption.el).toBe @player.el
|
||||
expect(@player.caption.youtubeId).toEqual 'normalSpeedYoutubeId'
|
||||
expect(@player.caption.youtubeId).toEqual 'cogebirgzzM'
|
||||
expect(@player.caption.currentSpeed).toEqual '1.0'
|
||||
expect(@player.caption.captionAssetPath).toEqual '/static/subs/'
|
||||
|
||||
@@ -60,7 +60,7 @@ describe 'VideoPlayer', ->
|
||||
showinfo: 0
|
||||
enablejsapi: 1
|
||||
modestbranding: 1
|
||||
videoId: 'normalSpeedYoutubeId'
|
||||
videoId: 'cogebirgzzM'
|
||||
events:
|
||||
onReady: @player.onReady
|
||||
onStateChange: @player.onStateChange
|
||||
@@ -290,7 +290,7 @@ describe 'VideoPlayer', ->
|
||||
@player.onSpeedChange {}, '0.75'
|
||||
|
||||
it 'load the video', ->
|
||||
expect(@player.player.loadVideoById).toHaveBeenCalledWith 'slowerSpeedYoutubeId', '80.000'
|
||||
expect(@player.player.loadVideoById).toHaveBeenCalledWith '7tqY6eQzVhE', '80.000'
|
||||
|
||||
it 'trigger updatePlayTime event', ->
|
||||
expect(@player.updatePlayTime).toHaveBeenCalledWith '80.000'
|
||||
@@ -301,7 +301,7 @@ describe 'VideoPlayer', ->
|
||||
@player.onSpeedChange {}, '0.75'
|
||||
|
||||
it 'cue the video', ->
|
||||
expect(@player.player.cueVideoById).toHaveBeenCalledWith 'slowerSpeedYoutubeId', '80.000'
|
||||
expect(@player.player.cueVideoById).toHaveBeenCalledWith '7tqY6eQzVhE', '80.000'
|
||||
|
||||
it 'trigger updatePlayTime event', ->
|
||||
expect(@player.updatePlayTime).toHaveBeenCalledWith '80.000'
|
||||
|
||||
@@ -5,14 +5,14 @@ describe 'Video', ->
|
||||
loadFixtures 'video.html'
|
||||
jasmine.stubRequests()
|
||||
|
||||
@slowerSpeedYoutubeId = 'slowerSpeedYoutubeId'
|
||||
@normalSpeedYoutubeId = 'normalSpeedYoutubeId'
|
||||
@['7tqY6eQzVhE'] = '7tqY6eQzVhE'
|
||||
@['cogebirgzzM'] = 'cogebirgzzM'
|
||||
metadata =
|
||||
slowerSpeedYoutubeId:
|
||||
id: @slowerSpeedYoutubeId
|
||||
'7tqY6eQzVhE':
|
||||
id: @['7tqY6eQzVhE']
|
||||
duration: 300
|
||||
normalSpeedYoutubeId:
|
||||
id: @normalSpeedYoutubeId
|
||||
'cogebirgzzM':
|
||||
id: @['cogebirgzzM']
|
||||
duration: 200
|
||||
|
||||
afterEach ->
|
||||
@@ -38,8 +38,8 @@ describe 'Video', ->
|
||||
|
||||
it 'parse the videos', ->
|
||||
expect(@video.videos).toEqual
|
||||
'0.75': @slowerSpeedYoutubeId
|
||||
'1.0': @normalSpeedYoutubeId
|
||||
'0.75': @['7tqY6eQzVhE']
|
||||
'1.0': @['cogebirgzzM']
|
||||
|
||||
it 'fetch the video metadata', ->
|
||||
expect(@video.fetchMetadata).toHaveBeenCalled
|
||||
@@ -102,12 +102,12 @@ describe 'Video', ->
|
||||
|
||||
describe 'with speed', ->
|
||||
it 'return the video id for given speed', ->
|
||||
expect(@video.youtubeId('0.75')).toEqual @slowerSpeedYoutubeId
|
||||
expect(@video.youtubeId('1.0')).toEqual @normalSpeedYoutubeId
|
||||
expect(@video.youtubeId('0.75')).toEqual @['7tqY6eQzVhE']
|
||||
expect(@video.youtubeId('1.0')).toEqual @['cogebirgzzM']
|
||||
|
||||
describe 'without speed', ->
|
||||
it 'return the video id for current speed', ->
|
||||
expect(@video.youtubeId()).toEqual @normalSpeedYoutubeId
|
||||
expect(@video.youtubeId()).toEqual @cogebirgzzM
|
||||
|
||||
describe 'setSpeed', ->
|
||||
beforeEach ->
|
||||
@@ -148,6 +148,6 @@ describe 'Video', ->
|
||||
it 'call the logger with valid parameters', ->
|
||||
expect(Logger.log).toHaveBeenCalledWith 'someEvent',
|
||||
id: 'id'
|
||||
code: @normalSpeedYoutubeId
|
||||
code: @cogebirgzzM
|
||||
currentTime: 25
|
||||
speed: '1.0'
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
jasmine.stubRequests();
|
||||
oldOTBD = window.onTouchBasedDevice;
|
||||
window.onTouchBasedDevice = jasmine.createSpy('onTouchBasedDevice').andReturn(false);
|
||||
this.videosDefinition = '0.75:slowerSpeedYoutubeId,1.0:normalSpeedYoutubeId';
|
||||
this.slowerSpeedYoutubeId = 'slowerSpeedYoutubeId';
|
||||
this.normalSpeedYoutubeId = 'normalSpeedYoutubeId';
|
||||
this.videosDefinition = '0.75:7tqY6eQzVhE,1.0:cogebirgzzM';
|
||||
this['7tqY6eQzVhE'] = '7tqY6eQzVhE';
|
||||
this['cogebirgzzM'] = 'cogebirgzzM';
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
@@ -45,8 +45,8 @@
|
||||
|
||||
it('parse the videos', function () {
|
||||
expect(this.state.videos).toEqual({
|
||||
'0.75': this.slowerSpeedYoutubeId,
|
||||
'1.0': this.normalSpeedYoutubeId
|
||||
'0.75': this['7tqY6eQzVhE'],
|
||||
'1.0': this['cogebirgzzM']
|
||||
});
|
||||
});
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
});
|
||||
|
||||
it('parse the videos if subtitles exist', function () {
|
||||
var sub = 'test_name_of_the_subtitles';
|
||||
var sub = 'Z5KLxerq05Y';
|
||||
|
||||
expect(state.videos).toEqual({
|
||||
'0.75': sub,
|
||||
@@ -165,14 +165,14 @@
|
||||
|
||||
describe('with speed', function () {
|
||||
it('return the video id for given speed', function () {
|
||||
expect(state.youtubeId('0.75')).toEqual(this.slowerSpeedYoutubeId);
|
||||
expect(state.youtubeId('1.0')).toEqual(this.normalSpeedYoutubeId);
|
||||
expect(state.youtubeId('0.75')).toEqual(this['7tqY6eQzVhE']);
|
||||
expect(state.youtubeId('1.0')).toEqual(this['cogebirgzzM']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('without speed', function () {
|
||||
it('return the video id for current speed', function () {
|
||||
expect(state.youtubeId()).toEqual(this.normalSpeedYoutubeId);
|
||||
expect(state.youtubeId()).toEqual(this.cogebirgzzM);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
Jasmine JavaScript tests status
|
||||
-------------------------------
|
||||
|
||||
As of 22.07.2013, all the tests in this directory pass. To disable each of them, change the top level "describe(" to "xdescribe(".
|
||||
As of 22.07.2013, all the tests in this directory pass. To enable a test file, change
|
||||
the top level "xdescribe(" to "describe(".
|
||||
|
||||
PS: When you are running the tests in chrome locally, make sure that chrome is started
|
||||
with the option "--allow-file-access-from-files".
|
||||
|
||||
@@ -130,7 +130,6 @@
|
||||
|
||||
describe('mouse movement', function() {
|
||||
beforeEach(function() {
|
||||
//initialize();
|
||||
window.setTimeout.andReturn(100);
|
||||
spyOn(window, 'clearTimeout');
|
||||
});
|
||||
@@ -221,10 +220,6 @@
|
||||
});
|
||||
|
||||
describe('search', function() {
|
||||
beforeEach(function() {
|
||||
//initialize();
|
||||
});
|
||||
|
||||
it('return a correct caption index', function() {
|
||||
expect(videoCaption.search(0)).toEqual(0);
|
||||
expect(videoCaption.search(3120)).toEqual(1);
|
||||
@@ -277,7 +272,6 @@
|
||||
|
||||
describe('pause', function() {
|
||||
beforeEach(function() {
|
||||
//initialize();
|
||||
videoCaption.playing = true;
|
||||
videoCaption.pause();
|
||||
});
|
||||
@@ -288,10 +282,6 @@
|
||||
});
|
||||
|
||||
describe('updatePlayTime', function() {
|
||||
/*beforeEach(function() {
|
||||
initialize();
|
||||
});*/
|
||||
|
||||
describe('when the video speed is 1.0x', function() {
|
||||
beforeEach(function() {
|
||||
videoSpeedControl.currentSpeed = '1.0';
|
||||
@@ -369,16 +359,21 @@
|
||||
});
|
||||
|
||||
it('when CC button is disabled ', function() {
|
||||
var realHeight = parseInt($('.subtitles').css('maxHeight'), 10),
|
||||
videoWrapperHeight = $('.video-wrapper').height(),
|
||||
controlsHeight = videoControl.el.height(),
|
||||
progressSliderHeight = videoControl.sliderEl.height(),
|
||||
shouldBeHeight = videoWrapperHeight - controlsHeight \
|
||||
- 0.5 * controlsHeight;
|
||||
var realHeight, videoWrapperHeight, progressSliderHeight,
|
||||
controlHeight, shouldBeHeight;
|
||||
|
||||
state.captionsHidden = true;
|
||||
videoCaption.setSubtitlesHeight();
|
||||
expect(realHeight).toBeCloseTo($('.video-wrapper').height(shouldBeHeight, 2));
|
||||
|
||||
realHeight = parseInt($('.subtitles').css('maxHeight'), 10);
|
||||
videoWrapperHeight = $('.video-wrapper').height();
|
||||
progressSliderHeight = videoControl.sliderEl.height();
|
||||
controlHeight = videoControl.el.height();
|
||||
shouldBeHeight = videoWrapperHeight -
|
||||
0.5 * progressSliderHeight -
|
||||
controlHeight;
|
||||
|
||||
expect(realHeight).toBe(shouldBeHeight);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -434,17 +429,6 @@
|
||||
});
|
||||
|
||||
it('scroll to current caption', function() {
|
||||
// Check for calledWith(parameters) for some reason fails...
|
||||
//
|
||||
// var offset = -0.5 * ($('.video-wrapper').height() - $('.subtitles .current:first').height());
|
||||
//
|
||||
// expect($.fn.scrollTo).toHaveBeenCalledWith(
|
||||
// $('.subtitles .current:first', videoCaption.el),
|
||||
// {
|
||||
// offset: offset
|
||||
// }
|
||||
// );
|
||||
|
||||
expect($.fn.scrollTo).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -454,7 +438,6 @@
|
||||
describe('seekPlayer', function() {
|
||||
describe('when the video speed is 1.0x', function() {
|
||||
beforeEach(function() {
|
||||
//initialize();
|
||||
videoSpeedControl.currentSpeed = '1.0';
|
||||
$('.subtitles li[data-start="14910"]').trigger('click');
|
||||
});
|
||||
|
||||
@@ -34,12 +34,6 @@
|
||||
});
|
||||
|
||||
describe('constructor', function() {
|
||||
beforeEach(function() {
|
||||
$.fn.qtip.andCallFake(function() {
|
||||
$(this).data('qtip', true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('always', function() {
|
||||
beforeEach(function() {
|
||||
initialize();
|
||||
@@ -60,7 +54,7 @@
|
||||
|
||||
it('create video caption', function() {
|
||||
expect(videoCaption).toBeDefined();
|
||||
expect(state.youtubeId()).toEqual('test_name_of_the_subtitles');
|
||||
expect(state.youtubeId()).toEqual('Z5KLxerq05Y');
|
||||
expect(state.speed).toEqual('1.0');
|
||||
expect(state.config.caption_asset_path).toEqual('/static/subs/');
|
||||
});
|
||||
@@ -80,38 +74,6 @@
|
||||
// All the toHandleWith() expect tests are not necessary for this version of Video Alpha.
|
||||
// jQuery event system is not used to trigger and invoke methods. This is an artifact from
|
||||
// previous version of Video Alpha.
|
||||
//
|
||||
// xit('bind to video control play event', function() {
|
||||
// expect($(videoControl)).toHandleWith('play', player.play);
|
||||
// });
|
||||
//
|
||||
// xit('bind to video control pause event', function() {
|
||||
// expect($(videoControl)).toHandleWith('pause', player.pause);
|
||||
// });
|
||||
//
|
||||
// xit('bind to video caption seek event', function() {
|
||||
// expect($(videoCaption)).toHandleWith('caption_seek', player.onSeek);
|
||||
// });
|
||||
//
|
||||
// xit('bind to video speed control speedChange event', function() {
|
||||
// expect($(videoSpeedControl)).toHandleWith('speedChange', player.onSpeedChange);
|
||||
// });
|
||||
//
|
||||
// xit('bind to video progress slider seek event', function() {
|
||||
// expect($(videoProgressSlider)).toHandleWith('slide_seek', player.onSeek);
|
||||
// });
|
||||
//
|
||||
// xit('bind to video volume control volumeChange event', function() {
|
||||
// expect($(videoVolumeControl)).toHandleWith('volumeChange', player.onVolumeChange);
|
||||
// });
|
||||
//
|
||||
// xit('bind to key press', function() {
|
||||
// expect($(document.documentElement)).toHandleWith('keyup', player.bindExitFullScreen);
|
||||
// });
|
||||
//
|
||||
// xit('bind to fullscreen switching button', function() {
|
||||
// expect($('.add-fullscreen')).toHandleWith('click', player.toggleFullScreen);
|
||||
// });
|
||||
});
|
||||
|
||||
it('create Youtube player', function() {
|
||||
@@ -136,7 +98,7 @@
|
||||
modestbranding: 1,
|
||||
html5: 1
|
||||
},
|
||||
videoId: 'normalSpeedYoutubeId',
|
||||
videoId: 'cogebirgzzM',
|
||||
events: {
|
||||
onReady: videoPlayer.onReady,
|
||||
onStateChange: videoPlayer.onStateChange,
|
||||
@@ -149,20 +111,6 @@
|
||||
|
||||
// We can't test the invocation of HTML5Video because it is not available
|
||||
// globally. It is defined within the scope of Require JS.
|
||||
//
|
||||
// xit('create HTML5 player', function() {
|
||||
// spyOn(state.HTML5Video, 'Player').andCallThrough();
|
||||
// initialize();
|
||||
//
|
||||
// expect(window.HTML5Video.Player).toHaveBeenCalledWith(this.video.el, {
|
||||
// playerVars: playerVars,
|
||||
// videoSources: this.video.html5Sources,
|
||||
// events: {
|
||||
// onReady: player.onReady,
|
||||
// onStateChange: player.onStateChange
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
|
||||
describe('when not on a touch based device', function() {
|
||||
beforeEach(function() {
|
||||
@@ -170,10 +118,6 @@
|
||||
initialize();
|
||||
});
|
||||
|
||||
it('does not add the tooltip to fullscreen button', function() {
|
||||
expect($('.add-fullscreen')).not.toHaveData('qtip');
|
||||
});
|
||||
|
||||
it('create video volume control', function() {
|
||||
expect(videoVolumeControl).toBeDefined();
|
||||
expect(videoVolumeControl.el).toHaveClass('volume');
|
||||
@@ -187,10 +131,6 @@
|
||||
initialize();
|
||||
});
|
||||
|
||||
it('add the tooltip to fullscreen button', function() {
|
||||
expect($('.add-fullscreen')).toHaveData('qtip');
|
||||
});
|
||||
|
||||
it('controls are in paused state', function() {
|
||||
expect(videoControl.isPlaying).toBe(false);
|
||||
});
|
||||
@@ -433,11 +373,9 @@
|
||||
expect(state.setSpeed).toHaveBeenCalledWith('0.75', false);
|
||||
});
|
||||
|
||||
// Not relevant any more.
|
||||
// Not relevant any more:
|
||||
//
|
||||
// it('tell video caption that the speed has changed', function() {
|
||||
// expect(this.player.caption.currentSpeed).toEqual('0.75');
|
||||
// });
|
||||
// expect( "tell video caption that the speed has changed" ) ...
|
||||
});
|
||||
|
||||
describe('when the video is playing', function() {
|
||||
@@ -548,8 +486,9 @@
|
||||
expect(true).toBe(false);
|
||||
}
|
||||
|
||||
// The below test has been replaced by above trickery.
|
||||
// expect($('.vidtime')).toHaveHtml('1:00 / 1:01');
|
||||
// The below test has been replaced by above trickery:
|
||||
//
|
||||
// expect($('.vidtime')).toHaveHtml('1:00 / 1:01');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -39,21 +39,6 @@
|
||||
|
||||
it('build the seek handle', function() {
|
||||
expect(videoProgressSlider.handle).toBe('.slider .ui-slider-handle');
|
||||
expect($.fn.qtip).toHaveBeenCalledWith({
|
||||
content: "0:00",
|
||||
position: {
|
||||
my: 'bottom center',
|
||||
at: 'top center',
|
||||
container: videoProgressSlider.handle
|
||||
},
|
||||
hide: {
|
||||
delay: 700
|
||||
},
|
||||
style: {
|
||||
classes: 'ui-tooltip-slider',
|
||||
widget: true
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -69,7 +54,6 @@
|
||||
|
||||
// We can't expect $.fn.slider not to have been called,
|
||||
// because sliders are used in other parts of VideoAlpha.
|
||||
// expect($.fn.slider).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -94,43 +78,6 @@
|
||||
});
|
||||
|
||||
// Currently, the slider is not rebuilt if it does not exist.
|
||||
//
|
||||
// describe('when the slider was not already built', function() {
|
||||
// beforeEach(function() {
|
||||
// spyOn($.fn, 'slider').andCallThrough();
|
||||
// videoProgressSlider.slider = null;
|
||||
// videoPlayer.play();
|
||||
// });
|
||||
//
|
||||
// it('build the slider', function() {
|
||||
// expect(videoProgressSlider.slider).toBe('.slider');
|
||||
// expect($.fn.slider).toHaveBeenCalledWith({
|
||||
// range: 'min',
|
||||
// change: videoProgressSlider.onChange,
|
||||
// slide: videoProgressSlider.onSlide,
|
||||
// stop: videoProgressSlider.onStop
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// it('build the seek handle', function() {
|
||||
// expect(videoProgressSlider.handle).toBe('.ui-slider-handle');
|
||||
// expect($.fn.qtip).toHaveBeenCalledWith({
|
||||
// content: "0:00",
|
||||
// position: {
|
||||
// my: 'bottom center',
|
||||
// at: 'top center',
|
||||
// container: videoProgressSlider.handle
|
||||
// },
|
||||
// hide: {
|
||||
// delay: 700
|
||||
// },
|
||||
// style: {
|
||||
// classes: 'ui-tooltip-slider',
|
||||
// widget: true
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
});
|
||||
|
||||
describe('updatePlayTime', function() {
|
||||
@@ -181,10 +128,6 @@
|
||||
expect(videoProgressSlider.frozen).toBeTruthy();
|
||||
});
|
||||
|
||||
it('update the tooltip', function() {
|
||||
expect($.fn.qtip).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('trigger seek event', function() {
|
||||
expect(videoPlayer.onSlideSeek).toHaveBeenCalled();
|
||||
expect(videoPlayer.currentTime).toEqual(20);
|
||||
@@ -199,9 +142,6 @@
|
||||
value: 20
|
||||
});
|
||||
});
|
||||
it('update the tooltip', function() {
|
||||
expect($.fn.qtip).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('onStop', function() {
|
||||
@@ -228,18 +168,6 @@
|
||||
expect(videoProgressSlider.frozen).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateTooltip', function() {
|
||||
beforeEach(function() {
|
||||
initialize();
|
||||
spyOn($.fn, 'slider').andCallThrough();
|
||||
videoProgressSlider.updateTooltip(90);
|
||||
});
|
||||
|
||||
it('set the tooltip value', function() {
|
||||
expect($.fn.qtip).toHaveBeenCalledWith('option', 'content.text', '1:30');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
}).call(this);
|
||||
|
||||
@@ -90,19 +90,7 @@
|
||||
// detect (and do not do anything) if there is a request for a speed that
|
||||
// is already set.
|
||||
//
|
||||
// describe('when new speed is the same', function() {
|
||||
// beforeEach(function() {
|
||||
// initialize();
|
||||
// videoSpeedControl.setSpeed(1.0);
|
||||
// spyOn(videoPlayer, 'onSpeedChange').andCallThrough();
|
||||
//
|
||||
// $('li[data-speed="1.0"] a').click();
|
||||
// });
|
||||
//
|
||||
// it('does not trigger speedChange event', function() {
|
||||
// expect(videoPlayer.onSpeedChange).not.toHaveBeenCalled();
|
||||
// });
|
||||
// });
|
||||
// describe("when new speed is the same") ...
|
||||
|
||||
describe('when new speed is not the same', function() {
|
||||
beforeEach(function() {
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
range: "min",
|
||||
min: 0,
|
||||
max: 100,
|
||||
/* value: 100, */
|
||||
value: videoVolumeControl.currentVolume,
|
||||
change: videoVolumeControl.onChange,
|
||||
slide: videoVolumeControl.onChange
|
||||
|
||||
@@ -93,14 +93,7 @@ function (VideoPlayer) {
|
||||
|
||||
fadeOutTimeout: 1400,
|
||||
|
||||
availableQualities: ['hd720', 'hd1080', 'highres'],
|
||||
|
||||
qTipConfig: {
|
||||
position: {
|
||||
my: 'top right',
|
||||
at: 'top center'
|
||||
}
|
||||
}
|
||||
availableQualities: ['hd720', 'hd1080', 'highres']
|
||||
};
|
||||
|
||||
if (!(_parseYouTubeIDs(state))) {
|
||||
|
||||
@@ -53,9 +53,6 @@ function () {
|
||||
|
||||
if (!onTouchBasedDevice()) {
|
||||
state.videoControl.pause();
|
||||
|
||||
state.videoControl.playPauseEl.qtip(state.config.qTipConfig);
|
||||
state.videoControl.fullScreenEl.qtip(state.config.qTipConfig);
|
||||
} else {
|
||||
state.videoControl.play();
|
||||
}
|
||||
@@ -77,7 +74,8 @@ function () {
|
||||
$(document).on('keyup', state.videoControl.exitFullScreen);
|
||||
|
||||
if (state.videoType === 'html5') {
|
||||
state.el.on('mousemove', state.videoControl.showControls)
|
||||
state.el.on('mousemove', state.videoControl.showControls);
|
||||
state.el.on('keydown', state.videoControl.showControls);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,10 +43,6 @@ function () {
|
||||
|
||||
state.videoQualityControl.el.show();
|
||||
state.videoQualityControl.quality = null;
|
||||
|
||||
if (!onTouchBasedDevice()) {
|
||||
state.videoQualityControl.el.qtip(state.config.qTipConfig);
|
||||
}
|
||||
}
|
||||
|
||||
// function _bindHandlers(state)
|
||||
|
||||
@@ -32,9 +32,7 @@ function () {
|
||||
// get the 'state' object as a context.
|
||||
function _makeFunctionsPublic(state) {
|
||||
state.videoProgressSlider.onSlide = _.bind(onSlide, state);
|
||||
state.videoProgressSlider.onChange = _.bind(onChange, state);
|
||||
state.videoProgressSlider.onStop = _.bind(onStop, state);
|
||||
state.videoProgressSlider.updateTooltip = _.bind(updateTooltip, state);
|
||||
state.videoProgressSlider.updatePlayTime = _.bind(updatePlayTime, state);
|
||||
//Added for tests -- JM
|
||||
state.videoProgressSlider.buildSlider = _.bind(buildSlider, state);
|
||||
@@ -56,22 +54,6 @@ function () {
|
||||
|
||||
function _buildHandle(state) {
|
||||
state.videoProgressSlider.handle = state.videoProgressSlider.el.find('.ui-slider-handle');
|
||||
|
||||
state.videoProgressSlider.handle.qtip({
|
||||
content: '' + Time.format(state.videoProgressSlider.slider.slider('value')),
|
||||
position: {
|
||||
my: 'bottom center',
|
||||
at: 'top center',
|
||||
container: state.videoProgressSlider.handle
|
||||
},
|
||||
hide: {
|
||||
delay: 700
|
||||
},
|
||||
style: {
|
||||
classes: 'ui-tooltip-slider',
|
||||
widget: true
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ***************************************************************
|
||||
@@ -83,7 +65,6 @@ function () {
|
||||
function buildSlider(state) {
|
||||
state.videoProgressSlider.slider = state.videoProgressSlider.el.slider({
|
||||
range: 'min',
|
||||
change: state.videoProgressSlider.onChange,
|
||||
slide: state.videoProgressSlider.onSlide,
|
||||
stop: state.videoProgressSlider.onStop
|
||||
});
|
||||
@@ -91,15 +72,10 @@ function () {
|
||||
|
||||
function onSlide(event, ui) {
|
||||
this.videoProgressSlider.frozen = true;
|
||||
this.videoProgressSlider.updateTooltip(ui.value);
|
||||
|
||||
this.trigger('videoPlayer.onSlideSeek', {'type': 'onSlideSeek', 'time': ui.value});
|
||||
}
|
||||
|
||||
function onChange(event, ui) {
|
||||
this.videoProgressSlider.updateTooltip(ui.value);
|
||||
}
|
||||
|
||||
function onStop(event, ui) {
|
||||
var _this = this;
|
||||
|
||||
@@ -112,10 +88,6 @@ function () {
|
||||
}, 200);
|
||||
}
|
||||
|
||||
function updateTooltip(value) {
|
||||
this.videoProgressSlider.handle.qtip('option', 'content.text', '' + Time.format(value));
|
||||
}
|
||||
|
||||
//Changed for tests -- JM: Check if it is the cause of Chrome Bug Valera noticed
|
||||
function updatePlayTime(params) {
|
||||
if ((this.videoProgressSlider.slider) && (!this.videoProgressSlider.frozen)) {
|
||||
|
||||
@@ -61,6 +61,9 @@ function () {
|
||||
slide: state.videoVolumeControl.onChange
|
||||
});
|
||||
|
||||
// Make sure that we can focus the actual volume slider while Tabing.
|
||||
state.videoVolumeControl.volumeSliderEl.find('a').attr('tabindex', '0');
|
||||
|
||||
state.videoVolumeControl.el.toggleClass('muted', state.videoVolumeControl.currentVolume === 0);
|
||||
}
|
||||
|
||||
@@ -74,9 +77,21 @@ function () {
|
||||
$(this).addClass('open');
|
||||
});
|
||||
|
||||
state.videoVolumeControl.buttonEl.on('focus', function() {
|
||||
$(this).parent().addClass('open');
|
||||
});
|
||||
|
||||
state.videoVolumeControl.el.on('mouseleave', function() {
|
||||
$(this).removeClass('open');
|
||||
});
|
||||
|
||||
state.videoVolumeControl.buttonEl.on('blur', function() {
|
||||
state.videoVolumeControl.volumeSliderEl.find('a').focus();
|
||||
});
|
||||
|
||||
state.videoVolumeControl.volumeSliderEl.find('a').on('blur', function () {
|
||||
state.videoVolumeControl.el.removeClass('open');
|
||||
});
|
||||
}
|
||||
|
||||
// ***************************************************************
|
||||
|
||||
@@ -21,34 +21,41 @@ function () {
|
||||
|
||||
// function _makeFunctionsPublic(state)
|
||||
//
|
||||
// Functions which will be accessible via 'state' object. When called, these functions will
|
||||
// get the 'state' object as a context.
|
||||
// Functions which will be accessible via 'state' object. When called,
|
||||
// these functions will get the 'state' object as a context.
|
||||
function _makeFunctionsPublic(state) {
|
||||
state.videoSpeedControl.changeVideoSpeed = _.bind(changeVideoSpeed, state);
|
||||
state.videoSpeedControl.changeVideoSpeed = _.bind(
|
||||
changeVideoSpeed, state
|
||||
);
|
||||
state.videoSpeedControl.setSpeed = _.bind(setSpeed, state);
|
||||
state.videoSpeedControl.reRender = _.bind(reRender, state);
|
||||
}
|
||||
|
||||
// function _renderElements(state)
|
||||
//
|
||||
// Create any necessary DOM elements, attach them, and set their initial configuration. Also
|
||||
// make the created DOM elements available via the 'state' object. Much easier to work this
|
||||
// way - you don't have to do repeated jQuery element selects.
|
||||
// Create any necessary DOM elements, attach them, and set their
|
||||
// initial configuration. Also make the created DOM elements available
|
||||
// via the 'state' object. Much easier to work this way - you don't
|
||||
// have to do repeated jQuery element selects.
|
||||
function _renderElements(state) {
|
||||
state.videoSpeedControl.speeds = state.speeds;
|
||||
|
||||
state.videoSpeedControl.el = state.el.find('div.speeds');
|
||||
|
||||
state.videoSpeedControl.videoSpeedsEl = state.videoSpeedControl.el.find('.video_speeds');
|
||||
state.videoSpeedControl.videoSpeedsEl = state.videoSpeedControl.el
|
||||
.find('.video_speeds');
|
||||
|
||||
state.videoControl.secondaryControlsEl.prepend(state.videoSpeedControl.el);
|
||||
state.videoControl.secondaryControlsEl.prepend(
|
||||
state.videoSpeedControl.el
|
||||
);
|
||||
|
||||
$.each(state.videoSpeedControl.speeds, function(index, speed) {
|
||||
var link = '<a class="speed_link" href="#">' + speed + 'x</a>';
|
||||
|
||||
//var link = $('<a href="#">' + speed + 'x</a>');
|
||||
var link = '<a href="#">' + speed + 'x</a>';
|
||||
|
||||
state.videoSpeedControl.videoSpeedsEl.prepend($('<li data-speed="' + speed + '">' + link + '</li>'));
|
||||
state.videoSpeedControl.videoSpeedsEl
|
||||
.prepend(
|
||||
$('<li data-speed="' + speed + '">' + link + '</li>')
|
||||
);
|
||||
});
|
||||
|
||||
state.videoSpeedControl.setSpeed(state.speed);
|
||||
@@ -56,9 +63,11 @@ function () {
|
||||
|
||||
// function _bindHandlers(state)
|
||||
//
|
||||
// Bind any necessary function callbacks to DOM events (click, mousemove, etc.).
|
||||
// Bind any necessary function callbacks to DOM events (click,
|
||||
// mousemove, etc.).
|
||||
function _bindHandlers(state) {
|
||||
state.videoSpeedControl.videoSpeedsEl.find('a').on('click', state.videoSpeedControl.changeVideoSpeed);
|
||||
state.videoSpeedControl.videoSpeedsEl.find('a')
|
||||
.on('click', state.videoSpeedControl.changeVideoSpeed);
|
||||
|
||||
if (onTouchBasedDevice()) {
|
||||
state.videoSpeedControl.el.on('click', function(event) {
|
||||
@@ -77,18 +86,36 @@ function () {
|
||||
event.preventDefault();
|
||||
$(this).removeClass('open');
|
||||
});
|
||||
|
||||
state.videoSpeedControl.el.children('a')
|
||||
.on('focus', function () {
|
||||
$(this).parent().addClass('open');
|
||||
})
|
||||
.on('blur', function () {
|
||||
state.videoSpeedControl.videoSpeedsEl
|
||||
.find('a.speed_link:first')
|
||||
.focus();
|
||||
});
|
||||
|
||||
state.videoSpeedControl.videoSpeedsEl.find('a.speed_link:last')
|
||||
.on('blur', function () {
|
||||
state.videoSpeedControl.el.removeClass('open');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// ***************************************************************
|
||||
// Public functions start here.
|
||||
// These are available via the 'state' object. Their context ('this' keyword) is the 'state' object.
|
||||
// The magic private function that makes them available and sets up their context is makeFunctionsPublic().
|
||||
// These are available via the 'state' object. Their context ('this'
|
||||
// keyword) is the 'state' object. The magic private function that makes
|
||||
// them available and sets up their context is makeFunctionsPublic().
|
||||
// ***************************************************************
|
||||
|
||||
function setSpeed(speed) {
|
||||
this.videoSpeedControl.videoSpeedsEl.find('li').removeClass('active');
|
||||
this.videoSpeedControl.videoSpeedsEl.find("li[data-speed='" + speed + "']").addClass('active');
|
||||
this.videoSpeedControl.videoSpeedsEl
|
||||
.find("li[data-speed='" + speed + "']")
|
||||
.addClass('active');
|
||||
this.videoSpeedControl.el.find('p.active').html('' + speed + 'x');
|
||||
}
|
||||
|
||||
@@ -102,10 +129,15 @@ function () {
|
||||
|
||||
this.videoSpeedControl.setSpeed(
|
||||
// To meet the API expected format.
|
||||
parseFloat(this.videoSpeedControl.currentSpeed).toFixed(2).replace(/\.00$/, '.0')
|
||||
parseFloat(this.videoSpeedControl.currentSpeed)
|
||||
.toFixed(2)
|
||||
.replace(/\.00$/, '.0')
|
||||
);
|
||||
|
||||
this.trigger('videoPlayer.onSpeedChange', this.videoSpeedControl.currentSpeed);
|
||||
this.trigger(
|
||||
'videoPlayer.onSpeedChange',
|
||||
this.videoSpeedControl.currentSpeed
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +151,6 @@ function () {
|
||||
$.each(this.videoSpeedControl.speeds, function(index, speed) {
|
||||
var link, listItem;
|
||||
|
||||
//link = $('<a href="#">' + speed + 'x</a>');
|
||||
link = '<a href="#">' + speed + 'x</a>';
|
||||
|
||||
listItem = $('<li data-speed="' + speed + '">' + link + '</li>');
|
||||
@@ -131,7 +162,11 @@ function () {
|
||||
_this.videoSpeedControl.videoSpeedsEl.prepend(listItem);
|
||||
});
|
||||
|
||||
this.videoSpeedControl.videoSpeedsEl.find('a').on('click', this.videoSpeedControl.changeVideoSpeed);
|
||||
this.videoSpeedControl.videoSpeedsEl.find('a')
|
||||
.on('click', this.videoSpeedControl.changeVideoSpeed);
|
||||
|
||||
// TODO: After the control was re-rendered, we should attach 'focus'
|
||||
// and 'blur' events once more.
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@@ -109,6 +109,7 @@ function () {
|
||||
|
||||
if (this.videoType === 'html5') {
|
||||
this.el.on('mousemove', this.videoCaption.autoShowCaptions);
|
||||
this.el.on('keydown', this.videoCaption.autoShowCaptions);
|
||||
|
||||
// Moving slider on subtitles is not a mouse move,
|
||||
// but captions and controls should be showed.
|
||||
@@ -122,6 +123,10 @@ function () {
|
||||
|
||||
this.videoCaption.hideCaptions(this.hide_captions);
|
||||
|
||||
if (!this.youtubeId('1.0')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajaxWithPrefix({
|
||||
url: _this.videoCaption.captionURL(),
|
||||
notifyOnError: false,
|
||||
|
||||
@@ -1,82 +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
|
||||
|
||||
<div
|
||||
id="video_${id}"
|
||||
class="videoalpha"
|
||||
id="video_${id}"
|
||||
class="videoalpha"
|
||||
|
||||
% if not settings.MITX_FEATURES['STUB_VIDEO_FOR_TESTING']:
|
||||
data-streams="${youtube_streams}"
|
||||
% endif
|
||||
% 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-sub="{}"'.format(sub) if sub else ''}
|
||||
${'data-autoplay="{}"'.format(autoplay) if autoplay else ''}
|
||||
|
||||
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}"
|
||||
% 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"></div>
|
||||
<div>
|
||||
<ul class="vcr">
|
||||
<li><a class="video_control" href="#" title="${_('Play')}"></a></li>
|
||||
<li><div class="vidtime">0:00 / 0:00</div></li>
|
||||
</ul>
|
||||
<div class="secondary-controls">
|
||||
<div class="speeds">
|
||||
<a href="#">
|
||||
<h3>${_('Speed')}</h3>
|
||||
<p class="active"></p>
|
||||
</a>
|
||||
<ol class="video_speeds"></ol>
|
||||
</div>
|
||||
<div class="volume">
|
||||
<a href="#"></a>
|
||||
<div class="volume-slider-container">
|
||||
<div class="volume-slider"></div>
|
||||
<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>
|
||||
<a href="#" class="add-fullscreen" title="${_('Fill browser')}">${_('Fill browser')}</a>
|
||||
<a href="#" class="quality_control" title="${_('HD')}">${_('HD')}</a>
|
||||
|
||||
<a href="#" class="hide-subtitles" title="${_('Turn off captions')}">Captions</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</article>
|
||||
</section>
|
||||
</article>
|
||||
|
||||
<ol class="subtitles"><li></li></ol>
|
||||
|
||||
</div>
|
||||
<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>
|
||||
<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
|
||||
|
||||
Reference in New Issue
Block a user