diff --git a/cms/djangoapps/contentstore/views.py b/cms/djangoapps/contentstore/views.py index a79aa0e18f..aa6f6ce235 100644 --- a/cms/djangoapps/contentstore/views.py +++ b/cms/djangoapps/contentstore/views.py @@ -98,7 +98,7 @@ def edit_item(request): item = modulestore().get_item(item_location) return render_to_response('unit.html', { 'contents': item.get_html(), - 'js_module': item.js_module_name(), + 'js_module': item.__class__.__name__, 'category': item.category, 'name': item.name, 'previews': get_module_previews(item), diff --git a/cms/envs/common.py b/cms/envs/common.py index 7b1f6e3fcd..c11ca297b6 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -177,6 +177,8 @@ PIPELINE_CSS = { PIPELINE_ALWAYS_RECOMPILE = ['sass/base-style.scss'] +# Load javascript from all of the available descriptors, and +# prep it for use in pipeline js from xmodule.x_module import XModuleDescriptor from xmodule.raw_module import RawDescriptor js_file_dir = PROJECT_ROOT / "static" / "coffee" / "module" diff --git a/common/lib/xmodule/xmodule/capa_module.py b/common/lib/xmodule/xmodule/capa_module.py index 50eb495c5e..006978861b 100644 --- a/common/lib/xmodule/xmodule/capa_module.py +++ b/common/lib/xmodule/xmodule/capa_module.py @@ -8,6 +8,7 @@ import re from datetime import timedelta from lxml import etree +from pkg_resources import resource_string from xmodule.x_module import XModule from xmodule.raw_module import RawDescriptor @@ -70,6 +71,8 @@ class CapaModule(XModule): ''' icon_class = 'problem' + js = {'coffee': [resource_string(__name__, 'js/src/capa/display.coffee')]} + def __init__(self, system, location, definition, instance_state=None, shared_state=None, **kwargs): XModule.__init__(self, system, location, definition, instance_state, shared_state, **kwargs) diff --git a/common/lib/xmodule/xmodule/js/fixtures/items.json b/common/lib/xmodule/xmodule/js/fixtures/items.json new file mode 100644 index 0000000000..cbd71a61c7 --- /dev/null +++ b/common/lib/xmodule/xmodule/js/fixtures/items.json @@ -0,0 +1,15 @@ +[ + { + "content": "Video 1", + "type": "video", + "title": "Video 1" + }, { + "content": "Video 2", + "type": "video", + "title": "Video 2" + }, { + "content": "Sample Problem", + "type": "problem", + "title": "Sample Problem" + } +] diff --git a/lms/static/coffee/fixtures/problem.html b/common/lib/xmodule/xmodule/js/fixtures/problem.html similarity index 100% rename from lms/static/coffee/fixtures/problem.html rename to common/lib/xmodule/xmodule/js/fixtures/problem.html diff --git a/lms/static/coffee/fixtures/problem_content.html b/common/lib/xmodule/xmodule/js/fixtures/problem_content.html similarity index 100% rename from lms/static/coffee/fixtures/problem_content.html rename to common/lib/xmodule/xmodule/js/fixtures/problem_content.html diff --git a/lms/static/coffee/fixtures/sequence.html b/common/lib/xmodule/xmodule/js/fixtures/sequence.html similarity index 100% rename from lms/static/coffee/fixtures/sequence.html rename to common/lib/xmodule/xmodule/js/fixtures/sequence.html diff --git a/lms/static/coffee/fixtures/video.html b/common/lib/xmodule/xmodule/js/fixtures/video.html similarity index 100% rename from lms/static/coffee/fixtures/video.html rename to common/lib/xmodule/xmodule/js/fixtures/video.html diff --git a/common/lib/xmodule/xmodule/js/module/raw.coffee b/common/lib/xmodule/xmodule/js/module/raw.coffee deleted file mode 100644 index 632818f99f..0000000000 --- a/common/lib/xmodule/xmodule/js/module/raw.coffee +++ /dev/null @@ -1,5 +0,0 @@ -class @Raw - constructor: (@element) -> - @edit_box = $(".edit-box", @element) - - save: -> @edit_box.val() diff --git a/lms/static/coffee/spec/modules/problem_spec.coffee b/common/lib/xmodule/xmodule/js/spec/capa/display_spec.coffee similarity index 100% rename from lms/static/coffee/spec/modules/problem_spec.coffee rename to common/lib/xmodule/xmodule/js/spec/capa/display_spec.coffee diff --git a/lms/static/coffee/spec/modules/sequence_spec.coffee b/common/lib/xmodule/xmodule/js/spec/sequence/display_spec.coffee similarity index 100% rename from lms/static/coffee/spec/modules/sequence_spec.coffee rename to common/lib/xmodule/xmodule/js/spec/sequence/display_spec.coffee diff --git a/lms/static/coffee/spec/modules/video/video_caption_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display/video_caption_spec.coffee similarity index 100% rename from lms/static/coffee/spec/modules/video/video_caption_spec.coffee rename to common/lib/xmodule/xmodule/js/spec/video/display/video_caption_spec.coffee diff --git a/lms/static/coffee/spec/modules/video/video_control_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display/video_control_spec.coffee similarity index 100% rename from lms/static/coffee/spec/modules/video/video_control_spec.coffee rename to common/lib/xmodule/xmodule/js/spec/video/display/video_control_spec.coffee diff --git a/lms/static/coffee/spec/modules/video/video_player_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display/video_player_spec.coffee similarity index 100% rename from lms/static/coffee/spec/modules/video/video_player_spec.coffee rename to common/lib/xmodule/xmodule/js/spec/video/display/video_player_spec.coffee diff --git a/lms/static/coffee/spec/modules/video/video_progress_slider_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display/video_progress_slider_spec.coffee similarity index 100% rename from lms/static/coffee/spec/modules/video/video_progress_slider_spec.coffee rename to common/lib/xmodule/xmodule/js/spec/video/display/video_progress_slider_spec.coffee diff --git a/lms/static/coffee/spec/modules/video/video_speed_control_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display/video_speed_control_spec.coffee similarity index 100% rename from lms/static/coffee/spec/modules/video/video_speed_control_spec.coffee rename to common/lib/xmodule/xmodule/js/spec/video/display/video_speed_control_spec.coffee diff --git a/lms/static/coffee/spec/modules/video/video_volume_control_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display/video_volume_control_spec.coffee similarity index 100% rename from lms/static/coffee/spec/modules/video/video_volume_control_spec.coffee rename to common/lib/xmodule/xmodule/js/spec/video/display/video_volume_control_spec.coffee diff --git a/lms/static/coffee/spec/modules/video_spec.coffee b/common/lib/xmodule/xmodule/js/spec/video/display_spec.coffee similarity index 100% rename from lms/static/coffee/spec/modules/video_spec.coffee rename to common/lib/xmodule/xmodule/js/spec/video/display_spec.coffee diff --git a/lms/static/coffee/src/modules/problem.coffee b/common/lib/xmodule/xmodule/js/src/capa/display.coffee similarity index 100% rename from lms/static/coffee/src/modules/problem.coffee rename to common/lib/xmodule/xmodule/js/src/capa/display.coffee diff --git a/common/lib/xmodule/xmodule/js/module/html.coffee b/common/lib/xmodule/xmodule/js/src/raw/edit.coffee similarity index 83% rename from common/lib/xmodule/xmodule/js/module/html.coffee rename to common/lib/xmodule/xmodule/js/src/raw/edit.coffee index 2c743cb7a1..da40effcb3 100644 --- a/common/lib/xmodule/xmodule/js/module/html.coffee +++ b/common/lib/xmodule/xmodule/js/src/raw/edit.coffee @@ -1,4 +1,4 @@ -class @HTML +class @RawDescriptor constructor: (@element) -> @edit_box = $(".edit-box", @element) diff --git a/lms/static/coffee/src/modules/sequence.coffee b/common/lib/xmodule/xmodule/js/src/sequence/display.coffee similarity index 100% rename from lms/static/coffee/src/modules/sequence.coffee rename to common/lib/xmodule/xmodule/js/src/sequence/display.coffee diff --git a/lms/static/coffee/src/modules/video.coffee b/common/lib/xmodule/xmodule/js/src/video/display.coffee similarity index 96% rename from lms/static/coffee/src/modules/video.coffee rename to common/lib/xmodule/xmodule/js/src/video/display.coffee index 7062d2d7ce..373a79939d 100644 --- a/lms/static/coffee/src/modules/video.coffee +++ b/common/lib/xmodule/xmodule/js/src/video/display.coffee @@ -1,5 +1,5 @@ class @Video - constructor: (@id, videos) -> + constructor: (@id, videos, @caption_url_base) -> window.player = null @el = $("#video_#{@id}") @parseVideos videos diff --git a/lms/static/coffee/src/modules/video/video_caption.coffee b/common/lib/xmodule/xmodule/js/src/video/display/video_caption.coffee similarity index 98% rename from lms/static/coffee/src/modules/video/video_caption.coffee rename to common/lib/xmodule/xmodule/js/src/video/display/video_caption.coffee index e310eb4223..734c2643a6 100644 --- a/lms/static/coffee/src/modules/video/video_caption.coffee +++ b/common/lib/xmodule/xmodule/js/src/video/display/video_caption.coffee @@ -7,7 +7,7 @@ class @VideoCaption extends Subview .bind('DOMMouseScroll', @onMovement) captionURL: -> - "/static/subs/#{@youtubeId}.srt.sjson" + "#{@captionURLBase}/#{@youtubeId}.srt.sjson" render: -> @$('.video-wrapper').after """ diff --git a/lms/static/coffee/src/modules/video/video_control.coffee b/common/lib/xmodule/xmodule/js/src/video/display/video_control.coffee similarity index 100% rename from lms/static/coffee/src/modules/video/video_control.coffee rename to common/lib/xmodule/xmodule/js/src/video/display/video_control.coffee diff --git a/lms/static/coffee/src/modules/video/video_player.coffee b/common/lib/xmodule/xmodule/js/src/video/display/video_player.coffee similarity index 98% rename from lms/static/coffee/src/modules/video/video_player.coffee rename to common/lib/xmodule/xmodule/js/src/video/display/video_player.coffee index 03c2c8f4df..f840a24d90 100644 --- a/lms/static/coffee/src/modules/video/video_player.coffee +++ b/common/lib/xmodule/xmodule/js/src/video/display/video_player.coffee @@ -25,7 +25,7 @@ class @VideoPlayer extends Subview render: -> @control = new VideoControl el: @$('.video-controls') - @caption = new VideoCaption el: @el, youtubeId: @video.youtubeId('1.0'), currentSpeed: @currentSpeed() + @caption = new VideoCaption el: @el, youtubeId: @video.youtubeId('1.0'), currentSpeed: @currentSpeed(), captionURLBase: @video.caption_url_base unless onTouchBasedDevice() @volumeControl = new VideoVolumeControl el: @$('.secondary-controls') @speedControl = new VideoSpeedControl el: @$('.secondary-controls'), speeds: @video.speeds, currentSpeed: @currentSpeed() diff --git a/lms/static/coffee/src/modules/video/video_progress_slider.coffee b/common/lib/xmodule/xmodule/js/src/video/display/video_progress_slider.coffee similarity index 100% rename from lms/static/coffee/src/modules/video/video_progress_slider.coffee rename to common/lib/xmodule/xmodule/js/src/video/display/video_progress_slider.coffee diff --git a/lms/static/coffee/src/modules/video/video_speed_control.coffee b/common/lib/xmodule/xmodule/js/src/video/display/video_speed_control.coffee similarity index 100% rename from lms/static/coffee/src/modules/video/video_speed_control.coffee rename to common/lib/xmodule/xmodule/js/src/video/display/video_speed_control.coffee diff --git a/lms/static/coffee/src/modules/video/video_volume_control.coffee b/common/lib/xmodule/xmodule/js/src/video/display/video_volume_control.coffee similarity index 100% rename from lms/static/coffee/src/modules/video/video_volume_control.coffee rename to common/lib/xmodule/xmodule/js/src/video/display/video_volume_control.coffee diff --git a/common/lib/xmodule/xmodule/raw_module.py b/common/lib/xmodule/xmodule/raw_module.py index 7cead5990c..8cc6b3bb5f 100644 --- a/common/lib/xmodule/xmodule/raw_module.py +++ b/common/lib/xmodule/xmodule/raw_module.py @@ -12,8 +12,7 @@ class RawDescriptor(MakoModuleDescriptor, XmlDescriptor): """ mako_template = "widgets/raw-edit.html" - js = {'coffee': [resource_string(__name__, 'js/module/raw.coffee')]} - js_module = 'Raw' + js = {'coffee': [resource_string(__name__, 'js/src/raw/edit.coffee')]} def get_context(self): return { diff --git a/common/lib/xmodule/xmodule/seq_module.py b/common/lib/xmodule/xmodule/seq_module.py index bb26e83d7b..4a142a83cc 100644 --- a/common/lib/xmodule/xmodule/seq_module.py +++ b/common/lib/xmodule/xmodule/seq_module.py @@ -8,6 +8,7 @@ from xmodule.xml_module import XmlDescriptor from xmodule.x_module import XModule from xmodule.progress import Progress from xmodule.exceptions import NotFoundError +from pkg_resources import resource_string log = logging.getLogger("mitx.common.lib.seq_module") @@ -19,6 +20,7 @@ class_priority = ['video', 'problem'] class SequenceModule(XModule): ''' Layout module which lays out content in a temporal sequence ''' + js = {'coffee': [resource_string(__name__, 'js/src/sequence/display.coffee')]} def __init__(self, system, location, definition, instance_state=None, shared_state=None, **kwargs): XModule.__init__(self, system, location, definition, instance_state, shared_state, **kwargs) diff --git a/common/lib/xmodule/xmodule/video_module.py b/common/lib/xmodule/xmodule/video_module.py index 5403230a7b..36aab199a0 100644 --- a/common/lib/xmodule/xmodule/video_module.py +++ b/common/lib/xmodule/xmodule/video_module.py @@ -2,6 +2,7 @@ import json import logging from lxml import etree +from pkg_resources import resource_string, resource_listdir from xmodule.x_module import XModule from xmodule.raw_module import RawDescriptor @@ -13,6 +14,13 @@ class VideoModule(XModule): video_time = 0 icon_class = 'video' + js = {'coffee': + [resource_string(__name__, 'js/src/video/display.coffee')] + + [resource_string(__name__, 'js/src/video/display/' + filename) + for filename + in resource_listdir(__name__, 'js/src/video/display') + ]} + def __init__(self, system, location, definition, instance_state=None, shared_state=None, **kwargs): XModule.__init__(self, system, location, definition, instance_state, shared_state, **kwargs) xmltree = etree.fromstring(self.definition['data']) diff --git a/common/lib/xmodule/xmodule/x_module.py b/common/lib/xmodule/xmodule/x_module.py index ecdbb4e532..12872f64f1 100644 --- a/common/lib/xmodule/xmodule/x_module.py +++ b/common/lib/xmodule/xmodule/x_module.py @@ -77,6 +77,8 @@ class XModule(object): # if the icon class depends on the data in the module icon_class = 'other' + js = {} + def __init__(self, system, location, definition, instance_state=None, shared_state=None, **kwargs): ''' Construct a new xmodule @@ -179,11 +181,6 @@ class XModule(object): ''' return None - def get_html(self): - ''' HTML, as shown in the browser. This is the only method that must be implemented - ''' - raise NotImplementedError("get_html must be defined for all XModules that appear on the screen. Not defined in %s" % self.__class__.__name__) - def get_progress(self): ''' Return a progress.Progress object that represents how far the student has gone in this module. Must be implemented to get correct progress tracking behavior in @@ -198,6 +195,25 @@ class XModule(object): get is a dictionary-like object ''' return "" + # ================================== HTML INTERFACE DEFINITIONS ====================== + @classmethod + def get_javascript(cls): + """ + Return a dictionary containing some of the following keys: + coffee: A list of coffeescript fragments that should be compiled and + placed on the page + js: A list of javascript fragments that should be included on the page + + All of these will be loaded onto the page in the LMS + """ + return cls.js + + def get_html(self): + ''' HTML, as shown in the browser. This is the only method that must be implemented + ''' + raise NotImplementedError("get_html must be defined for all XModules that appear on the screen. Not defined in %s" % self.__class__.__name__) + + class XModuleDescriptor(Plugin): """ @@ -211,7 +227,6 @@ class XModuleDescriptor(Plugin): """ entry_point = "xmodule.v1" js = {} - js_module = None # A list of metadata that this module can inherit from its parent module inheritable_metadata = ( @@ -398,13 +413,6 @@ class XModuleDescriptor(Plugin): """ return cls.js - def js_module_name(self): - """ - Return the name of the javascript class to instantiate when - this module descriptor is loaded for editing - """ - return self.js_module - def get_html(self): """ Return the html used to edit this module diff --git a/lms/envs/common.py b/lms/envs/common.py index 22e5fcf993..37ec0de15b 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -22,6 +22,7 @@ import sys import os import tempfile import glob2 +import errno import djcelery from path import path @@ -327,6 +328,37 @@ main_vendor_js = [ 'js/vendor/jquery.qtip.min.js', ] +# Load javascript from all of the available xmodules, and +# prep it for use in pipeline js +from xmodule.x_module import XModuleDescriptor +from xmodule.hidden_module import HiddenDescriptor +js_file_dir = PROJECT_ROOT / "static" / "coffee" / "module" +try: + os.makedirs(js_file_dir) +except OSError as exc: + if exc.errno == errno.EEXIST: + pass + else: + raise + +module_js_sources = [] +for descriptor in XModuleDescriptor.load_classes() + [HiddenDescriptor]: + module = getattr(descriptor, 'module_class', None) + if module is None: + continue + + js = module.get_javascript() + for filetype in ('coffee', 'js'): + for idx, fragment in enumerate(js.get(filetype, [])): + path = os.path.join(js_file_dir, "{name}.{idx}.{type}".format( + name=module.__name__, + idx=idx, + type=filetype)) + with open(path, 'w') as js_file: + js_file.write(fragment) + module_js_sources.append(path.replace(PROJECT_ROOT / "static/", "")) + + PIPELINE_JS = { 'application': { # Application will contain all paths not in courseware_only_js @@ -350,6 +382,10 @@ PIPELINE_JS = { 'source_filenames': main_vendor_js, 'output_filename': 'js/main_vendor.js', }, + 'module-js': { + 'source_filenames': module_js_sources, + 'output_filename': 'js/modules.js', + }, 'spec': { 'source_filenames': [pth.replace(PROJECT_ROOT / 'static/', '') for pth in glob2.glob(PROJECT_ROOT / 'static/coffee/spec/**/*.coffee')], 'output_filename': 'js/spec.js' diff --git a/lms/static/coffee/.gitignore b/lms/static/coffee/.gitignore index a6c7c2852d..bb90193362 100644 --- a/lms/static/coffee/.gitignore +++ b/lms/static/coffee/.gitignore @@ -1 +1,2 @@ *.js +module diff --git a/lms/static/coffee/src/courseware.coffee b/lms/static/coffee/src/courseware.coffee index 39c4dec2fe..675df8cc36 100644 --- a/lms/static/coffee/src/courseware.coffee +++ b/lms/static/coffee/src/courseware.coffee @@ -18,7 +18,7 @@ class @Courseware render: -> $('.course-content .video').each -> id = $(this).attr('id').replace(/video_/, '') - new Video id, $(this).data('streams') + new Video id, $(this).data('streams'), $(this).data('caption-url-base') $('.course-content .problems-wrapper').each -> id = $(this).data('problem-id') new Problem id, $(this).attr('id'), $(this).data('url') diff --git a/lms/static/js/vendor/jquery.scrollTo-1.4.2-min.js b/lms/static/js/vendor/jquery.scrollTo-1.4.2-min.js new file mode 100644 index 0000000000..73a334184e --- /dev/null +++ b/lms/static/js/vendor/jquery.scrollTo-1.4.2-min.js @@ -0,0 +1,11 @@ +/** + * jQuery.ScrollTo - Easy element scrolling using jQuery. + * Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com + * Dual licensed under MIT and GPL. + * Date: 5/25/2009 + * @author Ariel Flesler + * @version 1.4.2 + * + * http://flesler.blogspot.com/2007/10/jqueryscrollto.html + */ +;(function(d){var k=d.scrollTo=function(a,i,e){d(window).scrollTo(a,i,e)};k.defaults={axis:'xy',duration:parseFloat(d.fn.jquery)>=1.3?0:1};k.window=function(a){return d(window)._scrollable()};d.fn._scrollable=function(){return this.map(function(){var a=this,i=!a.nodeName||d.inArray(a.nodeName.toLowerCase(),['iframe','#document','html','body'])!=-1;if(!i)return a;var e=(a.contentWindow||a).document||a.ownerDocument||a;return d.browser.safari||e.compatMode=='BackCompat'?e.body:e.documentElement})};d.fn.scrollTo=function(n,j,b){if(typeof j=='object'){b=j;j=0}if(typeof b=='function')b={onAfter:b};if(n=='max')n=9e9;b=d.extend({},k.defaults,b);j=j||b.speed||b.duration;b.queue=b.queue&&b.axis.length>1;if(b.queue)j/=2;b.offset=p(b.offset);b.over=p(b.over);return this._scrollable().each(function(){var q=this,r=d(q),f=n,s,g={},u=r.is('html,body');switch(typeof f){case'number':case'string':if(/^([+-]=)?\d+(\.\d+)?(px|%)?$/.test(f)){f=p(f);break}f=d(f,this);case'object':if(f.is||f.style)s=(f=d(f)).offset()}d.each(b.axis.split(''),function(a,i){var e=i=='x'?'Left':'Top',h=e.toLowerCase(),c='scroll'+e,l=q[c],m=k.max(q,i);if(s){g[c]=s[h]+(u?0:l-r.offset()[h]);if(b.margin){g[c]-=parseInt(f.css('margin'+e))||0;g[c]-=parseInt(f.css('border'+e+'Width'))||0}g[c]+=b.offset[h]||0;if(b.over[h])g[c]+=f[i=='x'?'width':'height']()*b.over[h]}else{var o=f[h];g[c]=o.slice&&o.slice(-1)=='%'?parseFloat(o)/100*m:o}if(/^\d+$/.test(g[c]))g[c]=g[c]<=0?0:Math.min(g[c],m);if(!a&&b.queue){if(l!=g[c])t(b.onAfterFirst);delete g[c]}});t(b.onAfter);function t(a){r.animate(g,j,b.easing,a&&function(){a.call(this,n,b)})}}).end()};k.max=function(a,i){var e=i=='x'?'Width':'Height',h='scroll'+e;if(!d(a).is('html,body'))return a[h]-d(a)[e.toLowerCase()]();var c='client'+e,l=a.ownerDocument.documentElement,m=a.ownerDocument.body;return Math.max(l[h],m[h])-Math.min(l[c],m[c])};function p(a){return typeof a=='object'?a:{top:a,left:a}}})(jQuery); \ No newline at end of file diff --git a/lms/templates/jasmine/base.html b/lms/templates/jasmine/base.html index e0d2522b9b..199af334f9 100644 --- a/lms/templates/jasmine/base.html +++ b/lms/templates/jasmine/base.html @@ -20,6 +20,7 @@ {% load compressed %} {# static files #} {% compressed_js 'application' %} + {% compressed_js 'module-js' %} {# spec files #} {% compressed_js 'spec' %} diff --git a/lms/templates/main.html b/lms/templates/main.html index 9085447169..9af7121cf1 100644 --- a/lms/templates/main.html +++ b/lms/templates/main.html @@ -30,6 +30,7 @@ <%include file="footer.html" /> <%static:js group='application'/> + <%static:js group='module-js'/> <%block name="js_extra"/> diff --git a/lms/templates/video.html b/lms/templates/video.html index 9f38d386a4..df98805152 100644 --- a/lms/templates/video.html +++ b/lms/templates/video.html @@ -2,7 +2,7 @@

${name}

% endif -
+
diff --git a/static/coffee/src/courseware.js b/static/coffee/src/courseware.js index 934a66c493..fe830f5154 100755 --- a/static/coffee/src/courseware.js +++ b/static/coffee/src/courseware.js @@ -27,7 +27,7 @@ $('.course-content .video').each(function() { var id; id = $(this).attr('id').replace(/video_/, ''); - return new Video(id, $(this).data('streams')); + return new Video(id, $(this).data('streams'), $(this).data('caption-url')); }); $('.course-content .problems-wrapper').each(function() { var id;