Work in progress on GST.
This commit is contained in:
committed by
Alexander Kryklia
parent
5990fa2ef5
commit
080e96fdc4
@@ -26,10 +26,10 @@ class GraphicalSliderToolModule(XModule):
|
||||
js = {
|
||||
'js': [
|
||||
resource_string(__name__, 'js/src/graphical_slider_tool/gst_main.js'),
|
||||
resource_string(__name__, 'js/src/graphical_slider_tool/mod1.js'),
|
||||
resource_string(__name__, 'js/src/graphical_slider_tool/mod2.js'),
|
||||
resource_string(__name__, 'js/src/graphical_slider_tool/mod3.js'),
|
||||
resource_string(__name__, 'js/src/graphical_slider_tool/mod4.js'),
|
||||
resource_string(__name__, 'js/src/graphical_slider_tool/state.js'),
|
||||
resource_string(__name__, 'js/src/graphical_slider_tool/logme.js'),
|
||||
resource_string(__name__, 'js/src/graphical_slider_tool/general_methods.js'),
|
||||
resource_string(__name__, 'js/src/graphical_slider_tool/sliders.js'),
|
||||
resource_string(__name__, 'js/src/graphical_slider_tool/mod5.js'),
|
||||
|
||||
resource_string(__name__, 'js/src/graphical_slider_tool/gst.js')
|
||||
@@ -128,7 +128,7 @@ class GraphicalSliderToolModule(XModule):
|
||||
Simple variant: slider and plot controls are not inside any tag.
|
||||
"""
|
||||
#substitute plot
|
||||
plot_div = '<div class="${element_class}_plot" id="${element_id}_plot" \
|
||||
plot_div = '<div class="' + self.html_class + '_plot" id="' + self.html_id + '_plot" \
|
||||
style="width: 600px; height: 600px; padding: 0px; position: relative;"> \
|
||||
This is plot</div>'
|
||||
html_string = html_string.replace('$plot$', plot_div)
|
||||
@@ -139,7 +139,7 @@ class GraphicalSliderToolModule(XModule):
|
||||
sliders = [sliders]
|
||||
vars = [x['@var'] for x in sliders]
|
||||
|
||||
slider_div = '<div class="{element_class}_slider" id="{element_id}_{var}" \
|
||||
slider_div = '<div class="{element_class}_slider" id="{element_id}_slider_{var}" \
|
||||
data-var="{var}">This is slider</div>'
|
||||
|
||||
for var in vars:
|
||||
@@ -155,7 +155,7 @@ class GraphicalSliderToolModule(XModule):
|
||||
inputs = [inputs]
|
||||
vars = [x['@var'] for x in inputs]
|
||||
|
||||
input_div = '<div class="{element_class}_input" id="{element_id}_{var}" \
|
||||
input_div = '<div class="{element_class}_input" id="{element_id}_input_{var}" \
|
||||
data-var="{var}">This is input</div>'
|
||||
|
||||
for var in vars:
|
||||
|
||||
@@ -2,12 +2,16 @@
|
||||
// define() functions from Require JS available inside the anonymous function.
|
||||
(function (requirejs, require, define) {
|
||||
|
||||
define('mod3', ['mod5'], function (mod5) {
|
||||
console.log('we are in the mod3 callback');
|
||||
|
||||
console.log('mod5 status: [' + mod5.module_status + '].');
|
||||
define('GeneralMethods', [], function () {
|
||||
if (!String.prototype.trim) {
|
||||
// http://blog.stevenlevithan.com/archives/faster-trim-javascript
|
||||
String.prototype.trim = function trim(str) {
|
||||
return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
'module_name': 'GeneralMethods',
|
||||
'module_status': 'OK'
|
||||
};
|
||||
});
|
||||
@@ -2,11 +2,19 @@
|
||||
// define() functions from Require JS available inside the anonymous function.
|
||||
(function (requirejs, require, define) {
|
||||
|
||||
define('GstMain', ['mod1', 'mod2', 'mod3', 'mod4'], function (mod1, mod2, mod3, mod4) {
|
||||
define('GstMain', ['State', 'logme', 'GeneralMethods', 'Sliders'], function (State, logme, GeneralMethods, Sliders) {
|
||||
logme(GeneralMethods);
|
||||
|
||||
return GstMain;
|
||||
|
||||
function GstMain(gstId) {
|
||||
console.log('The DOM ID of the current GST element is ' + gstId);
|
||||
var config, state;
|
||||
|
||||
config = JSON.parse($('#' + gstId + '_json').html()).root;
|
||||
|
||||
state = State(gstId, config);
|
||||
|
||||
Sliders(gstId, config, state);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
// Wrapper for RequireJS. It will make the standard requirejs(), require(), and
|
||||
// define() functions from Require JS available inside the anonymous function.
|
||||
(function (requirejs, require, define) {
|
||||
|
||||
define('logme', [], function () {
|
||||
var debugMode;
|
||||
|
||||
// debugMode can be one of the following:
|
||||
//
|
||||
// true - All messages passed to logme will be written to the internal
|
||||
// browser console.
|
||||
// false - Suppress all output to the internal browser console.
|
||||
//
|
||||
// Obviously, if anywhere there is a direct console.log() call, we can't do
|
||||
// anything about it. That's why use logme() - it will allow to turn off
|
||||
// the output of debug information with a single change to a variable.
|
||||
debugMode = true;
|
||||
|
||||
return logme;
|
||||
|
||||
/*
|
||||
* function: logme
|
||||
*
|
||||
* A helper function that provides logging facilities. We don't want
|
||||
* to call console.log() directly, because sometimes it is not supported
|
||||
* by the browser. Also when everything is routed through this function.
|
||||
* the logging output can be easily turned off.
|
||||
*
|
||||
* logme() supports multiple parameters. Each parameter will be passed to
|
||||
* console.log() function separately.
|
||||
*
|
||||
*/
|
||||
function logme() {
|
||||
var i;
|
||||
|
||||
if (
|
||||
(typeof debugMode === 'undefined') ||
|
||||
(debugMode !== true) ||
|
||||
(typeof window.console === 'undefined')
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < arguments.length; i++) {
|
||||
window.console.log(arguments[i]);
|
||||
}
|
||||
} // End-of: function logme
|
||||
});
|
||||
|
||||
// End of wrapper for RequireJS. As you can see, we are passing
|
||||
// namespaced Require JS variables to an anonymous function. Within
|
||||
// it, you can use the standard requirejs(), require(), and define()
|
||||
// functions as if they were in the global namespace.
|
||||
}(RequireJS.requirejs, RequireJS.require, RequireJS.define)); // End-of: (function (requirejs, require, define)
|
||||
@@ -1,16 +0,0 @@
|
||||
// Wrapper for RequireJS. It will make the standard requirejs(), require(), and
|
||||
// define() functions from Require JS available inside the anonymous function.
|
||||
(function (requirejs, require, define) {
|
||||
|
||||
define('mod1', [], function () {
|
||||
console.log('we are in the mod1 callback');
|
||||
return {
|
||||
'module_status': 'OK'
|
||||
};
|
||||
});
|
||||
|
||||
// End of wrapper for RequireJS. As you can see, we are passing
|
||||
// namespaced Require JS variables to an anonymous function. Within
|
||||
// it, you can use the standard requirejs(), require(), and define()
|
||||
// functions as if they were in the global namespace.
|
||||
}(RequireJS.requirejs, RequireJS.require, RequireJS.define)); // End-of: (function (requirejs, require, define)
|
||||
@@ -1,16 +0,0 @@
|
||||
// Wrapper for RequireJS. It will make the standard requirejs(), require(), and
|
||||
// define() functions from Require JS available inside the anonymous function.
|
||||
(function (requirejs, require, define) {
|
||||
|
||||
define('mod2', [], function () {
|
||||
console.log('we are in the mod2 callback');
|
||||
return {
|
||||
'module_status': 'OK'
|
||||
};
|
||||
});
|
||||
|
||||
// End of wrapper for RequireJS. As you can see, we are passing
|
||||
// namespaced Require JS variables to an anonymous function. Within
|
||||
// it, you can use the standard requirejs(), require(), and define()
|
||||
// functions as if they were in the global namespace.
|
||||
}(RequireJS.requirejs, RequireJS.require, RequireJS.define)); // End-of: (function (requirejs, require, define)
|
||||
@@ -1,16 +0,0 @@
|
||||
// Wrapper for RequireJS. It will make the standard requirejs(), require(), and
|
||||
// define() functions from Require JS available inside the anonymous function.
|
||||
(function (requirejs, require, define) {
|
||||
|
||||
define('mod4', [], function () {
|
||||
console.log('we are in the mod4 callback');
|
||||
return {
|
||||
'module_status': 'OK'
|
||||
};
|
||||
});
|
||||
|
||||
// End of wrapper for RequireJS. As you can see, we are passing
|
||||
// namespaced Require JS variables to an anonymous function. Within
|
||||
// it, you can use the standard requirejs(), require(), and define()
|
||||
// functions as if they were in the global namespace.
|
||||
}(RequireJS.requirejs, RequireJS.require, RequireJS.define)); // End-of: (function (requirejs, require, define)
|
||||
@@ -0,0 +1,142 @@
|
||||
// Wrapper for RequireJS. It will make the standard requirejs(), require(), and
|
||||
// define() functions from Require JS available inside the anonymous function.
|
||||
(function (requirejs, require, define) {
|
||||
|
||||
define('Sliders', ['logme'], function (logme) {
|
||||
return Sliders;
|
||||
|
||||
function Sliders(gstId, config, state) {
|
||||
logme('We are inside Sliders function.');
|
||||
|
||||
logme('gstId: ' + gstId);
|
||||
logme(config);
|
||||
logme(state);
|
||||
|
||||
// We will go through all of the sliders. For each one, we will make a
|
||||
// jQuery UI slider for it, attach "on change" events, and set it's
|
||||
// state - initial value, max, and min parameters.
|
||||
if ((typeof config.sliders !== 'undefined') &&
|
||||
(typeof config.sliders.slider !== 'undefined')) {
|
||||
if ($.isArray(config.sliders.slider)) {
|
||||
// config.sliders.slider is an array
|
||||
|
||||
for (c1 = 0; c1 < config.sliders.slider.length; c1++) {
|
||||
createSlider(config.sliders.slider[c1]);
|
||||
}
|
||||
} else if ($.isPlainObject(config.sliders.slider)) {
|
||||
// config.sliders.slider is an object
|
||||
createSlider(config.sliders.slider);
|
||||
}
|
||||
}
|
||||
|
||||
function createSlider(obj) {
|
||||
var constName, constValue, rangeBlobs, valueMin, valueMax,
|
||||
sliderDiv, sliderWidth;
|
||||
|
||||
// The name of the constant is obj['@var']. Multiple sliders and/or
|
||||
// inputs can represent the same constant - therefore we will get
|
||||
// the most recent const value from the state object. The range is
|
||||
// a string composed of 3 blobs, separated by commas. The first
|
||||
// blob is the min value for the slider, the third blob is the max
|
||||
// value for the slider.
|
||||
|
||||
if (typeof obj['@var'] === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
constName = obj['@var'];
|
||||
|
||||
constValue = state.getConstValue(constName);
|
||||
if (constValue === undefined) {
|
||||
constValue = 0;
|
||||
}
|
||||
|
||||
if (typeof obj['@range'] !== 'string') {
|
||||
valueMin = constValue - 10;
|
||||
valueMax = constValue + 10;
|
||||
} else {
|
||||
rangeBlobs = obj['@range'].split(',');
|
||||
|
||||
// We must have gotten exactly 3 blobs (pieces) from the split.
|
||||
if (rangeBlobs.length !== 3) {
|
||||
valueMin = constValue - 10;
|
||||
valueMax = constValue + 10;
|
||||
} else {
|
||||
// Get the first blob from the split string.
|
||||
valueMin = parseFloat(rangeBlobs[0]);
|
||||
|
||||
if (isNaN(valueMin) === true) {
|
||||
valueMin = constValue - 10;
|
||||
}
|
||||
|
||||
// Get the third blob from the split string.
|
||||
valueMax = parseFloat(rangeBlobs[2]);
|
||||
|
||||
if (isNaN(valueMax) === true) {
|
||||
valueMax = constValue + 10;
|
||||
}
|
||||
|
||||
// Logically, the min, value, and max should make sense.
|
||||
// I.e. we will make sure that:
|
||||
//
|
||||
// min <= value <= max
|
||||
//
|
||||
// If this is not the case, we will set some defaults.
|
||||
if ((valueMin > valueMax) ||
|
||||
(valueMin > constValue) ||
|
||||
(valueMax < constValue)) {
|
||||
valueMin = constValue - 10;
|
||||
valueMax = constValue + 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sliderDiv = $('#' + gstId + '_slider_' + constName);
|
||||
|
||||
// If a corresponding slider DIV for this constant does not exist,
|
||||
// do not do anything.
|
||||
if (sliderDiv.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The default slider width.
|
||||
sliderWidth = 400;
|
||||
|
||||
logme('width: 0');
|
||||
logme(obj['@width']);
|
||||
if (typeof obj['@width'] === 'string') {
|
||||
logme('width: 1');
|
||||
if (isNaN(parseInt(obj['@width'], 10)) === false) {
|
||||
logme('width: 2');
|
||||
sliderWidth = parseInt(obj['@width'], 10);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the new width to the slider.
|
||||
sliderDiv.width(sliderWidth);
|
||||
|
||||
// Create a jQuery UI slider from the current DIV. We will set
|
||||
// starting parameters, and will also attach a handler to update
|
||||
// the state on the change event.
|
||||
sliderDiv.slider({
|
||||
'min': valueMin,
|
||||
'max': valueMax,
|
||||
'value': constValue,
|
||||
|
||||
'change': sliderOnChange
|
||||
});
|
||||
|
||||
return;
|
||||
|
||||
function sliderOnChange(event, ui) {
|
||||
state.setConstValue(constName, ui.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// End of wrapper for RequireJS. As you can see, we are passing
|
||||
// namespaced Require JS variables to an anonymous function. Within
|
||||
// it, you can use the standard requirejs(), require(), and define()
|
||||
// functions as if they were in the global namespace.
|
||||
}(RequireJS.requirejs, RequireJS.require, RequireJS.define)); // End-of: (function (requirejs, require, define)
|
||||
165
common/lib/xmodule/xmodule/js/src/graphical_slider_tool/state.js
Normal file
165
common/lib/xmodule/xmodule/js/src/graphical_slider_tool/state.js
Normal file
@@ -0,0 +1,165 @@
|
||||
// Wrapper for RequireJS. It will make the standard requirejs(), require(), and
|
||||
// define() functions from Require JS available inside the anonymous function.
|
||||
(function (requirejs, require, define) {
|
||||
|
||||
define('State', ['logme'], function (logme) {
|
||||
// Since there will be (can be) multiple GST on a page, and each will have
|
||||
// a separate state, we will create a factory constructor function. The
|
||||
// constructor will expect the ID of the DIV with the GST contents, and the
|
||||
// configuration object (parsed from a JSON string). It will return and
|
||||
// object containing methods to set and get the private state properties.
|
||||
|
||||
// This module defines and returns a factory constructor.
|
||||
return State;
|
||||
|
||||
/*
|
||||
* function: State
|
||||
*
|
||||
*
|
||||
*/
|
||||
function State(gstId, config) {
|
||||
var constants, c1;
|
||||
|
||||
constants = {};
|
||||
|
||||
// We must go through all of the input, and slider elements and
|
||||
// retrieve all of the available constants. These will be added to an
|
||||
// object as it's properties.
|
||||
//
|
||||
// First we will go through all of the inputs.
|
||||
if ((typeof config.inputs !== 'undefined') &&
|
||||
(typeof config.inputs.input !== 'undefined')) {
|
||||
if ($.isArray(config.inputs.input)) {
|
||||
// config.inputs.input is an array
|
||||
|
||||
for (c1 = 0; c1 < config.inputs.input.length; c1++) {
|
||||
addConstFromInput(config.inputs.input[c1]);
|
||||
}
|
||||
} else if ($.isPlainObject(config.inputs.input)) {
|
||||
// config.inputs.input is an object
|
||||
addConstFromInput(config.inputs.input);
|
||||
}
|
||||
}
|
||||
|
||||
// Now we will go through all of the sliders.
|
||||
if ((typeof config.sliders !== 'undefined') &&
|
||||
(typeof config.sliders.slider !== 'undefined')) {
|
||||
if ($.isArray(config.sliders.slider)) {
|
||||
// config.sliders.slider is an array
|
||||
|
||||
for (c1 = 0; c1 < config.sliders.slider.length; c1++) {
|
||||
addConstFromSlider(config.sliders.slider[c1]);
|
||||
}
|
||||
} else if ($.isPlainObject(config.sliders.slider)) {
|
||||
// config.sliders.slider is an object
|
||||
addConstFromSlider(config.sliders.slider);
|
||||
}
|
||||
}
|
||||
|
||||
logme(constants);
|
||||
|
||||
// The constructor will return an object with methods to operate on
|
||||
// it's private properties.
|
||||
return {
|
||||
'getConstValue': getConstValue,
|
||||
'setConstValue': setConstValue
|
||||
};
|
||||
|
||||
function getConstValue(constName) {
|
||||
if (constants.hasOwnProperty(constName) === false) {
|
||||
// If the name of the constant is not tracked by state, return an
|
||||
// 'undefined' value.
|
||||
return;
|
||||
}
|
||||
|
||||
return constants[constName];
|
||||
}
|
||||
|
||||
function setConstValue(constName, constValue) {
|
||||
if (constants.hasOwnProperty(constName) === false) {
|
||||
// If the name of the constant is not tracked by state, return an
|
||||
// 'undefined' value.
|
||||
return;
|
||||
}
|
||||
|
||||
if (isNaN(parseFloat(constValue)) === true) {
|
||||
// We are interested only in valid float values.
|
||||
return;
|
||||
}
|
||||
|
||||
constants[constName] = parseFloat(constValue);
|
||||
|
||||
logme('From setConstValue: new value for "' + constName + '" is ' + constValue);
|
||||
}
|
||||
|
||||
function addConstFromInput(obj) {
|
||||
var constName, constValue;
|
||||
|
||||
// The name of the constant is obj['@var']. The value (initial) of
|
||||
// the constant is obj['@initial']. I have taken the word 'initial'
|
||||
// into brackets, because multiple inputs and/or sliders can
|
||||
// represent the state of a single constant.
|
||||
|
||||
if (typeof obj['@var'] === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
constName = obj['@var'];
|
||||
|
||||
if (typeof obj['@initial'] === 'undefined') {
|
||||
constValue = 0;
|
||||
} else {
|
||||
constValue = parseFloat(obj['@initial']);
|
||||
|
||||
if (isNaN(constValue) === true) {
|
||||
constValue = 0;
|
||||
}
|
||||
}
|
||||
|
||||
constants[constName] = constValue;
|
||||
}
|
||||
|
||||
function addConstFromSlider(obj) {
|
||||
var constName, constValue, rangeBlobs;
|
||||
|
||||
// The name of the constant is obj['@var']. The value (initial) of
|
||||
// the constant is the second blob of the 'range' parameter of the
|
||||
// slider which is obj['@range']. Multiple sliders and/or inputs
|
||||
// can represent the same constant - therefore 'initial' is in
|
||||
// brackets. The range is a string composed of 3 blobs, separated
|
||||
// by commas.
|
||||
|
||||
if (typeof obj['@var'] === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
constName = obj['@var'];
|
||||
|
||||
if (typeof obj['@range'] !== 'string') {
|
||||
constValue = 0;
|
||||
} else {
|
||||
rangeBlobs = obj['@range'].split(',');
|
||||
|
||||
// We must have gotten exactly 3 blobs (pieces) from the split.
|
||||
if (rangeBlobs.length !== 3) {
|
||||
constValue = 0;
|
||||
} else {
|
||||
// Get the second blob from the split string.
|
||||
constValue = parseFloat(rangeBlobs[1]);
|
||||
|
||||
if (isNaN(constValue) === true) {
|
||||
constValue = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constants[constName] = constValue;
|
||||
}
|
||||
} // End-of: function State
|
||||
});
|
||||
|
||||
// End of wrapper for RequireJS. As you can see, we are passing
|
||||
// namespaced Require JS variables to an anonymous function. Within
|
||||
// it, you can use the standard requirejs(), require(), and define()
|
||||
// functions as if they were in the global namespace.
|
||||
}(RequireJS.requirejs, RequireJS.require, RequireJS.define)); // End-of: (function (requirejs, require, define)
|
||||
@@ -1,12 +1,14 @@
|
||||
<div align="center" id="${element_id}" class="${element_class}">
|
||||
<!-- xidden field to read configuration json from -->
|
||||
<div class="${element_class}" id="${element_id}_json" style="hidden"
|
||||
data-json="${configuration_json}"></div>
|
||||
<!-- hidden field to read configuration json from -->
|
||||
<div class="${element_class}" id="${element_id}_json" style="display: none;">
|
||||
${configuration_json}
|
||||
</div>
|
||||
|
||||
<!-- xidden field to read configuration json from -->
|
||||
<div class="${element_class}" id="${element_id}_plot_code" style="hidden"
|
||||
data-plot="${plot_code}"></div>
|
||||
<!-- hidden field to read configuration json from -->
|
||||
<div class="${element_class}" id="${element_id}_plot_code" style="display: none;">
|
||||
${plot_code}
|
||||
</div>
|
||||
|
||||
<!-- main xml with marked places for sliders, number and plots -->
|
||||
<!-- main xml with marked places for sliders, numbers, and plot -->
|
||||
${gst_html}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user