143 lines
5.6 KiB
JavaScript
143 lines
5.6 KiB
JavaScript
(function($, JSON) {
|
|
|
|
'use strict';
|
|
|
|
function initializeBlockLikes(block_class, initializer, element, requestToken) {
|
|
var requestToken = requestToken || $(element).data('request-token');
|
|
if (requestToken) {
|
|
var selector = '.' + block_class + '[data-request-token="' + requestToken + '"]';
|
|
} else {
|
|
var selector = '.' + block_class;
|
|
}
|
|
return $(element).immediateDescendents(selector).map(function(idx, elem) {
|
|
return initializer(elem, requestToken);
|
|
}).toArray();
|
|
}
|
|
|
|
function elementRuntime(element) {
|
|
var $element = $(element);
|
|
var runtime = $element.data('runtime-class');
|
|
var version = $element.data('runtime-version');
|
|
var initFnName = $element.data('init');
|
|
|
|
if (runtime && version && initFnName) {
|
|
return new window[runtime]['v' + version];
|
|
} else {
|
|
if (runtime || version || initFnName) {
|
|
var elementTag = $('<div>').append($element.clone()).html();
|
|
console.log('Block ' + elementTag + ' is missing data-runtime, data-runtime-version or data-init, and can\'t be initialized');
|
|
} // else this XBlock doesn't have a JS init function.
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function initArgs(element) {
|
|
var initargs = $(element).children('.xblock-json-init-args').remove().text();
|
|
return initargs ? JSON.parse(initargs) : {};
|
|
}
|
|
|
|
/**
|
|
* Construct an XBlock family object from an element. The constructor
|
|
* function is loaded from the 'data-init' attribute of the element.
|
|
* The constructor is called with the arguments 'runtime', 'element',
|
|
* and then all of 'block_args'.
|
|
*/
|
|
function constructBlock(element, block_args) {
|
|
var block;
|
|
var $element = $(element);
|
|
var runtime = elementRuntime(element);
|
|
|
|
block_args.unshift(element);
|
|
block_args.unshift(runtime);
|
|
|
|
|
|
if (runtime) {
|
|
|
|
block = (function() {
|
|
var initFn = window[$element.data('init')];
|
|
|
|
// This create a new constructor that can then apply() the block_args
|
|
// to the initFn.
|
|
function Block() {
|
|
return initFn.apply(this, block_args);
|
|
}
|
|
Block.prototype = initFn.prototype;
|
|
|
|
return new Block();
|
|
})();
|
|
block.runtime = runtime;
|
|
} else {
|
|
block = {};
|
|
}
|
|
block.element = element;
|
|
block.name = $element.data('name');
|
|
block.type = $element.data('block-type');
|
|
$element.trigger('xblock-initialized');
|
|
$element.data('initialized', true);
|
|
$element.addClass('xblock-initialized');
|
|
return block;
|
|
}
|
|
|
|
var XBlock = {
|
|
Runtime: {},
|
|
|
|
/**
|
|
* Initialize the javascript for a single xblock element, and for all of it's
|
|
* xblock children that match requestToken. If requestToken is omitted, use the
|
|
* data-request-token attribute from element, or use the request-tokens specified on
|
|
* the children themselves.
|
|
*/
|
|
initializeBlock: function(element, requestToken) {
|
|
var $element = $(element);
|
|
|
|
var requestToken = requestToken || $element.data('request-token');
|
|
var children = XBlock.initializeXBlocks($element, requestToken);
|
|
$element.prop('xblock_children', children);
|
|
|
|
return constructBlock(element, [initArgs(element)]);
|
|
},
|
|
|
|
/**
|
|
* Initialize the javascript for a single xblock aside element that matches requestToken.
|
|
* If requestToken is omitted, use the data-request-token attribute from element, or use
|
|
* the request-tokens specified on the children themselves.
|
|
*/
|
|
initializeAside: function(element, requestToken) {
|
|
var blockUsageId = $(element).data('block-id');
|
|
var blockElement = $(element).siblings('[data-usage-id="' + blockUsageId + '"]')[0];
|
|
return constructBlock(element, [blockElement, initArgs(element)]);
|
|
},
|
|
|
|
/**
|
|
* Initialize all XBlocks inside element that were rendered with requestToken.
|
|
* If requestToken is omitted, and element has a 'data-request-token' attribute, use that.
|
|
* If neither is available, then use the request tokens of the immediateDescendent xblocks.
|
|
*/
|
|
initializeXBlocks: function(element, requestToken) {
|
|
return initializeBlockLikes('xblock', XBlock.initializeBlock, element, requestToken);
|
|
},
|
|
|
|
/**
|
|
* Initialize all XBlockAsides inside element that were rendered with requestToken.
|
|
* If requestToken is omitted, and element has a 'data-request-token' attribute, use that.
|
|
* If neither is available, then use the request tokens of the immediateDescendent xblocks.
|
|
*/
|
|
initializeXBlockAsides: function(element, requestToken) {
|
|
return initializeBlockLikes('xblock_asides-v1', XBlock.initializeAside, element, requestToken);
|
|
},
|
|
|
|
/**
|
|
* Initialize all XBlock-family blocks inside element that were rendered with requestToken.
|
|
* If requestToken is omitted, and element has a 'data-request-token' attribute, use that.
|
|
* If neither is available, then use the request tokens of the immediateDescendent xblocks.
|
|
*/
|
|
initializeBlocks: function(element, requestToken) {
|
|
XBlock.initializeXBlockAsides(element, requestToken);
|
|
return XBlock.initializeXBlocks(element, requestToken);
|
|
}
|
|
};
|
|
|
|
this.XBlock = XBlock;
|
|
|
|
}).call(this, $, JSON);
|