Merge pull request #13705 from edx/christina/javascript_loader
Christina/javascript loader
This commit is contained in:
@@ -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/html/display.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/raw/edit/json.js
|
||||
common/lib/xmodule/xmodule/js/src/raw/edit/metadata-only.js
|
||||
|
||||
@@ -48,11 +48,11 @@ class AnnotatableFields(object):
|
||||
class AnnotatableModule(AnnotatableFields, XModule):
|
||||
js = {
|
||||
'coffee': [
|
||||
resource_string(__name__, 'js/src/javascript_loader.coffee'),
|
||||
resource_string(__name__, 'js/src/html/display.coffee'),
|
||||
resource_string(__name__, 'js/src/annotatable/display.coffee'),
|
||||
],
|
||||
'js': [
|
||||
resource_string(__name__, 'js/src/javascript_loader.js'),
|
||||
resource_string(__name__, 'js/src/collapsible.js'),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -31,9 +31,9 @@ class CapaModule(CapaMixin, XModule):
|
||||
js = {
|
||||
'coffee': [
|
||||
resource_string(__name__, 'js/src/capa/display.coffee'),
|
||||
resource_string(__name__, 'js/src/javascript_loader.coffee'),
|
||||
],
|
||||
'js': [
|
||||
resource_string(__name__, 'js/src/javascript_loader.js'),
|
||||
resource_string(__name__, 'js/src/collapsible.js'),
|
||||
resource_string(__name__, 'js/src/capa/imageinput.js'),
|
||||
resource_string(__name__, 'js/src/capa/schematic.js'),
|
||||
|
||||
@@ -114,10 +114,10 @@ class ConditionalModule(ConditionalFields, XModule, StudioEditableModule):
|
||||
|
||||
js = {
|
||||
'coffee': [
|
||||
resource_string(__name__, 'js/src/javascript_loader.coffee'),
|
||||
resource_string(__name__, 'js/src/conditional/display.coffee'),
|
||||
],
|
||||
'js': [
|
||||
resource_string(__name__, 'js/src/javascript_loader.js'),
|
||||
resource_string(__name__, 'js/src/collapsible.js'),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -92,10 +92,10 @@ class HtmlModuleMixin(HtmlBlock, XModule):
|
||||
"""
|
||||
js = {
|
||||
'coffee': [
|
||||
resource_string(__name__, 'js/src/javascript_loader.coffee'),
|
||||
resource_string(__name__, 'js/src/html/display.coffee'),
|
||||
],
|
||||
'js': [
|
||||
resource_string(__name__, 'js/src/javascript_loader.js'),
|
||||
resource_string(__name__, 'js/src/collapsible.js'),
|
||||
resource_string(__name__, 'js/src/html/imageModal.js'),
|
||||
resource_string(__name__, 'js/common_static/js/vendor/draggabilly.js'),
|
||||
|
||||
@@ -92,11 +92,11 @@ class ImageAnnotationModule(AnnotatableFields, XModule):
|
||||
'''Image Annotation Module'''
|
||||
js = {
|
||||
'coffee': [
|
||||
resource_string(__name__, 'js/src/javascript_loader.coffee'),
|
||||
resource_string(__name__, 'js/src/html/display.coffee'),
|
||||
resource_string(__name__, 'js/src/annotatable/display.coffee'),
|
||||
],
|
||||
'js': [
|
||||
resource_string(__name__, 'js/src/javascript_loader.js'),
|
||||
resource_string(__name__, 'js/src/collapsible.js'),
|
||||
]
|
||||
}
|
||||
|
||||
1
common/lib/xmodule/xmodule/js/src/.gitignore
vendored
1
common/lib/xmodule/xmodule/js/src/.gitignore
vendored
@@ -13,3 +13,4 @@
|
||||
!time.js
|
||||
!collapsible.js
|
||||
!xmodule.js
|
||||
!javascript_loader.js
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
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()
|
||||
|
||||
|
||||
89
common/lib/xmodule/xmodule/js/src/javascript_loader.js
Normal file
89
common/lib/xmodule/xmodule/js/src/javascript_loader.js
Normal file
@@ -0,0 +1,89 @@
|
||||
(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):
|
||||
class PollModule(PollFields, XModule):
|
||||
"""Poll Module"""
|
||||
js = {
|
||||
'coffee': [resource_string(__name__, 'js/src/javascript_loader.coffee')],
|
||||
'js': [
|
||||
resource_string(__name__, 'js/src/javascript_loader.js'),
|
||||
resource_string(__name__, 'js/src/poll/poll.js'),
|
||||
resource_string(__name__, 'js/src/poll/poll_main.js')
|
||||
]
|
||||
|
||||
@@ -86,11 +86,11 @@ class VideoAnnotationModule(AnnotatableFields, XModule):
|
||||
'''Video Annotation Module'''
|
||||
js = {
|
||||
'coffee': [
|
||||
resource_string(__name__, 'js/src/javascript_loader.coffee'),
|
||||
resource_string(__name__, 'js/src/html/display.coffee'),
|
||||
resource_string(__name__, 'js/src/annotatable/display.coffee'),
|
||||
],
|
||||
'js': [
|
||||
resource_string(__name__, 'js/src/javascript_loader.js'),
|
||||
resource_string(__name__, 'js/src/collapsible.js'),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -91,8 +91,8 @@ class WordCloudFields(object):
|
||||
class WordCloudModule(WordCloudFields, XModule):
|
||||
"""WordCloud Xmodule"""
|
||||
js = {
|
||||
'coffee': [resource_string(__name__, 'js/src/javascript_loader.coffee')],
|
||||
'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.layout.cloud.js'),
|
||||
resource_string(__name__, 'js/src/word_cloud/word_cloud.js'),
|
||||
|
||||
Reference in New Issue
Block a user