Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
I
insights
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
insights
Commits
e78558e9
Commit
e78558e9
authored
Mar 26, 2013
by
Vik Paruchuri
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix some labeling, add in axis titles
parent
806e774d
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
404 additions
and
8 deletions
+404
-8
anserv/modules/course_stats/course_stats.py
+4
-1
anserv/settings.py
+2
-0
anserv/templates/grade_distribution/student_grade_distribution.html
+18
-7
css_js_src/js/jquery.flot.axislabels.js
+140
-0
css_js_src/js/jquery.flot.tooltip.js
+240
-0
No files found.
anserv/modules/course_stats/course_stats.py
View file @
e78558e9
...
...
@@ -123,10 +123,13 @@ def problem_grades_view(fs, db, course, params):
return
course_grades_view_base
(
fs
,
db
,
course
,
type
,
params
)
def
course_grades_view_base
(
fs
,
db
,
course
,
type
,
params
):
y_label
=
"Count"
if
type
==
"course_grades"
:
query_data
=
course_grades_query
(
fs
,
db
,
course
,
params
)
x_label
=
"Weighted Score"
else
:
query_data
=
problem_grades_query
(
fs
,
db
,
course
,
params
)
x_label
=
"Unweighted Score"
json_data
=
query_data
[
'json'
]
results
=
json_data
[
'results'
]
headers
=
results
[
0
]
.
keys
()
...
...
@@ -143,7 +146,7 @@ def course_grades_view_base(fs, db, course, type,params):
tick_data
=
[
float
(
c
)
for
c
in
counter_keys
]
min_val
=
min
(
tick_data
+
[
0
])
max_val
=
max
(
tick_data
+
[
1
])
context_dict
=
{
'graph_name'
:
fixed_name
,
'chart_data'
:
counter_list
,
'graph_title'
:
header
,
'tick_data'
:
tick_data
,
'x_min'
:
min_val
,
'x_max'
:
max_val
}
context_dict
=
{
'graph_name'
:
fixed_name
,
'chart_data'
:
counter_list
,
'graph_title'
:
header
,
'tick_data'
:
tick_data
,
'x_min'
:
min_val
,
'x_max'
:
max_val
,
'x_label'
:
x_label
,
'y_label'
:
y_label
}
rendered_data
=
django
.
template
.
loader
.
render_to_string
(
"grade_distribution/student_grade_distribution.html"
,
context_dict
)
charts
.
append
(
rendered_data
)
chart_string
=
" "
.
join
(
charts
)
...
...
anserv/settings.py
View file @
e78558e9
...
...
@@ -277,6 +277,8 @@ PIPELINE_JS = {
'js/bootstrap.js'
,
'js/jquery-ui-1.10.2.custom.js'
,
'js/jquery.flot.patched-multi.js'
,
'js/jquery.flot.tooltip.js'
,
'js/jquery.flot.axislabels.js'
,
],
'output_filename'
:
'js/util.js'
,
},
...
...
anserv/templates/grade_distribution/student_grade_distribution.html
View file @
e78558e9
...
...
@@ -20,11 +20,6 @@ function render{{graph_name}}()
$
.
plot
(
$
(
"#"
+
graph_name
),
[
{
data
:
chart_data
,
bars
:
{
show
:
true
,
barWidth
:
1.0
/
((
chart_data
.
length
)
/
2
),
align
:
"center"
}
}],
{
...
...
@@ -32,13 +27,29 @@ function render{{graph_name}}()
hoverable
:
true
},
xaxis
:
{
axisLabel
:
'Score'
,
axisLabel
:
"{{x_label}}"
,
ticks
:
ticks
,
min
:
{{
x_min
}},
max
:
{{
x_max
}}
},
yaxis
:
{
axisLabel
:
'Count'
axisLabel
:
"{{y_label}}"
},
series
:
{
lines
:
{
show
:
true
},
points
:
{
radius
:
3
,
show
:
true
,
fill
:
true
}
},
tooltip
:
false
,
tooltipOpts
:
{
content
:
"Score: %x Count: %y"
,
shifts
:
{
x
:
-
60
,
y
:
25
}
}
}
);
...
...
css_js_src/js/jquery.flot.axislabels.js
0 → 100644
View file @
e78558e9
/*
CAxis Labels Plugin for flot. :P
Copyright (c) 2010 Xuan Luo
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
(
function
(
$
)
{
var
options
=
{
};
function
init
(
plot
)
{
// This is kind of a hack. There are no hooks in Flot between
// the creation and measuring of the ticks (setTicks, measureTickLabels
// in setupGrid() ) and the drawing of the ticks and plot box
// (insertAxisLabels in setupGrid() ).
//
// Therefore, we use a trick where we run the draw routine twice:
// the first time to get the tick measurements, so that we can change
// them, and then have it draw it again.
var
secondPass
=
false
;
plot
.
hooks
.
draw
.
push
(
function
(
plot
,
ctx
)
{
if
(
!
secondPass
)
{
// MEASURE AND SET OPTIONS
$
.
each
(
plot
.
getAxes
(),
function
(
axisName
,
axis
)
{
var
opts
=
axis
.
options
// Flot 0.7
||
plot
.
getOptions
()[
axisName
];
// Flot 0.6
if
(
!
opts
||
!
opts
.
axisLabel
)
return
;
var
w
,
h
;
if
(
opts
.
axisLabelUseCanvas
!=
false
)
opts
.
axisLabelUseCanvas
=
true
;
if
(
opts
.
axisLabelUseCanvas
)
{
// canvas text
if
(
!
opts
.
axisLabelFontSizePixels
)
opts
.
axisLabelFontSizePixels
=
14
;
if
(
!
opts
.
axisLabelFontFamily
)
opts
.
axisLabelFontFamily
=
'sans-serif'
;
// since we currently always display x as horiz.
// and y as vertical, we only care about the height
w
=
opts
.
axisLabelFontSizePixels
;
h
=
opts
.
axisLabelFontSizePixels
;
}
else
{
// HTML text
var
elem
=
$
(
'<div class="axisLabels" style="position:absolute;">'
+
opts
.
axisLabel
+
'</div>'
);
plot
.
getPlaceholder
().
append
(
elem
);
w
=
elem
.
outerWidth
(
true
);
h
=
elem
.
outerHeight
(
true
);
elem
.
remove
();
}
if
(
axisName
.
charAt
(
0
)
==
'x'
)
axis
.
labelHeight
+=
h
;
else
axis
.
labelWidth
+=
w
;
opts
.
labelHeight
=
axis
.
labelHeight
;
opts
.
labelWidth
=
axis
.
labelWidth
;
});
// re-draw with new label widths and heights
secondPass
=
true
;
plot
.
setupGrid
();
plot
.
draw
();
}
else
{
// DRAW
$
.
each
(
plot
.
getAxes
(),
function
(
axisName
,
axis
)
{
var
opts
=
axis
.
options
// Flot 0.7
||
plot
.
getOptions
()[
axisName
];
// Flot 0.6
if
(
!
opts
||
!
opts
.
axisLabel
)
return
;
if
(
opts
.
axisLabelUseCanvas
)
{
// canvas text
var
ctx
=
plot
.
getCanvas
().
getContext
(
'2d'
);
ctx
.
save
();
ctx
.
font
=
opts
.
axisLabelFontSizePixels
+
'px '
+
opts
.
axisLabelFontFamily
;
var
width
=
ctx
.
measureText
(
opts
.
axisLabel
).
width
;
var
height
=
opts
.
axisLabelFontSizePixels
;
var
x
,
y
;
if
(
axisName
.
charAt
(
0
)
==
'x'
)
{
x
=
plot
.
getPlotOffset
().
left
+
plot
.
width
()
/
2
-
width
/
2
;
y
=
plot
.
getCanvas
().
height
;
}
else
{
x
=
height
*
0.72
;
y
=
plot
.
getPlotOffset
().
top
+
plot
.
height
()
/
2
-
width
/
2
;
}
ctx
.
translate
(
x
,
y
);
ctx
.
rotate
((
axisName
.
charAt
(
0
)
==
'x'
)
?
0
:
-
Math
.
PI
/
2
);
ctx
.
fillText
(
opts
.
axisLabel
,
0
,
0
);
ctx
.
restore
();
}
else
{
// HTML text
plot
.
getPlaceholder
().
find
(
'#'
+
axisName
+
'Label'
).
remove
();
var
elem
=
$
(
'<div id="'
+
axisName
+
'Label" " class="axisLabels" style="position:absolute;">'
+
opts
.
axisLabel
+
'</div>'
);
if
(
axisName
.
charAt
(
0
)
==
'x'
)
{
elem
.
css
(
'left'
,
plot
.
getPlotOffset
().
left
+
plot
.
width
()
/
2
-
elem
.
outerWidth
()
/
2
+
'px'
);
elem
.
css
(
'bottom'
,
'0px'
);
}
else
{
elem
.
css
(
'top'
,
plot
.
getPlotOffset
().
top
+
plot
.
height
()
/
2
-
elem
.
outerHeight
()
/
2
+
'px'
);
elem
.
css
(
'left'
,
'0px'
);
}
plot
.
getPlaceholder
().
append
(
elem
);
}
});
secondPass
=
false
;
}
});
}
$
.
plot
.
plugins
.
push
({
init
:
init
,
options
:
options
,
name
:
'axisLabels'
,
version
:
'1.0'
});
})(
jQuery
);
css_js_src/js/jquery.flot.tooltip.js
0 → 100644
View file @
e78558e9
/*
* jquery.flot.tooltip
*
* description: easy-to-use tooltips for Flot charts
* version: 0.6.1
* author: Krzysztof Urbas @krzysu [myviews.pl]
* website: https://github.com/krzysu/flot.tooltip
*
* build on 2013-03-24
* released under MIT License, 2012
*/
(
function
(
$
)
{
// plugin options, default values
var
defaultOptions
=
{
tooltip
:
false
,
tooltipOpts
:
{
content
:
"%s | X: %x | Y: %y"
,
// allowed templates are:
// %s -> series label,
// %x -> X value,
// %y -> Y value,
// %x.2 -> precision of X value,
// %p -> percent
xDateFormat
:
null
,
yDateFormat
:
null
,
shifts
:
{
x
:
10
,
y
:
20
},
defaultTheme
:
true
,
// callbacks
onHover
:
function
(
flotItem
,
$tooltipEl
)
{}
}
};
// object
var
FlotTooltip
=
function
(
plot
)
{
// variables
this
.
tipPosition
=
{
x
:
0
,
y
:
0
};
this
.
init
(
plot
);
};
// main plugin function
FlotTooltip
.
prototype
.
init
=
function
(
plot
)
{
var
that
=
this
;
plot
.
hooks
.
bindEvents
.
push
(
function
(
plot
,
eventHolder
)
{
// get plot options
that
.
plotOptions
=
plot
.
getOptions
();
// if not enabled return
if
(
that
.
plotOptions
.
tooltip
===
false
||
typeof
that
.
plotOptions
.
tooltip
===
'undefined'
)
return
;
// shortcut to access tooltip options
that
.
tooltipOptions
=
that
.
plotOptions
.
tooltipOpts
;
// create tooltip DOM element
var
$tip
=
that
.
getDomElement
();
// bind event
$
(
plot
.
getPlaceholder
()
).
bind
(
"plothover"
,
function
(
event
,
pos
,
item
)
{
if
(
item
)
{
var
tipText
;
// convert tooltip content template to real tipText
tipText
=
that
.
stringFormat
(
that
.
tooltipOptions
.
content
,
item
);
$tip
.
html
(
tipText
)
.
css
({
left
:
that
.
tipPosition
.
x
+
that
.
tooltipOptions
.
shifts
.
x
,
top
:
that
.
tipPosition
.
y
+
that
.
tooltipOptions
.
shifts
.
y
})
.
show
();
// run callback
if
(
typeof
that
.
tooltipOptions
.
onHover
===
'function'
)
{
that
.
tooltipOptions
.
onHover
(
item
,
$tip
);
}
}
else
{
$tip
.
hide
().
html
(
''
);
}
});
eventHolder
.
mousemove
(
function
(
e
)
{
var
pos
=
{};
pos
.
x
=
e
.
pageX
;
pos
.
y
=
e
.
pageY
;
that
.
updateTooltipPosition
(
pos
);
});
});
};
/**
* get or create tooltip DOM element
* @return jQuery object
*/
FlotTooltip
.
prototype
.
getDomElement
=
function
()
{
var
$tip
;
if
(
$
(
'#flotTip'
).
length
>
0
){
$tip
=
$
(
'#flotTip'
);
}
else
{
$tip
=
$
(
'<div />'
).
attr
(
'id'
,
'flotTip'
);
$tip
.
appendTo
(
'body'
).
hide
().
css
({
position
:
'absolute'
});
if
(
this
.
tooltipOptions
.
defaultTheme
)
{
$tip
.
css
({
'background'
:
'#fff'
,
'z-index'
:
'100'
,
'padding'
:
'0.4em 0.6em'
,
'border-radius'
:
'0.5em'
,
'font-size'
:
'0.8em'
,
'border'
:
'1px solid #111'
});
}
}
return
$tip
;
};
// as the name says
FlotTooltip
.
prototype
.
updateTooltipPosition
=
function
(
pos
)
{
this
.
tipPosition
.
x
=
pos
.
x
;
this
.
tipPosition
.
y
=
pos
.
y
;
};
/**
* core function, create tooltip content
* @param {string} content - template with tooltip content
* @param {object} item - Flot item
* @return {string} real tooltip content for current item
*/
FlotTooltip
.
prototype
.
stringFormat
=
function
(
content
,
item
)
{
var
percentPattern
=
/%p
\.{0,1}(\d{0,})
/
;
var
seriesPattern
=
/%s/
;
var
xPattern
=
/%x
\.{0,1}(\d{0,})
/
;
var
yPattern
=
/%y
\.{0,1}(\d{0,})
/
;
// if it is a function callback get the content string
if
(
typeof
(
content
)
===
'function'
)
{
content
=
content
(
item
.
series
.
data
[
item
.
dataIndex
][
0
],
item
.
series
.
data
[
item
.
dataIndex
][
1
]);
}
// percent match for pie charts
if
(
typeof
(
item
.
series
.
percent
)
!==
'undefined'
)
{
content
=
this
.
adjustValPrecision
(
percentPattern
,
content
,
item
.
series
.
percent
);
}
// series match
if
(
typeof
(
item
.
series
.
label
)
!==
'undefined'
)
{
content
=
content
.
replace
(
seriesPattern
,
item
.
series
.
label
);
}
// time mode axes with custom dateFormat
if
(
this
.
isTimeMode
(
'xaxis'
,
item
)
&&
this
.
isXDateFormat
(
item
))
{
content
=
content
.
replace
(
xPattern
,
this
.
timestampToDate
(
item
.
series
.
data
[
item
.
dataIndex
][
0
],
this
.
tooltipOptions
.
xDateFormat
));
}
if
(
this
.
isTimeMode
(
'yaxis'
,
item
)
&&
this
.
isYDateFormat
(
item
))
{
content
=
content
.
replace
(
yPattern
,
this
.
timestampToDate
(
item
.
series
.
data
[
item
.
dataIndex
][
1
],
this
.
tooltipOptions
.
yDateFormat
));
}
// set precision if defined
if
(
typeof
item
.
series
.
data
[
item
.
dataIndex
][
0
]
===
'number'
)
{
content
=
this
.
adjustValPrecision
(
xPattern
,
content
,
item
.
series
.
data
[
item
.
dataIndex
][
0
]);
}
if
(
typeof
item
.
series
.
data
[
item
.
dataIndex
][
1
]
===
'number'
)
{
content
=
this
.
adjustValPrecision
(
yPattern
,
content
,
item
.
series
.
data
[
item
.
dataIndex
][
1
]);
}
// if no value customization, use tickFormatter by default
if
(
typeof
item
.
series
.
xaxis
.
tickFormatter
!==
'undefined'
)
{
content
=
content
.
replace
(
xPattern
,
item
.
series
.
xaxis
.
tickFormatter
(
item
.
series
.
data
[
item
.
dataIndex
][
0
],
item
.
series
.
xaxis
));
}
if
(
typeof
item
.
series
.
yaxis
.
tickFormatter
!==
'undefined'
)
{
content
=
content
.
replace
(
yPattern
,
item
.
series
.
yaxis
.
tickFormatter
(
item
.
series
.
data
[
item
.
dataIndex
][
1
],
item
.
series
.
yaxis
));
}
return
content
;
};
// helpers just for readability
FlotTooltip
.
prototype
.
isTimeMode
=
function
(
axisName
,
item
)
{
return
(
typeof
item
.
series
[
axisName
].
options
.
mode
!==
'undefined'
&&
item
.
series
[
axisName
].
options
.
mode
===
'time'
);
};
FlotTooltip
.
prototype
.
isXDateFormat
=
function
(
item
)
{
return
(
typeof
this
.
tooltipOptions
.
xDateFormat
!==
'undefined'
&&
this
.
tooltipOptions
.
xDateFormat
!==
null
);
};
FlotTooltip
.
prototype
.
isYDateFormat
=
function
(
item
)
{
return
(
typeof
this
.
tooltipOptions
.
yDateFormat
!==
'undefined'
&&
this
.
tooltipOptions
.
yDateFormat
!==
null
);
};
//
FlotTooltip
.
prototype
.
timestampToDate
=
function
(
tmst
,
dateFormat
)
{
var
theDate
=
new
Date
(
tmst
);
return
$
.
plot
.
formatDate
(
theDate
,
dateFormat
);
};
//
FlotTooltip
.
prototype
.
adjustValPrecision
=
function
(
pattern
,
content
,
value
)
{
var
precision
;
if
(
content
.
match
(
pattern
)
!==
null
)
{
if
(
RegExp
.
$1
!==
''
)
{
precision
=
RegExp
.
$1
;
value
=
value
.
toFixed
(
precision
);
// only replace content if precision exists
content
=
content
.
replace
(
pattern
,
value
);
}
}
return
content
;
};
//
var
init
=
function
(
plot
)
{
new
FlotTooltip
(
plot
);
};
// define Flot plugin
$
.
plot
.
plugins
.
push
({
init
:
init
,
options
:
defaultOptions
,
name
:
'tooltip'
,
version
:
'0.6.1'
});
})(
jQuery
);
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