2 * g.Raphael 0.51 - Charting library, based on Raphaƫl
4 * Copyright (c) 2009-2012 Dmitry Baranovskiy (http://g.raphaeljs.com)
5 * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
8 if (typeof(Raphael) == 'undefined') {
9 // support for seed/simple browser usage
10 importz = imports['seed/importz.js'].importz;
12 Raphael = importz('Raphael');
18 function clearAr(ar) {
19 var ret = new Array();
20 //Roo.log(JSON.stringify(ar));
21 for (var i = 0; i < ar.length; i++) {
22 //print(typeof(ar[i]));
23 if (Raphael.is(ar[i], "object")) {
24 ret.push(clearAr(ar[i]));
27 ret.push(parseInt(ar[i]));
35 * Creates a vertical bar chart
39 - x (number) x coordinate of the chart
40 - y (number) y coordinate of the chart
41 - width (number) width of the chart (respected by all elements in the set)
42 - height (number) height of the chart (respected by all elements in the set)
43 - values (array) values
44 - opts (object) options for the chart
46 background (string) : background color
47 gutter (string) (number) : indicate width of gutters with repsect to the bars in terms of percentage (e.g. '20%' means that the width ratio of gutter to bar is 10:2)
48 barsteps (number) : number of bars shown
49 barfill (string) : color to fill the empty bar (not filling if not provided)
50 baroffset (number) : distance between the rightmost bar and y axis;
51 colors (array) : colors of the bars
52 axis (string) : composed of 4 '0' / '1' separated by space (indicated whether top / right / bottom / left axis should be shown)
53 (e.g. '0 1 1 0' indicates that the right and the bottom axis should be shown)
54 asixxheight (number) : height of x axis area
55 axisxlabels (string) : labels in x axis
56 asixywidth (number) : width of y axis area
57 axisystep (number) : number of steps in y axis
58 axislinecolor (string) : color of lines in axes
59 axisstrokewidth (number) : stroke width of lines in axes
60 axisfont (string) : font family of labels in axes
61 axisfontsize (number) : font size of labels in axes
62 axisfontweight (string) (number) : font weight of labels in axes
63 axisfontcolor (string) : font color of labels in axes
64 labelfont (string) : font family of labels
65 labelsize (number) : font size of labels
66 labelweight (string)(number) : font weight of labels
67 labelcolors (array) : font colors of the labels
68 labelborderradius (number) : border radius of the label boxes
69 labelmaxheight (number) : max height for the label boxes
70 labeloffsety (number) : horizontal distance between the label boxes and the bars below
71 legends (array) : legend
72 legendheight : height of the legend
73 legendkeyshape (string) : shape of the legend keys ('circle' / 'rect')
74 legendkeysize (number) : size of the legend keys (diameter for 'circle' and width for 'rect')
75 legendkeyoffsetx (number) : horizontal distance between the left border of the chart and the first top left legend key
76 legendkeyoffsety (number) : vertical distance between the top border of the chart and the first top left legend key
77 legendfont (string) : font family of the legend labels
78 legendfontsize (number) : font size of the legend labels
79 legendfontweight (string)(number) : font weight of the legend labels
80 legendfontcolor (string) : font color of the legend colors
86 function MVBarchart(paper, x, y, width, height, values, opts) {
88 values = clearAr(values);
95 gutter = parseFloat(opts.gutter || "0%"),
96 barsteps = opts.barsteps || 20,
97 barFill = opts.barfill || false, // default no fill
98 colors = opts.colors || chartinst.colors,
99 axisLineColor = opts.axislinecolor || '#BABABA',
100 axisStrokeWidth = opts.axisstrokewidth || 2,
101 axisFont = opts.axisfont || "'Fontin Sans', Fontin-Sans, sans-serif",
102 axisFontSize = opts.axisfontsize || ((barsteps > 10) ? 12 : 14),
103 axisFontWeight = opts.axisfontweight || 'bold',
104 axisFontColor = opts.axisfontcolor || '#BABABA',
105 labelFont = opts.labelfont || "'Fontin Sans', Fontin-Sans, sans-serif",
106 labelSize = opts.labelsize || ((barsteps > 10) ? 10 : 12),
107 labelWeight = opts.labelweight || 'bold',
108 labelColors = opts.labelcolors || [],
109 labelBorderRadius = opts.labelborderradius || 4,
110 labelMaxHeight = opts.labelmaxheight || 30,
111 labelOffsetY = opts.labeloffsety || 20,
112 legendKeyShape = opts.legendkeyshape || 'circle',
113 legendKeySize = opts.legendkeysize || 16,
114 legendKeyOffsetX = typeof(opts.legendkeyoffsetx) != 'undefined' ? opts.legendkeyoffsetx : 10,
115 legendKeyOffsetY = typeof(opts.legendkeyoffsety) != 'undefined' ? opts.legendkeyoffsety : 10,
116 legendFont = opts.legendfont || "'Fontin Sans', Fontin-Sans, sans-serif",
117 legendFontSize = opts.legendfontsize || 14,
118 legendFontWeight = opts.legendfontweight || 'bold',
119 legendFontColor = opts.legendfontcolor || '#0C014D';
121 for(var i = 0; i < len; i++) {
122 labelColors.push('#FFFFFF');
126 opts.axis = opts.axis || "";
127 opts.baroffset = opts.baroffset || 10;
128 axisXHeight = opts.asixxheight || 100;
129 axisYWidth = opts.asixywidth || 100;
130 opts.axisxlabels = opts.axisxlabels || [];
131 opts.legendheight = opts.legendheight || 80;
132 opts.legends = opts.legends || 100;
135 paper.rect(0, 0, width, height).attr({ stroke: "none", fill: (opts.background || "#F0F4F7") });
136 // background.toBack();
138 // bar border && bar gutter
139 // total 'barsteps' of bars and 'barsteps - 1' of gutters
140 var barWidth = (width - x - axisYWidth - opts.baroffset) / (barsteps * (100 + gutter) - gutter) * 100;
141 var barGutter = barWidth * gutter / 100;
142 var barHeight = height - y - axisXHeight - opts.legendheight || 100;
145 for (var i = 0; i < barsteps; i++) {
146 path = path.concat(["M", x + (i * (barWidth + barGutter)), height - axisXHeight, "l", 0, -1 * barHeight, "l", barWidth, 0, "l", 0, barHeight]);
149 paper.rect(x + (i * (barWidth + barGutter)) + 1 , y + opts.legendheight + 1, barWidth - 2, barHeight - 2).attr({ stroke: "none", fill: barFill });
153 paper.path(path).attr({ stroke: "#FFF", "stroke-width": 2});
157 values.forEach(function(value,i) {
158 if (!Raphael.is(values[0], "array")) {
162 value.forEach(function(v,k) {
166 max = (v > max) ? v : max;
172 values.forEach(function(value,i) {
173 if (!Raphael.is(value, "array")) {
177 if(legendKeyShape == 'rect') {
178 // pass top left position for 'rect'
179 paper.rect(x + (i * (width - x) / len) + legendKeyOffsetX, y + legendKeyOffsetY, legendKeySize, legendKeySize, 0).attr({ fill: colors[i%colors.length], "stroke": "#fff" });
182 // pass center position for 'circle'
183 paper.circle(x + (i * (width - x) / len) + legendKeyOffsetX + (legendKeySize / 2), y + legendKeyOffsetY + (legendKeySize / 2), legendKeySize / 2).attr({ fill: colors[i%colors.length], "stroke": "#fff" });
186 // 10 pixels away from right of the legend key
187 // align legend key and text horizontally
188 paper.text(x + (i * (width - x) / len) + legendKeyOffsetX + legendKeySize + 10, y + legendKeyOffsetY + (legendKeySize / 2) - legendFontSize / 10, opts.legends[i%opts.legends.length]).attr({
189 "font-size": legendFontSize,
190 "font-family": legendFont,
191 "font-weight": legendFontWeight,
192 "text-anchor": "start",
193 fill : legendFontColor
198 var unit = barHeight / max;
200 values.forEach(function(value,i) {
201 if (!Raphael.is(values, "array")) {
205 value.forEach(function(v,k) {
206 if(v == 0 || k >= barsteps) {
210 paper.rect(x + (k * (barWidth + barGutter)) + 1 , y + opts.legendheight + 1 + (max - v) * unit, barWidth - 2, v * unit - 2).attr({ stroke: "none", fill: colors[i%colors.length] });
212 // width and height of indicator
213 var iw = barWidth * 0.8;
214 var ih = Math.min(labelMaxHeight, iw * 0.5);
216 // position of indicator
217 var ix = x + (k * (barWidth + barGutter)) + 1 + (barWidth - iw) / 2;
218 var iy = y + opts.legendheight + 1 + (max - v) * unit - ih - labelOffsetY;
221 iy = y + opts.legendheight + 1 - ih - labelOffsetY;
224 paper.rect(ix , iy, iw, ih, labelBorderRadius).attr({ stroke: "none", fill: colors[i%colors.length] });
225 paper.path(["M", ix + (iw - 10) / 2, iy + ih, "l", 5, 10, "l", 5, -10]).attr({ stroke: "none", fill: colors[i%colors.length] });
226 // align labels center
227 paper.text(ix + iw / 2, iy + ih / 2 - labelSize / 10, Roo.util.Format.number(v, 0)).attr({
228 "font-size": labelSize,
229 "font-family": labelFont,
230 "font-weight": labelWeight,
231 fill : labelColors[i]
236 var ax = (opts.axis + "").split(/[,\s]+/),
243 height - axisXHeight,
244 height - y - axisXHeight - opts.legendheight,
246 opts.axisystep || 10,
260 chartinst.bottomAxis(
262 height - axisXHeight,
263 width - x - axisYWidth / 2,
279 chart.push(bars, covers);
281 chart.covers = covers;
286 var F = function() {};
287 F.prototype = Raphael.g;
288 MVBarchart.prototype = new F; //prototype reused by hbarchart
290 Raphael.fn.mbarchart = function(x, y, width, height, values, opts) {
291 return new MVBarchart(this, x, y, width, height, values, opts);
294 MVBarchart.prototype.rightAxis = function (x, y, length, max, steps, axisYWidth, paper, axisLineColor, axisStrokeWidth, axisFont, axisFontSize, axisFontWeight, axisFontColor)
296 // Roo.log('Right Axis');
297 // Roo.log([x, y, length, max, steps, axisYWidth]);
301 d = Math.ceil(max / steps);
308 for(var i = 0; i <= steps; i++) {
311 // 6 pixels away from bottom of the line
312 paper.text(x + (axisYWidth / 2), Y + axisFontSize / 2 + 6, Roo.util.Format.number(label, 0)).attr({
313 "font-size": axisFontSize,
314 "font-family": axisFont,
315 "font-weight": axisFontWeight,
316 "text-anchor": "end",
319 path = path.concat(["M", x , Y, "l", axisYWidth / 2, 0]);
327 var res = paper.path(path).attr({ stroke: axisLineColor, "stroke-width": axisStrokeWidth });
330 res.all = paper.set([res, text]);
331 res.remove = function () {
333 this.constructor.prototype.remove.call(this);
339 MVBarchart.prototype.bottomAxis = function (x, y, length, labels, barsteps, barWidth, barGutter, height, paper, axisLineColor, axisStrokeWidth, axisFont, axisFontSize, axisFontWeight, axisFontColor)
341 // Roo.log('Bottom Axis');
342 // Roo.log([x, y, length, steps, labels, barWidth]);
344 var path = ["M", x, y, "l", length, 0],
346 offset = Math.round(barWidth / 2);
348 labels.forEach(function(v,k) {
352 paper.text(x + (k * (barWidth + barGutter)) + offset, y + (height / 2), v).attr({
353 "font-size": axisFontSize,
354 "font-family": axisFont,
355 "font-weight": axisFontWeight,
360 var res = paper.path(path).attr({ stroke: axisLineColor, "stroke-width": axisStrokeWidth });
363 res.all = paper.set([res, text]);
364 res.remove = function () {
366 this.constructor.prototype.remove.call(this);