Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
dc42f181
Commit
dc42f181
authored
Dec 17, 2012
by
Valera Rozuvan
Committed by
Alexander Kryklia
Jan 15, 2013
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
GST: work in progress on refactoring.
parent
488140bf
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
208 additions
and
334 deletions
+208
-334
common/lib/xmodule/xmodule/gst_module.py
+2
-2
common/lib/xmodule/xmodule/js/src/graphical_slider_tool/graph.js
+14
-14
common/lib/xmodule/xmodule/js/src/graphical_slider_tool/gst_main.js
+9
-6
common/lib/xmodule/xmodule/js/src/graphical_slider_tool/inputs.js
+51
-94
common/lib/xmodule/xmodule/js/src/graphical_slider_tool/sliders.js
+32
-184
common/lib/xmodule/xmodule/js/src/graphical_slider_tool/state.js
+100
-34
No files found.
common/lib/xmodule/xmodule/gst_module.py
View file @
dc42f181
...
@@ -85,7 +85,7 @@ class GraphicalSliderToolModule(XModule):
...
@@ -85,7 +85,7 @@ class GraphicalSliderToolModule(XModule):
#substitute sliders
#substitute sliders
slider_div
=
'<div class="{element_class}_slider"
\
slider_div
=
'<div class="{element_class}_slider"
\
id="{element_id}_slider_{var}"
\
id="{element_id}_slider_{var}"
\
data-var="{var}" data-el_width="{width}"
\
data-var="{var}" data-el_width="{width}"
>
\
</div>'
</div>'
for
var
in
variables
:
for
var
in
variables
:
# find $slider var='var' ... $
# find $slider var='var' ... $
...
@@ -151,7 +151,7 @@ class GraphicalSliderToolModule(XModule):
...
@@ -151,7 +151,7 @@ class GraphicalSliderToolModule(XModule):
"""
"""
# root added for interface compatibility with xmltodict.parse
# root added for interface compatibility with xmltodict.parse
self
.
configuration_json
=
json
.
dumps
(
self
.
configuration_json
=
json
.
dumps
(
xmltodict
.
parse
(
'<root>'
+
xmltodict
.
parse
(
'<root
class="'
+
self
.
location
.
category
+
'"
>'
+
stringify_children
(
self
.
definition
[
'configuration'
])
stringify_children
(
self
.
definition
[
'configuration'
])
+
'</root>'
))
+
'</root>'
))
return
self
.
configuration_json
return
self
.
configuration_json
...
...
common/lib/xmodule/xmodule/js/src/graphical_slider_tool/graph.js
View file @
dc42f181
...
@@ -268,7 +268,7 @@ define('Graph', ['logme'], function (logme) {
...
@@ -268,7 +268,7 @@ define('Graph', ['logme'], function (logme) {
}
}
function
addFunction
(
funcString
,
color
,
line
,
dot
,
label
)
{
function
addFunction
(
funcString
,
color
,
line
,
dot
,
label
)
{
var
newFunctionObject
,
func
,
const
Names
;
var
newFunctionObject
,
func
,
param
Names
;
// The main requirement is function string. Without it we can't
// The main requirement is function string. Without it we can't
// create a function, and the series cannot be calculated.
// create a function, and the series cannot be calculated.
...
@@ -283,19 +283,19 @@ define('Graph', ['logme'], function (logme) {
...
@@ -283,19 +283,19 @@ define('Graph', ['logme'], function (logme) {
'dot'
:
false
'dot'
:
false
};
};
// Get all of the
constant
names defined by the user in the
// Get all of the
parameter
names defined by the user in the
// XML.
// XML.
constNames
=
state
.
getAllConstant
Names
();
paramNames
=
state
.
getAllParameter
Names
();
// The 'x' is always one of the function parameters.
// The 'x' is always one of the function parameters.
const
Names
.
push
(
'x'
);
param
Names
.
push
(
'x'
);
// Must make sure that the function body also gets passed to
// Must make sure that the function body also gets passed to
// the Function constructor.
// the Function constructor.
const
Names
.
push
(
funcString
);
param
Names
.
push
(
funcString
);
// Create the function from the function string, and all of the
// Create the function from the function string, and all of the
// available
constants +
the 'x' variable as it's parameters.
// available
parameters AND
the 'x' variable as it's parameters.
// For this we will use the built-in Function object
// For this we will use the built-in Function object
// constructor.
// constructor.
//
//
...
@@ -303,7 +303,7 @@ define('Graph', ['logme'], function (logme) {
...
@@ -303,7 +303,7 @@ define('Graph', ['logme'], function (logme) {
// likely the user supplied an invalid JavaScript function body
// likely the user supplied an invalid JavaScript function body
// string. In this case we will not proceed.
// string. In this case we will not proceed.
try
{
try
{
func
=
Function
.
apply
(
null
,
const
Names
);
func
=
Function
.
apply
(
null
,
param
Names
);
}
catch
(
err
)
{
}
catch
(
err
)
{
// Let's tell the user. He will see a nice red error
// Let's tell the user. He will see a nice red error
// message instead of a graph.
// message instead of a graph.
...
@@ -363,9 +363,9 @@ define('Graph', ['logme'], function (logme) {
...
@@ -363,9 +363,9 @@ define('Graph', ['logme'], function (logme) {
}
}
function
generateData
()
{
function
generateData
()
{
var
c0
,
functionObj
,
seriesObj
,
dataPoints
,
const
Values
,
x
,
y
;
var
c0
,
functionObj
,
seriesObj
,
dataPoints
,
param
Values
,
x
,
y
;
constValues
=
state
.
getAllConstant
Values
();
paramValues
=
state
.
getAllParameter
Values
();
dataSeries
=
[];
dataSeries
=
[];
...
@@ -379,16 +379,16 @@ define('Graph', ['logme'], function (logme) {
...
@@ -379,16 +379,16 @@ define('Graph', ['logme'], function (logme) {
for
(
x
=
xrange
.
start
;
x
<=
xrange
.
end
;
x
+=
xrange
.
step
)
{
for
(
x
=
xrange
.
start
;
x
<=
xrange
.
end
;
x
+=
xrange
.
step
)
{
// Push the 'x' variable to the end of the parameter array.
// Push the 'x' variable to the end of the parameter array.
const
Values
.
push
(
x
);
param
Values
.
push
(
x
);
// We call the user defined function, passing all of the
// We call the user defined function, passing all of the
// available
constant values. i
nside this function they
// available
parameter values. I
nside this function they
// will be accessible by their names.
// will be accessible by their names.
y
=
functionObj
.
func
.
apply
(
window
,
const
Values
);
y
=
functionObj
.
func
.
apply
(
window
,
param
Values
);
// Return the
const
Values array to how it was before we
// Return the
param
Values array to how it was before we
// added 'x' variable to the end of it.
// added 'x' variable to the end of it.
const
Values
.
pop
();
param
Values
.
pop
();
// Add the generated point to the data points set.
// Add the generated point to the data points set.
dataPoints
.
push
([
x
,
y
]);
dataPoints
.
push
([
x
,
y
]);
...
...
common/lib/xmodule/xmodule/js/src/graphical_slider_tool/gst_main.js
View file @
dc42f181
...
@@ -8,26 +8,29 @@ define(
...
@@ -8,26 +8,29 @@ define(
// Even though it is not explicitly in this module, we have to specify
// Even though it is not explicitly in this module, we have to specify
// 'GeneralMethods' as a dependency. It expands some of the core JS objects
// 'GeneralMethods' as a dependency. It expands some of the core JS objects
// with additional useful methods that are used in other modules.
// with additional useful methods that are used in other modules.
[
'State'
,
'GeneralMethods'
,
'Sliders'
,
'Inputs'
,
'Graph'
],
[
'State'
,
'GeneralMethods'
,
'Sliders'
,
'Inputs'
,
'Graph'
,
'logme'
],
function
(
State
,
GeneralMethods
,
Sliders
,
Inputs
,
Graph
)
{
function
(
State
,
GeneralMethods
,
Sliders
,
Inputs
,
Graph
,
logme
)
{
return
GstMain
;
return
GstMain
;
function
GstMain
(
gstId
)
{
function
GstMain
(
gstId
)
{
var
config
,
state
;
var
config
,
gstClass
,
state
;
// Get the JSON configuration, and parse it, and store as an object.
// Get the JSON configuration, and parse it, and store as an object.
config
=
JSON
.
parse
(
$
(
'#'
+
gstId
+
'_json'
).
html
()).
root
;
config
=
JSON
.
parse
(
$
(
'#'
+
gstId
+
'_json'
).
html
()).
root
;
gstClass
=
config
[
'@class'
];
logme
(
'gstClass: '
+
gstClass
);
// Parse the configuration settings for sliders and text inputs, and
// Parse the configuration settings for sliders and text inputs, and
// extract all of the defined constants (their names along with their
// extract all of the defined constants (their names along with their
// initial values).
// initial values).
state
=
State
(
gstId
,
config
);
state
=
State
(
gstId
,
gstClass
,
config
);
// Create the sliders and the text inputs, attaching them to
// Create the sliders and the text inputs, attaching them to
// approriate constants.
// approriate constants.
Sliders
(
gstId
,
config
,
state
);
Sliders
(
gstId
,
gstClass
,
state
);
Inputs
(
gstId
,
config
,
state
);
Inputs
(
gstId
,
gstClass
,
state
);
// Configure and display the loop. Attach event for the graph to be
// Configure and display the loop. Attach event for the graph to be
// updated on any change of a slider or a text input.
// updated on any change of a slider or a text input.
...
...
common/lib/xmodule/xmodule/js/src/graphical_slider_tool/inputs.js
View file @
dc42f181
...
@@ -2,108 +2,60 @@
...
@@ -2,108 +2,60 @@
// define() functions from Require JS available inside the anonymous function.
// define() functions from Require JS available inside the anonymous function.
(
function
(
requirejs
,
require
,
define
)
{
(
function
(
requirejs
,
require
,
define
)
{
define
(
'Inputs'
,
[
],
function
(
)
{
define
(
'Inputs'
,
[
'logme'
],
function
(
logme
)
{
return
Inputs
;
return
Inputs
;
function
Inputs
(
gstId
,
config
,
state
)
{
function
Inputs
(
gstId
,
gstClass
,
state
)
{
var
constNamesUsed
;
var
c1
,
paramName
,
allParamNames
;
// There should not be more than one text input per a constant. This
// just does not make sense. However, nothing really prevents the user
// from specifying more than one text input for the same constant name.
// That's why we have to track which constant names already have
// text inputs for them, and prevent adding further text inputs to
// these constants.
//
// constNamesUsed is an object to which we will add properties having
// the name of the constant to which we are adding a text input to.
// When creating a new text input, we must consult with this object, to
// see if the constant name is not defined as it's property.
constNamesUsed
=
{};
// We will go thorugh all of the inputs, and those that have a valid
// '@var' property will be added to the page as a HTML text input
// element.
if
((
typeof
config
.
inputs
!==
'undefined'
)
&&
(
typeof
config
.
inputs
.
input
!==
'undefined'
))
{
if
(
$
.
isArray
(
config
.
inputs
.
input
))
{
// config.inputs.input is an array. For each element, we will
// add a text input.
for
(
c1
=
0
;
c1
<
config
.
inputs
.
input
.
length
;
c1
++
)
{
createInput
(
config
.
inputs
.
input
[
c1
]);
}
}
else
if
(
$
.
isPlainObject
(
config
.
inputs
.
input
))
{
// config.inputs.input is an object. Add a text input for it.
allParamNames
=
state
.
getAllParameterNames
();
createInput
(
config
.
inputs
.
input
);
}
console
.
log
(
allParamNames
);
}
function
createInput
(
obj
)
{
for
(
c1
=
0
;
c1
<
allParamNames
.
length
;
c1
+=
1
)
{
var
constName
,
constValue
,
spanEl
,
inputEl
,
readOnly
;
$
(
'#'
+
gstId
).
children
(
'.'
+
gstClass
+
'_input'
).
each
(
function
(
index
,
value
)
{
var
inputDiv
,
paramName
;
// The name of the constant is obj['@var']. If it is not specified,
paramName
=
allParamNames
[
c1
];
// we will skip creating a text input for this constant.
if
(
typeof
obj
[
'@var'
]
!==
'string'
)
{
return
;
}
constName
=
obj
[
'@var'
];
// We will not add a text input for a constant which already has a
inputDiv
=
$
(
value
);
// text input defined for it.
//
// We will add the constant name to the 'constNamesUsed' object in
// the end, when everything went successfully.
if
(
constNamesUsed
.
hasOwnProperty
(
constName
))
{
return
;
}
// Multiple sliders and/or inputs can represent the same constant.
if
(
paramName
===
inputDiv
.
data
(
'var'
))
{
// Therefore we will get the most recent const value from the state
createInput
(
inputDiv
,
paramName
);
// object. If it is undefined, we will skip creating a text input
}
// for this constant.
});
constValue
=
state
.
getConstValue
(
constName
);
}
if
(
constValue
===
undefined
)
{
return
;
}
// With the constant name, and the constant value being defined,
return
;
// lets get the element on the page into which the text input will
// be inserted.
spanEl
=
$
(
'#'
+
gstId
+
'_input_'
+
constName
);
// If a corresponding element for this constant does not exist on
function
createInput
(
inputDiv
,
paramName
)
{
// the page, we will not be making a text input.
var
paramObj
,
inputWidth
,
readOnly
;
if
(
spanEl
.
length
===
0
)
{
return
;
paramObj
=
state
.
getParamObj
(
paramName
);
// We will define the width of the slider to a sensible default.
inputWidth
=
400
;
// See if it was specified by the user.
if
(
isFinite
(
parseInt
(
inputDiv
.
data
(
'el_width'
)))
===
true
)
{
inputWidth
=
parseInt
(
inputDiv
.
data
(
'el_width'
));
}
}
//
Create the text input
element.
//
Set the width of the
element.
input
El
=
$
(
'<input type"text" />'
);
input
Div
.
width
(
inputWidth
);
// Set the current constant to the text input. It will be visible
inputDiv
.
css
(
'display'
,
'inline-block'
);
// to the user.
inputEl
.
val
(
constValue
);
// Before binding a 'change' event, we will check if this text
readOnly
=
false
;
// input is specified as 'read only'.
if
(
inputDiv
.
attr
(
'data-el_readonly'
).
toLowerCase
()
===
'true'
)
{
//
readOnly
=
true
;
// By default, this setting is false - the user can change the
// value in the text input.
readonly
=
false
;
if
(
typeof
obj
[
'@readonly'
]
===
'string'
)
{
if
(
obj
[
'@readonly'
]
===
'true'
)
{
readonly
=
true
;
}
}
}
if
(
read
o
nly
===
true
)
{
if
(
read
O
nly
===
true
)
{
// In the case of a readonly config option, configure the text
// In the case of a readonly config option, configure the text
// inputit as read-only, and NOT bind an event to it.
// inputit as read-only, and NOT bind an event to it.
input
El
.
attr
(
'readonly'
,
'readonly'
);
input
Div
.
attr
(
'readonly'
,
'readonly'
);
}
else
{
// readonly !== true
}
else
{
// readonly !== true
...
@@ -111,14 +63,16 @@ define('Inputs', [], function () {
...
@@ -111,14 +63,16 @@ define('Inputs', [], function () {
// the value of this text input, and presses 'enter' (or clicks
// the value of this text input, and presses 'enter' (or clicks
// somewhere else on the page), this event will be triggered, and
// somewhere else on the page), this event will be triggered, and
// our callback will be called.
// our callback will be called.
input
El
.
bind
(
'change'
,
inputOnChange
);
input
Div
.
bind
(
'change'
,
inputOnChange
);
}
}
inputDiv
.
val
(
paramObj
.
value
);
// Lets style the input element nicely. We will use the button()
// Lets style the input element nicely. We will use the button()
// widget for this since there is no native widget for the text
// widget for this since there is no native widget for the text
// input.
// input.
input
El
.
button
().
css
({
input
Div
.
button
().
css
({
'font'
:
'inherit'
,
'font'
:
'inherit'
,
'color'
:
'inherit'
,
'color'
:
'inherit'
,
'text-align'
:
'left'
,
'text-align'
:
'left'
,
...
@@ -128,19 +82,22 @@ define('Inputs', [], function () {
...
@@ -128,19 +82,22 @@ define('Inputs', [], function () {
// 'width': '50px'
// 'width': '50px'
});
});
// And finally, publish the text input element to the page.
paramObj
.
inputDivs
.
push
(
inputDiv
);
inputEl
.
appendTo
(
spanEl
);
// Don't forget to add the constant to the list of used constants.
// Next time a slider for this constant will not be created.
constNamesUsed
[
constName
]
=
true
;
return
;
return
;
// When the user changes the value of this text input, the 'state'
// Update the 'state' - i.e. set the value of the parameter this
// will be updated, forcing the plot to be redrawn.
// input is attached to to a new value.
//
// This will cause the plot to be redrawn each time after the user
// changes the value in the input. Note that he has to either press
// 'Enter', or click somewhere else on the page in order for the
// 'change' event to be tiggered.
function
inputOnChange
(
event
)
{
function
inputOnChange
(
event
)
{
state
.
setConstValue
(
constName
,
$
(
this
).
val
());
var
inputDiv
;
inputDiv
=
$
(
this
);
state
.
setParameterValue
(
paramName
,
inputDiv
.
val
(),
inputDiv
);
}
}
}
}
}
}
...
...
common/lib/xmodule/xmodule/js/src/graphical_slider_tool/sliders.js
View file @
dc42f181
...
@@ -2,222 +2,70 @@
...
@@ -2,222 +2,70 @@
// define() functions from Require JS available inside the anonymous function.
// define() functions from Require JS available inside the anonymous function.
(
function
(
requirejs
,
require
,
define
)
{
(
function
(
requirejs
,
require
,
define
)
{
define
(
'Sliders'
,
[
],
function
(
)
{
define
(
'Sliders'
,
[
'logme'
],
function
(
logme
)
{
return
Sliders
;
return
Sliders
;
function
Sliders
(
gstId
,
config
,
state
)
{
function
Sliders
(
gstId
,
gstClass
,
state
)
{
var
constNamesUsed
;
var
c1
,
paramName
,
allParamNames
,
sliderDiv
;
// There should not be more than one slider per a constant. This just
// does not make sense. However, nothing really prevents the user from
// specifying more than one slider for the same constant name. That's
// why we have to track which constant names already have sliders for
// them, and prevent adding further sliders to these constants.
//
// constNamesUsed is an object to which we will add properties having
// the name of the constant to which we are adding a slider to. When
// creating a new slider, we must consult with this object, to see if
// the constant name is not defined as it's property.
constNamesUsed
=
{};
// 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 each object in the
// array, create a slider.
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. Create a slider for it.
createSlider
(
config
.
sliders
.
slider
);
}
allParamNames
=
state
.
getAllParameterNames
();
}
function
createSlider
(
obj
)
{
var
constName
,
constValue
,
rangeBlobs
,
valueMin
,
valueMax
,
spanEl
,
sliderEl
,
sliderWidth
;
// The name of the constant is obj['@var']. If it is not specified,
// we will skip creating a slider for this constant.
if
(
typeof
obj
[
'@var'
]
!==
'string'
)
{
return
;
}
constName
=
obj
[
'@var'
];
// We will not add a slider for a constant which already has a
// slider defined for it.
//
// We will add the constant name to the 'constNamesUsed' object in
// the end, when everything went successfully.
if
(
constNamesUsed
.
hasOwnProperty
(
constName
))
{
return
;
}
// Multiple sliders and/or inputs can represent the same constant.
// Therefore we will get the most recent const value from the state
// object. If it is undefined, then something terrible has
// happened! We will skip creating a slider for this constant.
constValue
=
state
.
getConstValue
(
constName
);
if
(
constValue
===
undefined
)
{
return
;
}
// The range is a string composed of 3 blobs, separated by commas.
for
(
c1
=
0
;
c1
<
allParamNames
.
length
;
c1
+=
1
)
{
// The first blob is the min value for the slider, the third blob
paramName
=
allParamNames
[
c1
];
// is the max value for the slider.
if
(
typeof
obj
[
'@range'
]
!==
'string'
)
{
// If the range is not a string, we will set a default range.
logme
(
'Looking for slider with ID: '
+
gstId
+
'_slider_'
+
paramName
);
// No promise as to the quality of the data points that this
sliderDiv
=
$
(
'#'
+
gstId
+
'_slider_'
+
paramName
);
// range will produce.
valueMin
=
constValue
-
10
;
valueMax
=
constValue
+
10
;
if
(
sliderDiv
.
length
===
1
)
{
logme
(
'Found one slider DIV with such an ID.'
);
createSlider
(
sliderDiv
,
paramName
);
}
else
{
}
else
{
logme
(
'Did not find such a slider.'
);
// Separate the range string by commas, and store each blob as
// an element in an array.
rangeBlobs
=
obj
[
'@range'
].
split
(
','
);
// We must have gotten exactly 3 blobs (pieces) from the split.
if
(
rangeBlobs
.
length
!==
3
)
{
// Set some sensible defaults, if the range string was
// split into more or less than 3 pieces.
setDefaultMinMax
();
}
else
{
// Get the first blob from the split string. It is the min
// value.
valueMin
=
parseFloat
(
rangeBlobs
[
0
]);
// Is it a well-formed float number?
if
(
isNaN
(
valueMin
)
===
true
)
{
// No? Then set a sensible default value.
valueMin
=
constValue
-
10
;
}
// Get the third blob from the split string. It is the max.
valueMax
=
parseFloat
(
rangeBlobs
[
2
]);
// Is it a well-formed float number?
if
(
isNaN
(
valueMax
)
===
true
)
{
// No? Then set a sensible default value.
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
))
{
// Set some sensible defaults, if min/value/max logic
// is broken.
setDefaultMinMax
();
}
}
}
}
}
// At this point we have the constant name, the constant value, and
function
createSlider
(
sliderDiv
,
paramName
)
{
// the min and max values for this slider. Lets get the element on
var
paramObj
,
sliderWidth
;
// the page into which the slider will be inserted.
spanEl
=
$
(
'#'
+
gstId
+
'_slider_'
+
constName
);
// If a corresponding element for this constant does not exist on
paramObj
=
state
.
getParamObj
(
paramName
);
// the page, we will not be making a slider.
if
(
spanEl
.
length
===
0
)
{
return
;
}
// Create the slider DIV.
sliderEl
=
$
(
'<div>'
);
// We will define the width of the slider to a sensible default.
// We will define the width of the slider to a sensible default.
sliderWidth
=
400
;
sliderWidth
=
400
;
// Then we will see if one is provided in the config for this
// See if it was specified by the user.
// slider. If we find it, and it is a well-formed integer, we will
if
(
isFinite
(
parseInt
(
sliderDiv
.
data
(
'el_width'
)))
===
true
)
{
// use it, instead of the default width.
sliderWidth
=
parseInt
(
sliderDiv
.
data
(
'el_width'
));
if
(
typeof
obj
[
'@width'
]
===
'string'
)
{
if
(
isNaN
(
parseInt
(
obj
[
'@width'
],
10
))
===
false
)
{
sliderWidth
=
parseInt
(
obj
[
'@width'
],
10
);
}
}
}
// Set the defined width to the slider.
// Set the width of the element.
// sliderEl.width(sliderWidth);
sliderDiv
.
width
(
sliderWidth
);
console
.
log
(
'[Before]'
);
console
.
log
(
'sliderEl.width: '
+
sliderEl
.
width
());
sliderEl
.
width
(
spanEl
.
data
(
'el_width'
));
console
.
log
(
'[After]'
);
console
.
log
(
'sliderEl.width: '
+
sliderEl
.
width
());
// And make sure that it gets added to the page as an
sliderDiv
.
css
(
'display'
,
'inline-block'
);
// 'inline-block' element. This will allow for the insertion of the
// slider into a paragraph, without the browser forcing it out of
// the paragraph onto a new line, separate line.
sliderEl
.
css
(
'display'
,
'inline-block'
);
// Create a jQuery UI slider from the slider DIV. We will set
// Create a jQuery UI slider from the slider DIV. We will set
// starting parameters, and will also attach a handler to update
// starting parameters, and will also attach a handler to update
// the 'state' on the 'change' event.
// the 'state' on the 'change' event.
slider
El
.
slider
({
slider
Div
.
slider
({
'min'
:
valueM
in
,
'min'
:
paramObj
.
m
in
,
'max'
:
valueM
ax
,
'max'
:
paramObj
.
m
ax
,
'value'
:
constV
alue
,
'value'
:
paramObj
.
v
alue
,
'step'
:
(
valueMax
-
valueMin
)
/
50.0
,
'step'
:
paramObj
.
step
,
// 'change': sliderOnChange,
// 'change': sliderOnChange,
'slide'
:
sliderOn
Chang
e
'slide'
:
sliderOn
Slid
e
});
});
// Append the slider DIV to the element on the page where the user
paramObj
.
sliderDiv
=
sliderDiv
;
// wants to see it.
sliderEl
.
appendTo
(
spanEl
);
// OK! So we made it this far...
//
// Adding the constant to the list of used constants. Next time a
// slider for this constant will not be created.
constNamesUsed
[
constName
]
=
true
;
return
;
return
;
// Update the 'state' - i.e. set the value of the
constant
this
// Update the 'state' - i.e. set the value of the
parameter
this
// slider is attached to to a new value.
// slider is attached to to a new value.
//
//
// This will cause the plot to be redrawn each time after the user
// This will cause the plot to be redrawn each time after the user
// drags the slider handle and releases it.
// drags the slider handle and releases it.
function
sliderOnChange
(
event
,
ui
)
{
function
sliderOnSlide
(
event
,
ui
)
{
state
.
setConstValue
(
constName
,
ui
.
value
);
state
.
setParameterValue
(
paramName
,
ui
.
value
,
sliderDiv
);
}
// The sensible defaults for the slider's range.
function
setDefaultMinMax
()
{
valueMin
=
constValue
-
10
;
valueMax
=
constValue
+
10
;
}
}
}
}
}
}
...
...
common/lib/xmodule/xmodule/js/src/graphical_slider_tool/state.js
View file @
dc42f181
...
@@ -13,11 +13,22 @@ define('State', ['logme'], function (logme) {
...
@@ -13,11 +13,22 @@ define('State', ['logme'], function (logme) {
return
State
;
return
State
;
// function: State
// function: State
function
State
(
gstId
,
config
)
{
function
State
(
gstId
,
gstClass
,
config
)
{
var
parameters
,
allParameterNames
,
allParameterValues
,
plotDiv
;
var
parameters
,
allParameterNames
,
allParameterValues
,
plotDiv
;
// Initially, there are no parameters to track. So, we will instantiate
// an empty object.
//
// As we parse the JSON config object, we will add parameters as
// named properties (for example
//
// parameters.a = {...};
//
// for the parameter 'a'.
parameters
=
{};
parameters
=
{};
// Check that the required object is available.
if
(
if
(
(
typeof
config
.
parameters
!==
'undefined'
)
&&
(
typeof
config
.
parameters
!==
'undefined'
)
&&
(
typeof
config
.
parameters
.
param
!==
'undefined'
)
(
typeof
config
.
parameters
.
param
!==
'undefined'
)
...
@@ -28,7 +39,7 @@ define('State', ['logme'], function (logme) {
...
@@ -28,7 +39,7 @@ define('State', ['logme'], function (logme) {
if
(
$
.
isArray
(
config
.
parameters
.
param
)
===
true
)
{
if
(
$
.
isArray
(
config
.
parameters
.
param
)
===
true
)
{
(
function
(
c1
)
{
(
function
(
c1
)
{
while
(
c1
<
config
.
parameters
.
param
.
length
)
{
while
(
c1
<
config
.
parameters
.
param
.
length
)
{
addConstFromInput
(
config
.
parameters
.
param
[
c1
]);
processParameter
(
config
.
parameters
.
param
[
c1
]);
c1
+=
1
;
c1
+=
1
;
}
}
}(
0
));
}(
0
));
...
@@ -37,44 +48,53 @@ define('State', ['logme'], function (logme) {
...
@@ -37,44 +48,53 @@ define('State', ['logme'], function (logme) {
// If config.parameters.param is an object, pass this object to the
// If config.parameters.param is an object, pass this object to the
// processor directly.
// processor directly.
else
if
(
$
.
isPlainObject
(
config
.
inputs
.
input
)
===
true
)
{
else
if
(
$
.
isPlainObject
(
config
.
inputs
.
input
)
===
true
)
{
addConstFromInput
(
config
.
parameters
.
param
);
processParameter
(
config
.
parameters
.
param
);
}
}
}
}
// Instead of building these arrays every time when some component
// requests them, we will create them in the beginning, and then update
// by element when some parameter's value changes.
//
// Then we can just return the required array, instead of iterating
// over all of the properties of the 'parameters' object, and
// extracting their names/values one by one.
allParameterNames
=
[];
allParameterValues
=
[];
generateHelperArrays
();
logme
(
parameters
,
allParameterNames
,
allParameterValues
);
// The constructor will return an object with methods to operate on
// The constructor will return an object with methods to operate on
// it's private properties.
// it's private properties.
return
{
return
{
'getParameterValue'
:
getParameterValue
,
'getParameterValue'
:
getParameterValue
,
'setParameterValue'
:
setParameterValue
,
'setParameterValue'
:
setParameterValue
,
'getParamObj'
:
getParamObj
,
'getAllParameterNames'
:
getAllParameterNames
,
'getAllParameterNames'
:
getAllParameterNames
,
'getAllParameterValues'
:
getAllParameterValues
,
'getAllParameterValues'
:
getAllParameterValues
,
'bindUpdatePlotEvent'
:
bindUpdatePlotEvent
'bindUpdatePlotEvent'
:
bindUpdatePlotEvent
};
};
// ####################################################################
function
getAllParameterNames
()
{
//
return
allParameterNames
;
// To get all parameter names, you would do:
}
//
// allParamNames = getAllParameterProperties('name');
//
// To get all parameter values, you would do:
//
// allParamValues = getAllParameterProperties('value');
//
// ####################################################################
function
getAllParameterProperties
(
propertyName
)
{
var
paramName
,
allParamProperties
;
allParamProperties
=
[];
function
getAllParameterValues
()
{
return
allParameterValues
;
}
for
(
paramName
in
parameters
)
{
function
getParamObj
(
paramName
)
{
allParamProperties
.
push
(
parameters
[
paramName
][
propertyName
]);
if
(
parameters
.
hasOwnProperty
(
paramName
)
===
false
)
{
return
;
}
}
return
allParamProperties
;
return
parameters
[
paramName
]
;
}
}
function
bindUpdatePlotEvent
(
newPlotDiv
,
callback
)
{
function
bindUpdatePlotEvent
(
newPlotDiv
,
callback
)
{
...
@@ -118,6 +138,8 @@ define('State', ['logme'], function (logme) {
...
@@ -118,6 +138,8 @@ define('State', ['logme'], function (logme) {
// the stored value in the parameter with the new value, and also
// the stored value in the parameter with the new value, and also
// update all of the text inputs and the slider that correspond to this
// update all of the text inputs and the slider that correspond to this
// parameter (if any), so that they reflect the new parameter's value.
// parameter (if any), so that they reflect the new parameter's value.
// Finally, the helper array 'allParameterValues' will also be updated
// to reflect the change.
//
//
// If something went wrong (for example the new value is outside the
// If something went wrong (for example the new value is outside the
// allowed range), then we will reset the 'element' to display the
// allowed range), then we will reset the 'element' to display the
...
@@ -125,29 +147,50 @@ define('State', ['logme'], function (logme) {
...
@@ -125,29 +147,50 @@ define('State', ['logme'], function (logme) {
//
//
// ####################################################################
// ####################################################################
function
setParameterValue
(
paramName
,
paramValue
,
element
)
{
function
setParameterValue
(
paramName
,
paramValue
,
element
)
{
var
inputDiv
;
var
paramValueNum
,
c1
;
if
(
constants
.
hasOwnProperty
(
constName
)
===
false
)
{
// If a parameter with the name specified by the 'paramName'
// If the name of the constant is not tracked by state, return an
// parameter is not tracked by state, do not do anything.
// 'undefined' value.
if
(
parameters
.
hasOwnProperty
(
paramName
)
===
false
)
{
return
;
return
;
}
}
if
(
isNaN
(
parseFloat
(
constValue
))
===
true
)
{
// Try to convert the passed value to a valid floating-point
// We are interested only in valid float values.
// number.
paramValueNum
=
parseFloat
(
paramValue
);
if
(
// We are interested only in valid float values. NaN, -INF,
// +INF we will disregard.
(
isFinite
(
paramValueNum
)
===
false
)
||
// If the new parameter's value is valid, but lies outised of
// the parameter's allowed range, we will also disregard it.
(
paramValueNum
<
parameters
[
paramName
].
min
)
||
(
paramValueNum
>
parameters
[
paramName
].
max
)
)
{
// We will also change the element's value back to the current
// parameter's value.
element
.
val
(
parameters
[
paramName
].
value
);
return
;
return
;
}
}
constants
[
constName
]
=
parseFloat
(
constValue
)
;
parameters
[
paramName
].
value
=
paramValueNum
;
if
(
plotDiv
!==
undefined
)
{
if
(
plotDiv
!==
undefined
)
{
plotDiv
.
trigger
(
'update_plot'
);
plotDiv
.
trigger
(
'update_plot'
);
}
}
inputDiv
=
$
(
'#'
+
gstId
+
'_input_'
+
constName
).
children
(
'input'
);
for
(
c1
=
0
;
c1
<
parameters
[
paramName
].
inputDivs
.
length
;
c1
+=
1
)
{
if
(
inputDiv
.
length
!==
0
)
{
parameters
[
paramName
].
inputDivs
[
c1
].
val
(
paramValueNum
);
inputDiv
.
val
(
constValue
);
}
if
(
parameters
[
paramName
].
sliderDiv
!==
null
)
{
parameters
[
paramName
].
sliderDiv
.
slider
(
'value'
,
paramValueNum
);
}
}
allParameterValues
[
parameters
[
paramName
].
helperArrayIndex
]
=
paramValueNum
;
}
// End-of: function setParameterValue
}
// End-of: function setParameterValue
// ####################################################################
// ####################################################################
...
@@ -156,7 +199,8 @@ define('State', ['logme'], function (logme) {
...
@@ -156,7 +199,8 @@ define('State', ['logme'], function (logme) {
// -------------------------------
// -------------------------------
//
//
//
//
// This function will be run once for each instance of a GST.
// This function will be run once for each instance of a GST when
// parsing the JSON config object.
//
//
// 'newParamObj' must be empty from the start for each invocation of
// 'newParamObj' must be empty from the start for each invocation of
// this function, that's why we will declare it locally.
// this function, that's why we will declare it locally.
...
@@ -201,6 +245,7 @@ define('State', ['logme'], function (logme) {
...
@@ -201,6 +245,7 @@ define('State', ['logme'], function (logme) {
if
(
if
(
(
processFloat
(
'@min'
,
'min'
)
===
false
)
||
(
processFloat
(
'@min'
,
'min'
)
===
false
)
||
(
processFloat
(
'@max'
,
'max'
)
===
false
)
||
(
processFloat
(
'@max'
,
'max'
)
===
false
)
||
(
processFloat
(
'@step'
,
'step'
)
===
false
)
||
(
processFloat
(
'@initial'
,
'value'
)
===
false
)
(
processFloat
(
'@initial'
,
'value'
)
===
false
)
)
{
)
{
logme
(
'---> Not adding a parameter named "'
+
paramName
+
'".'
);
logme
(
'---> Not adding a parameter named "'
+
paramName
+
'".'
);
...
@@ -208,7 +253,10 @@ define('State', ['logme'], function (logme) {
...
@@ -208,7 +253,10 @@ define('State', ['logme'], function (logme) {
return
;
return
;
}
}
constants
[
constName
]
=
constValue
;
newParamObj
.
inputDivs
=
[];
newParamObj
.
sliderDiv
=
null
;
parameters
[
paramName
]
=
newParamObj
;
return
;
return
;
...
@@ -234,11 +282,29 @@ define('State', ['logme'], function (logme) {
...
@@ -234,11 +282,29 @@ define('State', ['logme'], function (logme) {
}
}
}
}
newParamObj
[
newAttrName
]
=
param
Value
;
newParamObj
[
newAttrName
]
=
attr
Value
;
return
true
;
return
true
;
}
// End-of: function processFloat
}
// End-of: function processFloat
}
// End-of: function processParameter
}
// End-of: function processParameter
// Populate 'allParameterNames' and 'allParameterValues' with data.
// Link each parameter object with the corresponding helper array via
// an index ('helperArrayIndex'). It will be the same for both of the
// arrays.
function
generateHelperArrays
()
{
var
paramName
,
c1
;
c1
=
0
;
for
(
paramName
in
parameters
)
{
allParameterNames
.
push
(
paramName
);
allParameterValues
.
push
(
parameters
[
paramName
].
value
);
parameters
[
paramName
].
helperArrayIndex
=
c1
;
c1
+=
1
;
}
}
}
// End-of: function State
}
// End-of: function State
});
});
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment