mirror of
https://github.com/YunoHost-Apps/lutim_ynh.git
synced 2024-09-03 19:36:24 +02:00
346 lines
12 KiB
JavaScript
346 lines
12 KiB
JavaScript
function SimpleGraph(data, labels, canvas, settings) {
|
|
|
|
this.settings = settings;
|
|
|
|
setStyleDefaults(settings);
|
|
|
|
this.dataSet = new DataSet(data, labels, this.settings);
|
|
this.grid = new Grid(this.dataSet, this.settings);
|
|
this.canvas = canvas;
|
|
|
|
this.draw = function() {
|
|
if (this.settings.drawGrid) {
|
|
this.grid.draw(this.canvas);
|
|
}
|
|
if (this.settings.yAxisCaption) {
|
|
this.dataSet.labelYAxis(this.grid, this.canvas);
|
|
}
|
|
this.dataSet.labelXAxis(this.grid, this.canvas);
|
|
this.dataSet.plot(this.grid, this.canvas);
|
|
};
|
|
|
|
this.replaceDataSet = function(dataSet) {
|
|
this.dataSet = new DataSet(dataSet, dataSet.labels, this.settings);
|
|
this.grid = new Grid(this.dataSet, this.settings);
|
|
};
|
|
|
|
this.plotCurrentDataSet = function() {
|
|
this.dataSet.plot(this.grid, this.canvas);
|
|
};
|
|
|
|
function setStyleDefaults(settings) {
|
|
var targets = ["xAxisLabel", "yAxisLabel", "yAxisCaption", "hoverLabel", "hoverValue"];
|
|
var types = ["Color", "Font", "FontSize", "FontWeight"];
|
|
jQuery.each(targets, function(index, target) {
|
|
jQuery.each(types, function(index, type) {
|
|
if (!settings[target + type]) {
|
|
settings[target + type] = settings["label" + type];
|
|
}
|
|
});
|
|
});
|
|
|
|
settings.labelStyle = {
|
|
font: settings.labelFontSize + '"' + settings.labelFont + '"',
|
|
fill: settings.labelColor
|
|
};
|
|
|
|
jQuery.each(targets, function(index, target) {
|
|
settings[target + "Style"] = {
|
|
font: settings[target + "FontSize"] + ' ' + settings[target + "Font"],
|
|
fill: settings[target + "Color"],
|
|
"font-weight": settings[target + "FontWeight"]
|
|
};
|
|
});
|
|
}
|
|
}
|
|
|
|
// Holds the data and labels to be plotted, provides methods for labelling the x and y axes,
|
|
// and for plotting it's own points. Each method requires a grid object for translating values to
|
|
// x,y pixel coordinates and a canvas object on which to draw.
|
|
function DataSet(data, labels, settings) {
|
|
this.data = data;
|
|
this.labels = labels;
|
|
this.settings = settings;
|
|
|
|
this.labelXAxis = function(grid, canvas) {
|
|
(function(ds) {
|
|
jQuery.each(ds.labels, function(i, label) {
|
|
var x = grid.x(i);
|
|
canvas.text(x + ds.settings.xAxisLabelOffset, ds.settings.height - 6, label).attr(ds.settings.xAxisLabelStyle);
|
|
});
|
|
})(this);
|
|
};
|
|
|
|
this.labelYAxis = function(grid, canvas) {
|
|
// Legend
|
|
canvas.rect(
|
|
grid.leftEdge - (30 + this.settings.yAxisOffset), //TODO PARAM - Label Colum Width
|
|
grid.topEdge,
|
|
30, //TODO PARAM - Label Column Width
|
|
grid.height
|
|
).attr({stroke: this.settings.lineColor, fill: this.settings.lineColor, opacity: 0.3}); //TODO PARAMS - legend border and fill style
|
|
|
|
for (var i = 1, ii = (grid.rows); i < (ii - this.settings.lowerBound/2); i = i + 2) {
|
|
var value = (ii - i)*2,
|
|
y = grid.y(value) + 4, // TODO: Value of 4 works for default dimensions, expect will need to scale
|
|
x = grid.leftEdge - (6 + this.settings.yAxisOffset);
|
|
canvas.text(x, y, value).attr(this.settings.yAxisLabelStyle);
|
|
}
|
|
var caption = canvas.text(
|
|
grid.leftEdge - (20 + this.settings.yAxisOffset),
|
|
(grid.height/2) + (this.settings.yAxisCaption.length / 2),
|
|
this.settings.yAxisCaption + " (" + this.settings.units + ")").attr(this.settings.yAxisCaptionStyle).rotate(270);
|
|
// Increase the offset for the next caption (if any)
|
|
this.settings.yAxisOffset = this.settings.yAxisOffset + 30;
|
|
};
|
|
|
|
this.plot = function(grid, canvas) {
|
|
var line_path = canvas.path({
|
|
stroke: this.settings.lineColor,
|
|
"stroke-width": this.settings.lineWidth,
|
|
"stroke-linejoin": this.settings.lineJoin
|
|
});
|
|
|
|
var fill_path = canvas.path({
|
|
stroke: "none",
|
|
fill: this.settings.fillColor,
|
|
opacity: this.settings.fillOpacity
|
|
}).moveTo(this.settings.leftGutter, this.settings.height - this.settings.bottomGutter);
|
|
|
|
var bars = canvas.group(),
|
|
dots = canvas.group(),
|
|
cover = canvas.group();
|
|
|
|
var hoverFrame = dots.rect(10, 10, 100, 40, 5).attr({
|
|
fill: "#fff", stroke: "#474747", "stroke-width": 2}).hide(); //TODO PARAM - fill colour, border colour, border width
|
|
var hoverText = [];
|
|
hoverText[0] = canvas.text(60, 25, "").attr(this.settings.hoverValueStyle).hide();
|
|
hoverText[1] = canvas.text(60, 40, "").attr(this.settings.hoverLabelStyle).hide();
|
|
|
|
// Plot the points
|
|
(function(dataSet) {
|
|
jQuery.each(dataSet.data, function(i, value) {
|
|
var y = grid.y(value),
|
|
x = grid.x(i),
|
|
label = dataSet.labels ? dataSet.labels[i] : " ";
|
|
|
|
if (dataSet.settings.drawPoints) {
|
|
var dot = dots.circle(x, y, dataSet.settings.pointRadius).attr({fill: dataSet.settings.pointColor, stroke: dataSet.settings.pointColor});
|
|
}
|
|
if (dataSet.settings.drawBars) {
|
|
bars.rect(x + dataSet.settings.barOffset, y, dataSet.settings.barWidth, (dataSet.settings.height - dataSet.settings.bottomGutter) - y).attr({fill: dataSet.settings.barColor, stroke: "none"});
|
|
}
|
|
if (dataSet.settings.drawLine) {
|
|
line_path[i == 0 ? "moveTo" : "cplineTo"](x, y, 5);
|
|
}
|
|
if (dataSet.settings.fillUnderLine) {
|
|
fill_path[i == 0 ? "lineTo" : "cplineTo"](x, y, 5);
|
|
}
|
|
if (dataSet.settings.addHover) {
|
|
var rect = canvas.rect(x - 50, y - 50, 100, 100).attr({stroke: "none", fill: "#fff", opacity: 0}); //TODO PARAM - hover target width / height
|
|
jQuery(rect[0]).hover( function() {
|
|
jQuery.fn.simplegraph.hoverIn(canvas, value, label, x, y, hoverFrame, hoverText, dot, dataSet.settings);
|
|
},
|
|
function() {
|
|
jQuery.fn.simplegraph.hoverOut(canvas, hoverFrame, hoverText, dot, dataSet.settings);
|
|
});
|
|
}
|
|
});
|
|
})(this);
|
|
|
|
if (this.settings.fillUnderLine) {
|
|
fill_path.lineTo(grid.x(this.data.length - 1), this.settings.height - this.settings.bottomGutter).andClose();
|
|
}
|
|
hoverFrame.toFront();
|
|
};
|
|
}
|
|
|
|
// Holds the dimensions of the grid, and provides methods to convert values into x,y
|
|
// pixel coordinates. Also, provides a method to draw a grid on a supplied canvas.
|
|
function Grid(dataSet, settings) {
|
|
this.dataSet = dataSet;
|
|
this.settings = settings;
|
|
|
|
this.calculateMaxYAxis = function() {
|
|
var max = Math.max.apply(Math, this.dataSet.data),
|
|
maxOveride = this.settings.minYAxisValue;
|
|
if (maxOveride && maxOveride > max) {
|
|
max = maxOveride;
|
|
}
|
|
return max;
|
|
};
|
|
|
|
this.setYAxis = function() {
|
|
this.height = this.settings.height - this.settings.topGutter - this.settings.bottomGutter;
|
|
this.maxValueYAxis = this.calculateMaxYAxis();
|
|
this.Y = this.height / (this.maxValueYAxis - this.settings.lowerBound);
|
|
};
|
|
|
|
this.setXAxis = function() {
|
|
this.X = (this.settings.width - this.settings.leftGutter) / (this.dataSet.data.length - 0.4);
|
|
};
|
|
|
|
this.setDimensions = function() {
|
|
this.leftEdge = this.settings.leftGutter;
|
|
this.topEdge = this.settings.topGutter;
|
|
this.width = this.settings.width - this.settings.leftGutter - this.X;
|
|
this.columns = this.dataSet.data.length - 1;
|
|
this.rows = (this.maxValueYAxis - this.settings.lowerBound) / 2; //TODO PARAM - steps per row
|
|
};
|
|
|
|
this.draw = function(canvas) {
|
|
canvas.drawGrid(
|
|
this.leftEdge,
|
|
this.topEdge,
|
|
this.width,
|
|
this.height,
|
|
this.columns,
|
|
this.rows,
|
|
this.settings.gridBorderColor
|
|
);
|
|
};
|
|
|
|
this.x = function(value) {
|
|
return this.settings.leftGutter + this.X * value;
|
|
};
|
|
|
|
this.y = function(value) {
|
|
return this.settings.height - this.settings.bottomGutter - this.Y * (value - this.settings.lowerBound);
|
|
};
|
|
|
|
this.setYAxis();
|
|
this.setXAxis();
|
|
this.setDimensions();
|
|
|
|
};
|
|
|
|
(function($) {
|
|
|
|
//- required to implement hover function
|
|
var isLabelVisible;
|
|
var leaveTimer;
|
|
|
|
$.fn.simplegraph = function(data, labels, options) {
|
|
var settings = $.extend({}, $.fn.simplegraph.defaults, options);
|
|
setPenColor(settings);
|
|
|
|
return this.each( function() {
|
|
var canvas = Raphael(this, settings.width, settings.height);
|
|
var simplegraph = new SimpleGraph(data, labels, canvas, settings);
|
|
|
|
simplegraph.draw();
|
|
|
|
// Stash simplegraph object away for future reference
|
|
$.data(this, "simplegraph", simplegraph);
|
|
});
|
|
};
|
|
|
|
// Plot another set of values on an existing graph, use it like this:
|
|
// $("#target").simplegraph(data, labels).simplegraph_more(moreData);
|
|
$.fn.simplegraph_more = function(data, options) {
|
|
return this.each( function() {
|
|
var sg = $.data(this, "simplegraph");
|
|
sg.dataSet = new DataSet(data, sg.dataSet.labels, sg.settings);
|
|
sg.settings.penColor = options.penColor;
|
|
setPenColor(sg.settings);
|
|
sg.settings = $.extend(sg.settings, options);
|
|
sg.grid = new Grid(sg.dataSet, sg.settings);
|
|
sg.dataSet.labelYAxis(sg.grid, sg.canvas);
|
|
sg.dataSet.plot(sg.grid, sg.canvas);
|
|
});
|
|
};
|
|
|
|
// Public
|
|
|
|
$.fn.simplegraph.defaults = {
|
|
drawGrid: false,
|
|
units: "",
|
|
// Dimensions
|
|
width: 600,
|
|
height: 250,
|
|
leftGutter: 30,
|
|
bottomGutter: 20,
|
|
topGutter: 20,
|
|
// Label Style
|
|
labelColor: "#000",
|
|
labelFont: "Helvetica",
|
|
labelFontSize: "10px",
|
|
labelFontWeight: "normal",
|
|
// Grid Style
|
|
gridBorderColor: "#ccc",
|
|
// -- Y Axis Captions
|
|
yAxisOffset: 0,
|
|
// -- Y Axis Captions
|
|
xAxisLabelOffset: 0,
|
|
// Graph Style
|
|
// -- Points
|
|
drawPoints: false,
|
|
pointColor: "#000",
|
|
pointRadius: 3,
|
|
activePointRadius: 5,
|
|
// -- Line
|
|
drawLine: true,
|
|
lineColor: "#000",
|
|
lineWidth: 3,
|
|
lineJoin: "round",
|
|
// -- Bars
|
|
drawBars: false,
|
|
barColor: "#000",
|
|
barWidth: 10,
|
|
barOffset: 0,
|
|
// -- Fill
|
|
fillUnderLine: false,
|
|
fillColor: "#000",
|
|
fillOpacity: 0.2,
|
|
// -- Hover
|
|
addHover: true,
|
|
// Calculations
|
|
lowerBound: 0
|
|
};
|
|
|
|
// Default hoverIn callback, this is public and as such can be overwritten. You can write your
|
|
// own call back with the same signature if you want different behaviour.
|
|
$.fn.simplegraph.hoverIn = function(canvas, value, label, x, y, frame, hoverLabel, dot, settings) {
|
|
clearTimeout(leaveTimer);
|
|
var newcoord = {x: x * 1 + 7.5, y: y - 19};
|
|
if (newcoord.x + 100 > settings.width) {
|
|
newcoord.x -= 114;
|
|
}
|
|
hoverLabel[0].attr({text: value}).show().animate({x : newcoord.x + 50, y : newcoord.y + 15}, (isLabelVisible ? 100 : 0));
|
|
hoverLabel[1].attr({text: label}).show().animate({x : newcoord.x + 50, y : newcoord.y + 30}, (isLabelVisible ? 100 : 0));
|
|
frame.show().animate({x: newcoord.x, y: newcoord.y}, (isLabelVisible ? 100 : 0));
|
|
if (settings.drawPoints) {
|
|
dot.attr("r", settings.activePointRadius);
|
|
}
|
|
isLabelVisible = true;
|
|
canvas.safari();
|
|
};
|
|
|
|
// Default hoverOut callback, this is public and as such can be overwritten. You can write your
|
|
// own call back with the same signature if you want different behaviour.
|
|
$.fn.simplegraph.hoverOut = function(canvas, frame, label, dot, settings) {
|
|
if (settings.drawPoints) {
|
|
dot.attr("r", settings.pointRadius);
|
|
}
|
|
canvas.safari();
|
|
leaveTimer = setTimeout(function () {
|
|
isLabelVisible = false;
|
|
frame.hide();
|
|
label[0].hide();
|
|
label[1].hide();
|
|
canvas.safari();
|
|
}, 1);
|
|
};
|
|
|
|
// Private
|
|
|
|
function setPenColor(settings) {
|
|
if (settings.penColor) {
|
|
settings.lineColor = settings.penColor;
|
|
settings.pointColor = settings.penColor;
|
|
settings.fillColor = settings.penColor;
|
|
settings.barColor = settings.penColor;
|
|
}
|
|
}
|
|
|
|
})(jQuery);
|