Commit c8a33672 by Christina Roberts Committed by GitHub

Merge pull request #13705 from edx/christina/javascript_loader

Christina/javascript loader
parents 21eb03e1 bee04095
...@@ -50,7 +50,6 @@ common/lib/xmodule/xmodule/js/src/conditional/display.js ...@@ -50,7 +50,6 @@ common/lib/xmodule/xmodule/js/src/conditional/display.js
common/lib/xmodule/xmodule/js/src/discussion/display.js common/lib/xmodule/xmodule/js/src/discussion/display.js
common/lib/xmodule/xmodule/js/src/html/display.js common/lib/xmodule/xmodule/js/src/html/display.js
common/lib/xmodule/xmodule/js/src/html/edit.js common/lib/xmodule/xmodule/js/src/html/edit.js
common/lib/xmodule/xmodule/js/src/javascript_loader.js
common/lib/xmodule/xmodule/js/src/problem/edit.js common/lib/xmodule/xmodule/js/src/problem/edit.js
common/lib/xmodule/xmodule/js/src/raw/edit/json.js common/lib/xmodule/xmodule/js/src/raw/edit/json.js
common/lib/xmodule/xmodule/js/src/raw/edit/metadata-only.js common/lib/xmodule/xmodule/js/src/raw/edit/metadata-only.js
......
...@@ -48,11 +48,11 @@ class AnnotatableFields(object): ...@@ -48,11 +48,11 @@ class AnnotatableFields(object):
class AnnotatableModule(AnnotatableFields, XModule): class AnnotatableModule(AnnotatableFields, XModule):
js = { js = {
'coffee': [ 'coffee': [
resource_string(__name__, 'js/src/javascript_loader.coffee'),
resource_string(__name__, 'js/src/html/display.coffee'), resource_string(__name__, 'js/src/html/display.coffee'),
resource_string(__name__, 'js/src/annotatable/display.coffee'), resource_string(__name__, 'js/src/annotatable/display.coffee'),
], ],
'js': [ 'js': [
resource_string(__name__, 'js/src/javascript_loader.js'),
resource_string(__name__, 'js/src/collapsible.js'), resource_string(__name__, 'js/src/collapsible.js'),
] ]
} }
......
...@@ -31,9 +31,9 @@ class CapaModule(CapaMixin, XModule): ...@@ -31,9 +31,9 @@ class CapaModule(CapaMixin, XModule):
js = { js = {
'coffee': [ 'coffee': [
resource_string(__name__, 'js/src/capa/display.coffee'), resource_string(__name__, 'js/src/capa/display.coffee'),
resource_string(__name__, 'js/src/javascript_loader.coffee'),
], ],
'js': [ 'js': [
resource_string(__name__, 'js/src/javascript_loader.js'),
resource_string(__name__, 'js/src/collapsible.js'), resource_string(__name__, 'js/src/collapsible.js'),
resource_string(__name__, 'js/src/capa/imageinput.js'), resource_string(__name__, 'js/src/capa/imageinput.js'),
resource_string(__name__, 'js/src/capa/schematic.js'), resource_string(__name__, 'js/src/capa/schematic.js'),
......
...@@ -114,10 +114,10 @@ class ConditionalModule(ConditionalFields, XModule, StudioEditableModule): ...@@ -114,10 +114,10 @@ class ConditionalModule(ConditionalFields, XModule, StudioEditableModule):
js = { js = {
'coffee': [ 'coffee': [
resource_string(__name__, 'js/src/javascript_loader.coffee'),
resource_string(__name__, 'js/src/conditional/display.coffee'), resource_string(__name__, 'js/src/conditional/display.coffee'),
], ],
'js': [ 'js': [
resource_string(__name__, 'js/src/javascript_loader.js'),
resource_string(__name__, 'js/src/collapsible.js'), resource_string(__name__, 'js/src/collapsible.js'),
] ]
} }
......
...@@ -92,10 +92,10 @@ class HtmlModuleMixin(HtmlBlock, XModule): ...@@ -92,10 +92,10 @@ class HtmlModuleMixin(HtmlBlock, XModule):
""" """
js = { js = {
'coffee': [ 'coffee': [
resource_string(__name__, 'js/src/javascript_loader.coffee'),
resource_string(__name__, 'js/src/html/display.coffee'), resource_string(__name__, 'js/src/html/display.coffee'),
], ],
'js': [ 'js': [
resource_string(__name__, 'js/src/javascript_loader.js'),
resource_string(__name__, 'js/src/collapsible.js'), resource_string(__name__, 'js/src/collapsible.js'),
resource_string(__name__, 'js/src/html/imageModal.js'), resource_string(__name__, 'js/src/html/imageModal.js'),
resource_string(__name__, 'js/common_static/js/vendor/draggabilly.js'), resource_string(__name__, 'js/common_static/js/vendor/draggabilly.js'),
......
...@@ -92,11 +92,11 @@ class ImageAnnotationModule(AnnotatableFields, XModule): ...@@ -92,11 +92,11 @@ class ImageAnnotationModule(AnnotatableFields, XModule):
'''Image Annotation Module''' '''Image Annotation Module'''
js = { js = {
'coffee': [ 'coffee': [
resource_string(__name__, 'js/src/javascript_loader.coffee'),
resource_string(__name__, 'js/src/html/display.coffee'), resource_string(__name__, 'js/src/html/display.coffee'),
resource_string(__name__, 'js/src/annotatable/display.coffee'), resource_string(__name__, 'js/src/annotatable/display.coffee'),
], ],
'js': [ 'js': [
resource_string(__name__, 'js/src/javascript_loader.js'),
resource_string(__name__, 'js/src/collapsible.js'), resource_string(__name__, 'js/src/collapsible.js'),
] ]
} }
......
...@@ -13,3 +13,4 @@ ...@@ -13,3 +13,4 @@
!time.js !time.js
!collapsible.js !collapsible.js
!xmodule.js !xmodule.js
!javascript_loader.js
class @JavascriptLoader
# Set of library functions that provide common interface for javascript loading
# for all module types. All functionality provided by JavascriptLoader should take
# place at module scope, i.e. don't run jQuery over entire page
# executeModuleScripts:
# Scan the module ('el') for "script_placeholder"s, then:
# 1) Fetch each script from server
# 2) Explicitly attach the script to the <head> of document
# 3) Explicitly wait for each script to be loaded
# 4) Return to callback function when all scripts loaded
@executeModuleScripts: (el, callback=null) ->
placeholders = el.find(".script_placeholder")
if placeholders.length == 0
callback() if callback?
return
# TODO: Verify the execution order of multiple placeholders
completed = (false for i in [1..placeholders.length])
callbackCalled = false
# This is required for IE8 support.
completionHandlerGeneratorIE = (index) =>
return () ->
if (this.readyState == 'complete' || this.readyState == 'loaded')
#completionHandlerGenerator.call(self, index)()
completionHandlerGenerator(index)()
completionHandlerGenerator = (index) =>
return () =>
allComplete = true
completed[index] = true
for flag in completed
if not flag
allComplete = false
break
if allComplete and not callbackCalled
callbackCalled = true
callback() if callback?
# Keep a map of what sources we're loaded from, and don't do it twice.
loaded = {}
placeholders.each (index, placeholder) ->
# TODO: Check if the script already exists in DOM. If so, (1) copy it
# into memory; (2) delete the DOM script element; (3) reappend it.
# This would prevent memory bloat and save a network request.
src = $(placeholder).attr("data-src")
if src not of loaded
loaded[src] = true
s = document.createElement('script')
s.setAttribute('src', src)
s.setAttribute('type', "text/javascript")
s.onload = completionHandlerGenerator(index)
# s.onload does not fire in IE8; this does.
s.onreadystatechange = completionHandlerGeneratorIE(index)
# Need to use the DOM elements directly or the scripts won't execute
# properly.
$('head')[0].appendChild(s)
else
# just call the completion callback directly, without reloading the file
completionHandlerGenerator(index)()
$(placeholder).remove()
(function() {
'use strict';
this.JavascriptLoader = (function() {
function JavascriptLoader() {
}
/**
* Set of library functions that provide common interface for javascript loading
* for all module types. All functionality provided by JavascriptLoader should take
* place at module scope, i.e. don't run jQuery over entire page.
*
* executeModuleScripts:
* Scan the module ('el') for "script_placeholder"s, then:
*
* 1) Fetch each script from server
* 2) Explicitly attach the script to the <head> of document
* 3) Explicitly wait for each script to be loaded
* 4) Return to callback function when all scripts loaded
*/
JavascriptLoader.executeModuleScripts = function(el, callback) {
var callbackCalled, completed, completionHandlerGenerator, loaded, placeholders;
if (!callback) {
callback = null; // eslint-disable-line no-param-reassign
}
placeholders = el.find('.script_placeholder');
if (placeholders.length === 0) {
if (callback !== null) {
callback();
}
return [];
}
// TODO: Verify the execution order of multiple placeholders
completed = (function() {
var i, ref, results;
results = [];
for (i = 1, ref = placeholders.length; ref >= 1 ? i <= ref : i >= ref; ref >= 1 ? ++i : --i) {
results.push(false);
}
return results;
}());
callbackCalled = false;
completionHandlerGenerator = function(index) {
return function() {
var allComplete, flag, i, len;
allComplete = true;
completed[index] = true;
for (i = 0, len = completed.length; i < len; i++) {
flag = completed[i];
if (!flag) {
allComplete = false;
break;
}
}
if (allComplete && !callbackCalled) {
callbackCalled = true;
if (callback !== null) {
return callback();
}
}
return undefined;
};
};
// Keep a map of what sources we're loaded from, and don't do it twice.
loaded = {};
return placeholders.each(function(index, placeholder) {
var s, src;
// TODO: Check if the script already exists in DOM. If so, (1) copy it
// into memory; (2) delete the DOM script element; (3) reappend it.
// This would prevent memory bloat and save a network request.
src = $(placeholder).attr('data-src');
if (!(src in loaded)) {
loaded[src] = true;
s = document.createElement('script');
s.setAttribute('src', src);
s.setAttribute('type', 'text/javascript');
s.onload = completionHandlerGenerator(index);
// Need to use the DOM elements directly or the scripts won't execute properly.
$('head')[0].appendChild(s);
} else {
// just call the completion callback directly, without reloading the file
completionHandlerGenerator(index)();
}
return $(placeholder).remove();
});
};
return JavascriptLoader;
}());
}).call(this);
...@@ -42,8 +42,8 @@ class PollFields(object): ...@@ -42,8 +42,8 @@ class PollFields(object):
class PollModule(PollFields, XModule): class PollModule(PollFields, XModule):
"""Poll Module""" """Poll Module"""
js = { js = {
'coffee': [resource_string(__name__, 'js/src/javascript_loader.coffee')],
'js': [ 'js': [
resource_string(__name__, 'js/src/javascript_loader.js'),
resource_string(__name__, 'js/src/poll/poll.js'), resource_string(__name__, 'js/src/poll/poll.js'),
resource_string(__name__, 'js/src/poll/poll_main.js') resource_string(__name__, 'js/src/poll/poll_main.js')
] ]
......
...@@ -86,11 +86,11 @@ class VideoAnnotationModule(AnnotatableFields, XModule): ...@@ -86,11 +86,11 @@ class VideoAnnotationModule(AnnotatableFields, XModule):
'''Video Annotation Module''' '''Video Annotation Module'''
js = { js = {
'coffee': [ 'coffee': [
resource_string(__name__, 'js/src/javascript_loader.coffee'),
resource_string(__name__, 'js/src/html/display.coffee'), resource_string(__name__, 'js/src/html/display.coffee'),
resource_string(__name__, 'js/src/annotatable/display.coffee'), resource_string(__name__, 'js/src/annotatable/display.coffee'),
], ],
'js': [ 'js': [
resource_string(__name__, 'js/src/javascript_loader.js'),
resource_string(__name__, 'js/src/collapsible.js'), resource_string(__name__, 'js/src/collapsible.js'),
] ]
} }
......
...@@ -91,8 +91,8 @@ class WordCloudFields(object): ...@@ -91,8 +91,8 @@ class WordCloudFields(object):
class WordCloudModule(WordCloudFields, XModule): class WordCloudModule(WordCloudFields, XModule):
"""WordCloud Xmodule""" """WordCloud Xmodule"""
js = { js = {
'coffee': [resource_string(__name__, 'js/src/javascript_loader.coffee')],
'js': [ 'js': [
resource_string(__name__, 'js/src/javascript_loader.js'),
resource_string(__name__, 'js/src/word_cloud/d3.min.js'), resource_string(__name__, 'js/src/word_cloud/d3.min.js'),
resource_string(__name__, 'js/src/word_cloud/d3.layout.cloud.js'), resource_string(__name__, 'js/src/word_cloud/d3.layout.cloud.js'),
resource_string(__name__, 'js/src/word_cloud/word_cloud.js'), resource_string(__name__, 'js/src/word_cloud/word_cloud.js'),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment