\ No newline at end of file
diff --git a/common/lib/xmodule/xmodule/js/spec/.gitignore b/common/lib/xmodule/xmodule/js/spec/.gitignore
index a8db2aae70..138742c14c 100644
--- a/common/lib/xmodule/xmodule/js/spec/.gitignore
+++ b/common/lib/xmodule/xmodule/js/spec/.gitignore
@@ -1,4 +1,4 @@
*.js
-# Tests for videoalpha are written in pure JavaScript.
-!videoalpha/*.js
+# Tests for video are written in pure JavaScript.
+!video/*.js
diff --git a/common/lib/xmodule/xmodule/js/spec/helper.coffee b/common/lib/xmodule/xmodule/js/spec/helper.coffee
index 360f2914aa..1dfccdf521 100644
--- a/common/lib/xmodule/xmodule/js/spec/helper.coffee
+++ b/common/lib/xmodule/xmodule/js/spec/helper.coffee
@@ -111,34 +111,18 @@ jasmine.stubYoutubePlayer = ->
obj['getAvailablePlaybackRates'] = jasmine.createSpy('getAvailablePlaybackRates').andReturn [0.75, 1.0, 1.25, 1.5]
obj
-jasmine.stubVideoPlayer = (context, enableParts, createPlayer=true) ->
- enableParts = [enableParts] unless $.isArray(enableParts)
- suite = context.suite
- currentPartName = suite.description while suite = suite.parentSuite
- enableParts.push currentPartName
-
- loadFixtures 'video.html'
- jasmine.stubRequests()
- YT.Player = undefined
- videosDefinition = '0.75:7tqY6eQzVhE,1.0:cogebirgzzM'
- context.video = new Video '#example', videosDefinition
- jasmine.stubYoutubePlayer()
- if createPlayer
- return new VideoPlayer(video: context.video)
-
-jasmine.stubVideoPlayerAlpha = (context, enableParts, html5=false) ->
- console.log('stubVideoPlayerAlpha called')
+jasmine.stubVideoPlayer = (context, enableParts, html5=false) ->
suite = context.suite
currentPartName = suite.description while suite = suite.parentSuite
if html5 == false
- loadFixtures 'videoalpha.html'
+ loadFixtures 'video.html'
else
- loadFixtures 'videoalpha_html5.html'
+ loadFixtures 'video_html5.html'
jasmine.stubRequests()
YT.Player = undefined
- window.OldVideoPlayerAlpha = undefined
+ window.OldVideoPlayer = undefined
jasmine.stubYoutubePlayer()
- return new VideoAlpha '#example', '.75:7tqY6eQzVhE,1.0:cogebirgzzM'
+ return new Video '#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
deleted file mode 100644
index 2c339b3ca2..0000000000
--- a/common/lib/xmodule/xmodule/js/spec/video/display/video_caption_spec.coffee
+++ /dev/null
@@ -1,361 +0,0 @@
-describe 'VideoCaption', ->
-
- beforeEach ->
- spyOn(VideoCaption.prototype, 'fetchCaption').andCallThrough()
- spyOn($, 'ajaxWithPrefix').andCallThrough()
- window.onTouchBasedDevice = jasmine.createSpy('onTouchBasedDevice').andReturn false
-
- afterEach ->
- YT.Player = undefined
- $.fn.scrollTo.reset()
- $('.subtitles').remove()
-
- describe 'constructor', ->
-
- describe 'always', ->
-
- beforeEach ->
- @player = jasmine.stubVideoPlayer @
- @caption = @player.caption
-
- it 'set the youtube id', ->
- expect(@caption.youtubeId).toEqual 'cogebirgzzM'
-
- it 'create the caption element', ->
- expect($('.video')).toContain 'ol.subtitles'
-
- it 'add caption control to video player', ->
- expect($('.video')).toContain 'a.hide-subtitles'
-
- it 'fetch the caption', ->
- expect(@caption.loaded).toBeTruthy()
- expect(@caption.fetchCaption).toHaveBeenCalled()
- expect($.ajaxWithPrefix).toHaveBeenCalledWith
- url: @caption.captionURL()
- notifyOnError: false
- success: jasmine.any(Function)
-
- it 'bind window resize event', ->
- expect($(window)).toHandleWith 'resize', @caption.resize
-
- it 'bind the hide caption button', ->
- expect($('.hide-subtitles')).toHandleWith 'click', @caption.toggle
-
- it 'bind the mouse movement', ->
- expect($('.subtitles')).toHandleWith 'mouseover', @caption.onMouseEnter
- expect($('.subtitles')).toHandleWith 'mouseout', @caption.onMouseLeave
- expect($('.subtitles')).toHandleWith 'mousemove', @caption.onMovement
- expect($('.subtitles')).toHandleWith 'mousewheel', @caption.onMovement
- expect($('.subtitles')).toHandleWith 'DOMMouseScroll', @caption.onMovement
-
- describe 'when on a non touch-based device', ->
-
- beforeEach ->
- @player = jasmine.stubVideoPlayer @
- @caption = @player.caption
-
- it 'render the caption', ->
- captionsData = jasmine.stubbedCaption
- $('.subtitles li[data-index]').each (index, link) =>
- expect($(link)).toHaveData 'index', index
- expect($(link)).toHaveData 'start', captionsData.start[index]
- expect($(link)).toHaveText captionsData.text[index]
-
- it 'add a padding element to caption', ->
- expect($('.subtitles li:first')).toBe '.spacing'
- expect($('.subtitles li:last')).toBe '.spacing'
-
- it 'bind all the caption link', ->
- $('.subtitles li[data-index]').each (index, link) =>
- expect($(link)).toHandleWith 'click', @caption.seekPlayer
-
- it 'set rendered to true', ->
- expect(@caption.rendered).toBeTruthy()
-
- describe 'when on a touch-based device', ->
-
- beforeEach ->
- window.onTouchBasedDevice.andReturn true
- @player = jasmine.stubVideoPlayer @
- @caption = @player.caption
-
- it 'show explaination message', ->
- expect($('.subtitles li')).toHaveHtml "Caption will be displayed when you start playing the video."
-
- it 'does not set rendered to true', ->
- expect(@caption.rendered).toBeFalsy()
-
- describe 'mouse movement', ->
-
- beforeEach ->
- @player = jasmine.stubVideoPlayer @
- @caption = @player.caption
- window.setTimeout.andReturn(100)
- spyOn window, 'clearTimeout'
-
- describe 'when cursor is outside of the caption box', ->
-
- beforeEach ->
- $(window).trigger jQuery.Event 'mousemove'
-
- it 'does not set freezing timeout', ->
- expect(@caption.frozen).toBeFalsy()
-
- describe 'when cursor is in the caption box', ->
-
- beforeEach ->
- $('.subtitles').trigger jQuery.Event 'mouseenter'
-
- it 'set the freezing timeout', ->
- expect(@caption.frozen).toEqual 100
-
- describe 'when the cursor is moving', ->
- beforeEach ->
- $('.subtitles').trigger jQuery.Event 'mousemove'
-
- it 'reset the freezing timeout', ->
- expect(window.clearTimeout).toHaveBeenCalledWith 100
-
- describe 'when the mouse is scrolling', ->
- beforeEach ->
- $('.subtitles').trigger jQuery.Event 'mousewheel'
-
- it 'reset the freezing timeout', ->
- expect(window.clearTimeout).toHaveBeenCalledWith 100
-
- describe 'when cursor is moving out of the caption box', ->
- beforeEach ->
- @caption.frozen = 100
- $.fn.scrollTo.reset()
-
- describe 'always', ->
- beforeEach ->
- $('.subtitles').trigger jQuery.Event 'mouseout'
-
- it 'reset the freezing timeout', ->
- expect(window.clearTimeout).toHaveBeenCalledWith 100
-
- it 'unfreeze the caption', ->
- expect(@caption.frozen).toBeNull()
-
- describe 'when the player is playing', ->
- beforeEach ->
- @caption.playing = true
- $('.subtitles li[data-index]:first').addClass 'current'
- $('.subtitles').trigger jQuery.Event 'mouseout'
-
- it 'scroll the caption', ->
- expect($.fn.scrollTo).toHaveBeenCalled()
-
- describe 'when the player is not playing', ->
- beforeEach ->
- @caption.playing = false
- $('.subtitles').trigger jQuery.Event 'mouseout'
-
- it 'does not scroll the caption', ->
- expect($.fn.scrollTo).not.toHaveBeenCalled()
-
- describe 'search', ->
-
- beforeEach ->
- @player = jasmine.stubVideoPlayer @
- @caption = @player.caption
-
- it 'return a correct caption index', ->
- expect(@caption.search(0)).toEqual 0
- expect(@caption.search(9999)).toEqual 2
- expect(@caption.search(10000)).toEqual 2
- expect(@caption.search(15000)).toEqual 3
- expect(@caption.search(30000)).toEqual 7
- expect(@caption.search(30001)).toEqual 7
-
- describe 'play', ->
- describe 'when the caption was not rendered', ->
- beforeEach ->
- window.onTouchBasedDevice.andReturn true
- @player = jasmine.stubVideoPlayer @
- @caption = @player.caption
- @caption.play()
-
- it 'render the caption', ->
- captionsData = jasmine.stubbedCaption
- $('.subtitles li[data-index]').each (index, link) =>
- expect($(link)).toHaveData 'index', index
- expect($(link)).toHaveData 'start', captionsData.start[index]
- expect($(link)).toHaveText captionsData.text[index]
-
- it 'add a padding element to caption', ->
- expect($('.subtitles li:first')).toBe '.spacing'
- expect($('.subtitles li:last')).toBe '.spacing'
-
- it 'bind all the caption link', ->
- $('.subtitles li[data-index]').each (index, link) =>
- expect($(link)).toHandleWith 'click', @caption.seekPlayer
-
- it 'set rendered to true', ->
- expect(@caption.rendered).toBeTruthy()
-
- it 'set playing to true', ->
- expect(@caption.playing).toBeTruthy()
-
- describe 'pause', ->
- beforeEach ->
- @player = jasmine.stubVideoPlayer @
- @caption = @player.caption
- @caption.playing = true
- @caption.pause()
-
- it 'set playing to false', ->
- expect(@caption.playing).toBeFalsy()
-
- describe 'updatePlayTime', ->
-
- beforeEach ->
- @player = jasmine.stubVideoPlayer @
- @caption = @player.caption
-
- describe 'when the video speed is 1.0x', ->
- beforeEach ->
- @caption.currentSpeed = '1.0'
- @caption.updatePlayTime 25.000
-
- it 'search the caption based on time', ->
- expect(@caption.currentIndex).toEqual 5
-
- describe 'when the video speed is not 1.0x', ->
- beforeEach ->
- @caption.currentSpeed = '0.75'
- @caption.updatePlayTime 25.000
-
- it 'search the caption based on 1.0x speed', ->
- expect(@caption.currentIndex).toEqual 3
-
- describe 'when the index is not the same', ->
- beforeEach ->
- @caption.currentIndex = 1
- $('.subtitles li[data-index=1]').addClass 'current'
- @caption.updatePlayTime 25.000
-
- it 'deactivate the previous caption', ->
- expect($('.subtitles li[data-index=1]')).not.toHaveClass 'current'
-
- it 'activate new caption', ->
- expect($('.subtitles li[data-index=5]')).toHaveClass 'current'
-
- it 'save new index', ->
- expect(@caption.currentIndex).toEqual 5
-
- it 'scroll caption to new position', ->
- expect($.fn.scrollTo).toHaveBeenCalled()
-
- describe 'when the index is the same', ->
- beforeEach ->
- @caption.currentIndex = 1
- $('.subtitles li[data-index=3]').addClass 'current'
- @caption.updatePlayTime 15.000
-
- it 'does not change current subtitle', ->
- expect($('.subtitles li[data-index=3]')).toHaveClass 'current'
-
- describe 'resize', ->
-
- beforeEach ->
- @player = jasmine.stubVideoPlayer @
- @caption = @player.caption
- $('.subtitles li[data-index=1]').addClass 'current'
- @caption.resize()
-
- it 'set the height of caption container', ->
- expect(parseInt($('.subtitles').css('maxHeight'))).toBeCloseTo $('.video-wrapper').height(), 2
-
- it 'set the height of caption spacing', ->
- expect(Math.abs(parseInt($('.subtitles .spacing:first').css('height')) - @caption.topSpacingHeight())).toBeLessThan 1
- expect(Math.abs(parseInt($('.subtitles .spacing:last').css('height')) - @caption.bottomSpacingHeight())).toBeLessThan 1
-
-
- it 'scroll caption to new position', ->
- expect($.fn.scrollTo).toHaveBeenCalled()
-
- describe 'scrollCaption', ->
-
- beforeEach ->
- @player = jasmine.stubVideoPlayer @
- @caption = @player.caption
-
- describe 'when frozen', ->
- beforeEach ->
- @caption.frozen = true
- $('.subtitles li[data-index=1]').addClass 'current'
- @caption.scrollCaption()
-
- it 'does not scroll the caption', ->
- expect($.fn.scrollTo).not.toHaveBeenCalled()
-
- describe 'when not frozen', ->
- beforeEach ->
- @caption.frozen = false
-
- describe 'when there is no current caption', ->
- beforeEach ->
- @caption.scrollCaption()
-
- it 'does not scroll the caption', ->
- expect($.fn.scrollTo).not.toHaveBeenCalled()
-
- describe 'when there is a current caption', ->
- beforeEach ->
- $('.subtitles li[data-index=1]').addClass 'current'
- @caption.scrollCaption()
-
- it 'scroll to current caption', ->
- expect($.fn.scrollTo).toHaveBeenCalledWith $('.subtitles .current:first', @caption.el),
- offset: - ($('.video-wrapper').height() / 2 - $('.subtitles .current:first').height() / 2)
-
- describe 'seekPlayer', ->
-
- beforeEach ->
- @player = jasmine.stubVideoPlayer @
- @caption = @player.caption
- @time = null
- $(@caption).bind 'seek', (event, time) => @time = time
-
- describe 'when the video speed is 1.0x', ->
- beforeEach ->
- @caption.currentSpeed = '1.0'
- $('.subtitles li[data-start="27900"]').trigger('click')
-
- it 'trigger seek event with the correct time', ->
- expect(@time).toEqual 28.000
-
- describe 'when the video speed is not 1.0x', ->
- beforeEach ->
- @caption.currentSpeed = '0.75'
- $('.subtitles li[data-start="27900"]').trigger('click')
-
- it 'trigger seek event with the correct time', ->
- expect(@time).toEqual 37.000
-
- describe 'toggle', ->
- beforeEach ->
- @player = jasmine.stubVideoPlayer @
- @caption = @player.caption
- $('.subtitles li[data-index=1]').addClass 'current'
-
- describe 'when the caption is visible', ->
- beforeEach ->
- @caption.el.removeClass 'closed'
- @caption.toggle jQuery.Event('click')
-
- it 'hide the caption', ->
- expect(@caption.el).toHaveClass 'closed'
-
- describe 'when the caption is hidden', ->
- beforeEach ->
- @caption.el.addClass 'closed'
- @caption.toggle jQuery.Event('click')
-
- it 'show the caption', ->
- expect(@caption.el).not.toHaveClass 'closed'
-
- it 'scroll the caption', ->
- expect($.fn.scrollTo).toHaveBeenCalled()
diff --git a/common/lib/xmodule/xmodule/js/spec/video/display/video_control_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display/video_control_spec.coffee
deleted file mode 100644
index e15b0c856a..0000000000
--- a/common/lib/xmodule/xmodule/js/spec/video/display/video_control_spec.coffee
+++ /dev/null
@@ -1,103 +0,0 @@
-describe 'VideoControl', ->
- beforeEach ->
- window.onTouchBasedDevice = jasmine.createSpy('onTouchBasedDevice').andReturn false
- loadFixtures 'video.html'
- $('.video-controls').html ''
-
- describe 'constructor', ->
-
- it 'render the video controls', ->
- @control = new window.VideoControl(el: $('.video-controls'))
- expect($('.video-controls')).toContain
- ['.slider', 'ul.vcr', 'a.play', '.vidtime', '.add-fullscreen'].join(',')
- expect($('.video-controls').find('.vidtime')).toHaveText '0:00 / 0:00'
-
- it 'bind the playback button', ->
- @control = new window.VideoControl(el: $('.video-controls'))
- expect($('.video_control')).toHandleWith 'click', @control.togglePlayback
-
- describe 'when on a touch based device', ->
- beforeEach ->
- window.onTouchBasedDevice.andReturn true
- @control = new window.VideoControl(el: $('.video-controls'))
-
- it 'does not add the play class to video control', ->
- expect($('.video_control')).not.toHaveClass 'play'
- expect($('.video_control')).not.toHaveHtml 'Play'
-
-
- describe 'when on a non-touch based device', ->
-
- beforeEach ->
- @control = new window.VideoControl(el: $('.video-controls'))
-
- it 'add the play class to video control', ->
- expect($('.video_control')).toHaveClass 'play'
- expect($('.video_control')).toHaveHtml 'Play'
-
- describe 'play', ->
-
- beforeEach ->
- @control = new window.VideoControl(el: $('.video-controls'))
- @control.play()
-
- it 'switch playback button to play state', ->
- expect($('.video_control')).not.toHaveClass 'play'
- expect($('.video_control')).toHaveClass 'pause'
- expect($('.video_control')).toHaveHtml 'Pause'
-
- describe 'pause', ->
-
- beforeEach ->
- @control = new window.VideoControl(el: $('.video-controls'))
- @control.pause()
-
- it 'switch playback button to pause state', ->
- expect($('.video_control')).not.toHaveClass 'pause'
- expect($('.video_control')).toHaveClass 'play'
- expect($('.video_control')).toHaveHtml 'Play'
-
- describe 'togglePlayback', ->
-
- beforeEach ->
- @control = new window.VideoControl(el: $('.video-controls'))
-
- describe 'when the control does not have play or pause class', ->
- beforeEach ->
- $('.video_control').removeClass('play').removeClass('pause')
-
- describe 'when the video is playing', ->
- beforeEach ->
- $('.video_control').addClass('play')
- spyOnEvent @control, 'pause'
- @control.togglePlayback jQuery.Event('click')
-
- it 'does not trigger the pause event', ->
- expect('pause').not.toHaveBeenTriggeredOn @control
-
- describe 'when the video is paused', ->
- beforeEach ->
- $('.video_control').addClass('pause')
- spyOnEvent @control, 'play'
- @control.togglePlayback jQuery.Event('click')
-
- it 'does not trigger the play event', ->
- expect('play').not.toHaveBeenTriggeredOn @control
-
- describe 'when the video is playing', ->
- beforeEach ->
- spyOnEvent @control, 'pause'
- $('.video_control').addClass 'pause'
- @control.togglePlayback jQuery.Event('click')
-
- it 'trigger the pause event', ->
- expect('pause').toHaveBeenTriggeredOn @control
-
- describe 'when the video is paused', ->
- beforeEach ->
- spyOnEvent @control, 'play'
- $('.video_control').addClass 'play'
- @control.togglePlayback jQuery.Event('click')
-
- it 'trigger the play event', ->
- expect('play').toHaveBeenTriggeredOn @control
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
deleted file mode 100644
index 9cec0e6e96..0000000000
--- a/common/lib/xmodule/xmodule/js/spec/video/display/video_player_spec.coffee
+++ /dev/null
@@ -1,466 +0,0 @@
-describe 'VideoPlayer', ->
- beforeEach ->
- window.onTouchBasedDevice = jasmine.createSpy('onTouchBasedDevice').andReturn false
- # It tries to call methods of VideoProgressSlider on Spy
- for part in ['VideoCaption', 'VideoSpeedControl', 'VideoVolumeControl', 'VideoProgressSlider', 'VideoControl']
- spyOn(window[part].prototype, 'initialize').andCallThrough()
- jasmine.stubVideoPlayer @, [], false
-
- afterEach ->
- YT.Player = undefined
-
- describe 'constructor', ->
- beforeEach ->
- spyOn YT, 'Player'
- $.fn.qtip.andCallFake ->
- $(this).data('qtip', true)
- $('.video').append $('
')
-
- describe 'always', ->
- beforeEach ->
- @player = new VideoPlayer video: @video
-
- it 'instanticate current time to zero', ->
- expect(@player.currentTime).toEqual 0
-
- it 'set the element', ->
- expect(@player.el).toHaveId 'video_id'
-
- it 'create video control', ->
- expect(window.VideoControl.prototype.initialize).toHaveBeenCalled()
- expect(@player.control).toBeDefined()
- expect(@player.control.el).toBe $('.video-controls', @player.el)
-
- it 'create video caption', ->
- expect(window.VideoCaption.prototype.initialize).toHaveBeenCalled()
- expect(@player.caption).toBeDefined()
- expect(@player.caption.el).toBe @player.el
- expect(@player.caption.youtubeId).toEqual 'cogebirgzzM'
- expect(@player.caption.currentSpeed).toEqual '1.0'
- expect(@player.caption.captionAssetPath).toEqual '/static/subs/'
-
- it 'create video speed control', ->
- expect(window.VideoSpeedControl.prototype.initialize).toHaveBeenCalled()
- expect(@player.speedControl).toBeDefined()
- expect(@player.speedControl.el).toBe $('.secondary-controls', @player.el)
- expect(@player.speedControl.speeds).toEqual ['0.75', '1.0']
- expect(@player.speedControl.currentSpeed).toEqual '1.0'
-
- it 'create video progress slider', ->
- expect(window.VideoSpeedControl.prototype.initialize).toHaveBeenCalled()
- expect(@player.progressSlider).toBeDefined()
- expect(@player.progressSlider.el).toBe $('.slider', @player.el)
-
- it 'create Youtube player', ->
- expect(YT.Player).toHaveBeenCalledWith('id', {
- playerVars:
- controls: 0
- wmode: 'transparent'
- rel: 0
- showinfo: 0
- enablejsapi: 1
- modestbranding: 1
- videoId: 'cogebirgzzM'
- events:
- onReady: @player.onReady
- onStateChange: @player.onStateChange
- onPlaybackQualityChange: @player.onPlaybackQualityChange
- })
-
- it 'bind to video control play event', ->
- expect($(@player.control)).toHandleWith 'play', @player.play
-
- it 'bind to video control pause event', ->
- expect($(@player.control)).toHandleWith 'pause', @player.pause
-
- it 'bind to video caption seek event', ->
- expect($(@player.caption)).toHandleWith 'seek', @player.onSeek
-
- it 'bind to video speed control speedChange event', ->
- expect($(@player.speedControl)).toHandleWith 'speedChange', @player.onSpeedChange
-
- it 'bind to video progress slider seek event', ->
- expect($(@player.progressSlider)).toHandleWith 'seek', @player.onSeek
-
- it 'bind to video volume control volumeChange event', ->
- expect($(@player.volumeControl)).toHandleWith 'volumeChange', @player.onVolumeChange
-
- it 'bind to key press', ->
- expect($(document.documentElement)).toHandleWith 'keyup', @player.bindExitFullScreen
-
- it 'bind to fullscreen switching button', ->
- expect($('.add-fullscreen')).toHandleWith 'click', @player.toggleFullScreen
-
- describe 'when not on a touch based device', ->
- beforeEach ->
- $('.add-fullscreen, .hide-subtitles').removeData 'qtip'
- @player = new VideoPlayer video: @video
-
- it 'add the tooltip to fullscreen and subtitle button', ->
- expect($('.add-fullscreen')).toHaveData 'qtip'
- expect($('.hide-subtitles')).toHaveData 'qtip'
-
- it 'create video volume control', ->
- expect(window.VideoVolumeControl.prototype.initialize).toHaveBeenCalled()
- expect(@player.volumeControl).toBeDefined()
- expect(@player.volumeControl.el).toBe $('.secondary-controls', @player.el)
-
- describe 'when on a touch based device', ->
- beforeEach ->
- window.onTouchBasedDevice.andReturn true
- $('.add-fullscreen, .hide-subtitles').removeData 'qtip'
- @player = new VideoPlayer video: @video
-
- it 'does not add the tooltip to fullscreen and subtitle button', ->
- expect($('.add-fullscreen')).not.toHaveData 'qtip'
- expect($('.hide-subtitles')).not.toHaveData 'qtip'
-
- it 'does not create video volume control', ->
- expect(window.VideoVolumeControl.prototype.initialize).not.toHaveBeenCalled()
- expect(@player.volumeControl).not.toBeDefined()
-
- describe 'onReady', ->
- beforeEach ->
- @video.embed()
- @player = @video.player
- spyOnEvent @player, 'ready'
- spyOnEvent @player, 'updatePlayTime'
- @player.onReady()
-
- describe 'when not on a touch based device', ->
- beforeEach ->
- spyOn @player, 'play'
- @player.onReady()
-
- it 'autoplay the first video', ->
- expect(@player.play).toHaveBeenCalled()
-
- describe 'when on a touch based device', ->
- beforeEach ->
- window.onTouchBasedDevice.andReturn true
- spyOn @player, 'play'
- @player.onReady()
-
- it 'does not autoplay the first video', ->
- expect(@player.play).not.toHaveBeenCalled()
-
- describe 'onStateChange', ->
- beforeEach ->
- @player = new VideoPlayer video: @video
-
- describe 'when the video is unstarted', ->
- beforeEach ->
- spyOn @player.control, 'pause'
- @player.caption.pause = jasmine.createSpy('VideoCaption.pause')
- @player.onStateChange data: YT.PlayerState.UNSTARTED
-
- it 'pause the video control', ->
- expect(@player.control.pause).toHaveBeenCalled()
-
- it 'pause the video caption', ->
- expect(@player.caption.pause).toHaveBeenCalled()
-
- describe 'when the video is playing', ->
- beforeEach ->
- @anotherPlayer = jasmine.createSpyObj 'AnotherPlayer', ['pauseVideo']
- window.player = @anotherPlayer
- spyOn @video, 'log'
- spyOn(window, 'setInterval').andReturn 100
- spyOn @player.control, 'play'
- @player.caption.play = jasmine.createSpy('VideoCaption.play')
- @player.progressSlider.play = jasmine.createSpy('VideoProgressSlider.play')
- @player.player.getVideoEmbedCode.andReturn 'embedCode'
- @player.onStateChange data: YT.PlayerState.PLAYING
-
- it 'log the play_video event', ->
- expect(@video.log).toHaveBeenCalledWith 'play_video'
-
- it 'pause other video player', ->
- expect(@anotherPlayer.pauseVideo).toHaveBeenCalled()
-
- it 'set current video player as active player', ->
- expect(window.player).toEqual @player.player
-
- it 'set update interval', ->
- expect(window.setInterval).toHaveBeenCalledWith @player.update, 200
- expect(@player.player.interval).toEqual 100
-
- it 'play the video control', ->
- expect(@player.control.play).toHaveBeenCalled()
-
- it 'play the video caption', ->
- expect(@player.caption.play).toHaveBeenCalled()
-
- it 'play the video progress slider', ->
- expect(@player.progressSlider.play).toHaveBeenCalled()
-
- describe 'when the video is paused', ->
- beforeEach ->
- @player = new VideoPlayer video: @video
- window.player = @player.player
- spyOn @video, 'log'
- spyOn window, 'clearInterval'
- spyOn @player.control, 'pause'
- @player.caption.pause = jasmine.createSpy('VideoCaption.pause')
- @player.player.interval = 100
- @player.player.getVideoEmbedCode.andReturn 'embedCode'
- @player.onStateChange data: YT.PlayerState.PAUSED
-
- it 'log the pause_video event', ->
- expect(@video.log).toHaveBeenCalledWith 'pause_video'
-
- it 'set current video player as inactive', ->
- expect(window.player).toBeNull()
-
- it 'clear update interval', ->
- expect(window.clearInterval).toHaveBeenCalledWith 100
- expect(@player.player.interval).toBeNull()
-
- it 'pause the video control', ->
- expect(@player.control.pause).toHaveBeenCalled()
-
- it 'pause the video caption', ->
- expect(@player.caption.pause).toHaveBeenCalled()
-
- describe 'when the video is ended', ->
- beforeEach ->
- spyOn @player.control, 'pause'
- @player.caption.pause = jasmine.createSpy('VideoCaption.pause')
- @player.onStateChange data: YT.PlayerState.ENDED
-
- it 'pause the video control', ->
- expect(@player.control.pause).toHaveBeenCalled()
-
- it 'pause the video caption', ->
- expect(@player.caption.pause).toHaveBeenCalled()
-
- describe 'onSeek', ->
- beforeEach ->
- @player = new VideoPlayer video: @video
- spyOn window, 'clearInterval'
- @player.player.interval = 100
- spyOn @player, 'updatePlayTime'
- @player.onSeek {}, 60
-
- it 'seek the player', ->
- expect(@player.player.seekTo).toHaveBeenCalledWith 60, true
-
- it 'call updatePlayTime on player', ->
- expect(@player.updatePlayTime).toHaveBeenCalledWith 60
-
- describe 'when the player is playing', ->
- beforeEach ->
- @player.player.getPlayerState.andReturn YT.PlayerState.PLAYING
- @player.onSeek {}, 60
-
- it 'reset the update interval', ->
- expect(window.clearInterval).toHaveBeenCalledWith 100
-
- describe 'when the player is not playing', ->
- beforeEach ->
- @player.player.getPlayerState.andReturn YT.PlayerState.PAUSED
- @player.onSeek {}, 60
-
- it 'set the current time', ->
- expect(@player.currentTime).toEqual 60
-
- describe 'onSpeedChange', ->
- beforeEach ->
- @player = new VideoPlayer video: @video
- @player.currentTime = 60
- spyOn @player, 'updatePlayTime'
- spyOn(@video, 'setSpeed').andCallThrough()
-
- describe 'always', ->
- beforeEach ->
- @player.onSpeedChange {}, '0.75'
-
- it 'convert the current time to the new speed', ->
- expect(@player.currentTime).toEqual '80.000'
-
- it 'set video speed to the new speed', ->
- expect(@video.setSpeed).toHaveBeenCalledWith '0.75'
-
- it 'tell video caption that the speed has changed', ->
- expect(@player.caption.currentSpeed).toEqual '0.75'
-
- describe 'when the video is playing', ->
- beforeEach ->
- @player.player.getPlayerState.andReturn YT.PlayerState.PLAYING
- @player.onSpeedChange {}, '0.75'
-
- it 'load the video', ->
- expect(@player.player.loadVideoById).toHaveBeenCalledWith '7tqY6eQzVhE', '80.000'
-
- it 'trigger updatePlayTime event', ->
- expect(@player.updatePlayTime).toHaveBeenCalledWith '80.000'
-
- describe 'when the video is not playing', ->
- beforeEach ->
- @player.player.getPlayerState.andReturn YT.PlayerState.PAUSED
- @player.onSpeedChange {}, '0.75'
-
- it 'cue the video', ->
- expect(@player.player.cueVideoById).toHaveBeenCalledWith '7tqY6eQzVhE', '80.000'
-
- it 'trigger updatePlayTime event', ->
- expect(@player.updatePlayTime).toHaveBeenCalledWith '80.000'
-
- describe 'onVolumeChange', ->
- beforeEach ->
- @player = new VideoPlayer video: @video
- @player.onVolumeChange undefined, 60
-
- it 'set the volume on player', ->
- expect(@player.player.setVolume).toHaveBeenCalledWith 60
-
- describe 'update', ->
- beforeEach ->
- @player = new VideoPlayer video: @video
- spyOn @player, 'updatePlayTime'
-
- describe 'when the current time is unavailable from the player', ->
- beforeEach ->
- @player.player.getCurrentTime.andReturn undefined
- @player.update()
-
- it 'does not trigger updatePlayTime event', ->
- expect(@player.updatePlayTime).not.toHaveBeenCalled()
-
- describe 'when the current time is available from the player', ->
- beforeEach ->
- @player.player.getCurrentTime.andReturn 60
- @player.update()
-
- it 'trigger updatePlayTime event', ->
- expect(@player.updatePlayTime).toHaveBeenCalledWith(60)
-
- describe 'updatePlayTime', ->
- beforeEach ->
- @player = new VideoPlayer video: @video
- spyOn(@video, 'getDuration').andReturn 1800
- @player.caption.updatePlayTime = jasmine.createSpy('VideoCaption.updatePlayTime')
- @player.progressSlider.updatePlayTime = jasmine.createSpy('VideoProgressSlider.updatePlayTime')
- @player.updatePlayTime 60
-
- it 'update the video playback time', ->
- expect($('.vidtime')).toHaveHtml '1:00 / 30:00'
-
- it 'update the playback time on caption', ->
- expect(@player.caption.updatePlayTime).toHaveBeenCalledWith 60
-
- it 'update the playback time on progress slider', ->
- expect(@player.progressSlider.updatePlayTime).toHaveBeenCalledWith 60, 1800
-
- describe 'toggleFullScreen', ->
- beforeEach ->
- @player = new VideoPlayer video: @video
- @player.caption.resize = jasmine.createSpy('VideoCaption.resize')
-
- describe 'when the video player is not full screen', ->
- beforeEach ->
- @player.el.removeClass 'fullscreen'
- @player.toggleFullScreen(jQuery.Event("click"))
-
- it 'replace the full screen button tooltip', ->
- expect($('.add-fullscreen')).toHaveAttr 'title', 'Exit fill browser'
-
- it 'add the fullscreen class', ->
- expect(@player.el).toHaveClass 'fullscreen'
-
- it 'tell VideoCaption to resize', ->
- expect(@player.caption.resize).toHaveBeenCalled()
-
- describe 'when the video player already full screen', ->
- beforeEach ->
- @player.el.addClass 'fullscreen'
- @player.toggleFullScreen(jQuery.Event("click"))
-
- it 'replace the full screen button tooltip', ->
- expect($('.add-fullscreen')).toHaveAttr 'title', 'Fill browser'
-
- it 'remove exit full screen button', ->
- expect(@player.el).not.toContain 'a.exit'
-
- it 'remove the fullscreen class', ->
- expect(@player.el).not.toHaveClass 'fullscreen'
-
- it 'tell VideoCaption to resize', ->
- expect(@player.caption.resize).toHaveBeenCalled()
-
- describe 'play', ->
- beforeEach ->
- @player = new VideoPlayer video: @video
-
- describe 'when the player is not ready', ->
- beforeEach ->
- @player.player.playVideo = undefined
- @player.play()
-
- it 'does nothing', ->
- expect(@player.player.playVideo).toBeUndefined()
-
- describe 'when the player is ready', ->
- beforeEach ->
- @player.player.playVideo.andReturn true
- @player.play()
-
- it 'delegate to the Youtube player', ->
- expect(@player.player.playVideo).toHaveBeenCalled()
-
- describe 'isPlaying', ->
- beforeEach ->
- @player = new VideoPlayer video: @video
-
- describe 'when the video is playing', ->
- beforeEach ->
- @player.player.getPlayerState.andReturn YT.PlayerState.PLAYING
-
- it 'return true', ->
- expect(@player.isPlaying()).toBeTruthy()
-
- describe 'when the video is not playing', ->
- beforeEach ->
- @player.player.getPlayerState.andReturn YT.PlayerState.PAUSED
-
- it 'return false', ->
- expect(@player.isPlaying()).toBeFalsy()
-
- describe 'pause', ->
- beforeEach ->
- @player = new VideoPlayer video: @video
- @player.pause()
-
- it 'delegate to the Youtube player', ->
- expect(@player.player.pauseVideo).toHaveBeenCalled()
-
- describe 'duration', ->
- beforeEach ->
- @player = new VideoPlayer video: @video
- spyOn @video, 'getDuration'
- @player.duration()
-
- it 'delegate to the video', ->
- expect(@video.getDuration).toHaveBeenCalled()
-
- describe 'currentSpeed', ->
- beforeEach ->
- @player = new VideoPlayer video: @video
- @video.speed = '3.0'
-
- it 'delegate to the video', ->
- expect(@player.currentSpeed()).toEqual '3.0'
-
- describe 'volume', ->
- beforeEach ->
- @player = new VideoPlayer video: @video
- @player.player.getVolume.andReturn 42
-
- describe 'without value', ->
- it 'return current volume', ->
- expect(@player.volume()).toEqual 42
-
- describe 'with value', ->
- it 'set player volume', ->
- @player.volume(60)
- expect(@player.player.setVolume).toHaveBeenCalledWith(60)
diff --git a/common/lib/xmodule/xmodule/js/spec/video/display/video_progress_slider_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display/video_progress_slider_spec.coffee
deleted file mode 100644
index bf6dada93b..0000000000
--- a/common/lib/xmodule/xmodule/js/spec/video/display/video_progress_slider_spec.coffee
+++ /dev/null
@@ -1,169 +0,0 @@
-describe 'VideoProgressSlider', ->
- beforeEach ->
- window.onTouchBasedDevice = jasmine.createSpy('onTouchBasedDevice').andReturn false
-
- describe 'constructor', ->
- describe 'on a non-touch based device', ->
- beforeEach ->
- spyOn($.fn, 'slider').andCallThrough()
- @player = jasmine.stubVideoPlayer @
- @progressSlider = @player.progressSlider
-
- it 'build the slider', ->
- expect(@progressSlider.slider).toBe '.slider'
- expect($.fn.slider).toHaveBeenCalledWith
- range: 'min'
- change: @progressSlider.onChange
- slide: @progressSlider.onSlide
- stop: @progressSlider.onStop
-
- it 'build the seek handle', ->
- expect(@progressSlider.handle).toBe '.slider .ui-slider-handle'
- expect($.fn.qtip).toHaveBeenCalledWith
- content: "0:00"
- position:
- my: 'bottom center'
- at: 'top center'
- container: @progressSlider.handle
- hide:
- delay: 700
- style:
- classes: 'ui-tooltip-slider'
- widget: true
-
- describe 'on a touch-based device', ->
- beforeEach ->
- window.onTouchBasedDevice.andReturn true
- spyOn($.fn, 'slider').andCallThrough()
- @player = jasmine.stubVideoPlayer @
- @progressSlider = @player.progressSlider
-
- it 'does not build the slider', ->
- expect(@progressSlider.slider).toBeUndefined
- expect($.fn.slider).not.toHaveBeenCalled()
-
- describe 'play', ->
- beforeEach ->
- spyOn(VideoProgressSlider.prototype, 'buildSlider').andCallThrough()
- @player = jasmine.stubVideoPlayer @
- @progressSlider = @player.progressSlider
-
- describe 'when the slider was already built', ->
-
- beforeEach ->
- @progressSlider.play()
-
- it 'does not build the slider', ->
- expect(@progressSlider.buildSlider.calls.length).toEqual 1
-
- describe 'when the slider was not already built', ->
- beforeEach ->
- spyOn($.fn, 'slider').andCallThrough()
- @progressSlider.slider = null
- @progressSlider.play()
-
- it 'build the slider', ->
- expect(@progressSlider.slider).toBe '.slider'
- expect($.fn.slider).toHaveBeenCalledWith
- range: 'min'
- change: @progressSlider.onChange
- slide: @progressSlider.onSlide
- stop: @progressSlider.onStop
-
- it 'build the seek handle', ->
- expect(@progressSlider.handle).toBe '.ui-slider-handle'
- expect($.fn.qtip).toHaveBeenCalledWith
- content: "0:00"
- position:
- my: 'bottom center'
- at: 'top center'
- container: @progressSlider.handle
- hide:
- delay: 700
- style:
- classes: 'ui-tooltip-slider'
- widget: true
-
- describe 'updatePlayTime', ->
- beforeEach ->
- @player = jasmine.stubVideoPlayer @
- @progressSlider = @player.progressSlider
-
- describe 'when frozen', ->
- beforeEach ->
- spyOn($.fn, 'slider').andCallThrough()
- @progressSlider.frozen = true
- @progressSlider.updatePlayTime 20, 120
-
- it 'does not update the slider', ->
- expect($.fn.slider).not.toHaveBeenCalled()
-
- describe 'when not frozen', ->
- beforeEach ->
- spyOn($.fn, 'slider').andCallThrough()
- @progressSlider.frozen = false
- @progressSlider.updatePlayTime 20, 120
-
- it 'update the max value of the slider', ->
- expect($.fn.slider).toHaveBeenCalledWith 'option', 'max', 120
-
- it 'update current value of the slider', ->
- expect($.fn.slider).toHaveBeenCalledWith 'value', 20
-
- describe 'onSlide', ->
- beforeEach ->
- @player = jasmine.stubVideoPlayer @
- @progressSlider = @player.progressSlider
- @time = null
- $(@progressSlider).bind 'seek', (event, time) => @time = time
- spyOnEvent @progressSlider, 'seek'
- @progressSlider.onSlide {}, value: 20
-
- it 'freeze the slider', ->
- expect(@progressSlider.frozen).toBeTruthy()
-
- it 'update the tooltip', ->
- expect($.fn.qtip).toHaveBeenCalled()
-
- it 'trigger seek event', ->
- expect('seek').toHaveBeenTriggeredOn @progressSlider
- expect(@time).toEqual 20
-
- describe 'onChange', ->
- beforeEach ->
- @player = jasmine.stubVideoPlayer @
- @progressSlider = @player.progressSlider
- @progressSlider.onChange {}, value: 20
-
- it 'update the tooltip', ->
- expect($.fn.qtip).toHaveBeenCalled()
-
- describe 'onStop', ->
- beforeEach ->
- @player = jasmine.stubVideoPlayer @
- @progressSlider = @player.progressSlider
- @time = null
- $(@progressSlider).bind 'seek', (event, time) => @time = time
- spyOnEvent @progressSlider, 'seek'
- @progressSlider.onStop {}, value: 20
-
- it 'freeze the slider', ->
- expect(@progressSlider.frozen).toBeTruthy()
-
- it 'trigger seek event', ->
- expect('seek').toHaveBeenTriggeredOn @progressSlider
- expect(@time).toEqual 20
-
- it 'set timeout to unfreeze the slider', ->
- expect(window.setTimeout).toHaveBeenCalledWith jasmine.any(Function), 200
- window.setTimeout.mostRecentCall.args[0]()
- expect(@progressSlider.frozen).toBeFalsy()
-
- describe 'updateTooltip', ->
- beforeEach ->
- @player = jasmine.stubVideoPlayer @
- @progressSlider = @player.progressSlider
- @progressSlider.updateTooltip 90
-
- it 'set the tooltip value', ->
- expect($.fn.qtip).toHaveBeenCalledWith 'option', 'content.text', '1:30'
diff --git a/common/lib/xmodule/xmodule/js/spec/video/display/video_speed_control_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display/video_speed_control_spec.coffee
deleted file mode 100644
index 687f90e030..0000000000
--- a/common/lib/xmodule/xmodule/js/spec/video/display/video_speed_control_spec.coffee
+++ /dev/null
@@ -1,91 +0,0 @@
-describe 'VideoSpeedControl', ->
- beforeEach ->
- window.onTouchBasedDevice = jasmine.createSpy('onTouchBasedDevice').andReturn false
- jasmine.stubVideoPlayer @
- $('.speeds').remove()
-
- describe 'constructor', ->
- describe 'always', ->
- beforeEach ->
- @speedControl = new VideoSpeedControl el: $('.secondary-controls'), speeds: @video.speeds, currentSpeed: '1.0'
-
- it 'add the video speed control to player', ->
- secondaryControls = $('.secondary-controls')
- li = secondaryControls.find('.video_speeds li')
- expect(secondaryControls).toContain '.speeds'
- expect(secondaryControls).toContain '.video_speeds'
- expect(secondaryControls.find('p.active').text()).toBe '1.0x'
- expect(li.filter('.active')).toHaveData 'speed', @speedControl.currentSpeed
- expect(li.length).toBe @speedControl.speeds.length
- $.each li.toArray().reverse(), (index, link) =>
- expect($(link)).toHaveData 'speed', @speedControl.speeds[index]
- expect($(link).find('a').text()).toBe @speedControl.speeds[index] + 'x'
-
- it 'bind to change video speed link', ->
- expect($('.video_speeds a')).toHandleWith 'click', @speedControl.changeVideoSpeed
-
- describe 'when running on touch based device', ->
- beforeEach ->
- window.onTouchBasedDevice.andReturn true
- $('.speeds').removeClass 'open'
- @speedControl = new VideoSpeedControl el: $('.secondary-controls'), speeds: @video.speeds, currentSpeed: '1.0'
-
- it 'open the speed toggle on click', ->
- $('.speeds').click()
- expect($('.speeds')).toHaveClass 'open'
- $('.speeds').click()
- expect($('.speeds')).not.toHaveClass 'open'
-
- describe 'when running on non-touch based device', ->
- beforeEach ->
- $('.speeds').removeClass 'open'
- @speedControl = new VideoSpeedControl el: $('.secondary-controls'), speeds: @video.speeds, currentSpeed: '1.0'
-
- it 'open the speed toggle on hover', ->
- $('.speeds').mouseenter()
- expect($('.speeds')).toHaveClass 'open'
- $('.speeds').mouseleave()
- expect($('.speeds')).not.toHaveClass 'open'
-
- it 'close the speed toggle on mouse out', ->
- $('.speeds').mouseenter().mouseleave()
- expect($('.speeds')).not.toHaveClass 'open'
-
- it 'close the speed toggle on click', ->
- $('.speeds').mouseenter().click()
- expect($('.speeds')).not.toHaveClass 'open'
-
- describe 'changeVideoSpeed', ->
- beforeEach ->
- @speedControl = new VideoSpeedControl el: $('.secondary-controls'), speeds: @video.speeds, currentSpeed: '1.0'
- @video.setSpeed '1.0'
-
- describe 'when new speed is the same', ->
- beforeEach ->
- spyOnEvent @speedControl, 'speedChange'
- $('li[data-speed="1.0"] a').click()
-
- it 'does not trigger speedChange event', ->
- expect('speedChange').not.toHaveBeenTriggeredOn @speedControl
-
- describe 'when new speed is not the same', ->
- beforeEach ->
- @newSpeed = null
- $(@speedControl).bind 'speedChange', (event, newSpeed) => @newSpeed = newSpeed
- spyOnEvent @speedControl, 'speedChange'
- $('li[data-speed="0.75"] a').click()
-
- it 'trigger speedChange event', ->
- expect('speedChange').toHaveBeenTriggeredOn @speedControl
- expect(@newSpeed).toEqual 0.75
-
- describe 'onSpeedChange', ->
- beforeEach ->
- @speedControl = new VideoSpeedControl el: $('.secondary-controls'), speeds: @video.speeds, currentSpeed: '1.0'
- $('li[data-speed="1.0"] a').addClass 'active'
- @speedControl.setSpeed '0.75'
-
- it 'set the new speed as active', ->
- expect($('.video_speeds li[data-speed="1.0"]')).not.toHaveClass 'active'
- expect($('.video_speeds li[data-speed="0.75"]')).toHaveClass 'active'
- expect($('.speeds p.active')).toHaveHtml '0.75x'
diff --git a/common/lib/xmodule/xmodule/js/spec/video/display/video_volume_control_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display/video_volume_control_spec.coffee
deleted file mode 100644
index a2b14afa55..0000000000
--- a/common/lib/xmodule/xmodule/js/spec/video/display/video_volume_control_spec.coffee
+++ /dev/null
@@ -1,94 +0,0 @@
-describe 'VideoVolumeControl', ->
- beforeEach ->
- jasmine.stubVideoPlayer @
- $('.volume').remove()
-
- describe 'constructor', ->
- beforeEach ->
- spyOn($.fn, 'slider')
- @volumeControl = new VideoVolumeControl el: $('.secondary-controls')
-
- it 'initialize currentVolume to 100', ->
- expect(@volumeControl.currentVolume).toEqual 100
-
- it 'render the volume control', ->
- expect($('.secondary-controls').html()).toContain """
-
- """
-
- it 'create the slider', ->
- expect($.fn.slider).toHaveBeenCalledWith
- orientation: "vertical"
- range: "min"
- min: 0
- max: 100
- value: 100
- change: @volumeControl.onChange
- slide: @volumeControl.onChange
-
- it 'bind the volume control', ->
- expect($('.volume>a')).toHandleWith 'click', @volumeControl.toggleMute
-
- expect($('.volume')).not.toHaveClass 'open'
- $('.volume').mouseenter()
- expect($('.volume')).toHaveClass 'open'
- $('.volume').mouseleave()
- expect($('.volume')).not.toHaveClass 'open'
-
- describe 'onChange', ->
- beforeEach ->
- spyOnEvent @volumeControl, 'volumeChange'
- @newVolume = undefined
- @volumeControl = new VideoVolumeControl el: $('.secondary-controls')
- $(@volumeControl).bind 'volumeChange', (event, volume) => @newVolume = volume
-
- describe 'when the new volume is more than 0', ->
- beforeEach ->
- @volumeControl.onChange undefined, value: 60
-
- it 'set the player volume', ->
- expect(@newVolume).toEqual 60
-
- it 'remote muted class', ->
- expect($('.volume')).not.toHaveClass 'muted'
-
- describe 'when the new volume is 0', ->
- beforeEach ->
- @volumeControl.onChange undefined, value: 0
-
- it 'set the player volume', ->
- expect(@newVolume).toEqual 0
-
- it 'add muted class', ->
- expect($('.volume')).toHaveClass 'muted'
-
- describe 'toggleMute', ->
- beforeEach ->
- @newVolume = undefined
- @volumeControl = new VideoVolumeControl el: $('.secondary-controls')
- $(@volumeControl).bind 'volumeChange', (event, volume) => @newVolume = volume
-
- describe 'when the current volume is more than 0', ->
- beforeEach ->
- @volumeControl.currentVolume = 60
- @volumeControl.toggleMute()
-
- it 'save the previous volume', ->
- expect(@volumeControl.previousVolume).toEqual 60
-
- it 'set the player volume', ->
- expect(@newVolume).toEqual 0
-
- describe 'when the current volume is 0', ->
- beforeEach ->
- @volumeControl.currentVolume = 0
- @volumeControl.previousVolume = 60
- @volumeControl.toggleMute()
-
- it 'set the player volume to previous volume', ->
- expect(@newVolume).toEqual 60
diff --git a/common/lib/xmodule/xmodule/js/spec/video/display_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display_spec.coffee
deleted file mode 100644
index 35a56a83ae..0000000000
--- a/common/lib/xmodule/xmodule/js/spec/video/display_spec.coffee
+++ /dev/null
@@ -1,153 +0,0 @@
-describe 'Video', ->
- metadata = undefined
-
- beforeEach ->
- loadFixtures 'video.html'
- jasmine.stubRequests()
-
- @['7tqY6eQzVhE'] = '7tqY6eQzVhE'
- @['cogebirgzzM'] = 'cogebirgzzM'
- metadata =
- '7tqY6eQzVhE':
- id: @['7tqY6eQzVhE']
- duration: 300
- 'cogebirgzzM':
- id: @['cogebirgzzM']
- duration: 200
-
- afterEach ->
- window.player = undefined
- window.onYouTubePlayerAPIReady = undefined
-
- describe 'constructor', ->
- beforeEach ->
- @stubVideoPlayer = jasmine.createSpy('VideoPlayer')
- $.cookie.andReturn '0.75'
- window.player = undefined
-
- describe 'by default', ->
- beforeEach ->
- spyOn(window.Video.prototype, 'fetchMetadata').andCallFake ->
- @metadata = metadata
- @video = new Video '#example'
- it 'reset the current video player', ->
- expect(window.player).toBeNull()
-
- it 'set the elements', ->
- expect(@video.el).toBe '#video_id'
-
- it 'parse the videos', ->
- expect(@video.videos).toEqual
- '0.75': @['7tqY6eQzVhE']
- '1.0': @['cogebirgzzM']
-
- it 'fetch the video metadata', ->
- expect(@video.fetchMetadata).toHaveBeenCalled
- expect(@video.metadata).toEqual metadata
-
- it 'parse available video speeds', ->
- expect(@video.speeds).toEqual ['0.75', '1.0']
-
- it 'set current video speed via cookie', ->
- expect(@video.speed).toEqual '0.75'
-
- it 'store a reference for this video player in the element', ->
- expect($('.video').data('video')).toEqual @video
-
- describe 'when the Youtube API is already available', ->
- beforeEach ->
- @originalYT = window.YT
- window.YT = { Player: true }
- spyOn(window, 'VideoPlayer').andReturn(@stubVideoPlayer)
- @video = new Video '#example'
-
- afterEach ->
- window.YT = @originalYT
-
- it 'create the Video Player', ->
- expect(window.VideoPlayer).toHaveBeenCalledWith(video: @video)
- expect(@video.player).toEqual @stubVideoPlayer
-
- describe 'when the Youtube API is not ready', ->
- beforeEach ->
- @originalYT = window.YT
- window.YT = {}
- @video = new Video '#example'
-
- afterEach ->
- window.YT = @originalYT
-
- it 'set the callback on the window object', ->
- expect(window.onYouTubePlayerAPIReady).toEqual jasmine.any(Function)
-
- describe 'when the Youtube API becoming ready', ->
- beforeEach ->
- @originalYT = window.YT
- window.YT = {}
- spyOn(window, 'VideoPlayer').andReturn(@stubVideoPlayer)
- @video = new Video '#example'
- window.onYouTubePlayerAPIReady()
-
- afterEach ->
- window.YT = @originalYT
-
- it 'create the Video Player for all video elements', ->
- expect(window.VideoPlayer).toHaveBeenCalledWith(video: @video)
- expect(@video.player).toEqual @stubVideoPlayer
-
- describe 'youtubeId', ->
- beforeEach ->
- $.cookie.andReturn '1.0'
- @video = new Video '#example'
-
- describe 'with speed', ->
- it 'return the video id for given speed', ->
- 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 @cogebirgzzM
-
- describe 'setSpeed', ->
- beforeEach ->
- @video = new Video '#example'
-
- describe 'when new speed is available', ->
- beforeEach ->
- @video.setSpeed '0.75'
-
- it 'set new speed', ->
- expect(@video.speed).toEqual '0.75'
-
- it 'save setting for new speed', ->
- expect($.cookie).toHaveBeenCalledWith 'video_speed', '0.75', expires: 3650, path: '/'
-
- describe 'when new speed is not available', ->
- beforeEach ->
- @video.setSpeed '1.75'
-
- it 'set speed to 1.0x', ->
- expect(@video.speed).toEqual '1.0'
-
- describe 'getDuration', ->
- beforeEach ->
- @video = new Video '#example'
-
- it 'return duration for current video', ->
- expect(@video.getDuration()).toEqual 200
-
- describe 'log', ->
- beforeEach ->
- @video = new Video '#example'
- @video.setSpeed '1.0'
- spyOn Logger, 'log'
- @video.player = { currentTime: 25 }
- @video.log 'someEvent'
-
- it 'call the logger with valid parameters', ->
- expect(Logger.log).toHaveBeenCalledWith 'someEvent',
- id: 'id'
- 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/video/general_spec.js
similarity index 86%
rename from common/lib/xmodule/xmodule/js/spec/videoalpha/general_spec.js
rename to common/lib/xmodule/xmodule/js/spec/video/general_spec.js
index bde4e6b43f..accfba0dbe 100644
--- a/common/lib/xmodule/xmodule/js/spec/videoalpha/general_spec.js
+++ b/common/lib/xmodule/xmodule/js/spec/video/general_spec.js
@@ -1,5 +1,5 @@
(function () {
- xdescribe('VideoAlpha', function () {
+ xdescribe('Video', function () {
var oldOTBD;
beforeEach(function () {
@@ -12,7 +12,7 @@
});
afterEach(function () {
- window.OldVideoPlayerAlpha = undefined;
+ window.OldVideoPlayer = undefined;
window.onYouTubePlayerAPIReady = undefined;
window.onHTML5PlayerAPIReady = undefined;
$('source').remove();
@@ -22,13 +22,13 @@
describe('constructor', function () {
describe('YT', function () {
beforeEach(function () {
- loadFixtures('videoalpha.html');
+ loadFixtures('video.html');
$.cookie.andReturn('0.75');
});
describe('by default', function () {
beforeEach(function () {
- this.state = new window.VideoAlpha('#example');
+ this.state = new window.Video('#example');
});
it('check videoType', function () {
@@ -36,7 +36,7 @@
});
it('reset the current video player', function () {
- expect(window.OldVideoPlayerAlpha).toBeUndefined();
+ expect(window.OldVideoPlayer).toBeUndefined();
});
it('set the elements', function () {
@@ -64,14 +64,14 @@
var state;
beforeEach(function () {
- loadFixtures('videoalpha_html5.html');
- this.stubVideoPlayerAlpha = jasmine.createSpy('VideoPlayerAlpha');
+ loadFixtures('video_html5.html');
+ this.stubVideoPlayer = jasmine.createSpy('VideoPlayer');
$.cookie.andReturn('0.75');
});
describe('by default', function () {
beforeEach(function () {
- state = new window.VideoAlpha('#example');
+ state = new window.Video('#example');
});
afterEach(function () {
@@ -83,7 +83,7 @@
});
it('reset the current video player', function () {
- expect(window.OldVideoPlayerAlpha).toBeUndefined();
+ expect(window.OldVideoPlayer).toBeUndefined();
});
it('set the elements', function () {
@@ -104,8 +104,8 @@
it('parse the videos if subtitles do not exist', function () {
var sub = '';
- $('#example').find('.videoalpha').data('sub', '');
- state = new window.VideoAlpha('#example');
+ $('#example').find('.video').data('sub', '');
+ state = new window.Video('#example');
expect(state.videos).toEqual({
'0.75': sub,
@@ -142,7 +142,7 @@
// is required.
describe('HTML5 API is available', function () {
beforeEach(function () {
- state = new VideoAlpha('#example');
+ state = new Video('#example');
});
afterEach(function () {
@@ -158,9 +158,9 @@
describe('youtubeId', function () {
beforeEach(function () {
- loadFixtures('videoalpha.html');
+ loadFixtures('video.html');
$.cookie.andReturn('1.0');
- state = new VideoAlpha('#example');
+ state = new Video('#example');
});
describe('with speed', function () {
@@ -180,13 +180,13 @@
describe('setSpeed', function () {
describe('YT', function () {
beforeEach(function () {
- loadFixtures('videoalpha.html');
- state = new VideoAlpha('#example');
+ loadFixtures('video.html');
+ state = new Video('#example');
});
describe('when new speed is available', function () {
beforeEach(function () {
- state.setSpeed('0.75');
+ state.setSpeed('0.75', true);
});
it('set new speed', function () {
@@ -214,13 +214,13 @@
describe('HTML5', function () {
beforeEach(function () {
- loadFixtures('videoalpha_html5.html');
- state = new VideoAlpha('#example');
+ loadFixtures('video_html5.html');
+ state = new Video('#example');
});
describe('when new speed is available', function () {
beforeEach(function () {
- state.setSpeed('0.75');
+ state.setSpeed('0.75', true);
});
it('set new speed', function () {
@@ -249,8 +249,8 @@
describe('getDuration', function () {
beforeEach(function () {
- loadFixtures('videoalpha.html');
- state = new VideoAlpha('#example');
+ loadFixtures('video.html');
+ state = new Video('#example');
});
it('return duration for current video', function () {
@@ -260,8 +260,8 @@
describe('log', function () {
beforeEach(function () {
- loadFixtures('videoalpha_html5.html');
- state = new VideoAlpha('#example');
+ loadFixtures('video_html5.html');
+ state = new Video('#example');
spyOn(Logger, 'log');
state.videoPlayer.log('someEvent', {
currentTime: 25,
diff --git a/common/lib/xmodule/xmodule/js/spec/videoalpha/html5_video_spec.js b/common/lib/xmodule/xmodule/js/spec/video/html5_video_spec.js
similarity index 98%
rename from common/lib/xmodule/xmodule/js/spec/videoalpha/html5_video_spec.js
rename to common/lib/xmodule/xmodule/js/spec/video/html5_video_spec.js
index 9a6c44052c..3c7f66a089 100644
--- a/common/lib/xmodule/xmodule/js/spec/videoalpha/html5_video_spec.js
+++ b/common/lib/xmodule/xmodule/js/spec/video/html5_video_spec.js
@@ -1,10 +1,10 @@
(function () {
- xdescribe('VideoAlpha HTML5Video', function () {
+ xdescribe('Video HTML5Video', function () {
var state, player, oldOTBD, playbackRates = [0.75, 1.0, 1.25, 1.5];
function initialize() {
- loadFixtures('videoalpha_html5.html');
- state = new VideoAlpha('#example');
+ loadFixtures('video_html5.html');
+ state = new Video('#example');
player = state.videoPlayer.player;
}
diff --git a/common/lib/xmodule/xmodule/js/spec/videoalpha/readme.md b/common/lib/xmodule/xmodule/js/spec/video/readme.md
similarity index 100%
rename from common/lib/xmodule/xmodule/js/spec/videoalpha/readme.md
rename to common/lib/xmodule/xmodule/js/spec/video/readme.md
diff --git a/common/lib/xmodule/xmodule/js/spec/videoalpha/video_caption_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_caption_spec.js
similarity index 98%
rename from common/lib/xmodule/xmodule/js/spec/videoalpha/video_caption_spec.js
rename to common/lib/xmodule/xmodule/js/spec/video/video_caption_spec.js
index 07c6c196c9..49e5df0e9a 100644
--- a/common/lib/xmodule/xmodule/js/spec/videoalpha/video_caption_spec.js
+++ b/common/lib/xmodule/xmodule/js/spec/video/video_caption_spec.js
@@ -1,10 +1,10 @@
(function() {
- xdescribe('VideoCaptionAlpha', function() {
+ xdescribe('VideoCaption', function() {
var state, videoPlayer, videoCaption, videoSpeedControl, oldOTBD;
function initialize() {
- loadFixtures('videoalpha_all.html');
- state = new VideoAlpha('#example');
+ loadFixtures('video_all.html');
+ state = new Video('#example');
videoPlayer = state.videoPlayer;
videoCaption = state.videoCaption;
videoSpeedControl = state.videoSpeedControl;
@@ -33,11 +33,11 @@
});
it('create the caption element', function() {
- expect($('.videoalpha')).toContain('ol.subtitles');
+ expect($('.video')).toContain('ol.subtitles');
});
it('add caption control to video player', function() {
- expect($('.videoalpha')).toContain('a.hide-subtitles');
+ expect($('.video')).toContain('a.hide-subtitles');
});
it('fetch the caption', function() {
diff --git a/common/lib/xmodule/xmodule/js/spec/videoalpha/video_control_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_control_spec.js
similarity index 96%
rename from common/lib/xmodule/xmodule/js/spec/videoalpha/video_control_spec.js
rename to common/lib/xmodule/xmodule/js/spec/video/video_control_spec.js
index b98fd1e413..d56af0febc 100644
--- a/common/lib/xmodule/xmodule/js/spec/videoalpha/video_control_spec.js
+++ b/common/lib/xmodule/xmodule/js/spec/video/video_control_spec.js
@@ -1,10 +1,10 @@
(function() {
- xdescribe('VideoControlAlpha', function() {
+ xdescribe('VideoControl', function() {
var state, videoControl, oldOTBD;
function initialize() {
- loadFixtures('videoalpha_all.html');
- state = new VideoAlpha('#example');
+ loadFixtures('video_all.html');
+ state = new Video('#example');
videoControl = state.videoControl;
}
diff --git a/common/lib/xmodule/xmodule/js/spec/videoalpha/video_player_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_player_spec.js
similarity index 98%
rename from common/lib/xmodule/xmodule/js/spec/videoalpha/video_player_spec.js
rename to common/lib/xmodule/xmodule/js/spec/video/video_player_spec.js
index 5e4e40cdec..e92f251f70 100644
--- a/common/lib/xmodule/xmodule/js/spec/videoalpha/video_player_spec.js
+++ b/common/lib/xmodule/xmodule/js/spec/video/video_player_spec.js
@@ -1,15 +1,15 @@
(function() {
- xdescribe('VideoPlayerAlpha', function() {
+ xdescribe('VideoPlayer', function() {
var state, videoPlayer, player, videoControl, videoCaption, videoProgressSlider, videoSpeedControl, videoVolumeControl, oldOTBD;
function initialize(fixture) {
if (typeof fixture === 'undefined') {
- loadFixtures('videoalpha_all.html');
+ loadFixtures('video_all.html');
} else {
loadFixtures(fixture);
}
- state = new VideoAlpha('#example');
+ state = new Video('#example');
videoPlayer = state.videoPlayer;
player = videoPlayer.player;
videoControl = state.videoControl;
@@ -20,7 +20,7 @@
}
function initializeYouTube() {
- initialize('videoalpha.html');
+ initialize('video.html');
}
beforeEach(function () {
@@ -71,9 +71,9 @@
expect(videoProgressSlider.el).toHaveClass('slider');
});
- // All the toHandleWith() expect tests are not necessary for this version of Video Alpha.
+ // All the toHandleWith() expect tests are not necessary for this version of Video.
// jQuery event system is not used to trigger and invoke methods. This is an artifact from
- // previous version of Video Alpha.
+ // previous version of Video.
});
it('create Youtube player', function() {
diff --git a/common/lib/xmodule/xmodule/js/spec/videoalpha/video_progress_slider_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_progress_slider_spec.js
similarity index 95%
rename from common/lib/xmodule/xmodule/js/spec/videoalpha/video_progress_slider_spec.js
rename to common/lib/xmodule/xmodule/js/spec/video/video_progress_slider_spec.js
index f0e177d5d7..b5d0ae029c 100644
--- a/common/lib/xmodule/xmodule/js/spec/videoalpha/video_progress_slider_spec.js
+++ b/common/lib/xmodule/xmodule/js/spec/video/video_progress_slider_spec.js
@@ -1,10 +1,10 @@
(function() {
- xdescribe('VideoProgressSliderAlpha', function() {
+ xdescribe('VideoProgressSlider', function() {
var state, videoPlayer, videoProgressSlider, oldOTBD;
function initialize() {
- loadFixtures('videoalpha_all.html');
- state = new VideoAlpha('#example');
+ loadFixtures('video_all.html');
+ state = new Video('#example');
videoPlayer = state.videoPlayer;
videoProgressSlider = state.videoProgressSlider;
}
@@ -53,7 +53,7 @@
expect(videoProgressSlider.slider).toBeUndefined();
// We can't expect $.fn.slider not to have been called,
- // because sliders are used in other parts of VideoAlpha.
+ // because sliders are used in other parts of Video.
});
});
});
diff --git a/common/lib/xmodule/xmodule/js/spec/videoalpha/video_quality_control_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_quality_control_spec.js
similarity index 87%
rename from common/lib/xmodule/xmodule/js/spec/videoalpha/video_quality_control_spec.js
rename to common/lib/xmodule/xmodule/js/spec/video/video_quality_control_spec.js
index 7126dc5921..988e28b74f 100644
--- a/common/lib/xmodule/xmodule/js/spec/videoalpha/video_quality_control_spec.js
+++ b/common/lib/xmodule/xmodule/js/spec/video/video_quality_control_spec.js
@@ -1,10 +1,10 @@
(function() {
- xdescribe('VideoQualityControlAlpha', function() {
+ xdescribe('VideoQualityControl', function() {
var state, videoControl, videoQualityControl, oldOTBD;
function initialize() {
- loadFixtures('videoalpha.html');
- state = new VideoAlpha('#example');
+ loadFixtures('video.html');
+ state = new Video('#example');
videoControl = state.videoControl;
videoQualityControl = state.videoQualityControl;
}
diff --git a/common/lib/xmodule/xmodule/js/spec/videoalpha/video_speed_control_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_speed_control_spec.js
similarity index 96%
rename from common/lib/xmodule/xmodule/js/spec/videoalpha/video_speed_control_spec.js
rename to common/lib/xmodule/xmodule/js/spec/video/video_speed_control_spec.js
index c40a9c7295..21d65fbc5b 100644
--- a/common/lib/xmodule/xmodule/js/spec/videoalpha/video_speed_control_spec.js
+++ b/common/lib/xmodule/xmodule/js/spec/video/video_speed_control_spec.js
@@ -1,10 +1,10 @@
(function() {
- xdescribe('VideoSpeedControlAlpha', function() {
+ xdescribe('VideoSpeedControl', function() {
var state, videoPlayer, videoControl, videoSpeedControl;
function initialize() {
- loadFixtures('videoalpha_all.html');
- state = new VideoAlpha('#example');
+ loadFixtures('video_all.html');
+ state = new Video('#example');
videoPlayer = state.videoPlayer;
videoControl = state.videoControl;
videoSpeedControl = state.videoSpeedControl;
diff --git a/common/lib/xmodule/xmodule/js/spec/videoalpha/video_volume_control_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_volume_control_spec.js
similarity index 96%
rename from common/lib/xmodule/xmodule/js/spec/videoalpha/video_volume_control_spec.js
rename to common/lib/xmodule/xmodule/js/spec/video/video_volume_control_spec.js
index 872b1fe18e..17e6d82c12 100644
--- a/common/lib/xmodule/xmodule/js/spec/videoalpha/video_volume_control_spec.js
+++ b/common/lib/xmodule/xmodule/js/spec/video/video_volume_control_spec.js
@@ -1,10 +1,10 @@
(function() {
- xdescribe('VideoVolumeControlAlpha', function() {
+ xdescribe('VideoVolumeControl', function() {
var state, videoControl, videoVolumeControl, oldOTBD;
function initialize() {
- loadFixtures('videoalpha_all.html');
- state = new VideoAlpha('#example');
+ loadFixtures('video_all.html');
+ state = new Video('#example');
videoControl = state.videoControl;
videoVolumeControl = state.videoVolumeControl;
}
diff --git a/common/lib/xmodule/xmodule/js/src/.gitignore b/common/lib/xmodule/xmodule/js/src/.gitignore
index 85b7a639d5..8978489f6f 100644
--- a/common/lib/xmodule/xmodule/js/src/.gitignore
+++ b/common/lib/xmodule/xmodule/js/src/.gitignore
@@ -4,5 +4,5 @@
*.js
-# Videoalpha are written in pure JavaScript.
-!videoalpha/*.js
\ No newline at end of file
+# Video are written in pure JavaScript.
+!video/*.js
\ No newline at end of file
diff --git a/common/lib/xmodule/xmodule/js/src/sequence/display.coffee b/common/lib/xmodule/xmodule/js/src/sequence/display.coffee
index 9bce9d3022..149a38e9ec 100644
--- a/common/lib/xmodule/xmodule/js/src/sequence/display.coffee
+++ b/common/lib/xmodule/xmodule/js/src/sequence/display.coffee
@@ -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()
diff --git a/common/lib/xmodule/xmodule/js/src/videoalpha/01_initialize.js b/common/lib/xmodule/xmodule/js/src/video/01_initialize.js
similarity index 98%
rename from common/lib/xmodule/xmodule/js/src/videoalpha/01_initialize.js
rename to common/lib/xmodule/xmodule/js/src/video/01_initialize.js
index 88d866cd32..9a6e20421d 100644
--- a/common/lib/xmodule/xmodule/js/src/videoalpha/01_initialize.js
+++ b/common/lib/xmodule/xmodule/js/src/video/01_initialize.js
@@ -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
diff --git a/common/lib/xmodule/xmodule/js/src/videoalpha/02_html5_video.js b/common/lib/xmodule/xmodule/js/src/video/02_html5_video.js
similarity index 99%
rename from common/lib/xmodule/xmodule/js/src/videoalpha/02_html5_video.js
rename to common/lib/xmodule/xmodule/js/src/video/02_html5_video.js
index 6aa60b59bc..541c5b0bf4 100644
--- a/common/lib/xmodule/xmodule/js/src/videoalpha/02_html5_video.js
+++ b/common/lib/xmodule/xmodule/js/src/video/02_html5_video.js
@@ -14,7 +14,7 @@
(function (requirejs, require, define) {
define(
-'videoalpha/02_html5_video.js',
+'video/02_html5_video.js',
[],
function () {
var HTML5Video = {};
diff --git a/common/lib/xmodule/xmodule/js/src/videoalpha/03_video_player.js b/common/lib/xmodule/xmodule/js/src/video/03_video_player.js
similarity index 99%
rename from common/lib/xmodule/xmodule/js/src/videoalpha/03_video_player.js
rename to common/lib/xmodule/xmodule/js/src/video/03_video_player.js
index be2287be6e..5bf1b8f66d 100644
--- a/common/lib/xmodule/xmodule/js/src/videoalpha/03_video_player.js
+++ b/common/lib/xmodule/xmodule/js/src/video/03_video_player.js
@@ -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();
}
}
diff --git a/common/lib/xmodule/xmodule/js/src/videoalpha/04_video_control.js b/common/lib/xmodule/xmodule/js/src/video/04_video_control.js
similarity index 99%
rename from common/lib/xmodule/xmodule/js/src/videoalpha/04_video_control.js
rename to common/lib/xmodule/xmodule/js/src/video/04_video_control.js
index d1a662712f..63c4cd5e85 100644
--- a/common/lib/xmodule/xmodule/js/src/videoalpha/04_video_control.js
+++ b/common/lib/xmodule/xmodule/js/src/video/04_video_control.js
@@ -2,7 +2,7 @@
// VideoControl module.
define(
-'videoalpha/04_video_control.js',
+'video/04_video_control.js',
[],
function () {
diff --git a/common/lib/xmodule/xmodule/js/src/videoalpha/05_video_quality_control.js b/common/lib/xmodule/xmodule/js/src/video/05_video_quality_control.js
similarity index 98%
rename from common/lib/xmodule/xmodule/js/src/videoalpha/05_video_quality_control.js
rename to common/lib/xmodule/xmodule/js/src/video/05_video_quality_control.js
index 24363cafed..cff103468d 100644
--- a/common/lib/xmodule/xmodule/js/src/videoalpha/05_video_quality_control.js
+++ b/common/lib/xmodule/xmodule/js/src/video/05_video_quality_control.js
@@ -2,7 +2,7 @@
// VideoQualityControl module.
define(
-'videoalpha/05_video_quality_control.js',
+'video/05_video_quality_control.js',
[],
function () {
diff --git a/common/lib/xmodule/xmodule/js/src/videoalpha/06_video_progress_slider.js b/common/lib/xmodule/xmodule/js/src/video/06_video_progress_slider.js
similarity index 98%
rename from common/lib/xmodule/xmodule/js/src/videoalpha/06_video_progress_slider.js
rename to common/lib/xmodule/xmodule/js/src/video/06_video_progress_slider.js
index b36fac6cd0..b45494ca34 100644
--- a/common/lib/xmodule/xmodule/js/src/videoalpha/06_video_progress_slider.js
+++ b/common/lib/xmodule/xmodule/js/src/video/06_video_progress_slider.js
@@ -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 () {
diff --git a/common/lib/xmodule/xmodule/js/src/videoalpha/07_video_volume_control.js b/common/lib/xmodule/xmodule/js/src/video/07_video_volume_control.js
similarity index 99%
rename from common/lib/xmodule/xmodule/js/src/videoalpha/07_video_volume_control.js
rename to common/lib/xmodule/xmodule/js/src/video/07_video_volume_control.js
index 0f1cd1182d..6b12783e9e 100644
--- a/common/lib/xmodule/xmodule/js/src/videoalpha/07_video_volume_control.js
+++ b/common/lib/xmodule/xmodule/js/src/video/07_video_volume_control.js
@@ -2,7 +2,7 @@
// VideoVolumeControl module.
define(
-'videoalpha/07_video_volume_control.js',
+'video/07_video_volume_control.js',
[],
function () {
diff --git a/common/lib/xmodule/xmodule/js/src/videoalpha/08_video_speed_control.js b/common/lib/xmodule/xmodule/js/src/video/08_video_speed_control.js
similarity index 99%
rename from common/lib/xmodule/xmodule/js/src/videoalpha/08_video_speed_control.js
rename to common/lib/xmodule/xmodule/js/src/video/08_video_speed_control.js
index b0f55d49a1..740a1aa63d 100644
--- a/common/lib/xmodule/xmodule/js/src/videoalpha/08_video_speed_control.js
+++ b/common/lib/xmodule/xmodule/js/src/video/08_video_speed_control.js
@@ -2,7 +2,7 @@
// VideoSpeedControl module.
define(
-'videoalpha/08_video_speed_control.js',
+'video/08_video_speed_control.js',
[],
function () {
diff --git a/common/lib/xmodule/xmodule/js/src/videoalpha/09_video_caption.js b/common/lib/xmodule/xmodule/js/src/video/09_video_caption.js
similarity index 99%
rename from common/lib/xmodule/xmodule/js/src/videoalpha/09_video_caption.js
rename to common/lib/xmodule/xmodule/js/src/video/09_video_caption.js
index b8bc432a1b..e8a30f6e9c 100644
--- a/common/lib/xmodule/xmodule/js/src/videoalpha/09_video_caption.js
+++ b/common/lib/xmodule/xmodule/js/src/video/09_video_caption.js
@@ -2,7 +2,7 @@
// VideoCaption module.
define(
-'videoalpha/09_video_caption.js',
+'video/09_video_caption.js',
[],
function () {
diff --git a/common/lib/xmodule/xmodule/js/src/videoalpha/10_main.js b/common/lib/xmodule/xmodule/js/src/video/10_main.js
similarity index 86%
rename from common/lib/xmodule/xmodule/js/src/videoalpha/10_main.js
rename to common/lib/xmodule/xmodule/js/src/video/10_main.js
index b5f647f563..70fdbc580d 100644
--- a/common/lib/xmodule/xmodule/js/src/videoalpha/10_main.js
+++ b/common/lib/xmodule/xmodule/js/src/video/10_main.js
@@ -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;
};
});
diff --git a/common/lib/xmodule/xmodule/js/src/video/display.coffee b/common/lib/xmodule/xmodule/js/src/video/display.coffee
deleted file mode 100644
index d9c31b2c8d..0000000000
--- a/common/lib/xmodule/xmodule/js/src/video/display.coffee
+++ /dev/null
@@ -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
diff --git a/common/lib/xmodule/xmodule/js/src/video/display/_subview.coffee b/common/lib/xmodule/xmodule/js/src/video/display/_subview.coffee
deleted file mode 100644
index 2e14289843..0000000000
--- a/common/lib/xmodule/xmodule/js/src/video/display/_subview.coffee
+++ /dev/null
@@ -1,14 +0,0 @@
-class @Subview
- constructor: (options) ->
- $.each options, (key, value) =>
- @[key] = value
- @initialize()
- @render()
- @bind()
-
- $: (selector) ->
- $(selector, @el)
-
- initialize: ->
- render: ->
- bind: ->
diff --git a/common/lib/xmodule/xmodule/js/src/video/display/video_caption.coffee b/common/lib/xmodule/xmodule/js/src/video/display/video_caption.coffee
deleted file mode 100644
index c72067b0dc..0000000000
--- a/common/lib/xmodule/xmodule/js/src/video/display/video_caption.coffee
+++ /dev/null
@@ -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 """
- #
Attempting to load captions...
- # """
- @$('.video-wrapper').after """
-
- """
- @$('.video-controls .secondary-controls').append """
-
Captions
- """#"
- @$('.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 "
Caption will be displayed when you start playing the video. "
- else
- @renderCaption()
-
- renderCaption: ->
- container = $('
')
-
- $.each @captions, (index, text) =>
- container.append $('').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 for cosmetic reason
- @$('.subtitles').prepend($(' ').height(@topSpacingHeight()))
- .append($(' ').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()
diff --git a/common/lib/xmodule/xmodule/js/src/video/display/video_control.coffee b/common/lib/xmodule/xmodule/js/src/video/display/video_control.coffee
deleted file mode 100644
index 856549c3e2..0000000000
--- a/common/lib/xmodule/xmodule/js/src/video/display/video_control.coffee
+++ /dev/null
@@ -1,35 +0,0 @@
-class @VideoControl extends Subview
- bind: ->
- @$('.video_control').click @togglePlayback
-
- render: ->
- @el.append """
-
-
- """#"
-
- 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')
diff --git a/common/lib/xmodule/xmodule/js/src/video/display/video_player.coffee b/common/lib/xmodule/xmodule/js/src/video/display/video_player.coffee
deleted file mode 100644
index 73ff3512e2..0000000000
--- a/common/lib/xmodule/xmodule/js/src/video/display/video_player.coffee
+++ /dev/null
@@ -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()
diff --git a/common/lib/xmodule/xmodule/js/src/video/display/video_progress_slider.coffee b/common/lib/xmodule/xmodule/js/src/video/display/video_progress_slider.coffee
deleted file mode 100644
index ef2f38698b..0000000000
--- a/common/lib/xmodule/xmodule/js/src/video/display/video_progress_slider.coffee
+++ /dev/null
@@ -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)}")
diff --git a/common/lib/xmodule/xmodule/js/src/video/display/video_quality_control.coffee b/common/lib/xmodule/xmodule/js/src/video/display/video_quality_control.coffee
deleted file mode 100644
index f8f6167075..0000000000
--- a/common/lib/xmodule/xmodule/js/src/video/display/video_quality_control.coffee
+++ /dev/null
@@ -1,26 +0,0 @@
-class @VideoQualityControl extends Subview
- initialize: ->
- @quality = null;
-
- bind: ->
- @$('.quality_control').click @toggleQuality
-
- render: ->
- @el.append """
- HD
- """#"
-
- 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)
\ No newline at end of file
diff --git a/common/lib/xmodule/xmodule/js/src/video/display/video_speed_control.coffee b/common/lib/xmodule/xmodule/js/src/video/display/video_speed_control.coffee
deleted file mode 100644
index 1d0d8b7d44..0000000000
--- a/common/lib/xmodule/xmodule/js/src/video/display/video_speed_control.coffee
+++ /dev/null
@@ -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 """
-
- """
-
- $.each @speeds, (index, speed) =>
- link = $('').attr(href: "#").html("#{speed}x")
- @$('.video_speeds').prepend($('').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")
diff --git a/common/lib/xmodule/xmodule/js/src/video/display/video_volume_control.coffee b/common/lib/xmodule/xmodule/js/src/video/display/video_volume_control.coffee
deleted file mode 100644
index 096b50042d..0000000000
--- a/common/lib/xmodule/xmodule/js/src/video/display/video_volume_control.coffee
+++ /dev/null
@@ -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 """
-
- """#"
- @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
diff --git a/common/lib/xmodule/xmodule/tests/test_editing_module.py b/common/lib/xmodule/xmodule/tests/test_editing_module.py
index 03e257940f..838a4f9ada 100644
--- a/common/lib/xmodule/xmodule/tests/test_editing_module.py
+++ b/common/lib/xmodule/xmodule/tests/test_editing_module.py
@@ -33,7 +33,7 @@ class TabsEditingDescriptorTestCase(unittest.TestCase):
},
{
'name': "Subtitles",
- 'template': "videoalpha/subtitles.html",
+ 'template': "video/subtitles.html",
},
{
'name': "Settings",
diff --git a/common/lib/xmodule/xmodule/tests/test_videoalpha.py b/common/lib/xmodule/xmodule/tests/test_video.py
similarity index 78%
rename from common/lib/xmodule/xmodule/tests/test_videoalpha.py
rename to common/lib/xmodule/xmodule/tests/test_video.py
index 76f86d6d4a..4a13d565cc 100644
--- a/common/lib/xmodule/xmodule/tests/test_videoalpha.py
+++ b/common/lib/xmodule/xmodule/tests/test_video.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#pylint: disable=W0212
-"""Test for Video Alpha Xmodule functional logic.
+"""Test for Video Xmodule functional logic.
These test data read from xml, not from mongo.
We have a ModuleStoreTestCase class defined in
@@ -17,37 +17,36 @@ import unittest
from . import LogicTest
from .import get_test_system
from xmodule.modulestore import Location
-from xmodule.videoalpha_module import VideoAlphaDescriptor, _create_youtube_string
-from xmodule.video_module import VideoDescriptor
+from xmodule.video_module import VideoDescriptor, _create_youtube_string
from .test_import import DummySystem
from textwrap import dedent
-class VideoAlphaModuleTest(LogicTest):
- """Logic tests for VideoAlpha Xmodule."""
- descriptor_class = VideoAlphaDescriptor
+class VideoModuleTest(LogicTest):
+ """Logic tests for Video Xmodule."""
+ descriptor_class = VideoDescriptor
raw_model_data = {
- 'data': ' '
+ 'data': ' '
}
def test_parse_time_empty(self):
"""Ensure parse_time returns correctly with None or empty string."""
expected = ''
- self.assertEqual(VideoAlphaDescriptor._parse_time(None), expected)
- self.assertEqual(VideoAlphaDescriptor._parse_time(''), expected)
+ self.assertEqual(VideoDescriptor._parse_time(None), expected)
+ self.assertEqual(VideoDescriptor._parse_time(''), expected)
def test_parse_time(self):
"""Ensure that times are parsed correctly into seconds."""
expected = 247
- output = VideoAlphaDescriptor._parse_time('00:04:07')
+ output = VideoDescriptor._parse_time('00:04:07')
self.assertEqual(output, expected)
def test_parse_youtube(self):
"""Test parsing old-style Youtube ID strings into a dict."""
youtube_str = '0.75:jNCf2gIqpeE,1.00:ZwkTiUPN0mg,1.25:rsq9auxASqI,1.50:kMyNdzVHHgg'
- output = VideoAlphaDescriptor._parse_youtube(youtube_str)
+ output = VideoDescriptor._parse_youtube(youtube_str)
self.assertEqual(output, {'0.75': 'jNCf2gIqpeE',
'1.00': 'ZwkTiUPN0mg',
'1.25': 'rsq9auxASqI',
@@ -59,7 +58,7 @@ class VideoAlphaModuleTest(LogicTest):
empty string.
"""
youtube_str = '0.75:jNCf2gIqpeE'
- output = VideoAlphaDescriptor._parse_youtube(youtube_str)
+ output = VideoDescriptor._parse_youtube(youtube_str)
self.assertEqual(output, {'0.75': 'jNCf2gIqpeE',
'1.00': '',
'1.25': '',
@@ -72,8 +71,8 @@ class VideoAlphaModuleTest(LogicTest):
youtube_str = '1.00:p2Q6BrNhdh8'
youtube_str_hack = '1.0:p2Q6BrNhdh8'
self.assertEqual(
- VideoAlphaDescriptor._parse_youtube(youtube_str),
- VideoAlphaDescriptor._parse_youtube(youtube_str_hack)
+ VideoDescriptor._parse_youtube(youtube_str),
+ VideoDescriptor._parse_youtube(youtube_str_hack)
)
def test_parse_youtube_empty(self):
@@ -82,7 +81,7 @@ class VideoAlphaModuleTest(LogicTest):
that well.
"""
self.assertEqual(
- VideoAlphaDescriptor._parse_youtube(''),
+ VideoDescriptor._parse_youtube(''),
{'0.75': '',
'1.00': '',
'1.25': '',
@@ -90,12 +89,12 @@ class VideoAlphaModuleTest(LogicTest):
)
-class VideoAlphaDescriptorTest(unittest.TestCase):
- """Test for VideoAlphaDescriptor"""
+class VideoDescriptorTest(unittest.TestCase):
+ """Test for VideoDescriptor"""
def setUp(self):
system = get_test_system()
- self.descriptor = VideoAlphaDescriptor(
+ self.descriptor = VideoDescriptor(
runtime=system,
model_data={})
@@ -117,9 +116,9 @@ class VideoAlphaDescriptorTest(unittest.TestCase):
back out to XML.
"""
system = DummySystem(load_error_modules=True)
- location = Location(["i4x", "edX", "videoalpha", "default", "SampleProblem1"])
+ location = Location(["i4x", "edX", "video", "default", "SampleProblem1"])
model_data = {'location': location}
- descriptor = VideoAlphaDescriptor(system, model_data)
+ descriptor = VideoDescriptor(system, model_data)
descriptor.youtube_id_0_75 = 'izygArpw-Qo'
descriptor.youtube_id_1_0 = 'p2Q6BrNhdh8'
descriptor.youtube_id_1_25 = '1EeWXzPdhSA'
@@ -133,9 +132,9 @@ class VideoAlphaDescriptorTest(unittest.TestCase):
in the output string.
"""
system = DummySystem(load_error_modules=True)
- location = Location(["i4x", "edX", "videoalpha", "default", "SampleProblem1"])
+ location = Location(["i4x", "edX", "video", "default", "SampleProblem1"])
model_data = {'location': location}
- descriptor = VideoAlphaDescriptor(system, model_data)
+ descriptor = VideoDescriptor(system, model_data)
descriptor.youtube_id_0_75 = 'izygArpw-Qo'
descriptor.youtube_id_1_0 = 'p2Q6BrNhdh8'
descriptor.youtube_id_1_25 = '1EeWXzPdhSA'
@@ -143,9 +142,9 @@ class VideoAlphaDescriptorTest(unittest.TestCase):
self.assertEqual(_create_youtube_string(descriptor), expected)
-class VideoAlphaDescriptorImportTestCase(unittest.TestCase):
+class VideoDescriptorImportTestCase(unittest.TestCase):
"""
- Make sure that VideoAlphaDescriptor can import an old XML-based video correctly.
+ Make sure that VideoDescriptor can import an old XML-based video correctly.
"""
def assert_attributes_equal(self, video, attrs):
@@ -158,7 +157,7 @@ class VideoAlphaDescriptorImportTestCase(unittest.TestCase):
def test_constructor(self):
sample_xml = '''
-
-
+
'''
- location = Location(["i4x", "edX", "videoalpha", "default",
+ location = Location(["i4x", "edX", "video", "default",
"SampleProblem1"])
model_data = {'data': sample_xml,
'location': location}
system = DummySystem(load_error_modules=True)
- descriptor = VideoAlphaDescriptor(system, model_data)
+ descriptor = VideoDescriptor(system, model_data)
self.assert_attributes_equal(descriptor, {
'youtube_id_0_75': 'izygArpw-Qo',
'youtube_id_1_0': 'p2Q6BrNhdh8',
@@ -190,16 +189,16 @@ class VideoAlphaDescriptorImportTestCase(unittest.TestCase):
def test_from_xml(self):
module_system = DummySystem(load_error_modules=True)
xml_data = '''
-
-
+
'''
- output = VideoAlphaDescriptor.from_xml(xml_data, module_system)
+ output = VideoDescriptor.from_xml(xml_data, module_system)
self.assert_attributes_equal(output, {
'youtube_id_0_75': 'izygArpw-Qo',
'youtube_id_1_0': 'p2Q6BrNhdh8',
@@ -221,14 +220,14 @@ class VideoAlphaDescriptorImportTestCase(unittest.TestCase):
"""
module_system = DummySystem(load_error_modules=True)
xml_data = '''
-
-
+
'''
- output = VideoAlphaDescriptor.from_xml(xml_data, module_system)
+ output = VideoDescriptor.from_xml(xml_data, module_system)
self.assert_attributes_equal(output, {
'youtube_id_0_75': '',
'youtube_id_1_0': 'p2Q6BrNhdh8',
@@ -248,8 +247,8 @@ class VideoAlphaDescriptorImportTestCase(unittest.TestCase):
Make sure settings are correct if none are explicitly set in XML.
"""
module_system = DummySystem(load_error_modules=True)
- xml_data = ' '
- output = VideoAlphaDescriptor.from_xml(xml_data, module_system)
+ xml_data = ' '
+ output = VideoDescriptor.from_xml(xml_data, module_system)
self.assert_attributes_equal(output, {
'youtube_id_0_75': '',
'youtube_id_1_0': 'OEoXaMPEzfM',
@@ -270,16 +269,16 @@ class VideoAlphaDescriptorImportTestCase(unittest.TestCase):
"""
module_system = DummySystem(load_error_modules=True)
xml_data = """
-
-
+
"""
- output = VideoAlphaDescriptor.from_xml(xml_data, module_system)
+ output = VideoDescriptor.from_xml(xml_data, module_system)
self.assert_attributes_equal(output, {
'youtube_id_0_75': 'izygArpw-Qo',
'youtube_id_1_0': 'p2Q6BrNhdh8',
@@ -295,7 +294,7 @@ class VideoAlphaDescriptorImportTestCase(unittest.TestCase):
def test_old_video_data(self):
"""
- Ensure that Video Alpha is able to read VideoModule's model data.
+ Ensure that Video is able to read VideoModule's model data.
"""
module_system = DummySystem(load_error_modules=True)
xml_data = """
@@ -309,8 +308,7 @@ class VideoAlphaDescriptorImportTestCase(unittest.TestCase):
"""
video = VideoDescriptor.from_xml(xml_data, module_system)
- video_alpha = VideoAlphaDescriptor(module_system, video._model_data)
- self.assert_attributes_equal(video_alpha, {
+ self.assert_attributes_equal(video, {
'youtube_id_0_75': 'izygArpw-Qo',
'youtube_id_1_0': 'p2Q6BrNhdh8',
'youtube_id_1_25': '1EeWXzPdhSA',
@@ -324,17 +322,17 @@ class VideoAlphaDescriptorImportTestCase(unittest.TestCase):
})
-class VideoAlphaExportTestCase(unittest.TestCase):
+class VideoExportTestCase(unittest.TestCase):
"""
- Make sure that VideoAlphaDescriptor can export itself to XML
+ Make sure that VideoDescriptor can export itself to XML
correctly.
"""
def test_export_to_xml(self):
"""Test that we write the correct XML on export."""
module_system = DummySystem(load_error_modules=True)
- location = Location(["i4x", "edX", "videoalpha", "default", "SampleProblem1"])
- desc = VideoAlphaDescriptor(module_system, {'location': location})
+ location = Location(["i4x", "edX", "video", "default", "SampleProblem1"])
+ desc = VideoDescriptor(module_system, {'location': location})
desc.youtube_id_0_75 = 'izygArpw-Qo'
desc.youtube_id_1_0 = 'p2Q6BrNhdh8'
@@ -348,11 +346,11 @@ class VideoAlphaExportTestCase(unittest.TestCase):
xml = desc.export_to_xml(None) # We don't use the `resource_fs` parameter
expected = dedent('''\
-
+
-
+
''')
self.assertEquals(expected, xml)
@@ -360,10 +358,10 @@ class VideoAlphaExportTestCase(unittest.TestCase):
def test_export_to_xml_empty_parameters(self):
"""Test XML export with defaults."""
module_system = DummySystem(load_error_modules=True)
- location = Location(["i4x", "edX", "videoalpha", "default", "SampleProblem1"])
- desc = VideoAlphaDescriptor(module_system, {'location': location})
+ location = Location(["i4x", "edX", "video", "default", "SampleProblem1"])
+ desc = VideoDescriptor(module_system, {'location': location})
xml = desc.export_to_xml(None)
- expected = ' \n'
+ expected = ' \n'
self.assertEquals(expected, xml)
diff --git a/common/lib/xmodule/xmodule/tests/test_video_module.py b/common/lib/xmodule/xmodule/tests/test_video_module.py
deleted file mode 100644
index e11686176a..0000000000
--- a/common/lib/xmodule/xmodule/tests/test_video_module.py
+++ /dev/null
@@ -1,104 +0,0 @@
-# -*- coding: utf-8 -*-
-import unittest
-
-from xmodule.modulestore import Location
-from xmodule.video_module import VideoDescriptor
-from .test_import import DummySystem
-
-
-class VideoDescriptorImportTestCase(unittest.TestCase):
- """
- Make sure that VideoDescriptor can import an old XML-based video correctly.
- """
-
- def test_constructor(self):
- sample_xml = '''
-
-
-
-
- '''
- location = Location(["i4x", "edX", "video", "default",
- "SampleProblem1"])
- model_data = {'data': sample_xml,
- 'location': location}
- system = DummySystem(load_error_modules=True)
- descriptor = VideoDescriptor(system, model_data)
- self.assertEquals(descriptor.youtube_id_0_75, 'izygArpw-Qo')
- self.assertEquals(descriptor.youtube_id_1_0, 'p2Q6BrNhdh8')
- self.assertEquals(descriptor.youtube_id_1_25, '1EeWXzPdhSA')
- self.assertEquals(descriptor.youtube_id_1_5, 'rABDYkeK0x8')
- self.assertEquals(descriptor.show_captions, False)
- self.assertEquals(descriptor.start_time, 1.0)
- self.assertEquals(descriptor.end_time, 60)
- self.assertEquals(descriptor.track, 'http://www.example.com/track')
- self.assertEquals(descriptor.source, 'http://www.example.com/source.mp4')
-
- def test_from_xml(self):
- module_system = DummySystem(load_error_modules=True)
- xml_data = '''
-
-
-
-
- '''
- output = VideoDescriptor.from_xml(xml_data, module_system)
- self.assertEquals(output.youtube_id_0_75, 'izygArpw-Qo')
- self.assertEquals(output.youtube_id_1_0, 'p2Q6BrNhdh8')
- self.assertEquals(output.youtube_id_1_25, '1EeWXzPdhSA')
- self.assertEquals(output.youtube_id_1_5, 'rABDYkeK0x8')
- self.assertEquals(output.show_captions, False)
- self.assertEquals(output.start_time, 1.0)
- self.assertEquals(output.end_time, 60)
- self.assertEquals(output.track, 'http://www.example.com/track')
- self.assertEquals(output.source, 'http://www.example.com/source.mp4')
-
- def test_from_xml_missing_attributes(self):
- """
- Ensure that attributes have the right values if they aren't
- explicitly set in XML.
- """
- module_system = DummySystem(load_error_modules=True)
- xml_data = '''
-
-
-
-
- '''
- output = VideoDescriptor.from_xml(xml_data, module_system)
- self.assertEquals(output.youtube_id_0_75, '')
- self.assertEquals(output.youtube_id_1_0, 'p2Q6BrNhdh8')
- self.assertEquals(output.youtube_id_1_25, '1EeWXzPdhSA')
- self.assertEquals(output.youtube_id_1_5, '')
- self.assertEquals(output.show_captions, True)
- self.assertEquals(output.start_time, 0.0)
- self.assertEquals(output.end_time, 0.0)
- self.assertEquals(output.track, 'http://www.example.com/track')
- self.assertEquals(output.source, 'http://www.example.com/source.mp4')
-
- def test_from_xml_no_attributes(self):
- """
- Make sure settings are correct if none are explicitly set in XML.
- """
- module_system = DummySystem(load_error_modules=True)
- xml_data = ' '
- output = VideoDescriptor.from_xml(xml_data, module_system)
- self.assertEquals(output.youtube_id_0_75, '')
- self.assertEquals(output.youtube_id_1_0, 'OEoXaMPEzfM')
- self.assertEquals(output.youtube_id_1_25, '')
- self.assertEquals(output.youtube_id_1_5, '')
- self.assertEquals(output.show_captions, True)
- self.assertEquals(output.start_time, 0.0)
- self.assertEquals(output.end_time, 0.0)
- self.assertEquals(output.track, '')
- self.assertEquals(output.source, '')
diff --git a/common/lib/xmodule/xmodule/tests/test_xblock_wrappers.py b/common/lib/xmodule/xmodule/tests/test_xblock_wrappers.py
index 90ff209c7d..c98f980c62 100644
--- a/common/lib/xmodule/xmodule/tests/test_xblock_wrappers.py
+++ b/common/lib/xmodule/xmodule/tests/test_xblock_wrappers.py
@@ -16,10 +16,9 @@ from xmodule.gst_module import GraphicalSliderToolDescriptor
from xmodule.html_module import HtmlDescriptor
from xmodule.peer_grading_module import PeerGradingDescriptor
from xmodule.poll_module import PollDescriptor
-from xmodule.video_module import VideoDescriptor
from xmodule.word_cloud_module import WordCloudDescriptor
from xmodule.crowdsource_hinter import CrowdsourceHinterDescriptor
-from xmodule.videoalpha_module import VideoAlphaDescriptor
+from xmodule.video_module import VideoDescriptor
from xmodule.seq_module import SequenceDescriptor
from xmodule.conditional_module import ConditionalDescriptor
from xmodule.randomize_module import RandomizeDescriptor
@@ -35,9 +34,8 @@ LEAF_XMODULES = (
HtmlDescriptor,
PeerGradingDescriptor,
PollDescriptor,
- VideoDescriptor,
# This is being excluded because it has dependencies on django
- #VideoAlphaDescriptor,
+ #VideoDescriptor,
WordCloudDescriptor,
)
diff --git a/common/lib/xmodule/xmodule/video_module.py b/common/lib/xmodule/xmodule/video_module.py
index 763975fc3b..407547d9bf 100644
--- a/common/lib/xmodule/xmodule/video_module.py
+++ b/common/lib/xmodule/xmodule/video_module.py
@@ -1,20 +1,36 @@
# pylint: disable=W0223
-"""Video is ungraded Xmodule for support video content."""
+"""Video is ungraded Xmodule for support video content.
+It's new improved video module, which support additional feature:
+
+- Can play non-YouTube video sources via in-browser HTML5 video player.
+- YouTube defaults to HTML5 mode from the start.
+- Speed changes in both YouTube and non-YouTube videos happen via
+in-browser HTML5 video method (when in HTML5 mode).
+- Navigational subtitles can be disabled altogether via an attribute
+in XML.
+"""
import json
import logging
from lxml import etree
-from pkg_resources import resource_string, resource_listdir
-import datetime
-import time
+from pkg_resources import resource_string
from django.http import Http404
+from django.conf import settings
from xmodule.x_module import XModule
+from xmodule.editing_module import TabsEditingDescriptor
from xmodule.raw_module import EmptyDataRawDescriptor
-from xmodule.editing_module import MetadataOnlyEditingDescriptor
-from xblock.core import Integer, Scope, String, Float, Boolean
+from xmodule.xml_module import is_pointer_tag, name_to_pathname
+from xmodule.modulestore import Location
+from xmodule.modulestore.mongo import MongoModuleStore
+from xmodule.modulestore.django import modulestore
+from xmodule.contentstore.content import StaticContent
+from xblock.core import Scope, String, Boolean, Float, List, Integer
+
+import datetime
+import time
log = logging.getLogger(__name__)
@@ -22,51 +38,118 @@ log = logging.getLogger(__name__)
class VideoFields(object):
"""Fields for `VideoModule` and `VideoDescriptor`."""
display_name = String(
- display_name="Display Name",
- help="This name appears in the horizontal navigation at the top of the page.",
+ display_name="Display Name", help="Display name for this module.",
+ default="Video",
+ scope=Scope.settings
+ )
+ position = Integer(
+ help="Current position in the video",
+ scope=Scope.user_state,
+ default=0
+ )
+ show_captions = Boolean(
+ help="This controls whether or not captions are shown by default.",
+ display_name="Show Captions",
scope=Scope.settings,
- # it'd be nice to have a useful default but it screws up other things; so,
- # use display_name_with_default for those
- default="Video"
+ default=True
)
- data = String(
- help="XML data for the problem",
- default='',
- scope=Scope.content
+ # TODO: This should be moved to Scope.content, but this will
+ # require data migration to support the old video module.
+ youtube_id_1_0 = String(
+ help="This is the Youtube ID reference for the normal speed video.",
+ display_name="Youtube ID",
+ scope=Scope.settings,
+ default="OEoXaMPEzfM"
+ )
+ youtube_id_0_75 = String(
+ help="The Youtube ID for the .75x speed video.",
+ display_name="Youtube ID for .75x speed",
+ scope=Scope.settings,
+ default=""
+ )
+ youtube_id_1_25 = String(
+ help="The Youtube ID for the 1.25x speed video.",
+ display_name="Youtube ID for 1.25x speed",
+ scope=Scope.settings,
+ default=""
+ )
+ youtube_id_1_5 = String(
+ help="The Youtube ID for the 1.5x speed video.",
+ display_name="Youtube ID for 1.5x speed",
+ scope=Scope.settings,
+ default=""
+ )
+ start_time = Float(
+ help="Start time for the video.",
+ display_name="Start Time",
+ scope=Scope.settings,
+ default=0.0
+ )
+ end_time = Float(
+ help="End time for the video.",
+ display_name="End Time",
+ scope=Scope.settings,
+ default=0.0
+ )
+ source = String(
+ help="The external URL to download the video. This appears as a link beneath the video.",
+ display_name="Download Video",
+ scope=Scope.settings,
+ default=""
+ )
+ html5_sources = List(
+ help="A list of filenames to be used with HTML5 video. The first supported filetype will be displayed.",
+ display_name="Video Sources",
+ scope=Scope.settings,
+ default=[]
+ )
+ track = String(
+ help="The external URL to download the subtitle track. This appears as a link beneath the video.",
+ display_name="Download Track",
+ scope=Scope.settings,
+ default=""
+ )
+ sub = String(
+ help="The name of the subtitle track (for non-Youtube videos).",
+ display_name="HTML5 Subtitles",
+ scope=Scope.settings,
+ default=""
)
- position = Integer(help="Current position in the video", scope=Scope.user_state, default=0)
- show_captions = Boolean(help="This controls whether or not captions are shown by default.", display_name="Show Captions", scope=Scope.settings, default=True)
- youtube_id_1_0 = String(help="This is the Youtube ID reference for the normal speed video.", display_name="Default Speed", scope=Scope.settings, default="OEoXaMPEzfM")
- youtube_id_0_75 = String(help="The Youtube ID for the .75x speed video.", display_name="Speed: .75x", scope=Scope.settings, default="")
- youtube_id_1_25 = String(help="The Youtube ID for the 1.25x speed video.", display_name="Speed: 1.25x", scope=Scope.settings, default="")
- youtube_id_1_5 = String(help="The Youtube ID for the 1.5x speed video.", display_name="Speed: 1.5x", scope=Scope.settings, default="")
- start_time = Float(help="Time the video starts", display_name="Start Time", scope=Scope.settings, default=0.0)
- end_time = Float(help="Time the video ends", display_name="End Time", scope=Scope.settings, default=0.0)
- source = String(help="The external URL to download the video. This appears as a link beneath the video.", display_name="Download Video", scope=Scope.settings, default="")
- track = String(help="The external URL to download the subtitle track. This appears as a link beneath the video.", display_name="Download Track", scope=Scope.settings, default="")
class VideoModule(VideoFields, XModule):
- """Video Xmodule."""
+ """
+ XML source example:
+
+
+
+
+
+
+ """
video_time = 0
icon_class = 'video'
js = {
- 'coffee': [
- resource_string(__name__, 'js/src/time.coffee'),
- resource_string(__name__, 'js/src/video/display.coffee')
- ] +
- [resource_string(__name__, 'js/src/video/display/' + filename)
- for filename
- in sorted(resource_listdir(__name__, 'js/src/video/display'))
- if filename.endswith('.coffee')]
+ 'js': [
+ resource_string(__name__, 'js/src/video/01_initialize.js'),
+ resource_string(__name__, 'js/src/video/02_html5_video.js'),
+ resource_string(__name__, 'js/src/video/03_video_player.js'),
+ resource_string(__name__, 'js/src/video/04_video_control.js'),
+ resource_string(__name__, 'js/src/video/05_video_quality_control.js'),
+ resource_string(__name__, 'js/src/video/06_video_progress_slider.js'),
+ resource_string(__name__, 'js/src/video/07_video_volume_control.js'),
+ resource_string(__name__, 'js/src/video/08_video_speed_control.js'),
+ resource_string(__name__, 'js/src/video/09_video_caption.js'),
+ resource_string(__name__, 'js/src/video/10_main.js')
+ ]
}
css = {'scss': [resource_string(__name__, 'css/video/display.scss')]}
js_module_name = "Video"
- def __init__(self, *args, **kwargs):
- XModule.__init__(self, *args, **kwargs)
-
def handle_ajax(self, dispatch, data):
"""This is not being called right now and we raise 404 error."""
log.debug(u"GET {0}".format(data))
@@ -78,41 +161,59 @@ class VideoModule(VideoFields, XModule):
return json.dumps({'position': self.position})
def get_html(self):
+ if isinstance(modulestore(), MongoModuleStore):
+ caption_asset_path = StaticContent.get_base_url_path_for_course_assets(self.location) + '/subs_'
+ else:
+ # VS[compat]
+ # cdodge: filesystem static content support.
+ caption_asset_path = "/static/subs/"
+
+ get_ext = lambda filename: filename.rpartition('.')[-1]
+ sources = {get_ext(src): src for src in self.html5_sources}
+ sources['main'] = self.source
+
return self.system.render_template('video.html', {
- 'youtube_id_0_75': self.youtube_id_0_75,
- 'youtube_id_1_0': self.youtube_id_1_0,
- 'youtube_id_1_25': self.youtube_id_1_25,
- 'youtube_id_1_5': self.youtube_id_1_5,
+ 'youtube_streams': _create_youtube_string(self),
'id': self.location.html_id(),
- 'position': self.position,
- 'source': self.source,
+ 'sub': self.sub,
+ 'sources': sources,
'track': self.track,
'display_name': self.display_name_with_default,
- 'caption_asset_path': "/static/subs/",
- 'show_captions': 'true' if self.show_captions else 'false',
+ # This won't work when we move to data that
+ # isn't on the filesystem
+ 'data_dir': getattr(self, 'data_dir', None),
+ 'caption_asset_path': caption_asset_path,
+ 'show_captions': json.dumps(self.show_captions),
'start': self.start_time,
- 'end': self.end_time
+ 'end': self.end_time,
+ 'autoplay': settings.MITX_FEATURES.get('AUTOPLAY_VIDEOS', True)
})
-class VideoDescriptor(VideoFields,
- MetadataOnlyEditingDescriptor,
- EmptyDataRawDescriptor):
+class VideoDescriptor(VideoFields, TabsEditingDescriptor, EmptyDataRawDescriptor):
+ """Descriptor for `VideoModule`."""
module_class = VideoModule
+ tabs = [
+ # {
+ # 'name': "Subtitles",
+ # 'template': "video/subtitles.html",
+ # },
+ {
+ 'name': "Settings",
+ 'template': "tabs/metadata-edit-tab.html",
+ 'current': True
+ }
+ ]
+
def __init__(self, *args, **kwargs):
super(VideoDescriptor, self).__init__(*args, **kwargs)
- # If we don't have a `youtube_id_1_0`, this is an XML course
- # and we parse out the fields.
- if self.data and 'youtube_id_1_0' not in self._model_data:
- _parse_video_xml(self, self.data)
-
- @property
- def non_editable_metadata_fields(self):
- non_editable_fields = super(MetadataOnlyEditingDescriptor, self).non_editable_metadata_fields
- non_editable_fields.extend([VideoModule.start_time,
- VideoModule.end_time])
- return non_editable_fields
+ # For backwards compatibility -- if we've got XML data, parse
+ # it out and set the metadata fields
+ if self.data:
+ model_data = VideoDescriptor._parse_video_xml(self.data)
+ self._model_data.update(model_data)
+ del self.data
@classmethod
def from_xml(cls, xml_data, system, org=None, course=None):
@@ -126,102 +227,164 @@ class VideoDescriptor(VideoFields,
org and course are optional strings that will be used in the generated modules
url identifiers
"""
- video = super(VideoDescriptor, cls).from_xml(xml_data, system, org, course)
- _parse_video_xml(video, video.data)
+ xml_object = etree.fromstring(xml_data)
+ url_name = xml_object.get('url_name', xml_object.get('slug'))
+ location = Location(
+ 'i4x', org, course, 'video', url_name
+ )
+ if is_pointer_tag(xml_object):
+ filepath = cls._format_filepath(xml_object.tag, name_to_pathname(url_name))
+ xml_data = etree.tostring(cls.load_file(filepath, system.resources_fs, location))
+ model_data = VideoDescriptor._parse_video_xml(xml_data)
+ model_data['location'] = location
+ video = cls(system, model_data)
return video
+ def export_to_xml(self, resource_fs):
+ """
+ Returns an xml string representing this module.
+ """
+ xml = etree.Element('video')
+ youtube_string = _create_youtube_string(self)
+ # Mild workaround to ensure that tests pass -- if a field
+ # is set to its default value, we don't need to write it out.
+ if youtube_string == '1.00:OEoXaMPEzfM':
+ youtube_string = ''
+ attrs = {
+ 'display_name': self.display_name,
+ 'show_captions': json.dumps(self.show_captions),
+ 'youtube': youtube_string,
+ 'start_time': datetime.timedelta(seconds=self.start_time),
+ 'end_time': datetime.timedelta(seconds=self.end_time),
+ 'sub': self.sub,
+ 'url_name': self.url_name
+ }
+ fields = {field.name: field for field in self.fields}
+ for key, value in attrs.items():
+ # Mild workaround to ensure that tests pass -- if a field
+ # is set to its default value, we don't need to write it out.
+ if key in fields and fields[key].default == getattr(self, key):
+ continue
+ if value:
+ xml.set(key, str(value))
-def _parse_video_xml(video, xml_data):
- """
- Parse video fields out of xml_data. The fields are set if they are
- present in the XML.
- """
- if not xml_data:
- return
+ for source in self.html5_sources:
+ ele = etree.Element('source')
+ ele.set('src', source)
+ xml.append(ele)
- xml = etree.fromstring(xml_data)
+ if self.track:
+ ele = etree.Element('track')
+ ele.set('src', self.track)
+ xml.append(ele)
+ return etree.tostring(xml, pretty_print=True)
- display_name = xml.get('display_name')
- if display_name:
- video.display_name = display_name
-
- youtube = xml.get('youtube')
- if youtube:
- speeds = _parse_youtube(youtube)
- if speeds['0.75']:
- video.youtube_id_0_75 = speeds['0.75']
- if speeds['1.00']:
- video.youtube_id_1_0 = speeds['1.00']
- if speeds['1.25']:
- video.youtube_id_1_25 = speeds['1.25']
- if speeds['1.50']:
- video.youtube_id_1_5 = speeds['1.50']
-
- show_captions = xml.get('show_captions')
- if show_captions:
- video.show_captions = json.loads(show_captions)
-
- source = _get_first_external(xml, 'source')
- if source:
- video.source = source
-
- track = _get_first_external(xml, 'track')
- if track:
- video.track = track
-
- start_time = _parse_time(xml.get('from'))
- if start_time:
- video.start_time = start_time
-
- end_time = _parse_time(xml.get('to'))
- if end_time:
- video.end_time = end_time
-
-
-def _get_first_external(xmltree, tag):
- """
- Returns the src attribute of the nested `tag` in `xmltree`, if it
- exists.
- """
- for element in xmltree.findall(tag):
- src = element.get('src')
- if src:
- return src
- return None
-
-
-def _parse_youtube(data):
- """
- Parses a string of Youtube IDs such as "1.0:AXdE34_U,1.5:VO3SxfeD"
- into a dictionary. Necessary for backwards compatibility with
- XML-based courses.
- """
- ret = {'0.75': '', '1.00': '', '1.25': '', '1.50': ''}
- if data == '':
+ @staticmethod
+ def _parse_youtube(data):
+ """
+ Parses a string of Youtube IDs such as "1.0:AXdE34_U,1.5:VO3SxfeD"
+ into a dictionary. Necessary for backwards compatibility with
+ XML-based courses.
+ """
+ ret = {'0.75': '', '1.00': '', '1.25': '', '1.50': ''}
+ if data == '':
+ return ret
+ videos = data.split(',')
+ for video in videos:
+ pieces = video.split(':')
+ # HACK
+ # To elaborate somewhat: in many LMS tests, the keys for
+ # Youtube IDs are inconsistent. Sometimes a particular
+ # speed isn't present, and formatting is also inconsistent
+ # ('1.0' versus '1.00'). So it's necessary to either do
+ # something like this or update all the tests to work
+ # properly.
+ ret['%.2f' % float(pieces[0])] = pieces[1]
return ret
- videos = data.split(',')
- for video in videos:
- pieces = video.split(':')
- # HACK
- # To elaborate somewhat: in many LMS tests, the keys for
- # Youtube IDs are inconsistent. Sometimes a particular
- # speed isn't present, and formatting is also inconsistent
- # ('1.0' versus '1.00'). So it's necessary to either do
- # something like this or update all the tests to work
- # properly.
- ret['%.2f' % float(pieces[0])] = pieces[1]
- return ret
+
+ @staticmethod
+ def _parse_video_xml(xml_data):
+ """
+ Parse video fields out of xml_data. The fields are set if they are
+ present in the XML.
+ """
+ xml = etree.fromstring(xml_data)
+ model_data = {}
+
+ conversions = {
+ 'show_captions': json.loads,
+ 'start_time': VideoDescriptor._parse_time,
+ 'end_time': VideoDescriptor._parse_time
+ }
+
+ # Convert between key names for certain attributes --
+ # necessary for backwards compatibility.
+ compat_keys = {
+ 'from': 'start_time',
+ 'to': 'end_time'
+ }
+
+ sources = xml.findall('source')
+ if sources:
+ model_data['html5_sources'] = [ele.get('src') for ele in sources]
+ model_data['source'] = model_data['html5_sources'][0]
+
+ track = xml.find('track')
+ if track is not None:
+ model_data['track'] = track.get('src')
+
+ for attr, value in xml.items():
+ if attr in compat_keys:
+ attr = compat_keys[attr]
+ if attr in VideoDescriptor.metadata_to_strip + ('url_name', 'name'):
+ continue
+ if attr == 'youtube':
+ speeds = VideoDescriptor._parse_youtube(value)
+ for speed, youtube_id in speeds.items():
+ # should have made these youtube_id_1_00 for
+ # cleanliness, but hindsight doesn't need glasses
+ normalized_speed = speed[:-1] if speed.endswith('0') else speed
+ # If the user has specified html5 sources, make sure we don't use the default video
+ if youtube_id != '' or 'html5_sources' in model_data:
+ model_data['youtube_id_{0}'.format(normalized_speed.replace('.', '_'))] = youtube_id
+ else:
+ # Convert XML attrs into Python values.
+ if attr in conversions:
+ value = conversions[attr](value)
+ model_data[attr] = value
+
+ return model_data
+
+ @staticmethod
+ def _parse_time(str_time):
+ """Converts s in '12:34:45' format to seconds. If s is
+ None, returns empty string"""
+ if not str_time:
+ return ''
+ else:
+ obj_time = time.strptime(str_time, '%H:%M:%S')
+ return datetime.timedelta(
+ hours=obj_time.tm_hour,
+ minutes=obj_time.tm_min,
+ seconds=obj_time.tm_sec
+ ).total_seconds()
-def _parse_time(str_time):
- """Converts s in '12:34:45' format to seconds. If s is
- None, returns empty string"""
- if str_time is None or str_time == '':
- return ''
- else:
- obj_time = time.strptime(str_time, '%H:%M:%S')
- return datetime.timedelta(
- hours=obj_time.tm_hour,
- minutes=obj_time.tm_min,
- seconds=obj_time.tm_sec
- ).total_seconds()
+def _create_youtube_string(module):
+ """
+ Create a string of Youtube IDs from `module`'s metadata
+ attributes. Only writes a speed if an ID is present in the
+ module. Necessary for backwards compatibility with XML-based
+ courses.
+ """
+ youtube_ids = [
+ module.youtube_id_0_75,
+ module.youtube_id_1_0,
+ module.youtube_id_1_25,
+ module.youtube_id_1_5
+ ]
+ youtube_speeds = ['0.75', '1.00', '1.25', '1.50']
+ return ','.join([':'.join(pair)
+ for pair
+ in zip(youtube_speeds, youtube_ids)
+ if pair[1]])
diff --git a/common/lib/xmodule/xmodule/videoalpha_module.py b/common/lib/xmodule/xmodule/videoalpha_module.py
deleted file mode 100644
index 176b192377..0000000000
--- a/common/lib/xmodule/xmodule/videoalpha_module.py
+++ /dev/null
@@ -1,367 +0,0 @@
-# pylint: disable=W0223
-"""VideoAlpha is ungraded Xmodule for support video content.
-It's new improved video module, which support additional feature:
-
-- Can play non-YouTube video sources via in-browser HTML5 video player.
-- YouTube defaults to HTML5 mode from the start.
-- Speed changes in both YouTube and non-YouTube videos happen via
-in-browser HTML5 video method (when in HTML5 mode).
-- Navigational subtitles can be disabled altogether via an attribute
-in XML.
-"""
-
-import json
-import logging
-
-from lxml import etree
-from pkg_resources import resource_string
-
-from django.http import Http404
-from django.conf import settings
-
-from xmodule.x_module import XModule
-from xmodule.editing_module import TabsEditingDescriptor
-from xmodule.raw_module import EmptyDataRawDescriptor
-from xmodule.modulestore.mongo import MongoModuleStore
-from xmodule.modulestore.django import modulestore
-from xmodule.contentstore.content import StaticContent
-from xblock.core import Scope, String, Boolean, Float, List, Integer
-
-import datetime
-import time
-
-log = logging.getLogger(__name__)
-
-
-class VideoAlphaFields(object):
- """Fields for `VideoAlphaModule` and `VideoAlphaDescriptor`."""
- display_name = String(
- display_name="Display Name", help="Display name for this module.",
- default="Video Alpha",
- scope=Scope.settings
- )
- position = Integer(
- help="Current position in the video",
- scope=Scope.user_state,
- default=0
- )
- show_captions = Boolean(
- help="This controls whether or not captions are shown by default.",
- display_name="Show Captions",
- scope=Scope.settings,
- default=True
- )
- # TODO: This should be moved to Scope.content, but this will
- # require data migration to support the old video module.
- youtube_id_1_0 = String(
- help="This is the Youtube ID reference for the normal speed video.",
- display_name="Youtube ID",
- scope=Scope.settings,
- default="OEoXaMPEzfM"
- )
- youtube_id_0_75 = String(
- help="The Youtube ID for the .75x speed video.",
- display_name="Youtube ID for .75x speed",
- scope=Scope.settings,
- default=""
- )
- youtube_id_1_25 = String(
- help="The Youtube ID for the 1.25x speed video.",
- display_name="Youtube ID for 1.25x speed",
- scope=Scope.settings,
- default=""
- )
- youtube_id_1_5 = String(
- help="The Youtube ID for the 1.5x speed video.",
- display_name="Youtube ID for 1.5x speed",
- scope=Scope.settings,
- default=""
- )
- start_time = Float(
- help="Start time for the video.",
- display_name="Start Time",
- scope=Scope.settings,
- default=0.0
- )
- end_time = Float(
- help="End time for the video.",
- display_name="End Time",
- scope=Scope.settings,
- default=0.0
- )
- source = String(
- help="The external URL to download the video. This appears as a link beneath the video.",
- display_name="Download Video",
- scope=Scope.settings,
- default=""
- )
- html5_sources = List(
- help="A list of filenames to be used with HTML5 video. The first supported filetype will be displayed.",
- display_name="Video Sources",
- scope=Scope.settings,
- default=[]
- )
- track = String(
- help="The external URL to download the subtitle track. This appears as a link beneath the video.",
- display_name="Download Track",
- scope=Scope.settings,
- default=""
- )
- sub = String(
- help="The name of the subtitle track (for non-Youtube videos).",
- display_name="HTML5 Subtitles",
- scope=Scope.settings,
- default=""
- )
-
-
-class VideoAlphaModule(VideoAlphaFields, XModule):
- """
- XML source example:
-
-
-
-
-
-
- """
- video_time = 0
- icon_class = 'video'
-
- js = {
- 'js': [
- resource_string(__name__, 'js/src/videoalpha/01_initialize.js'),
- resource_string(__name__, 'js/src/videoalpha/02_html5_video.js'),
- resource_string(__name__, 'js/src/videoalpha/03_video_player.js'),
- resource_string(__name__, 'js/src/videoalpha/04_video_control.js'),
- resource_string(__name__, 'js/src/videoalpha/05_video_quality_control.js'),
- resource_string(__name__, 'js/src/videoalpha/06_video_progress_slider.js'),
- resource_string(__name__, 'js/src/videoalpha/07_video_volume_control.js'),
- resource_string(__name__, 'js/src/videoalpha/08_video_speed_control.js'),
- resource_string(__name__, 'js/src/videoalpha/09_video_caption.js'),
- resource_string(__name__, 'js/src/videoalpha/10_main.js')
- ]
- }
- css = {'scss': [resource_string(__name__, 'css/videoalpha/display.scss')]}
- js_module_name = "VideoAlpha"
-
- def handle_ajax(self, dispatch, data):
- """This is not being called right now and we raise 404 error."""
- log.debug(u"GET {0}".format(data))
- log.debug(u"DISPATCH {0}".format(dispatch))
- raise Http404()
-
- def get_instance_state(self):
- """Return information about state (position)."""
- return json.dumps({'position': self.position})
-
- def get_html(self):
- if isinstance(modulestore(), MongoModuleStore):
- caption_asset_path = StaticContent.get_base_url_path_for_course_assets(self.location) + '/subs_'
- else:
- # VS[compat]
- # cdodge: filesystem static content support.
- caption_asset_path = "/static/subs/"
-
- get_ext = lambda filename: filename.rpartition('.')[-1]
- sources = {get_ext(src): src for src in self.html5_sources}
- sources['main'] = self.source
-
- return self.system.render_template('videoalpha.html', {
- 'youtube_streams': _create_youtube_string(self),
- 'id': self.location.html_id(),
- 'sub': self.sub,
- 'sources': sources,
- 'track': self.track,
- 'display_name': self.display_name_with_default,
- # This won't work when we move to data that
- # isn't on the filesystem
- 'data_dir': getattr(self, 'data_dir', None),
- 'caption_asset_path': caption_asset_path,
- 'show_captions': json.dumps(self.show_captions),
- 'start': self.start_time,
- 'end': self.end_time,
- 'autoplay': settings.MITX_FEATURES.get('AUTOPLAY_VIDEOS', True)
- })
-
-
-class VideoAlphaDescriptor(VideoAlphaFields, TabsEditingDescriptor, EmptyDataRawDescriptor):
- """Descriptor for `VideoAlphaModule`."""
- module_class = VideoAlphaModule
-
- tabs = [
- # {
- # 'name': "Subtitles",
- # 'template': "videoalpha/subtitles.html",
- # },
- {
- 'name': "Settings",
- 'template': "tabs/metadata-edit-tab.html",
- 'current': True
- }
- ]
-
- def __init__(self, *args, **kwargs):
- super(VideoAlphaDescriptor, self).__init__(*args, **kwargs)
- # For backwards compatibility -- if we've got XML data, parse
- # it out and set the metadata fields
- if self.data:
- model_data = VideoAlphaDescriptor._parse_video_xml(self.data)
- self._model_data.update(model_data)
- del self.data
-
- @classmethod
- def from_xml(cls, xml_data, system, org=None, course=None):
- """
- Creates an instance of this descriptor from the supplied xml_data.
- This may be overridden by subclasses
-
- xml_data: A string of xml that will be translated into data and children for
- this module
- system: A DescriptorSystem for interacting with external resources
- org and course are optional strings that will be used in the generated modules
- url identifiers
- """
- # Calling from_xml of XmlDescritor, to get right Location, when importing from XML
- video = super(VideoAlphaDescriptor, cls).from_xml(xml_data, system, org, course)
- return video
-
- def export_to_xml(self, resource_fs):
- """
- Returns an xml string representing this module.
- """
- xml = etree.Element('videoalpha')
- attrs = {
- 'display_name': self.display_name,
- 'show_captions': json.dumps(self.show_captions),
- 'youtube': _create_youtube_string(self),
- 'start_time': datetime.timedelta(seconds=self.start_time),
- 'end_time': datetime.timedelta(seconds=self.end_time),
- 'sub': self.sub
- }
- for key, value in attrs.items():
- if value:
- xml.set(key, str(value))
-
- for source in self.html5_sources:
- ele = etree.Element('source')
- ele.set('src', source)
- xml.append(ele)
-
- if self.track:
- ele = etree.Element('track')
- ele.set('src', self.track)
- xml.append(ele)
-
- return etree.tostring(xml, pretty_print=True)
-
- @staticmethod
- def _parse_youtube(data):
- """
- Parses a string of Youtube IDs such as "1.0:AXdE34_U,1.5:VO3SxfeD"
- into a dictionary. Necessary for backwards compatibility with
- XML-based courses.
- """
- ret = {'0.75': '', '1.00': '', '1.25': '', '1.50': ''}
- if data == '':
- return ret
- videos = data.split(',')
- for video in videos:
- pieces = video.split(':')
- # HACK
- # To elaborate somewhat: in many LMS tests, the keys for
- # Youtube IDs are inconsistent. Sometimes a particular
- # speed isn't present, and formatting is also inconsistent
- # ('1.0' versus '1.00'). So it's necessary to either do
- # something like this or update all the tests to work
- # properly.
- ret['%.2f' % float(pieces[0])] = pieces[1]
- return ret
-
- @staticmethod
- def _parse_video_xml(xml_data):
- """
- Parse video fields out of xml_data. The fields are set if they are
- present in the XML.
- """
- xml = etree.fromstring(xml_data)
- model_data = {}
-
- conversions = {
- 'show_captions': json.loads,
- 'start_time': VideoAlphaDescriptor._parse_time,
- 'end_time': VideoAlphaDescriptor._parse_time
- }
-
- # VideoModule and VideoAlphaModule use different names for
- # these attributes -- need to convert between them
- video_compat = {
- 'from': 'start_time',
- 'to': 'end_time'
- }
-
- sources = xml.findall('source')
- if sources:
- model_data['html5_sources'] = [ele.get('src') for ele in sources]
- model_data['source'] = model_data['html5_sources'][0]
-
- track = xml.find('track')
- if track is not None:
- model_data['track'] = track.get('src')
-
- for attr, value in xml.items():
- if attr in video_compat:
- attr = video_compat[attr]
- if attr == 'youtube':
- speeds = VideoAlphaDescriptor._parse_youtube(value)
- for speed, youtube_id in speeds.items():
- # should have made these youtube_id_1_00 for
- # cleanliness, but hindsight doesn't need glasses
- normalized_speed = speed[:-1] if speed.endswith('0') else speed
- # If the user has specified html5 sources, make sure we don't use the default video
- if youtube_id != '' or 'html5_sources' in model_data:
- model_data['youtube_id_{0}'.format(normalized_speed.replace('.', '_'))] = youtube_id
- else:
- # Convert XML attrs into Python values.
- if attr in conversions:
- value = conversions[attr](value)
- model_data[attr] = value
-
- return model_data
-
- @staticmethod
- def _parse_time(str_time):
- """Converts s in '12:34:45' format to seconds. If s is
- None, returns empty string"""
- if not str_time:
- return ''
- else:
- obj_time = time.strptime(str_time, '%H:%M:%S')
- return datetime.timedelta(
- hours=obj_time.tm_hour,
- minutes=obj_time.tm_min,
- seconds=obj_time.tm_sec
- ).total_seconds()
-
-
-def _create_youtube_string(module):
- """
- Create a string of Youtube IDs from `module`'s metadata
- attributes. Only writes a speed if an ID is present in the
- module. Necessary for backwards compatibility with XML-based
- courses.
- """
- youtube_ids = [
- module.youtube_id_0_75,
- module.youtube_id_1_0,
- module.youtube_id_1_25,
- module.youtube_id_1_5
- ]
- youtube_speeds = ['0.75', '1.00', '1.25', '1.50']
- return ','.join([':'.join(pair)
- for pair
- in zip(youtube_speeds, youtube_ids)
- if pair[1]])
diff --git a/common/test/data/toy/chapter/secret/magic.xml b/common/test/data/toy/chapter/secret/magic.xml
index f85d2e75da..fe7adb7967 100644
--- a/common/test/data/toy/chapter/secret/magic.xml
+++ b/common/test/data/toy/chapter/secret/magic.xml
@@ -1,3 +1,3 @@
-
+
diff --git a/common/test/data/toy/video/separate_file_video.xml b/common/test/data/toy/video/separate_file_video.xml
index b2bf08540a..b90ea9d8c4 100644
--- a/common/test/data/toy/video/separate_file_video.xml
+++ b/common/test/data/toy/video/separate_file_video.xml
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/lms/djangoapps/courseware/features/video.feature b/lms/djangoapps/courseware/features/video.feature
index 7ba60c4f92..74cd9cbcbb 100644
--- a/lms/djangoapps/courseware/features/video.feature
+++ b/lms/djangoapps/courseware/features/video.feature
@@ -1,10 +1,16 @@
Feature: Video component
As a student, I want to view course videos in LMS.
- Scenario: Autoplay is enabled in LMS for a Video component
- Given the course has a Video component
- Then when I view the video it has autoplay enabled
- Scenario: Autoplay is enabled in the LMS for a VideoAlpha component
- Given the course has a VideoAlpha component
- Then when I view the videoalpha it has autoplay enabled
+ Scenario: Video component is fully rendered in the LMS in HTML5 mode
+ Given the course has a Video component in HTML5 mode
+ Then when I view the video it has rendered in HTML5 mode
+ And all sources are correct
+
+ Scenario: Video component is fully rendered in the LMS in Youtube mode
+ Given the course has a Video component in Youtube mode
+ Then when I view the video it has rendered in Youtube mode
+
+ Scenario: Autoplay is enabled in LMS for a Video component
+ Given the course has a Video component in HTML5 mode
+ Then when I view the video it has autoplay enabled
\ No newline at end of file
diff --git a/lms/djangoapps/courseware/features/video.py b/lms/djangoapps/courseware/features/video.py
index 2e6665f6e8..b546669803 100644
--- a/lms/djangoapps/courseware/features/video.py
+++ b/lms/djangoapps/courseware/features/video.py
@@ -6,24 +6,24 @@ from common import i_am_registered_for_the_course, section_location
############### ACTIONS ####################
+HTML5_SOURCES = [
+ 'https://s3.amazonaws.com/edx-course-videos/edx-intro/edX-FA12-cware-1_100.mp4',
+ 'https://s3.amazonaws.com/edx-course-videos/edx-intro/edX-FA12-cware-1_100.webm',
+ 'https://s3.amazonaws.com/edx-course-videos/edx-intro/edX-FA12-cware-1_100.ogv'
+]
-@step('when I view the video it has autoplay enabled')
-def does_autoplay_video(_step):
- assert(world.css_find('.video')[0]['data-autoplay'] == 'True')
+@step('when I view the (.*) it has autoplay enabled')
+def does_autoplay_video(_step, video_type):
+ assert(world.css_find('.%s' % video_type)[0]['data-autoplay'] == 'True')
-@step('when I view the videoalpha it has autoplay enabled')
-def does_autoplay_videoalpha(_step):
- assert(world.css_find('.videoalpha')[0]['data-autoplay'] == 'True')
-
-
-@step('the course has a Video component')
-def view_video(_step):
+@step('the course has a Video component in (.*) mode')
+def view_video(_step, player_mode):
coursenum = 'test_course'
i_am_registered_for_the_course(step, coursenum)
# Make sure we have a video
- add_video_to_course(coursenum)
+ add_video_to_course(coursenum, player_mode.lower())
chapter_name = world.scenario_dict['SECTION'].display_name.replace(" ", "_")
section_name = chapter_name
url = django_url('/courses/%s/%s/%s/courseware/%s/%s' %
@@ -32,29 +32,43 @@ def view_video(_step):
world.browser.visit(url)
-@step('the course has a VideoAlpha component')
-def view_videoalpha(step):
- coursenum = 'test_course'
- i_am_registered_for_the_course(step, coursenum)
+def add_video_to_course(course, player_mode):
+ category = 'video'
- # Make sure we have a videoalpha
- add_videoalpha_to_course(coursenum)
- chapter_name = world.scenario_dict['SECTION'].display_name.replace(" ", "_")
- section_name = chapter_name
- url = django_url('/courses/%s/%s/%s/courseware/%s/%s' %
- (world.scenario_dict['COURSE'].org, world.scenario_dict['COURSE'].number, world.scenario_dict['COURSE'].display_name.replace(' ', '_'),
- chapter_name, section_name,))
- world.browser.visit(url)
+ kwargs = {
+ 'parent_location': section_location(course),
+ 'category': category,
+ 'display_name': 'Video'
+ }
+
+ if player_mode == 'html5':
+ kwargs.update({
+ 'metadata': {
+ 'youtube_id_1_0': '',
+ 'youtube_id_0_75': '',
+ 'youtube_id_1_25': '',
+ 'youtube_id_1_5': '',
+ 'html5_sources': HTML5_SOURCES
+ }
+ })
+
+ world.ItemFactory.create(**kwargs)
-def add_video_to_course(course):
- world.ItemFactory.create(parent_location=section_location(course),
- category='video',
- display_name='Video')
+@step('when I view the video it has rendered in (.*) mode')
+def video_is_rendered(_step, mode):
+ modes = {
+ 'html5': 'video',
+ 'youtube': 'iframe'
+ }
+ if mode.lower() in modes:
+ assert world.css_find('.video {0}'.format(modes[mode.lower()])).first
+ else:
+ assert False
+
+@step('all sources are correct')
+def all_sources_are_correct(_step):
+ sources = world.css_find('.video video source')
+ assert set(source['src'] for source in sources) == set(HTML5_SOURCES)
-def add_videoalpha_to_course(course):
- category = 'videoalpha'
- world.ItemFactory.create(parent_location=section_location(course),
- category=category,
- display_name='Video Alpha')
diff --git a/lms/djangoapps/courseware/tests/test_video_mongo.py b/lms/djangoapps/courseware/tests/test_video_mongo.py
index 829308423c..65da586812 100644
--- a/lms/djangoapps/courseware/tests/test_video_mongo.py
+++ b/lms/djangoapps/courseware/tests/test_video_mongo.py
@@ -2,21 +2,35 @@
"""Video xmodule tests in mongo."""
from . import BaseTestXmodule
+from .test_video_xml import SOURCE_XML
+from django.conf import settings
+from xmodule.video_module import _create_youtube_string
class TestVideo(BaseTestXmodule):
"""Integration tests: web client + mongo."""
- TEMPLATE_NAME = "video"
- DATA = ' '
+ CATEGORY = "video"
+ DATA = SOURCE_XML
+ MODEL_DATA = {
+ 'data': DATA
+ }
+
+ def setUp(self):
+ # Since the VideoDescriptor changes `self._model_data`,
+ # we need to instantiate `self.item_module` through
+ # `self.item_descriptor` rather than directly constructing it
+ super(TestVideo, self).setUp()
+ self.item_module = self.item_descriptor.xmodule(self.runtime)
+ self.item_module.runtime.render_template = lambda template, context: context
def test_handle_ajax_dispatch(self):
responses = {
user.username: self.clients[user.username].post(
self.get_url('whatever'),
{},
- HTTP_X_REQUESTED_WITH='XMLHttpRequest'
- ) for user in self.users
+ HTTP_X_REQUESTED_WITH='XMLHttpRequest')
+ for user in self.users
}
self.assertEqual(
@@ -25,3 +39,82 @@ class TestVideo(BaseTestXmodule):
for _, response in responses.items()
]).pop(),
404)
+
+ def test_video_constructor(self):
+ """Make sure that all parameters extracted correclty from xml"""
+
+ context = self.item_module.get_html()
+
+ sources = {
+ 'main': u'example.mp4',
+ u'mp4': u'example.mp4',
+ u'webm': u'example.webm',
+ u'ogv': u'example.ogv'
+ }
+
+ expected_context = {
+ 'data_dir': getattr(self, 'data_dir', None),
+ 'caption_asset_path': '/c4x/MITx/999/asset/subs_',
+ 'show_captions': 'true',
+ 'display_name': 'A Name',
+ 'end': 3610.0,
+ 'id': self.item_module.location.html_id(),
+ 'sources': sources,
+ 'start': 3603.0,
+ 'sub': u'a_sub_file.srt.sjson',
+ 'track': '',
+ 'youtube_streams': _create_youtube_string(self.item_module),
+ 'autoplay': settings.MITX_FEATURES.get('AUTOPLAY_VIDEOS', True)
+ }
+
+ self.maxDiff = None
+ self.assertEqual(context, expected_context)
+
+
+class TestVideoNonYouTube(TestVideo):
+ """Integration tests: web client + mongo."""
+
+ DATA = """
+
+
+
+
+
+ """
+ MODEL_DATA = {
+ 'data': DATA
+ }
+
+ def test_video_constructor(self):
+ """Make sure that if the 'youtube' attribute is omitted in XML, then
+ the template generates an empty string for the YouTube streams.
+ """
+ sources = {
+ u'main': u'example.mp4',
+ u'mp4': u'example.mp4',
+ u'webm': u'example.webm',
+ u'ogv': u'example.ogv'
+ }
+
+ context = self.item_module.get_html()
+
+ expected_context = {
+ 'data_dir': getattr(self, 'data_dir', None),
+ 'caption_asset_path': '/c4x/MITx/999/asset/subs_',
+ 'show_captions': 'true',
+ 'display_name': 'A Name',
+ 'end': 3610.0,
+ 'id': self.item_module.location.html_id(),
+ 'sources': sources,
+ 'start': 3603.0,
+ 'sub': 'a_sub_file.srt.sjson',
+ 'track': '',
+ 'youtube_streams': '1.00:OEoXaMPEzfM',
+ 'autoplay': settings.MITX_FEATURES.get('AUTOPLAY_VIDEOS', True)
+ }
+
+ self.assertEqual(context, expected_context)
diff --git a/common/lib/xmodule/xmodule/tests/test_video_xml.py b/lms/djangoapps/courseware/tests/test_video_xml.py
similarity index 54%
rename from common/lib/xmodule/xmodule/tests/test_video_xml.py
rename to lms/djangoapps/courseware/tests/test_video_xml.py
index 1ccc633ee2..64dbe4057b 100644
--- a/common/lib/xmodule/xmodule/tests/test_video_xml.py
+++ b/lms/djangoapps/courseware/tests/test_video_xml.py
@@ -1,6 +1,8 @@
# -*- coding: utf-8 -*-
+# pylint: disable=W0212
+
"""Test for Video Xmodule functional logic.
-These tests data readed from xml, not from mongo.
+These test data read from xml, not from mongo.
We have a ModuleStoreTestCase class defined in
common/lib/xmodule/xmodule/modulestore/tests/django_utils.py.
@@ -13,12 +15,29 @@ common/lib/xmodule/xmodule/modulestore/tests/factories.py to create the
course, section, subsection, unit, etc.
"""
-from mock import Mock
+import json
+import unittest
-from xmodule.video_module import VideoDescriptor, VideoModule, _parse_time, _parse_youtube
+from django.conf import settings
+
+from xmodule.video_module import (
+ VideoDescriptor, _create_youtube_string)
from xmodule.modulestore import Location
-from xmodule.tests import get_test_system
-from xmodule.tests import LogicTest
+from xmodule.tests import get_test_system, LogicTest
+
+
+SOURCE_XML = """
+
+
+
+
+
+"""
class VideoFactory(object):
@@ -27,34 +46,66 @@ class VideoFactory(object):
"""
# tag that uses youtube videos
- sample_problem_xml_youtube = """
-
-
-
- """
+ sample_problem_xml_youtube = SOURCE_XML
@staticmethod
def create():
"""Method return Video Xmodule instance."""
location = Location(["i4x", "edX", "video", "default",
"SampleProblem1"])
- model_data = {'data': VideoFactory.sample_problem_xml_youtube, 'location': location}
-
- descriptor = Mock(weight="1", url_name="SampleProblem1")
+ model_data = {'data': VideoFactory.sample_problem_xml_youtube,
+ 'location': location}
system = get_test_system()
system.render_template = lambda template, context: context
- module = VideoModule(system, descriptor, model_data)
+
+ descriptor = VideoDescriptor(system, model_data)
+
+ module = descriptor.xmodule(system)
return module
+class VideoModuleUnitTest(unittest.TestCase):
+ """Unit tests for Video Xmodule."""
+
+ def test_video_get_html(self):
+ """Make sure that all parameters extracted correclty from xml"""
+ module = VideoFactory.create()
+ module.runtime.render_template = lambda template, context: context
+
+ sources = {
+ 'main': 'example.mp4',
+ 'mp4': 'example.mp4',
+ 'webm': 'example.webm',
+ 'ogv': 'example.ogv'
+ }
+
+ expected_context = {
+ 'caption_asset_path': '/static/subs/',
+ 'sub': 'a_sub_file.srt.sjson',
+ 'data_dir': getattr(self, 'data_dir', None),
+ 'display_name': 'A Name',
+ 'end': 3610.0,
+ 'start': 3603.0,
+ 'id': module.location.html_id(),
+ 'show_captions': 'true',
+ 'sources': sources,
+ 'youtube_streams': _create_youtube_string(module),
+ 'track': '',
+ 'autoplay': settings.MITX_FEATURES.get('AUTOPLAY_VIDEOS', True)
+ }
+
+ self.assertEqual(module.get_html(), expected_context)
+
+ def test_video_instance_state(self):
+ module = VideoFactory.create()
+
+ self.assertDictEqual(
+ json.loads(module.get_instance_state()),
+ {'position': 0})
+
+
class VideoModuleLogicTest(LogicTest):
"""Tests for logic of Video Xmodule."""
@@ -66,23 +117,23 @@ class VideoModuleLogicTest(LogicTest):
def test_parse_time(self):
"""Ensure that times are parsed correctly into seconds."""
- output = _parse_time('00:04:07')
+ output = VideoDescriptor._parse_time('00:04:07')
self.assertEqual(output, 247)
def test_parse_time_none(self):
"""Check parsing of None."""
- output = _parse_time(None)
+ output = VideoDescriptor._parse_time(None)
self.assertEqual(output, '')
def test_parse_time_empty(self):
"""Check parsing of the empty string."""
- output = _parse_time('')
+ output = VideoDescriptor._parse_time('')
self.assertEqual(output, '')
def test_parse_youtube(self):
"""Test parsing old-style Youtube ID strings into a dict."""
youtube_str = '0.75:jNCf2gIqpeE,1.00:ZwkTiUPN0mg,1.25:rsq9auxASqI,1.50:kMyNdzVHHgg'
- output = _parse_youtube(youtube_str)
+ output = VideoDescriptor._parse_youtube(youtube_str)
self.assertEqual(output, {'0.75': 'jNCf2gIqpeE',
'1.00': 'ZwkTiUPN0mg',
'1.25': 'rsq9auxASqI',
@@ -94,7 +145,7 @@ class VideoModuleLogicTest(LogicTest):
empty string.
"""
youtube_str = '0.75:jNCf2gIqpeE'
- output = _parse_youtube(youtube_str)
+ output = VideoDescriptor._parse_youtube(youtube_str)
self.assertEqual(output, {'0.75': 'jNCf2gIqpeE',
'1.00': '',
'1.25': '',
@@ -106,14 +157,17 @@ class VideoModuleLogicTest(LogicTest):
"""
youtube_str = '1.00:p2Q6BrNhdh8'
youtube_str_hack = '1.0:p2Q6BrNhdh8'
- self.assertEqual(_parse_youtube(youtube_str), _parse_youtube(youtube_str_hack))
+ self.assertEqual(
+ VideoDescriptor._parse_youtube(youtube_str),
+ VideoDescriptor._parse_youtube(youtube_str_hack)
+ )
def test_parse_youtube_empty(self):
"""
Some courses have empty youtube attributes, so we should handle
that well.
"""
- self.assertEqual(_parse_youtube(''),
+ self.assertEqual(VideoDescriptor._parse_youtube(''),
{'0.75': '',
'1.00': '',
'1.25': '',
diff --git a/lms/djangoapps/courseware/tests/test_videoalpha_mongo.py b/lms/djangoapps/courseware/tests/test_videoalpha_mongo.py
deleted file mode 100644
index 38b2b6fb8d..0000000000
--- a/lms/djangoapps/courseware/tests/test_videoalpha_mongo.py
+++ /dev/null
@@ -1,119 +0,0 @@
-# -*- coding: utf-8 -*-
-"""Video xmodule tests in mongo."""
-
-from . import BaseTestXmodule
-from .test_videoalpha_xml import SOURCE_XML
-from django.conf import settings
-from xmodule.videoalpha_module import _create_youtube_string
-
-
-class TestVideo(BaseTestXmodule):
- """Integration tests: web client + mongo."""
-
- CATEGORY = "videoalpha"
- DATA = SOURCE_XML
- MODEL_DATA = {
- 'data': DATA
- }
-
- def setUp(self):
- # Since the VideoAlphaDescriptor changes `self._model_data`,
- # we need to instantiate `self.item_module` through
- # `self.item_descriptor` rather than directly constructing it
- super(TestVideo, self).setUp()
- self.item_module = self.item_descriptor.xmodule(self.runtime)
- self.item_module.runtime.render_template = lambda template, context: context
-
- def test_handle_ajax_dispatch(self):
- responses = {
- user.username: self.clients[user.username].post(
- self.get_url('whatever'),
- {},
- HTTP_X_REQUESTED_WITH='XMLHttpRequest')
- for user in self.users
- }
-
- self.assertEqual(
- set([
- response.status_code
- for _, response in responses.items()
- ]).pop(),
- 404)
-
- def test_videoalpha_constructor(self):
- """Make sure that all parameters extracted correclty from xml"""
-
- context = self.item_module.get_html()
-
- sources = {
- 'main': 'example.mp4',
- 'mp4': 'example.mp4',
- 'webm': 'example.webm',
- 'ogv': 'example.ogv'
- }
-
- expected_context = {
- 'data_dir': getattr(self, 'data_dir', None),
- 'caption_asset_path': '/c4x/MITx/999/asset/subs_',
- 'show_captions': 'true',
- 'display_name': 'A Name',
- 'end': 3610.0,
- 'id': self.item_module.location.html_id(),
- 'sources': sources,
- 'start': 3603.0,
- 'sub': 'a_sub_file.srt.sjson',
- 'track': '',
- 'youtube_streams': _create_youtube_string(self.item_module),
- 'autoplay': settings.MITX_FEATURES.get('AUTOPLAY_VIDEOS', True)
- }
-
- self.assertEqual(context, expected_context)
-
-
-class TestVideoNonYouTube(TestVideo):
- """Integration tests: web client + mongo."""
-
- DATA = """
-
-
-
-
-
- """
- MODEL_DATA = {
- 'data': DATA
- }
-
- def test_videoalpha_constructor(self):
- """Make sure that if the 'youtube' attribute is omitted in XML, then
- the template generates an empty string for the YouTube streams.
- """
- sources = {
- u'main': u'example.mp4',
- u'mp4': u'example.mp4',
- u'webm': u'example.webm',
- u'ogv': u'example.ogv'
- }
-
- context = self.item_module.get_html()
-
- expected_context = {
- 'data_dir': getattr(self, 'data_dir', None),
- 'caption_asset_path': '/c4x/MITx/999/asset/subs_',
- 'show_captions': 'true',
- 'display_name': 'A Name',
- 'end': 3610.0,
- 'id': self.item_module.location.html_id(),
- 'sources': sources,
- 'start': 3603.0,
- 'sub': 'a_sub_file.srt.sjson',
- 'track': '',
- 'youtube_streams': '1.00:OEoXaMPEzfM',
- 'autoplay': settings.MITX_FEATURES.get('AUTOPLAY_VIDEOS', True)
- }
-
- self.assertEqual(context, expected_context)
diff --git a/lms/djangoapps/courseware/tests/test_videoalpha_xml.py b/lms/djangoapps/courseware/tests/test_videoalpha_xml.py
deleted file mode 100644
index bd5010d16e..0000000000
--- a/lms/djangoapps/courseware/tests/test_videoalpha_xml.py
+++ /dev/null
@@ -1,103 +0,0 @@
-# -*- coding: utf-8 -*-
-"""Test for VideoAlpha Xmodule functional logic.
-These test data read from xml, not from mongo.
-
-We have a ModuleStoreTestCase class defined in
-common/lib/xmodule/xmodule/modulestore/tests/django_utils.py.
-You can search for usages of this in the cms and lms tests for examples.
-You use this so that it will do things like point the modulestore
-setting to mongo, flush the contentstore before and after, load the
-templates, etc.
-You can then use the CourseFactory and XModuleItemFactory as defined in
-common/lib/xmodule/xmodule/modulestore/tests/factories.py to create the
-course, section, subsection, unit, etc.
-"""
-
-import json
-import unittest
-
-from django.conf import settings
-
-from xmodule.videoalpha_module import VideoAlphaDescriptor, _create_youtube_string
-from xmodule.modulestore import Location
-from xmodule.tests import get_test_system
-
-
-SOURCE_XML = """
-
-
-
-
-
-"""
-
-
-class VideoAlphaFactory(object):
- """A helper class to create videoalpha modules with various parameters
- for testing.
- """
-
- # tag that uses youtube videos
- sample_problem_xml_youtube = SOURCE_XML
-
- @staticmethod
- def create():
- """Method return VideoAlpha Xmodule instance."""
- location = Location(["i4x", "edX", "videoalpha", "default",
- "SampleProblem1"])
- model_data = {'data': VideoAlphaFactory.sample_problem_xml_youtube,
- 'location': location}
-
- system = get_test_system()
- system.render_template = lambda template, context: context
-
- descriptor = VideoAlphaDescriptor(system, model_data)
-
- module = descriptor.xmodule(system)
-
- return module
-
-
-class VideoAlphaModuleUnitTest(unittest.TestCase):
- """Unit tests for VideoAlpha Xmodule."""
-
- def test_videoalpha_get_html(self):
- """Make sure that all parameters extracted correclty from xml"""
- module = VideoAlphaFactory.create()
- module.runtime.render_template = lambda template, context: context
-
- sources = {
- 'main': 'example.mp4',
- 'mp4': 'example.mp4',
- 'webm': 'example.webm',
- 'ogv': 'example.ogv'
- }
-
- expected_context = {
- 'caption_asset_path': '/static/subs/',
- 'sub': 'a_sub_file.srt.sjson',
- 'data_dir': getattr(self, 'data_dir', None),
- 'display_name': 'A Name',
- 'end': 3610.0,
- 'start': 3603.0,
- 'id': module.location.html_id(),
- 'show_captions': 'true',
- 'sources': sources,
- 'youtube_streams': _create_youtube_string(module),
- 'track': '',
- 'autoplay': settings.MITX_FEATURES.get('AUTOPLAY_VIDEOS', True)
- }
-
- self.assertEqual(module.get_html(), expected_context)
-
- def test_videoalpha_instance_state(self):
- module = VideoAlphaFactory.create()
-
- self.assertDictEqual(
- json.loads(module.get_instance_state()),
- {'position': 0})
diff --git a/lms/envs/acceptance.py b/lms/envs/acceptance.py
index a58420ab1e..e9ac9762c2 100644
--- a/lms/envs/acceptance.py
+++ b/lms/envs/acceptance.py
@@ -75,10 +75,6 @@ XQUEUE_INTERFACE = {
"basic_auth": ('anant', 'agarwal'),
}
-# Do not display the YouTube videos in the browser while running the
-# acceptance tests. This makes them faster and more reliable
-MITX_FEATURES['STUB_VIDEO_FOR_TESTING'] = True
-
# Forums are disabled in test.py to speed up unit tests, but we do not have
# per-test control for acceptance tests
MITX_FEATURES['ENABLE_DISCUSSION_SERVICE'] = True
diff --git a/lms/envs/acceptance_static.py b/lms/envs/acceptance_static.py
index 5672ea5bf5..27efb6160d 100644
--- a/lms/envs/acceptance_static.py
+++ b/lms/envs/acceptance_static.py
@@ -70,10 +70,6 @@ XQUEUE_INTERFACE = {
"basic_auth": ('anant', 'agarwal'),
}
-# Do not display the YouTube videos in the browser while running the
-# acceptance tests. This makes them faster and more reliable
-MITX_FEATURES['STUB_VIDEO_FOR_TESTING'] = True
-
# Include the lettuce app for acceptance testing, including the 'harvest' django-admin command
INSTALLED_APPS += ('lettuce.django',)
LETTUCE_APPS = ('courseware',)
diff --git a/lms/envs/common.py b/lms/envs/common.py
index de78816a10..0579fc94d6 100644
--- a/lms/envs/common.py
+++ b/lms/envs/common.py
@@ -86,8 +86,6 @@ MITX_FEATURES = {
'DISABLE_LOGIN_BUTTON': False, # used in systems where login is automatic, eg MIT SSL
- 'STUB_VIDEO_FOR_TESTING': False, # do not display video when running automated acceptance tests
-
# extrernal access methods
'ACCESS_REQUIRE_STAFF_FOR_COURSE': False,
'AUTH_USE_OPENID': False,
diff --git a/lms/templates/video.html b/lms/templates/video.html
index 4c9d178242..ab3fd08d0c 100644
--- a/lms/templates/video.html
+++ b/lms/templates/video.html
@@ -1,56 +1,82 @@
<%! 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 settings.MITX_FEATURES.get('USE_YOUTUBE_OBJECT_API') and normal_speed_video_id:
-
-
- % endif
-
-
-
-
-%else:
-
-%endif
+
-
${_('Download video here .') % source}
+ data-streams="${youtube_streams}"
+
+ ${'data-sub="{}"'.format(sub) if sub else ''}
+ ${'data-autoplay="{}"'.format(autoplay) if autoplay else ''}
+
+ ${'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 ''}
+
+ 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 sources.get('main'):
+
% endif
% if track:
-
-
${_('Download subtitles here .') % track}
-
+
% endif
diff --git a/lms/templates/videoalpha.html b/lms/templates/videoalpha.html
deleted file mode 100644
index d0eb7290a7..0000000000
--- a/lms/templates/videoalpha.html
+++ /dev/null
@@ -1,86 +0,0 @@
-<%! from django.utils.translation import ugettext as _ %>
-
-% if display_name is not UNDEFINED and display_name is not None:
- ${display_name}
-% endif
-
-
-
-% if sources.get('main'):
-
-% endif
-
-% if track:
-
-% endif
diff --git a/test_root/data/videoalpha/gizmo.mp4 b/test_root/data/video/gizmo.mp4
similarity index 100%
rename from test_root/data/videoalpha/gizmo.mp4
rename to test_root/data/video/gizmo.mp4
diff --git a/test_root/data/videoalpha/gizmo.ogv b/test_root/data/video/gizmo.ogv
similarity index 100%
rename from test_root/data/videoalpha/gizmo.ogv
rename to test_root/data/video/gizmo.ogv
diff --git a/test_root/data/videoalpha/gizmo.webm b/test_root/data/video/gizmo.webm
similarity index 100%
rename from test_root/data/videoalpha/gizmo.webm
rename to test_root/data/video/gizmo.webm