diff --git a/cms/djangoapps/contentstore/views/assets.py b/cms/djangoapps/contentstore/views/assets.py index ede6939398..74cb94a354 100644 --- a/cms/djangoapps/contentstore/views/assets.py +++ b/cms/djangoapps/contentstore/views/assets.py @@ -359,6 +359,8 @@ def generate_export_course(request, org, course, name): try: export_to_xml(modulestore('direct'), contentstore(), loc, root_dir, name, modulestore()) except SerializationError, e: + logging.exception('There was an error exporting course {0}. {1}'.format(course_module.location, unicode(e))) + unit = None failed_item = None parent = None @@ -391,6 +393,7 @@ def generate_export_course(request, org, course, name): }) }) except Exception, e: + logging.exception('There was an error exporting course {0}. {1}'.format(course_module.location, unicode(e))) return render_to_response('export.html', { 'context_course': course_module, 'successful_import_redirect_url': '', diff --git a/common/lib/xmodule/xmodule/js/src/video/09_video_caption.js b/common/lib/xmodule/xmodule/js/src/video/09_video_caption.js index e8a30f6e9c..a34f33ba4c 100644 --- a/common/lib/xmodule/xmodule/js/src/video/09_video_caption.js +++ b/common/lib/xmodule/xmodule/js/src/video/09_video_caption.js @@ -312,15 +312,34 @@ function () { var newIndex; if (this.videoCaption.loaded) { - time = Math.round(Time.convert(time, this.speed, '1.0') * 1000 + 250); + // Current mode === 'flash' can only be for YouTube videos. So, we + // don't have to also check for videoType === 'youtube'. + if (this.currentPlayerMode === 'flash') { + // Total play time changes with speed change. Also there is + // a 250 ms delay we have to take into account. + time = Math.round( + Time.convert(time, this.speed, '1.0') * 1000 + 250 + ); + } else { + // Total play time remains constant when speed changes. + time = Math.round(parseInt(time, 10) * 1000); + } + newIndex = this.videoCaption.search(time); - if (newIndex !== void 0 && this.videoCaption.currentIndex !== newIndex) { + if ( + newIndex !== void 0 && + this.videoCaption.currentIndex !== newIndex + ) { if (this.videoCaption.currentIndex) { - this.videoCaption.subtitlesEl.find('li.current').removeClass('current'); + this.videoCaption.subtitlesEl + .find('li.current') + .removeClass('current'); } - this.videoCaption.subtitlesEl.find("li[data-index='" + newIndex + "']").addClass('current'); + this.videoCaption.subtitlesEl + .find("li[data-index='" + newIndex + "']") + .addClass('current'); this.videoCaption.currentIndex = newIndex; @@ -333,9 +352,29 @@ function () { var time; event.preventDefault(); - time = Math.round(Time.convert($(event.target).data('start'), '1.0', this.speed) / 1000); - this.trigger('videoPlayer.onCaptionSeek', {'type': 'onCaptionSeek', 'time': time}); + // Current mode === 'flash' can only be for YouTube videos. So, we + // don't have to also check for videoType === 'youtube'. + if (this.currentPlayerMode === 'flash') { + // Total play time changes with speed change. Also there is + // a 250 ms delay we have to take into account. + time = Math.round( + Time.convert( + $(event.target).data('start'), '1.0', this.speed + ) / 1000 + ); + } else { + // Total play time remains constant when speed changes. + time = parseInt($(event.target).data('start'), 10)/1000; + } + + this.trigger( + 'videoPlayer.onCaptionSeek', + { + 'type': 'onCaptionSeek', + 'time': time + } + ); } function calculateOffset(element) { diff --git a/common/lib/xmodule/xmodule/tests/test_video.py b/common/lib/xmodule/xmodule/tests/test_video.py index 1ea4b4e187..a6a7d86510 100644 --- a/common/lib/xmodule/xmodule/tests/test_video.py +++ b/common/lib/xmodule/xmodule/tests/test_video.py @@ -15,6 +15,7 @@ the course, section, subsection, unit, etc. import unittest from . import LogicTest +from lxml import etree from .import get_test_system from xmodule.modulestore import Location from xmodule.video_module import VideoDescriptor, _create_youtube_string @@ -289,6 +290,62 @@ class VideoDescriptorImportTestCase(unittest.TestCase): 'data': '' }) + def test_from_xml_double_quotes(self): + """ + Make sure we can handle the double-quoted string format (which was used for exporting for + a few weeks). + """ + module_system = DummySystem(load_error_modules=True) + xml_data =''' +