diff --git a/cms/djangoapps/contentstore/features/common.py b/cms/djangoapps/contentstore/features/common.py index 8d13a39bb3..516659fadb 100644 --- a/cms/djangoapps/contentstore/features/common.py +++ b/cms/djangoapps/contentstore/features/common.py @@ -210,27 +210,6 @@ def set_date_and_time(date_css, desired_date, time_css, desired_time): time.sleep(float(1)) -@step('I have created a Video component$') -def i_created_a_video_component(step): - world.create_component_instance( - step, '.large-video-icon', - 'video', - '.xmodule_VideoModule', - has_multiple_templates=False - ) - - -@step('I have created a Video Alpha component$') -def i_created_video_alpha(step): - step.given('I have enabled the videoalpha advanced module') - world.css_click('a.course-link') - step.given('I have added a new subsection') - step.given('I expand the first section') - world.css_click('a.new-unit-item') - world.css_click('.large-advanced-icon') - world.click_component_from_menu('videoalpha', None, '.xmodule_VideoAlphaModule') - - @step('I have enabled the (.*) advanced module$') def i_enabled_the_advanced_module(step, module): step.given('I have opened a new course section in Studio') @@ -248,16 +227,6 @@ def open_new_unit(step): world.css_click('a.new-unit-item') -@step('when I view the (video.*) it (.*) show the captions') -def shows_captions(_step, video_type, show_captions): - # Prevent cookies from overriding course settings - world.browser.cookies.delete('hide_captions') - if show_captions == 'does not': - assert world.css_has_class('.%s' % video_type, 'closed') - else: - assert world.is_css_not_present('.%s.closed' % video_type) - - @step('the save button is disabled$') def save_button_disabled(step): button_css = '.action-save' diff --git a/cms/djangoapps/contentstore/features/video-editor.feature b/cms/djangoapps/contentstore/features/video-editor.feature index f28ee568dc..a53183e37c 100644 --- a/cms/djangoapps/contentstore/features/video-editor.feature +++ b/cms/djangoapps/contentstore/features/video-editor.feature @@ -1,16 +1,16 @@ Feature: Video Component Editor As a course author, I want to be able to create video components. - Scenario: User can view metadata + Scenario: User can view Video metadata Given I have created a Video component - And I edit and select Settings - Then I see the correct settings and default values + And I edit the component + Then I see the correct video settings and default values - Scenario: User can modify display name + Scenario: User can modify Video display name Given I have created a Video component - And I edit and select Settings + And I edit the component Then I can modify the display name - And my display name change is persisted on save + And my video display name change is persisted on save Scenario: Captions are hidden when "show captions" is false Given I have created a Video component diff --git a/cms/djangoapps/contentstore/features/video-editor.py b/cms/djangoapps/contentstore/features/video-editor.py index ad3229ab53..f9d433fc02 100644 --- a/cms/djangoapps/contentstore/features/video-editor.py +++ b/cms/djangoapps/contentstore/features/video-editor.py @@ -2,18 +2,7 @@ # pylint: disable=C0111 from lettuce import world, step - - -@step('I see the correct settings and default values$') -def i_see_the_correct_settings_and_values(step): - world.verify_all_setting_entries([['Default Speed', 'OEoXaMPEzfM', False], - ['Display Name', 'Video', False], - ['Download Track', '', False], - ['Download Video', '', False], - ['Show Captions', 'True', False], - ['Speed: .75x', '', False], - ['Speed: 1.25x', '', False], - ['Speed: 1.5x', '', False]]) +from terrain.steps import reload_the_page @step('I have set "show captions" to (.*)') @@ -24,9 +13,19 @@ def set_show_captions(step, setting): world.css_click('a.save-button') -@step('I see the correct videoalpha settings and default values$') -def correct_videoalpha_settings(_step): - world.verify_all_setting_entries([['Display Name', 'Video Alpha', False], +@step('when I view the (video.*) it (.*) show the captions') +def shows_captions(_step, video_type, show_captions): + # Prevent cookies from overriding course settings + world.browser.cookies.delete('hide_captions') + if show_captions == 'does not': + assert world.css_has_class('.%s' % video_type, 'closed') + else: + assert world.is_css_not_present('.%s.closed' % video_type) + + +@step('I see the correct video settings and default values$') +def correct_video_settings(_step): + world.verify_all_setting_entries([['Display Name', 'Video', False], ['Download Track', '', False], ['Download Video', '', False], ['End Time', '0', False], @@ -38,3 +37,12 @@ def correct_videoalpha_settings(_step): ['Youtube ID for .75x speed', '', False], ['Youtube ID for 1.25x speed', '', False], ['Youtube ID for 1.5x speed', '', False]]) + + +@step('my video display name change is persisted on save') +def video_name_persisted(step): + world.css_click('a.save-button') + reload_the_page(step) + world.edit_component() + world.verify_setting_entry(world.get_setting_entry('Display Name'), 'Display Name', '3.4', True) + diff --git a/cms/djangoapps/contentstore/features/video.feature b/cms/djangoapps/contentstore/features/video.feature index 634bb8a17f..50c06fde63 100644 --- a/cms/djangoapps/contentstore/features/video.feature +++ b/cms/djangoapps/contentstore/features/video.feature @@ -1,6 +1,7 @@ Feature: Video Component As a course author, I want to be able to view my created videos in Studio. + # Video Alpha Features will work in Firefox only when Firefox is the active window Scenario: Autoplay is disabled in Studio Given I have created a Video component Then when I view the video it does not have autoplay enabled @@ -23,32 +24,6 @@ Feature: Video Component And I have toggled captions Then when I view the video it does show the captions - # Video Alpha Features will work in Firefox only when Firefox is the active window - Scenario: Autoplay is disabled in Studio for Video Alpha - Given I have created a Video Alpha component - Then when I view the videoalpha it does not have autoplay enabled - - Scenario: User can view Video Alpha metadata - Given I have created a Video Alpha component - And I edit the component - Then I see the correct videoalpha settings and default values - - Scenario: User can modify Video Alpha display name - Given I have created a Video Alpha component - And I edit the component - Then I can modify the display name - And my videoalpha display name change is persisted on save - - Scenario: Video Alpha captions are hidden when "show captions" is false - Given I have created a Video Alpha component - And I have set "show captions" to False - Then when I view the videoalpha it does not show the captions - - Scenario: Video Alpha captions are shown when "show captions" is true - Given I have created a Video Alpha component - And I have set "show captions" to True - Then when I view the videoalpha it does show the captions - Scenario: Video data is shown correctly Given I have created a video with only XML data Then the correct Youtube video is shown diff --git a/cms/djangoapps/contentstore/features/video.py b/cms/djangoapps/contentstore/features/video.py index e27ca28eb7..2c3d2cdfa9 100644 --- a/cms/djangoapps/contentstore/features/video.py +++ b/cms/djangoapps/contentstore/features/video.py @@ -9,6 +9,16 @@ from contentstore.utils import get_modulestore ############### ACTIONS #################### +@step('I have created a Video component$') +def i_created_a_video_component(step): + world.create_component_instance( + step, '.large-video-icon', + 'video', + '.xmodule_VideoModule', + has_multiple_templates=False + ) + + @step('when I view the (.*) it does not have autoplay enabled') def does_not_autoplay(_step, video_type): assert world.css_find('.%s' % video_type)[0]['data-autoplay'] == 'False' @@ -22,6 +32,11 @@ def video_takes_a_single_click(_step): assert(world.is_css_present('.xmodule_VideoModule')) +@step('I edit the component') +def i_edit_the_component(_step): + world.edit_component() + + @step('I have (hidden|toggled) captions') def hide_or_show_captions(step, shown): button_css = 'a.hide-subtitles' @@ -38,18 +53,6 @@ def hide_or_show_captions(step, shown): button.mouse_out() world.css_click(button_css) -@step('I edit the component') -def i_edit_the_component(_step): - world.edit_component() - - -@step('my videoalpha display name change is persisted on save') -def videoalpha_name_persisted(step): - world.css_click('a.save-button') - reload_the_page(step) - world.edit_component() - world.verify_setting_entry(world.get_setting_entry('Display Name'), 'Display Name', '3.4', True) - @step('I have created a video with only XML data') def xml_only_video(step): @@ -84,4 +87,5 @@ def xml_only_video(step): @step('The correct Youtube video is shown') def the_youtube_video_is_shown(_step): ele = world.css_find('.video').first - assert ele['data-youtube-id-1-0'] == world.scenario_dict['YOUTUBE_ID'] + assert ele['data-streams'].split(':')[1] == world.scenario_dict['YOUTUBE_ID'] + diff --git a/cms/djangoapps/contentstore/tests/test_contentstore.py b/cms/djangoapps/contentstore/tests/test_contentstore.py index 09413be7b7..fe459a6f69 100644 --- a/cms/djangoapps/contentstore/tests/test_contentstore.py +++ b/cms/djangoapps/contentstore/tests/test_contentstore.py @@ -107,8 +107,8 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): expected_types is the list of elements that should appear on the page. expected_types and component_types should be similar, but not - exactly the same -- for example, 'videoalpha' in - component_types should cause 'Video Alpha' to be present. + exactly the same -- for example, 'video' in + component_types should cause 'Video' to be present. """ store = modulestore('direct') import_from_xml(store, 'common/test/data/', ['simple']) @@ -136,14 +136,13 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): def test_advanced_components_in_edit_unit(self): # This could be made better, but for now let's just assert that we see the advanced modules mentioned in the page # response HTML - self.check_components_on_page(ADVANCED_COMPONENT_TYPES, ['Video Alpha', - 'Word cloud', + self.check_components_on_page(ADVANCED_COMPONENT_TYPES, ['Word cloud', 'Annotation', 'Open Response Assessment', 'Peer Grading Interface']) def test_advanced_components_require_two_clicks(self): - self.check_components_on_page(['videoalpha'], ['Video Alpha']) + self.check_components_on_page(['word_cloud'], ['Word cloud']) def test_malformed_edit_unit_request(self): store = modulestore('direct') @@ -1597,12 +1596,15 @@ class ContentStoreTest(ModuleStoreTestCase): class MetadataSaveTestCase(ModuleStoreTestCase): - """ - Test that metadata is correctly decached. - """ + """Test that metadata is correctly cached and decached.""" def setUp(self): - sample_xml = ''' + CourseFactory.create( + org='edX', course='999', display_name='Robot Super Course') + course_location = Location( + ['i4x', 'edX', '999', 'course', 'Robot_Super_Course', None]) + + video_sample_xml = ''' ''' - CourseFactory.create(org='edX', course='999', display_name='Robot Super Course') - course_location = Location(['i4x', 'edX', '999', 'course', 'Robot_Super_Course', None]) + self.video_descriptor = ItemFactory.create( + parent_location=course_location, category='video', + data={'data': video_sample_xml} + ) - model_data = {'data': sample_xml} - self.descriptor = ItemFactory.create(parent_location=course_location, category='video', data=model_data) - - def test_metadata_persistence(self): + def test_metadata_not_persistence(self): """ Test that descriptors which set metadata fields in their - constructor are correctly persisted. + constructor are correctly deleted. """ - # We should start with a source field, from the XML's tag - self.assertIn('source', own_metadata(self.descriptor)) + self.assertIn('html5_sources', own_metadata(self.video_descriptor)) attrs_to_strip = { 'show_captions', 'youtube_id_1_0', @@ -1634,23 +1634,27 @@ class MetadataSaveTestCase(ModuleStoreTestCase): 'start_time', 'end_time', 'source', + 'html5_sources', 'track' } - # We strip out all metadata fields to reproduce a bug where - # constructors which set their fields (e.g. Video) didn't have - # those changes persisted. So in the end we have the XML data - # in `descriptor.data`, but not in the individual fields - fields = self.descriptor.fields + + fields = self.video_descriptor.fields + location = self.video_descriptor.location + for field in fields: if field.name in attrs_to_strip: - field.delete_from(self.descriptor) + field.delete_from(self.video_descriptor) - # Assert that we correctly stripped the field - self.assertNotIn('source', own_metadata(self.descriptor)) - get_modulestore(self.descriptor.location).update_metadata( - self.descriptor.location, - own_metadata(self.descriptor) + self.assertNotIn('html5_sources', own_metadata(self.video_descriptor)) + get_modulestore(location).update_metadata( + location, + own_metadata(self.video_descriptor) ) - module = get_modulestore(self.descriptor.location).get_item(self.descriptor.location) - # Assert that get_item correctly sets the metadata - self.assertIn('source', own_metadata(module)) + module = get_modulestore(location).get_item(location) + + self.assertNotIn('html5_sources', own_metadata(module)) + + def test_metadata_persistence(self): + # TODO: create the same test as `test_metadata_not_persistence`, + # but check persistence for some other module. + pass diff --git a/cms/djangoapps/contentstore/views/component.py b/cms/djangoapps/contentstore/views/component.py index 7cb503db1e..d7b41acb24 100644 --- a/cms/djangoapps/contentstore/views/component.py +++ b/cms/djangoapps/contentstore/views/component.py @@ -49,7 +49,6 @@ NOTE_COMPONENT_TYPES = ['notes'] ADVANCED_COMPONENT_TYPES = [ 'annotatable', 'word_cloud', - 'videoalpha', 'graphical_slider_tool' ] + OPEN_ENDED_COMPONENT_TYPES + NOTE_COMPONENT_TYPES ADVANCED_COMPONENT_CATEGORY = 'advanced' diff --git a/cms/envs/common.py b/cms/envs/common.py index 40084c20ae..9cdd7a4410 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -39,9 +39,6 @@ MITX_FEATURES = { 'AUTH_USE_MIT_CERTIFICATES': False, - # do not display video when running automated acceptance tests - 'STUB_VIDEO_FOR_TESTING': False, - # email address for studio staff (eg to request course creation) 'STUDIO_REQUEST_EMAIL': '', diff --git a/cms/static/sass/elements/_xmodules.scss b/cms/static/sass/elements/_xmodules.scss index a8ec208b02..db1a50b40c 100644 --- a/cms/static/sass/elements/_xmodules.scss +++ b/cms/static/sass/elements/_xmodules.scss @@ -2,7 +2,7 @@ // ==================== // Video Alpha -.xmodule_VideoAlphaModule { +.xmodule_VideoModule { // display mode &.xmodule_display { diff --git a/cms/templates/widgets/videoalpha/codemirror-edit.html b/cms/templates/widgets/video/codemirror-edit.html similarity index 100% rename from cms/templates/widgets/videoalpha/codemirror-edit.html rename to cms/templates/widgets/video/codemirror-edit.html diff --git a/cms/templates/widgets/videoalpha/subtitles.html b/cms/templates/widgets/video/subtitles.html similarity index 100% rename from cms/templates/widgets/videoalpha/subtitles.html rename to cms/templates/widgets/video/subtitles.html diff --git a/common/lib/xmodule/setup.py b/common/lib/xmodule/setup.py index 6b106dd94d..704de15ea7 100644 --- a/common/lib/xmodule/setup.py +++ b/common/lib/xmodule/setup.py @@ -40,7 +40,7 @@ setup( "timelimit = xmodule.timelimit_module:TimeLimitDescriptor", "vertical = xmodule.vertical_module:VerticalDescriptor", "video = xmodule.video_module:VideoDescriptor", - "videoalpha = xmodule.videoalpha_module:VideoAlphaDescriptor", + "videoalpha = xmodule.video_module:VideoDescriptor", "videodev = xmodule.backcompat_module:TranslateCustomTagDescriptor", "videosequence = xmodule.seq_module:SequenceDescriptor", "discussion = xmodule.discussion_module:DiscussionDescriptor", diff --git a/common/lib/xmodule/xmodule/css/video/display.scss b/common/lib/xmodule/xmodule/css/video/display.scss index 879aee3f72..533ab2aec0 100644 --- a/common/lib/xmodule/xmodule/css/video/display.scss +++ b/common/lib/xmodule/xmodule/css/video/display.scss @@ -10,11 +10,30 @@ div.video { padding: 12px; border-radius: 5px; + div.tc-wrapper { + position: relative; + @include clearfix; + } + article.video-wrapper { float: left; margin-right: flex-gutter(9); width: flex-grid(6, 9); + background-color: black; + + position: relative; + + div.video-player-pre { + height: 50px; + background-color: black; + } + + div.video-player-post { + height: 50px; + background-color: black; + } + section.video-player { height: 0; overflow: hidden; @@ -52,10 +71,19 @@ div.video { border-radius: 0; border-top: 1px solid #000; box-shadow: inset 0 1px 0 #eee, 0 1px 0 #555; - height: 7px; + position: absolute; + z-index: 1; + bottom: 100%; + left: 0; + right: 0; + height: 14px; margin-left: -1px; margin-right: -1px; - @include transition(height 2.0s ease-in-out 0s); + -webkit-transition: -webkit-transform 0.7s ease-in-out; + -moz-transition: -moz-transform 0.7s ease-in-out; + -ms-transition: -ms-transform 0.7s ease-in-out; + transition: transform 0.7s ease-in-out; + @include transform(scaleY(0.5) translate3d(0, 50%, 0)); div.ui-widget-header { background: #777; @@ -66,14 +94,18 @@ div.video { background: $pink url(../images/slider-handle.png) center center no-repeat; background-size: 50%; border: 1px solid darken($pink, 20%); - border-radius: 15px; + border-radius: 50%; box-shadow: inset 0 1px 0 lighten($pink, 10%); cursor: pointer; - height: 15px; - margin-left: -7px; - top: -4px; - @include transition(height 2.0s ease-in-out 0s, width 2.0s ease-in-out 0s); - width: 15px; + height: 20px; + margin-left: 0; + top: 0; + -webkit-transition: -webkit-transform 0.7s ease-in-out; + -moz-transition: -moz-transform 0.7s ease-in-out; + -ms-transition: -ms-transform 0.7s ease-in-out; + transition: transform 0.7s ease-in-out; + @include transform(scale(.7, 1.3) translate3d(-80%, -15%, 0)); + width: 20px; &:focus, &:hover { background-color: lighten($pink, 10%); @@ -101,7 +133,6 @@ div.video { line-height: 46px; padding: 0 lh(.75); text-indent: -9999px; - @include transition(background-color 0.75s linear 0s, opacity 0.75s linear 0s); width: 14px; background: url('../images/vcr.png') 15px 15px no-repeat; outline: 0; @@ -118,7 +149,7 @@ div.video { &.play { background-position: 17px -114px; - &:hover { + &:hover, &:focus { background-color: #444; } } @@ -126,7 +157,7 @@ div.video { &.pause { background-position: 16px -50px; - &:hover { + &:hover, &:focus { background-color: #444; } } @@ -213,7 +244,7 @@ div.video { // fix for now ol.video_speeds { - box-shadow: inset 1px 0 0 #555, 0 3px 0 #444; + box-shadow: inset 1px 0 0 #555, 0 4px 0 #444; @include transition(none); background-color: #444; border: 1px solid #000; @@ -221,7 +252,7 @@ div.video { display: none; opacity: 0.0; position: absolute; - width: 133px; + width: 131px; z-index: 10; li { @@ -268,12 +299,15 @@ div.video { &.muted { &>a { - background: url('../images/mute.png') 10px center no-repeat; + background-image: url('../images/mute.png'); } } > a { - background: url('../images/volume.png') 10px center no-repeat; + background-image: url('../images/volume.png'); + background-position: 10px center; + background-repeat: no-repeat; + border-right: 1px solid #000; box-shadow: 1px 0 0 #555, inset 1px 0 0 #555; @include clearfix(); @@ -350,7 +384,7 @@ div.video { @include transition(none); width: 30px; - &:hover { + &:hover, &:active, &:focus { background-color: #444; color: #fff; text-decoration: none; @@ -362,7 +396,7 @@ div.video { border-right: 1px solid #000; box-shadow: 1px 0 0 #555, inset 1px 0 0 #555; color: #797979; - display: block; + display: none; float: left; line-height: 46px; //height of play pause buttons margin-left: 0; @@ -371,7 +405,7 @@ div.video { @include transition(none); width: 30px; - &:hover { + &:hover, &:focus { background-color: #444; color: #fff; text-decoration: none; @@ -387,8 +421,6 @@ div.video { a.hide-subtitles { background: url('../images/cc.png') center no-repeat; - color: #797979; - display: block; float: left; font-weight: 800; line-height: 46px; //height of play pause buttons @@ -401,7 +433,7 @@ div.video { -webkit-font-smoothing: antialiased; width: 30px; - &:hover { + &:hover, &:focus { background-color: #444; color: #fff; text-decoration: none; @@ -410,6 +442,8 @@ div.video { &.off { opacity: 0.7; } + + color: #797979; } } } @@ -420,15 +454,10 @@ div.video { } div.slider { - height: 14px; - margin-top: -7px; + @include transform(scaleY(1) translate3d(0, 0, 0)); a.ui-slider-handle { - border-radius: 20px; - height: 20px; - margin-left: -10px; - top: -4px; - width: 20px; + @include transform(scale(1) translate3d(-50%, -15%, 0)); } } } @@ -471,22 +500,47 @@ div.video { article.video-wrapper { width: flex-grid(9,9); + + background-color: inherit; + } + + article.video-wrapper section.video-controls.html5 { + bottom: 0px; + left: 0px; + right: 0px; + position: absolute; + z-index: 1; + } + + article.video-wrapper div.video-player-pre, article.video-wrapper div.video-player-post { + height: 0px; } ol.subtitles { - width: 0; - height: 0; + width: 0; + height: 0; + } + + ol.subtitles.html5 { + background-color: rgba(243, 243, 243, 0.8); + height: 100%; + position: absolute; + right: 0; + bottom: 0; + top: 0; + width: 275px; + padding: 0 20px; + z-index: 0; } } - &.fullscreen { + &.video-fullscreen { background: rgba(#000, .95); border: 0; bottom: 0; height: 100%; left: 0; margin: 0; - overflow: hidden; padding: 0; position: fixed; top: 0; @@ -501,12 +555,22 @@ div.video { } } + article.video-wrapper div.video-player-pre, article.video-wrapper div.video-player-post { + height: 0px; + } + + article.video-wrapper { + position: static; + } + div.tc-wrapper { @include clearfix; display: table; width: 100%; height: 100%; + position: static; + article.video-wrapper { width: 100%; display: table-cell; @@ -536,7 +600,7 @@ div.video { background: rgba(#000, .8); bottom: 0; height: 100%; - max-height: 100%; + max-height: 460px; max-width: flex-grid(3); padding: lh(); position: fixed; diff --git a/common/lib/xmodule/xmodule/css/videoalpha/common_tabs_edit.scss b/common/lib/xmodule/xmodule/css/videoalpha/common_tabs_edit.scss deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/common/lib/xmodule/xmodule/css/videoalpha/display.scss b/common/lib/xmodule/xmodule/css/videoalpha/display.scss deleted file mode 100644 index 93c387315a..0000000000 --- a/common/lib/xmodule/xmodule/css/videoalpha/display.scss +++ /dev/null @@ -1,620 +0,0 @@ -& { - margin-bottom: 30px; -} - -div.videoalpha { - @include clearfix(); - background: #f3f3f3; - display: block; - margin: 0 -12px; - padding: 12px; - border-radius: 5px; - - div.tc-wrapper { - position: relative; - @include clearfix; - } - - article.video-wrapper { - float: left; - margin-right: flex-gutter(9); - width: flex-grid(6, 9); - - background-color: black; - - position: relative; - - div.video-player-pre { - height: 50px; - background-color: black; - } - - div.video-player-post { - height: 50px; - background-color: black; - } - - section.video-player { - height: 0; - overflow: hidden; - padding-bottom: 56.25%; - position: relative; - - object, iframe { - border: none; - height: 100%; - left: 0; - position: absolute; - top: 0; - width: 100%; - } - } - - section.video-controls { - @include clearfix(); - background: #333; - border: 1px solid #000; - border-top: 0; - color: #ccc; - position: relative; - - &:hover { - ul, div { - opacity: 1.0; - } - } - - div.slider { - @include clearfix(); - background: #c2c2c2; - border: 1px solid #000; - border-radius: 0; - border-top: 1px solid #000; - box-shadow: inset 0 1px 0 #eee, 0 1px 0 #555; - position: absolute; - z-index: 1; - bottom: 100%; - left: 0; - right: 0; - height: 14px; - margin-left: -1px; - margin-right: -1px; - -webkit-transition: -webkit-transform 0.7s ease-in-out; - -moz-transition: -moz-transform 0.7s ease-in-out; - -ms-transition: -ms-transform 0.7s ease-in-out; - transition: transform 0.7s ease-in-out; - @include transform(scaleY(0.5) translate3d(0, 50%, 0)); - - div.ui-widget-header { - background: #777; - box-shadow: inset 0 1px 0 #999; - } - - a.ui-slider-handle { - background: $pink url(../images/slider-handle.png) center center no-repeat; - background-size: 50%; - border: 1px solid darken($pink, 20%); - border-radius: 50%; - box-shadow: inset 0 1px 0 lighten($pink, 10%); - cursor: pointer; - height: 20px; - margin-left: 0; - top: 0; - -webkit-transition: -webkit-transform 0.7s ease-in-out; - -moz-transition: -moz-transform 0.7s ease-in-out; - -ms-transition: -ms-transform 0.7s ease-in-out; - transition: transform 0.7s ease-in-out; - @include transform(scale(.7, 1.3) translate3d(-80%, -15%, 0)); - width: 20px; - - &:focus, &:hover { - background-color: lighten($pink, 10%); - outline: none; - } - } - } - - ul.vcr { - float: left; - list-style: none; - margin: 0 lh() 0 0; - padding: 0; - - li { - float: left; - margin-bottom: 0; - - a { - border-bottom: none; - border-right: 1px solid #000; - box-shadow: 1px 0 0 #555; - cursor: pointer; - display: block; - line-height: 46px; - padding: 0 lh(.75); - text-indent: -9999px; - width: 14px; - background: url('../images/vcr.png') 15px 15px no-repeat; - outline: 0; - - &:focus { - outline: 0; - } - - &:empty { - height: 46px; - background: url('../images/vcr.png') 15px 15px no-repeat; - } - - &.play { - background-position: 17px -114px; - - &:hover, &:focus { - background-color: #444; - } - } - - &.pause { - background-position: 16px -50px; - - &:hover, &:focus { - background-color: #444; - } - } - } - - div.vidtime { - padding-left: lh(.75); - font-weight: bold; - line-height: 46px; //height of play pause buttons - padding-left: lh(.75); - -webkit-font-smoothing: antialiased; - } - } - } - - div.secondary-controls { - float: right; - - div.speeds { - float: left; - position: relative; - - &.open { - &>a { - background: url('../images/open-arrow.png') 10px center no-repeat; - } - - ol.video_speeds { - display: block; - opacity: 1.0; - padding: 0; - margin: 0; - list-style: none; - } - } - - &>a { - background: url('../images/closed-arrow.png') 10px center no-repeat; - border-left: 1px solid #000; - border-right: 1px solid #000; - box-shadow: 1px 0 0 #555, inset 1px 0 0 #555; - @include clearfix(); - color: #fff; - cursor: pointer; - display: block; - line-height: 46px; //height of play pause buttons - margin-right: 0; - padding-left: 15px; - position: relative; - @include transition(none); - -webkit-font-smoothing: antialiased; - width: 116px; - outline: 0; - - &:focus { - outline: 0; - } - - h3 { - color: #999; - float: left; - font-size: em(14); - font-weight: normal; - letter-spacing: 1px; - padding: 0 lh(.25) 0 lh(.5); - line-height: 46px; - text-transform: uppercase; - } - - p.active { - float: left; - font-weight: bold; - margin-bottom: 0; - padding: 0 lh(.5) 0 0; - line-height: 46px; - color: #fff; - } - - &:hover, &:active, &:focus { - opacity: 1.0; - background-color: #444; - } - } - - // fix for now - ol.video_speeds { - box-shadow: inset 1px 0 0 #555, 0 4px 0 #444; - @include transition(none); - background-color: #444; - border: 1px solid #000; - bottom: 46px; - display: none; - opacity: 0.0; - position: absolute; - width: 131px; - z-index: 10; - - li { - box-shadow: 0 1px 0 #555; - border-bottom: 1px solid #000; - color: #fff; - cursor: pointer; - - a { - border: 0; - color: #fff; - display: block; - padding: lh(.5); - - &:hover { - background-color: #666; - color: #aaa; - } - } - - &.active { - font-weight: bold; - } - - &:last-child { - box-shadow: none; - border-bottom: 0; - margin-top: 0; - } - } - } - } - - div.volume { - float: left; - position: relative; - - &.open { - .volume-slider-container { - display: block; - opacity: 1.0; - } - } - - &.muted { - &>a { - background-image: url('../images/mute.png'); - } - } - - > a { - background-image: url('../images/volume.png'); - background-position: 10px center; - background-repeat: no-repeat; - - border-right: 1px solid #000; - box-shadow: 1px 0 0 #555, inset 1px 0 0 #555; - @include clearfix(); - color: #fff; - cursor: pointer; - display: block; - height: 46px; - margin-right: 0; - padding-left: 15px; - position: relative; - @include transition(none); - -webkit-font-smoothing: antialiased; - width: 30px; - - &:hover, &:active, &:focus { - background-color: #444; - } - } - - .volume-slider-container { - box-shadow: inset 1px 0 0 #555, 0 3px 0 #444; - @include transition(none); - background-color: #444; - border: 1px solid #000; - bottom: 46px; - display: none; - opacity: 0.0; - position: absolute; - width: 45px; - height: 125px; - margin-left: -1px; - z-index: 10; - - .volume-slider { - height: 100px; - border: 0; - width: 5px; - margin: 14px auto; - background: #666; - border: 1px solid #000; - box-shadow: 0 1px 0 #333; - - a.ui-slider-handle { - background: $pink url(../images/slider-handle.png) center center no-repeat; - background-size: 50%; - border: 1px solid darken($pink, 20%); - border-radius: 15px; - box-shadow: inset 0 1px 0 lighten($pink, 10%); - cursor: pointer; - height: 15px; - left: -6px; - @include transition(height 2.0s ease-in-out 0s, width 2.0s ease-in-out 0s); - width: 15px; - } - - .ui-slider-range { - background: #ddd; - } - } - } - } - - a.add-fullscreen { - background: url(../images/fullscreen.png) center no-repeat; - border-right: 1px solid #000; - box-shadow: 1px 0 0 #555, inset 1px 0 0 #555; - color: #797979; - display: block; - float: left; - line-height: 46px; //height of play pause buttons - margin-left: 0; - padding: 0 lh(.5); - text-indent: -9999px; - @include transition(none); - width: 30px; - - &:hover, &:active, &:focus { - background-color: #444; - color: #fff; - text-decoration: none; - } - } - - a.quality_control { - background: url(../images/hd.png) center no-repeat; - border-right: 1px solid #000; - box-shadow: 1px 0 0 #555, inset 1px 0 0 #555; - color: #797979; - display: none; - float: left; - line-height: 46px; //height of play pause buttons - margin-left: 0; - padding: 0 lh(.5); - text-indent: -9999px; - @include transition(none); - width: 30px; - - &:hover, &:focus { - background-color: #444; - color: #fff; - text-decoration: none; - } - - &.active { - background-color: #F44; - color: #0ff; - text-decoration: none; - } - } - - - a.hide-subtitles { - background: url('../images/cc.png') center no-repeat; - float: left; - font-weight: 800; - line-height: 46px; //height of play pause buttons - margin-left: 0; - opacity: 1.0; - padding: 0 lh(.5); - position: relative; - text-indent: -9999px; - @include transition(none); - -webkit-font-smoothing: antialiased; - width: 30px; - - &:hover, &:focus { - background-color: #444; - color: #fff; - text-decoration: none; - } - - &.off { - opacity: 0.7; - } - - color: #797979; - } - } - } - - &:hover section.video-controls { - ul, div { - opacity: 1.0; - } - - div.slider { - @include transform(scaleY(1) translate3d(0, 0, 0)); - - a.ui-slider-handle { - @include transform(scale(1) translate3d(-50%, -15%, 0)); - } - } - } - } - - ol.subtitles { - padding-left: 0; - float: left; - max-height: 460px; - overflow: auto; - width: flex-grid(3, 9); - margin: 0; - font-size: 14px; - list-style: none; - - li { - border: 0; - color: #666; - cursor: pointer; - margin-bottom: 8px; - padding: 0; - line-height: lh(); - - &.current { - color: #333; - font-weight: 700; - } - - &:hover { - color: $blue; - } - - &:empty { - margin-bottom: 0px; - } - } - } - - &.closed { - - article.video-wrapper { - width: flex-grid(9,9); - - background-color: inherit; - } - - article.video-wrapper section.video-controls.html5 { - bottom: 0px; - left: 0px; - right: 0px; - position: absolute; - z-index: 1; - } - - article.video-wrapper div.video-player-pre, article.video-wrapper div.video-player-post { - height: 0px; - } - - ol.subtitles { - width: 0; - height: 0; - } - - ol.subtitles.html5 { - background-color: rgba(243, 243, 243, 0.8); - height: 100%; - position: absolute; - right: 0; - bottom: 0; - top: 0; - width: 275px; - padding: 0 20px; - z-index: 0; - } - } - - &.video-fullscreen { - background: rgba(#000, .95); - border: 0; - bottom: 0; - height: 100%; - left: 0; - margin: 0; - padding: 0; - position: fixed; - top: 0; - width: 100%; - z-index: 999; - vertical-align: middle; - - &.closed { - ol.subtitles { - right: -(flex-grid(4)); - width: auto; - } - } - - article.video-wrapper div.video-player-pre, article.video-wrapper div.video-player-post { - height: 0px; - } - - article.video-wrapper { - position: static; - } - - div.tc-wrapper { - @include clearfix; - display: table; - width: 100%; - height: 100%; - - position: static; - - article.video-wrapper { - width: 100%; - display: table-cell; - vertical-align: middle; - float: none; - } - - object, iframe { - bottom: 0; - height: 100%; - left: 0; - overflow: hidden; - position: fixed; - top: 0; - } - - section.video-controls { - bottom: 0; - left: 0; - position: absolute; - width: 100%; - z-index: 9999; - } - } - - ol.subtitles { - background: rgba(#000, .8); - bottom: 0; - height: 100%; - max-height: 460px; - max-width: flex-grid(3); - padding: lh(); - position: fixed; - right: 0; - top: 0; - @include transition(none); - - li { - color: #aaa; - - &.current { - color: #fff; - } - } - } - } -} diff --git a/common/lib/xmodule/xmodule/js/fixtures/video.html b/common/lib/xmodule/xmodule/js/fixtures/video.html index 3273dd3aa7..341e18ae9d 100644 --- a/common/lib/xmodule/xmodule/js/fixtures/video.html +++ b/common/lib/xmodule/xmodule/js/fixtures/video.html @@ -1,20 +1,53 @@
-
+ data-caption-asset-path="/static/subs/" + data-autoplay="False" + >
+ +
diff --git a/common/lib/xmodule/xmodule/js/fixtures/videoalpha_all.html b/common/lib/xmodule/xmodule/js/fixtures/video_all.html similarity index 98% rename from common/lib/xmodule/xmodule/js/fixtures/videoalpha_all.html rename to common/lib/xmodule/xmodule/js/fixtures/video_all.html index a98e2bf0a2..25a3c2c0ab 100644 --- a/common/lib/xmodule/xmodule/js/fixtures/videoalpha_all.html +++ b/common/lib/xmodule/xmodule/js/fixtures/video_all.html @@ -3,7 +3,7 @@
-
-
-
-
- - -
-
-
-
-
-
\ 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 """ - #
  1. 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 "
  1. Caption will be displayed when you start playing the video.
  2. " - else - @renderCaption() - - renderCaption: -> - container = $('
      ') - - $.each @captions, (index, text) => - container.append $('
    1. ').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
    2. for cosmetic reason - @$('.subtitles').prepend($('
    3. ').height(@topSpacingHeight())) - .append($('
    4. ').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 """ -
      -
      -
        -
      • -
      • -
        0:00 / 0:00
        -
      • -
      - -
      - """#" - - 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($('
    5. ').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': ' ''' - 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 = '