diff --git a/common/lib/xmodule/xmodule/css/videoalpha/display.scss b/common/lib/xmodule/xmodule/css/videoalpha/display.scss index 3b40809fa34a..93c387315ac2 100644 --- a/common/lib/xmodule/xmodule/css/videoalpha/display.scss +++ b/common/lib/xmodule/xmodule/css/videoalpha/display.scss @@ -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; } diff --git a/common/lib/xmodule/xmodule/js/fixtures/video.html b/common/lib/xmodule/xmodule/js/fixtures/video.html index 1b27255b1e02..3273dd3aa7ba 100644 --- a/common/lib/xmodule/xmodule/js/fixtures/video.html +++ b/common/lib/xmodule/xmodule/js/fixtures/video.html @@ -2,8 +2,8 @@
+ 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 diff --git a/common/lib/xmodule/xmodule/js/spec/video/display/video_caption_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display/video_caption_spec.coffee index 7f4f6073cbc9..2c339b3ca269 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/display/video_caption_spec.coffee +++ b/common/lib/xmodule/xmodule/js/spec/video/display/video_caption_spec.coffee @@ -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' diff --git a/common/lib/xmodule/xmodule/js/spec/video/display/video_player_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display/video_player_spec.coffee index dab8c0815a10..9cec0e6e96f5 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/display/video_player_spec.coffee +++ b/common/lib/xmodule/xmodule/js/spec/video/display/video_player_spec.coffee @@ -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' diff --git a/common/lib/xmodule/xmodule/js/spec/video/display_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display_spec.coffee index 0ba0cc85f8d6..35a56a83ae49 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/display_spec.coffee +++ b/common/lib/xmodule/xmodule/js/spec/video/display_spec.coffee @@ -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' diff --git a/common/lib/xmodule/xmodule/js/spec/videoalpha/general_spec.js b/common/lib/xmodule/xmodule/js/spec/videoalpha/general_spec.js index 415ac440ad9b..bde4e6b43f1f 100644 --- a/common/lib/xmodule/xmodule/js/spec/videoalpha/general_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/videoalpha/general_spec.js @@ -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); }); }); }); diff --git a/common/lib/xmodule/xmodule/js/spec/videoalpha/readme.md b/common/lib/xmodule/xmodule/js/spec/videoalpha/readme.md index 570827b9100a..1462c14acff2 100644 --- a/common/lib/xmodule/xmodule/js/spec/videoalpha/readme.md +++ b/common/lib/xmodule/xmodule/js/spec/videoalpha/readme.md @@ -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". diff --git a/common/lib/xmodule/xmodule/js/spec/videoalpha/video_caption_spec.js b/common/lib/xmodule/xmodule/js/spec/videoalpha/video_caption_spec.js index 2c138a734caf..07c6c196c9f4 100644 --- a/common/lib/xmodule/xmodule/js/spec/videoalpha/video_caption_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/videoalpha/video_caption_spec.js @@ -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'); }); diff --git a/common/lib/xmodule/xmodule/js/spec/videoalpha/video_player_spec.js b/common/lib/xmodule/xmodule/js/spec/videoalpha/video_player_spec.js index 467ecc75a27e..5e4e40cdecf9 100644 --- a/common/lib/xmodule/xmodule/js/spec/videoalpha/video_player_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/videoalpha/video_player_spec.js @@ -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'); }); }); diff --git a/common/lib/xmodule/xmodule/js/spec/videoalpha/video_progress_slider_spec.js b/common/lib/xmodule/xmodule/js/spec/videoalpha/video_progress_slider_spec.js index 93b839dedf60..f0e177d5d7a3 100644 --- a/common/lib/xmodule/xmodule/js/spec/videoalpha/video_progress_slider_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/videoalpha/video_progress_slider_spec.js @@ -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); diff --git a/common/lib/xmodule/xmodule/js/spec/videoalpha/video_speed_control_spec.js b/common/lib/xmodule/xmodule/js/spec/videoalpha/video_speed_control_spec.js index c56375f6f7cb..c40a9c7295d7 100644 --- a/common/lib/xmodule/xmodule/js/spec/videoalpha/video_speed_control_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/videoalpha/video_speed_control_spec.js @@ -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() { diff --git a/common/lib/xmodule/xmodule/js/spec/videoalpha/video_volume_control_spec.js b/common/lib/xmodule/xmodule/js/spec/videoalpha/video_volume_control_spec.js index f7f6c6c58325..872b1fe18e56 100644 --- a/common/lib/xmodule/xmodule/js/spec/videoalpha/video_volume_control_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/videoalpha/video_volume_control_spec.js @@ -39,7 +39,6 @@ range: "min", min: 0, max: 100, - /* value: 100, */ value: videoVolumeControl.currentVolume, change: videoVolumeControl.onChange, slide: videoVolumeControl.onChange diff --git a/common/lib/xmodule/xmodule/js/src/videoalpha/01_initialize.js b/common/lib/xmodule/xmodule/js/src/videoalpha/01_initialize.js index d5d7149ceb08..88d866cd32f7 100644 --- a/common/lib/xmodule/xmodule/js/src/videoalpha/01_initialize.js +++ b/common/lib/xmodule/xmodule/js/src/videoalpha/01_initialize.js @@ -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))) { diff --git a/common/lib/xmodule/xmodule/js/src/videoalpha/04_video_control.js b/common/lib/xmodule/xmodule/js/src/videoalpha/04_video_control.js index c7a575046f36..d1a662712f86 100644 --- a/common/lib/xmodule/xmodule/js/src/videoalpha/04_video_control.js +++ b/common/lib/xmodule/xmodule/js/src/videoalpha/04_video_control.js @@ -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); } } diff --git a/common/lib/xmodule/xmodule/js/src/videoalpha/05_video_quality_control.js b/common/lib/xmodule/xmodule/js/src/videoalpha/05_video_quality_control.js index 952d76061006..24363cafed93 100644 --- a/common/lib/xmodule/xmodule/js/src/videoalpha/05_video_quality_control.js +++ b/common/lib/xmodule/xmodule/js/src/videoalpha/05_video_quality_control.js @@ -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) diff --git a/common/lib/xmodule/xmodule/js/src/videoalpha/06_video_progress_slider.js b/common/lib/xmodule/xmodule/js/src/videoalpha/06_video_progress_slider.js index 4409446c2a3e..b36fac6cd0de 100644 --- a/common/lib/xmodule/xmodule/js/src/videoalpha/06_video_progress_slider.js +++ b/common/lib/xmodule/xmodule/js/src/videoalpha/06_video_progress_slider.js @@ -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)) { diff --git a/common/lib/xmodule/xmodule/js/src/videoalpha/07_video_volume_control.js b/common/lib/xmodule/xmodule/js/src/videoalpha/07_video_volume_control.js index b778a2cbd048..0f1cd1182d3c 100644 --- a/common/lib/xmodule/xmodule/js/src/videoalpha/07_video_volume_control.js +++ b/common/lib/xmodule/xmodule/js/src/videoalpha/07_video_volume_control.js @@ -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'); + }); } // *************************************************************** diff --git a/common/lib/xmodule/xmodule/js/src/videoalpha/08_video_speed_control.js b/common/lib/xmodule/xmodule/js/src/videoalpha/08_video_speed_control.js index a13aa03f4fcb..b0f55d49a13b 100644 --- a/common/lib/xmodule/xmodule/js/src/videoalpha/08_video_speed_control.js +++ b/common/lib/xmodule/xmodule/js/src/videoalpha/08_video_speed_control.js @@ -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 = '' + speed + 'x'; - //var link = $('' + speed + 'x'); - var link = '' + speed + 'x'; - - state.videoSpeedControl.videoSpeedsEl.prepend($('
  • ' + link + '
  • ')); + state.videoSpeedControl.videoSpeedsEl + .prepend( + $('
  • ' + link + '
  • ') + ); }); 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 = $('' + speed + 'x'); link = '' + speed + 'x'; listItem = $('
  • ' + link + '
  • '); @@ -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. } }); diff --git a/common/lib/xmodule/xmodule/js/src/videoalpha/09_video_caption.js b/common/lib/xmodule/xmodule/js/src/videoalpha/09_video_caption.js index e95f99109e75..b8bc432a1bb8 100644 --- a/common/lib/xmodule/xmodule/js/src/videoalpha/09_video_caption.js +++ b/common/lib/xmodule/xmodule/js/src/videoalpha/09_video_caption.js @@ -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, diff --git a/lms/templates/videoalpha.html b/lms/templates/videoalpha.html index 682c299e105a..d0eb7290a730 100644 --- a/lms/templates/videoalpha.html +++ b/lms/templates/videoalpha.html @@ -1,82 +1,86 @@ <%! from django.utils.translation import ugettext as _ %> % if display_name is not UNDEFINED and display_name is not None: -

    ${display_name}

    +

    ${display_name}

    % endif
    -
    - - -
    + + -
    +
    +
    % if sources.get('main'): -
    -

    ${_('Download video here.') % sources.get('main')}

    -
    +
    +

    ${(_('Download video') + ' ' + _('here') + '.') % sources.get('main')}

    +
    % endif % if track: -
    -

    ${_('Download subtitles here.') % track}

    -
    +
    +

    ${(_('Download subtitles') + ' ' + _('here') + '.') % track}

    +
    % endif