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
78a3b7cf
Commit
78a3b7cf
authored
Dec 12, 2012
by
Valera Rozuvan
Committed by
Alexander Kryklia
Jan 15, 2013
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added documentation for code. Fixed several minor issues. Added checks for some error cases.
parent
8efab2c9
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
132 additions
and
43 deletions
+132
-43
common/lib/xmodule/xmodule/js/src/graphical_slider_tool/graph.js
+124
-43
common/lib/xmodule/xmodule/js/src/graphical_slider_tool/gst_main.js
+8
-0
No files found.
common/lib/xmodule/xmodule/js/src/graphical_slider_tool/graph.js
View file @
78a3b7cf
...
...
@@ -9,29 +9,39 @@ define('Graph', [], function () {
function
Graph
(
gstId
,
config
,
state
)
{
var
plotDiv
,
dataSeries
,
functions
,
xaxis
,
yaxis
,
xrange
;
// We must have a graph container DIV element available in order to
// proceed.
plotDiv
=
$
(
'#'
+
gstId
+
'_plot'
);
if
(
plotDiv
.
length
===
0
)
{
return
;
}
// Configure some settings for the graph.
setGraphDimensions
();
setGraphAxes
();
setGraphXRange
();
state
.
bindUpdatePlotEvent
(
plotDiv
,
onUpdatePlot
);
// Get the user defined functions. If there aren't any, don't do
// anything else.
createFunctions
();
if
(
functions
.
length
===
0
)
{
return
;
}
// Create the initial graph and plot it for the user to see.
generateData
();
updatePlot
();
// Bind an event. Whenever some constant changes, the graph will be
// redrawn
state
.
bindUpdatePlotEvent
(
plotDiv
,
onUpdatePlot
);
return
;
function
setGraphDimensions
()
{
var
dimObj
,
width
,
height
,
tempInt
;
// If no dimensions are specified by the user, the graph have
// If no dimensions are specified by the user, the graph
will
have
// predefined dimensions.
width
=
300
;
height
=
300
;
...
...
@@ -51,27 +61,30 @@ define('Graph', [], function () {
}
}
// Apply the dimensions to the graph container DIV element.
plotDiv
.
width
(
width
);
plotDiv
.
height
(
height
);
}
function
setGraphAxes
()
{
// Define the xaxis Flot configuration, and then see if the user
// supplied custom values.
xaxis
=
{
'min'
:
0
,
'tickSize'
:
3
,
'max'
:
3
0
'tickSize'
:
1
,
'max'
:
1
0
};
if
(
typeof
config
.
plot
[
'xticks'
]
===
'string'
)
{
processTicks
(
config
.
plot
[
'xticks'
],
xaxis
);
}
// Define the yaxis Flot configuration, and then see if the user
// supplied custom values.
yaxis
=
{
'min'
:
-
5
,
'min'
:
0
,
'tickSize'
:
1
,
'max'
:
5
'max'
:
10
};
if
(
typeof
config
.
plot
[
'yticks'
]
===
'string'
)
{
processTicks
(
config
.
plot
[
'yticks'
],
yaxis
);
}
...
...
@@ -79,34 +92,41 @@ define('Graph', [], function () {
return
;
function
processTicks
(
ticksStr
,
ticksObj
)
{
var
ticksBlobs
,
min
,
tickSize
,
max
;
var
ticksBlobs
,
tempFloat
;
// The 'ticks' setting is a string containing 3 floating-point
// numbers.
ticksBlobs
=
ticksStr
.
split
(
','
);
if
(
ticksBlobs
.
length
!==
3
)
{
return
;
}
min
=
parseFloat
(
ticksBlobs
[
0
]);
if
(
isNaN
(
min
)
===
false
)
{
ticksObj
.
min
=
min
;
tempFloat
=
parseFloat
(
ticksBlobs
[
0
]);
if
(
isNaN
(
tempFloat
)
===
false
)
{
ticksObj
.
min
=
tempFloat
;
}
t
ickSize
=
parseFloat
(
ticksBlobs
[
1
]);
if
(
isNaN
(
t
ickSize
)
===
false
)
{
ticksObj
.
tickSize
=
t
ickSize
;
t
empFloat
=
parseFloat
(
ticksBlobs
[
1
]);
if
(
isNaN
(
t
empFloat
)
===
false
)
{
ticksObj
.
tickSize
=
t
empFloat
;
}
max
=
parseFloat
(
ticksBlobs
[
2
]);
if
(
isNaN
(
max
)
===
false
)
{
ticksObj
.
max
=
max
;
tempFloat
=
parseFloat
(
ticksBlobs
[
2
]);
if
(
isNaN
(
tempFloat
)
===
false
)
{
ticksObj
.
max
=
tempFloat
;
}
// Is the starting tick to the left of the ending tick (on the
// x-axis)? If not, set default starting and ending tick.
if
(
ticksObj
.
min
>=
ticksObj
.
max
)
{
ticksObj
.
min
=
0
;
ticksObj
.
max
=
10
;
}
// Make sure the range makes sense - i.e. that there are at
// least 3 ticks. If not, set a tickSize which will produce
// 11 ticks. tickSize is the spacing between the ticks.
if
(
ticksObj
.
tickSize
*
2
>=
ticksObj
.
max
-
ticksObj
.
min
)
{
ticksObj
.
tickSize
=
(
ticksObj
.
max
-
ticksObj
.
min
)
/
10.0
;
}
...
...
@@ -118,10 +138,13 @@ define('Graph', [], function () {
xrange
=
{
'start'
:
0
,
'end'
:
3
0
,
'end'
:
1
0
,
'step'
:
0.1
};
// The 'xrange' is a string containing two floating point numbers
// separated by a comma. The first number is the starting
// x-coordinate , the second number is the ending x-coordinate
if
(
typeof
config
.
plot
[
'xrange'
]
===
'string'
)
{
xRangeStr
=
config
.
plot
[
'xrange'
];
xRangeBlobs
=
xRangeStr
.
split
(
','
);
...
...
@@ -138,13 +161,25 @@ define('Graph', [], function () {
xrange
.
end
=
tempNum
;
}
if
(
xrange
.
start
>=
xrange
.
end
)
{
xrange
.
start
=
0
;
xrange
.
end
=
10
;
}
}
}
// The user can specify the number of points. However, internally
// we will use it to generate a 'step' - i.e. the distance (on
// x-axis) between two adjacent points.
if
(
typeof
config
.
plot
[
'num_points'
]
===
'string'
)
{
tempNum
=
parseInt
(
config
.
plot
[
'num_points'
],
10
);
if
(
isNaN
(
tempNum
)
===
false
)
{
xrange
.
step
=
(
xrange
.
end
-
xrange
.
start
)
/
tempNum
;
if
(
(
isNaN
(
tempNum
)
===
false
)
&&
(
tempNum
>=
2
)
&&
(
tempNum
<=
500
)
)
{
xrange
.
step
=
(
xrange
.
end
-
xrange
.
start
)
/
(
tempNum
-
1
);
}
}
}
...
...
@@ -192,67 +227,97 @@ define('Graph', [], function () {
return
;
// This function will reduce code duplication
s
. We have to call
// This function will reduce code duplication. We have to call
// the function addFunction() several times passing object
// properties
. A
parameters. Rather than writing them out every
// time, we will have a single p
oint of
// properties
as
parameters. Rather than writing them out every
// time, we will have a single p
lace where it is done.
function
callAddFunction
(
obj
)
{
addFunction
(
obj
[
'#text'
],
obj
[
'@color'
],
obj
[
'@line'
],
obj
[
'@dot'
],
obj
[
'@label'
],
obj
[
'@style'
],
obj
[
'@point_size'
]
obj
[
'@label'
]
);
}
function
addFunction
(
funcString
,
color
,
line
,
dot
,
label
,
style
,
point_size
)
{
function
addFunction
(
funcString
,
color
,
line
,
dot
,
label
)
{
var
newFunctionObject
,
func
,
constNames
;
// The main requirement is function string. Without it we can't
// create a function, and the series cannot be calculated.
if
(
typeof
funcString
!==
'string'
)
{
return
;
}
newFunctionObject
=
{};
// Some defaults. If no options are set for the graph, we will
// make sure that at least a line is drawn for a function.
newFunctionObject
=
{
'line'
:
true
,
'dot'
:
false
};
// Get all of the constant names defined by the user in the
// XML.
constNames
=
state
.
getAllConstantNames
();
// The 'x' is always one of the function parameters.
constNames
.
push
(
'x'
);
// Must make sure that the function body also gets passed to
// the Function co
sn
tructor.
// the Function co
ns
tructor.
constNames
.
push
(
funcString
);
func
=
Function
.
apply
(
null
,
constNames
);
// Create the function from the function string, and all of the
// available constants + the 'x' variable as it's parameters.
// For this we will use the built-in Function object
// constructor.
//
// If something goes wrong during this step, most
// likely the user supplied an invalid JavaScript function body
// string. In this case we will not proceed.
try
{
func
=
Function
.
apply
(
null
,
constNames
);
}
catch
(
err
)
{
// Let's tell the user. He will see a nice red error
// message instead of a graph.
plotDiv
.
html
(
'<span style="color: red;">'
+
'Error while parsing JavaScript function body string!'
+
'</span>'
);
return
;
}
newFunctionObject
[
'func'
]
=
func
;
if
(
typeof
color
===
'string'
)
{
newFunctionObject
[
'color'
]
=
color
;
}
if
(
(
typeof
line
===
'boolean'
)
||
(
typeof
line
===
'string'
)
)
{
if
(
(
line
===
'true'
)
||
(
line
===
true
)
)
{
if
(
typeof
line
===
'string'
)
{
if
(
line
===
'true'
)
{
newFunctionObject
[
'line'
]
=
true
;
}
else
{
}
else
if
(
line
===
'false'
)
{
newFunctionObject
[
'line'
]
=
false
;
}
}
if
(
(
typeof
dot
===
'boolean'
)
||
(
typeof
dot
===
'string'
)
)
{
if
(
(
dot
===
'true'
)
||
(
dot
===
true
)
)
{
if
(
typeof
dot
===
'string'
)
{
if
(
dot
===
'true'
)
{
newFunctionObject
[
'dot'
]
=
true
;
}
else
{
}
else
if
(
dot
===
'false'
)
{
newFunctionObject
[
'dot'
]
=
false
;
}
}
// By default, if no preference was set, or if the preference
// is conflicting (we must have either line or dot, none is
// not an option), we will show line.
if
((
newFunctionObject
[
'dot'
]
===
false
)
&&
(
newFunctionObject
[
'line'
]
===
false
))
{
// If the preference is conflicting (we must have either line
// or dot, none is not an option), we will show line.
if
(
(
newFunctionObject
[
'dot'
]
===
false
)
&&
(
newFunctionObject
[
'line'
]
===
false
)
)
{
newFunctionObject
[
'line'
]
=
true
;
}
...
...
@@ -264,6 +329,8 @@ define('Graph', [], function () {
}
}
// The callback that will be called whenever a constant changes (gets
// updated via a slider or a text input).
function
onUpdatePlot
(
event
)
{
generateData
();
updatePlot
();
...
...
@@ -282,6 +349,7 @@ define('Graph', [], function () {
seriesObj
=
{};
dataPoints
=
[];
// Generate the data points.
for
(
x
=
xrange
.
start
;
x
<=
xrange
.
end
;
x
+=
xrange
.
step
)
{
// Push the 'x' variable to the end of the parameter array.
...
...
@@ -314,19 +382,25 @@ define('Graph', [], function () {
seriesObj
.
label
=
functionObj
.
label
;
}
// Should the data points be connected by a line?
seriesObj
.
lines
=
{
'show'
:
functionObj
.
line
};
// Should each data point be represented by a point on the
// graph?
seriesObj
.
points
=
{
'show'
:
functionObj
.
dot
};
// Add the newly created series object to the series set which
// will be plotted by Flot.
dataSeries
.
push
(
seriesObj
);
}
}
function
updatePlot
()
{
// Tell Flot to draw the graph to our specification.
$
.
plot
(
plotDiv
,
dataSeries
,
...
...
@@ -350,6 +424,13 @@ define('Graph', [], function () {
}
);
// The first time that the graph gets added to the page, the legend
// is created from scratch. When it appears, MathJax works some
// magic, and all of the specially marked TeX gets rendered nicely.
// The next time when we update the graph, no such thing happens.
// We must ask MathJax to typeset the legend again (well, we will
// ask it to look at our entire graph DIV), the next time it's
// worker queue is available.
MathJax
.
Hub
.
Queue
([
'Typeset'
,
MathJax
.
Hub
,
...
...
common/lib/xmodule/xmodule/js/src/graphical_slider_tool/gst_main.js
View file @
78a3b7cf
...
...
@@ -16,13 +16,21 @@ define(
function
GstMain
(
gstId
)
{
var
config
,
state
;
// Get the JSON configuration, and parse it, and store as an object.
config
=
JSON
.
parse
(
$
(
'#'
+
gstId
+
'_json'
).
html
()).
root
;
// Parse the configuration settings for sliders and text inputs, and
// extract all of the defined constants (their names along with their
// initial values).
state
=
State
(
gstId
,
config
);
// Create the sliders and the text inputs, attaching them to
// approriate constants.
Sliders
(
gstId
,
config
,
state
);
Inputs
(
gstId
,
config
,
state
);
// Configure and display the loop. Attach event for the graph to be
// updated on any change of a slider or a text input.
Graph
(
gstId
,
config
,
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