diff --git a/xadmin/static/xadmin/js/xadmin.plugin.charts.js b/xadmin/static/xadmin/js/xadmin.plugin.charts.js
index f99e23180..099853375 100644
--- a/xadmin/static/xadmin/js/xadmin.plugin.charts.js
+++ b/xadmin/static/xadmin/js/xadmin.plugin.charts.js
@@ -1,7 +1,7 @@
$(document).ready(function(){
function showTooltip(x, y, contents) {
- $('
' + contents + '
').css( {
+ $('').css( {
position: 'absolute',
display: 'none',
top: y + 5,
@@ -27,10 +27,15 @@ $(document).ready(function(){
$("#chart-tooltip").remove();
var x = item.series.xaxis.tickFormatter(item.datapoint[0], item.series.xaxis),
- y = item.series.yaxis.tickFormatter(item.datapoint[1], item.series.yaxis);
-
+ y = item.series.yaxis.tickFormatter(item.datapoint[1], item.series.yaxis);
+ if (item.series.xaxis.options.mode=="categories") {
+ x = item.series.data[item.dataIndex][0];
+ }
+ if (item.series.yaxis.options.mode=="categories") {
+ y = item.series.data[item.dataIndex][1];
+ }
showTooltip(item.pageX, item.pageY,
- item.series.label + " : " + x + " , " + y);
+ item.series.label + " :
(" + x + " , " + y+")");
}
} else {
$("#chart-tooltip").remove();
diff --git a/xadmin/static/xadmin/vendor/flot/jquery.flot.aggregate.js b/xadmin/static/xadmin/vendor/flot/jquery.flot.aggregate.js
new file mode 100644
index 000000000..3975b8073
--- /dev/null
+++ b/xadmin/static/xadmin/vendor/flot/jquery.flot.aggregate.js
@@ -0,0 +1,140 @@
+/* Flot plugin for plotting grouping and aggregating data based on a common axis value.
+
+Copyright (c) 2014 Jairus Martin (frmdstryr@gmail.com)
+Licensed under the MIT license.
+
+To enable it, you must specify aggregate: "count","min","max","avg", or "sum"
+on the axis to use as the grouping axis.
+
+ $.plot("#placeholder", data, { xaxis: { aggregate: "avg" } });
+
+The possible values for aggregate are:
+ null,"count","min","max","avg", or "sum"
+
+Can be used with categories consider a dataset like
+ $.plot("#placeholder", data, { xaxis: { mode:"categories", aggregate: "count" } });
+ [["Pass", 1], ["Fail", 1], ["Pass", 1]...].
+
+*/
+
+(function ($) {
+ var options = {
+ xaxis: {
+ aggregate:null // null,"count","min","max","avg", or "sum"
+ },
+ yaxis: {
+ aggregate:null // null,"count","min","max","avg", or "sum"
+ }
+ };
+
+ function groupByAxis(data,axis) {
+ var groupedData = {};
+ $.each(data,function(i,point){
+ if (!(point[axis] in groupedData)) {
+ groupedData[point[axis]] = [point];
+ } else {
+ groupedData[point[axis]].push(point);
+ }
+ });
+ return groupedData;
+ }
+
+ function processRawData(plot, series, data, datapoints) {
+ // if categories are enabled, we need to disable
+ // auto-transformation to numbers so the strings are intact
+ // for later processing
+
+ var xAggregate = series.xaxis.options.aggregate != null,
+ yAggregate = series.yaxis.options.aggregate != null;
+
+ if (!(xAggregate || yAggregate))
+ return;
+
+
+ var aggregateMethod = null;
+ var groupAxis = 0;
+ var axis = 1;
+ if (xAggregate) {
+ aggregateMethod = series.xaxis.options.aggregate;
+ } else if (yAggregate) {
+ aggregateMethod = series.yaxis.options.aggregate;
+ groupAxis = 1;
+ axis = 0;
+ }
+
+ var groupedData = groupByAxis(data,groupAxis);
+ var newData = [];
+ switch (aggregateMethod) {
+ case "count":
+ $.each(groupedData,function(group,points) {
+ if (xAggregate){
+ newData.push([group,points.length]);
+ } else {
+ newData.push([points.length,group]);
+ }
+ });
+ break;
+ case "min":
+ $.each(groupedData,function(group,points) {
+ var yMin = points[0][axis];
+ $.each(points,function(i,point){yMin = Math.min(yMin,point[axis]);});
+ if (xAggregate){
+ newData.push([group,yMin]);
+ } else {
+ newData.push([yMin,group]);
+ }
+ });
+ break;
+ case "max":
+ $.each(groupedData,function(group,points) {
+ var yMax = points[0][axis];
+ $.each(points,function(i,point){yMax = Math.max(yMax,point[axis]);});
+ if (xAggregate){
+ newData.push([group,yMax]);
+ } else {
+ newData.push([yMax,group]);
+ }
+ });
+ break;
+ case "avg":
+ $.each(groupedData,function(group,points) {
+ var sum = 0;
+ $.each(points,function(i,point){sum+=point[axis];});
+ var avg = sum/points.length;
+ if (xAggregate){
+ newData.push([group,avg]);
+ } else {
+ newData.push([avg,group]);
+ }
+ });
+ break;
+ case "sum":
+ $.each(groupedData,function(group,points) {
+ var sum = 0;
+ $.each(points,function(i,point){sum+=point[axis];});
+ if (xAggregate){
+ newData.push([group,sum]);
+ } else {
+ newData.push([sum,group]);
+ }
+ });
+ break;
+ default:
+ return;
+ }
+ series.data = newData;
+ data = newData;
+ }
+
+
+ function init(plot) {
+ plot.hooks.processRawData.push(processRawData);
+ }
+
+ $.plot.plugins.push({
+ init: init,
+ options: options,
+ name: 'aggregate',
+ version: '1.0'
+ });
+})(jQuery);
diff --git a/xadmin/vendors.py b/xadmin/vendors.py
index 643cb9d8c..8eb947e2f 100644
--- a/xadmin/vendors.py
+++ b/xadmin/vendors.py
@@ -63,7 +63,7 @@
"flot": {
"js": {
'dev': ['xadmin/vendor/flot/jquery.flot.js', 'xadmin/vendor/flot/jquery.flot.pie.js', 'xadmin/vendor/flot/jquery.flot.time.js',
- 'xadmin/vendor/flot/jquery.flot.resize.js']
+ 'xadmin/vendor/flot/jquery.flot.resize.js','xadmin/vendor/flot/jquery.flot.aggregate.js','xadmin/vendor/flot/jquery.flot.categories.js']
}
},
"image-gallery": {