diff options
| author | Yuval Adam <yuv.adm@gmail.com> | 2011-08-06 16:45:21 +0300 |
|---|---|---|
| committer | Yuval Adam <yuv.adm@gmail.com> | 2011-08-06 16:45:21 +0300 |
| commit | bf054805514ea71dba7578d434a39f9531d51934 (patch) | |
| tree | ad496a442cb1817a2e3ef48cc328b14da5777bfb /linegraph-test/lc.js | |
| parent | 7e698d1909118041a49e08f271f92353f26befba (diff) | |
added linegraph test
Diffstat (limited to 'linegraph-test/lc.js')
| -rw-r--r-- | linegraph-test/lc.js | 856 |
1 files changed, 856 insertions, 0 deletions
diff --git a/linegraph-test/lc.js b/linegraph-test/lc.js new file mode 100644 index 0000000..658562d --- /dev/null +++ b/linegraph-test/lc.js @@ -0,0 +1,856 @@ +/* + * Raphael Line Chart 1.2 - Raphael Line Charts plugin + * + * Copyright (c) 2011 Sagie Maoz (http://sagie.maoz.info) + * Dual-licensed under the GPL (http://www.opensource.org/licenses/gpl-3.0) + * and the MIT (http://www.opensource.org/licenses/mit-license) licenses. + */ +(function() { + +// modified version of Raphael.fn.drawGrid() from the Raphael Analytics example +Raphael.fn.drawGrid = function(x, y, width, height, x_step, x_size, y_count, y_size) { + var path, + rowHeight, + columnWidth; + + // frame border + path = ["M", Math.round(x) + 0.5, Math.round(y) + 0.5, + "L", Math.round(x + width) + 0.5, Math.round(y) + 0.5, + Math.round(x + width) + 0.5, Math.round(y + height) + 0.5, + Math.round(x) + 0.5, Math.round(y + height) + 0.5, + Math.round(x) + 0.5, Math.round(y) + 0.5]; + + // horizontal lines + rowHeight = Math.ceil(height / y_count); + for (var i = 0; i < y_count; i++) { + path = path.concat(["M", Math.round(x) + 0.5, Math.round(y + i * rowHeight) + 0.5, + "H", Math.round(x + width) + 0.5]); + } + + // vertical lines + if (!x_step) { + x_step = 1; + x_size = 10; + } + columnWidth = Math.ceil(width / x_size); + for (i = 0; i < x_size; i+= x_step) { + path = path.concat(["M", Math.round(x + i * (columnWidth + 1.1)) + 0.5, Math.round(y) + 0.5, + "V", Math.round(y + height) + 0.5]); + } + + return this.path(path.join(",")); +}; + +Raphael.fn.popup = function(X, Y, set, position, ret) { + var pos = String(position || "top-middle").split("-"), + pos_x = pos[1] || "middle", + tokenRegex = /\{([^\}]+)\}/g, + objNotationRegex = /(?:(?:^|\.)(.+?)(?=\[|\.|$|\()|\[('|")(.+?)\2\])(\(\))?/g, + + replacer = function(all, key, obj) { + var res = obj; + key.replace(objNotationRegex, + function(all, name, quote, quotedName, isFunc) { + name = name || quotedName; + if (res) { + if (name in res) { + res = res[name]; + } + return (typeof res == "function") && isFunc && (res = res()); + } + }); + res = (res === null || res == obj ? all: res) + ""; + return res; + }, + + fill = function(str, obj) { + return String(str).replace(tokenRegex, + function(all, key) { + return replacer(all, key, obj); + }); + }, + + r = 5, + bb = set.getBBox(), + w = Math.round(bb.width), + h = Math.round(bb.height), + x = Math.round(bb.x) - r, + y = Math.round(bb.y) - r, + gap = Math.min(h / 2, w / 2, 10), + shapes = { + top: "M{x},{y}h{w4},{w4},{w4},{w4}a{r},{r},0,0,1,{r},{r}v{h4},{h4},{h4},{h4}a{r},{r},0,0,1,-{r},{r}l-{right},0-{gap},{gap}-{gap}-{gap}-{left},0a{r},{r},0,0,1-{r}-{r}v-{h4}-{h4}-{h4}-{h4}a{r},{r},0,0,1,{r}-{r}z", + bottom: "M{x},{y}l{left},0,{gap}-{gap},{gap},{gap},{right},0a{r},{r},0,0,1,{r},{r}v{h4},{h4},{h4},{h4}a{r},{r},0,0,1,-{r},{r}h-{w4}-{w4}-{w4}-{w4}a{r},{r},0,0,1-{r}-{r}v-{h4}-{h4}-{h4}-{h4}a{r},{r},0,0,1,{r}-{r}z", + right: "M{x},{y}h{w4},{w4},{w4},{w4}a{r},{r},0,0,1,{r},{r}v{h4},{h4},{h4},{h4}a{r},{r},0,0,1,-{r},{r}h-{w4}-{w4}-{w4}-{w4}a{r},{r},0,0,1-{r}-{r}l0-{bottom}-{gap}-{gap},{gap}-{gap},0-{top}a{r},{r},0,0,1,{r}-{r}z", + left: "M{x},{y}h{w4},{w4},{w4},{w4}a{r},{r},0,0,1,{r},{r}l0,{top},{gap},{gap}-{gap},{gap},0,{bottom}a{r},{r},0,0,1,-{r},{r}h-{w4}-{w4}-{w4}-{w4}a{r},{r},0,0,1-{r}-{r}v-{h4}-{h4}-{h4}-{h4}a{r},{r},0,0,1,{r}-{r}z" + }, + offset = { + hx0: X - (x + r + w - gap * 2), + hx1: X - (x + r + w / 2 - gap), + hx2: X - (x + r + gap), + vhy: Y - (y + r + h + r + gap), + "^hy": Y - (y - gap) + }, + mask = [{ + x: x + r, + y: y, + w: w, + w4: w / 4, + h4: h / 4, + right: 0, + left: w - gap * 2, + bottom: 0, + top: h - gap * 2, + r: r, + h: h, + gap: gap + }, + { + x: x + r, + y: y, + w: w, + w4: w / 4, + h4: h / 4, + left: w / 2 - gap, + right: w / 2 - gap, + top: h / 2 - gap, + bottom: h / 2 - gap, + r: r, + h: h, + gap: gap + }, + { + x: x + r, + y: y, + w: w, + w4: w / 4, + h4: h / 4, + left: 0, + right: w - gap * 2, + top: 0, + bottom: h - gap * 2, + r: r, + h: h, + gap: gap + }][pos_x == "middle" ? 1: (pos_x == "top" || pos_x == "left") * 2], + dx = 0, + dy = 0, + out = this.path(fill(shapes[pos[0]], mask)).insertBefore(set); + + switch (pos[0]) { + case "top": + dx = X - (x + r + mask.left + gap); + dy = Y - (y + r + h + r + gap); + break; + case "bottom": + dx = X - (x + r + mask.left + gap); + dy = Y - (y - gap); + break; + case "left": + dx = X - (x + r + w + r + gap); + dy = Y - (y + r + mask.top + gap); + break; + case "right": + dx = X - (x - gap); + dy = Y - (y + r + mask.top + gap); + break; + } + out.translate(dx, dy); + if (ret) { + ret = out.attr("path"); + out.remove(); + return { + path: ret, + dx: dx, + dy: dy + }; + } + set.translate(dx, dy); + return out; +}; + +Raphael.fn.lineChart = function(method) { + + // public methods + var methods = { + + init: function(options) { + + this.lineChart.settings = helpers.extend(true, {}, this.lineChart.defaults, options); + this.customAttributes.lineChart = {}; + + //TODO either data or data_holder is a must + + // let's go + var element = this, + o = this.customAttributes.lineChart, + settings = this.lineChart.settings, + width = settings.width, + height = settings.height, + + table = helpers.getTable(element, o, settings.data, settings.data_holder), + size = table.labels.length, + + max = Math.max.apply(Math, table.data), + + YLabelWidth = element.text(-50, -50, max).attr(settings.text.axis_labels).getBBox().width, + gutter = { + top: settings.gutter.top, + right: settings.gutter.right, + bottom: settings.gutter.bottom, + left: settings.gutter.left + YLabelWidth + }, + blanket = element.set(), + + X = (width - gutter.left) / size, + Y, p, bgpp, x, y; + + // fix max. value + if (max > settings.y_labels_count*10) { + p = 25*settings.y_labels_count; + max = Math.ceil(max/p)*p; + } + Y = max ? ((height - gutter.bottom - gutter.top) / max) : 0; + + o.gutter = gutter; + o.labelGutter = settings.gutter.left; + + o.size = size; + o.dots = []; + o.rects = []; + o.info = []; + //TODO allow customizing + o.path = element.path().attr({ + stroke: settings.colors.master, + "stroke-width": 4, + "stroke-linejoin": "round" + }); + // chart area + //TODO allow customizing + if (settings.show_area) { + o.bgp = element.path().attr({ + stroke: "none", + opacity: 0.3, + fill: settings.colors.master + }); + } + else { + o.bgp = element.path().attr({ + stroke: "none", + opacity: 0, + fill: settings.colors.master + }).hide(); + } + + // draw background grid + if (!o.gridDrawn && settings.no_grid === false) { + var grid = element.drawGrid(gutter.left + X * 0.5 + 0.5, + gutter.top + 0.5, + width - gutter.left - X, + height - gutter.top - gutter.bottom, + settings.x_labels_step, + size, + settings.y_labels_count, + max) + .attr({ stroke: "#eaeaea" }); + + grid.toBack(); + } + o.gridDrawn = true; + + // draw x axis labels + o.XLabels = []; + if (settings.x_labels_step) { + helpers.drawXLabels(element, table.labels); + } + + // draw y axis labels + o.YLabels = []; + if (settings.y_labels_count) { + helpers.drawYLabels(element, max); + } + + // prepare popup + o.label = element.set(); + //TODO ?? + o.label.push(element.text(60, 12, "24 hits").attr(settings.text.popup_line1)); + o.label.push(element.text(60, 27, "22 September 2008").attr(settings.text.popup_line2).attr({ + fill: settings.colors.master + })); + o.label.hide(); + + //TODO allow customizing + o.frame = element.popup(100, 100, o.label, "right").attr({ + fill: "#ffffff", + stroke: "#666", + "stroke-width": 2, + "fill-opacity": 0.8 + }).hide(); + + for (var i = 0, ii = size; i < ii; i++) { + var dot, rect; + + // calculate current x, y + y = Math.round(height - gutter.bottom - Y * table.data[i]) || 0; + x = Math.round(gutter.left + X * (i + 0.5)); + + if (!i) { + p = ["M", x, y, "C", x, y]; + bgpp = ["M", gutter.left + X * 0.5, height - gutter.bottom, "L", x, y, "C", x, y]; + } + else if (i < ii - 1) { + var Y0 = Math.round(height - gutter.bottom - Y * table.data[i - 1]), + X0 = Math.round(gutter.left + X * (i - 0.5)), + Y2 = Math.round(height - gutter.bottom - Y * table.data[i + 1]), + X2 = Math.round(gutter.left + X * (i + 1.5)), + a = helpers.getAnchors(X0, Y0, x, y, X2, Y2); + p = p.concat([a.x1, a.y1, x, y, a.x2, a.y2]); + bgpp = bgpp.concat([a.x1, a.y1, x, y, a.x2, a.y2]); + } + + //TODO allow customizing all of these + dot = element.circle(x, y, 4).attr({ + fill: "#ffffff", + stroke: settings.colors.master, + "stroke-width": 2 + }); + if (y === 0) { + dot.attr({ + opacity: 0 + }); + } + + o.dots.push(dot); + + if (settings.mouse_coords == 'circle') { + blanket.push(element.circle(x, y, 14).attr({ + stroke: "none", + fill: "#fff", + opacity: 0 + })); + } else if (settings.mouse_coords == 'rect') { + blanket.push(element.rect(gutter.left + X * i, 0, X, height - gutter.bottom).attr({ + stroke: "none", + fill: "#fff", + opacity: 0 + })); + } + rect = blanket[blanket.length - 1]; + o.rects.push(rect); + + o.info.push({ + x: x, + y: y, + data: table.data[i], + label: table.labels[i], + line1: table.lines1[i], + line2: table.lines2[i] + }); + helpers.bindHoverEvent(this, i, dot, rect, o.frame, o.label); + } + + p = p.concat([x, y, x, y]); + bgpp = bgpp.concat([x, y, x, y, "L", x, height - gutter.bottom, "z"]); + o.path.attr({ + path: p + }); + o.bgp.attr({ + path: bgpp + }); + o.frame.toFront(); + o.label[0].toFront(); + o.label[1].toFront(); + blanket.toFront(); + }, + + setDataIndex: function(index) { + var o = this.customAttributes.lineChart; + + if (index < o.dataArray.data.length) { + var one = { + labels: o.dataArray.labels, + data: o.dataArray.data[index], + lines1: o.dataArray.lines1[index], + lines2: o.dataArray.lines2[index] + }; + return this.lineChart('setData', one); + } + else + { + return helpers.error('Data index out of range.'); + } + }, + + setDataHolder: function(holder) { + var table = helpers.loadTableData(this, holder); + if (table) { + return this.lineChart('setData', table); + } + else { + return helpers.error('No data holder element supplied.'); + } + }, + + // Caution: this would only work for the same number of records + setData: function(table) { + var element = this, + settings = this.lineChart.settings, + o = this.customAttributes.lineChart, + width = settings.width, + height = settings.height, + gutter = o.gutter, + + X = (width - gutter.left) / table.labels.length, + max = Math.max.apply(Math, table.data), + Y, p, bgpp; + + table = helpers.getTable(element, o, table); + + if (table.labels.length != o.size) { + return helpers.error('New data source has to be of same size'); + } + + // fix max. value + if (max > settings.y_labels_count*10) { + p = 25*settings.y_labels_count; + max = Math.ceil(max/p)*p; + } + Y = max ? ((height - gutter.bottom - gutter.top) / max) : 0; + + for (var i = 0, ii = table.labels.length; i < ii; i++) { + var dot = o.dots[i], + rect = o.rects[i]; + + // calculate current x, y + y = Math.round(height - gutter.bottom - Y * table.data[i]) || 0; + x = Math.round(gutter.left + X * (i + 0.5)); + + if (!i) { + p = ["M", x, y, "C", x, y]; + bgpp = ["M", gutter.left + X * 0.5, height - gutter.bottom, "L", x, y, "C", x, y]; + } + else if (i < ii - 1) { + var Y0 = Math.round(height - gutter.bottom - Y * table.data[i - 1]), + X0 = Math.round(gutter.left + X * (i - 0.5)), + Y2 = Math.round(height - gutter.bottom - Y * table.data[i + 1]), + X2 = Math.round(gutter.left + X * (i + 1.5)), + a = helpers.getAnchors(X0, Y0, x, y, X2, Y2); + + p = p.concat([a.x1, a.y1, x, y, a.x2, a.y2]); + bgpp = bgpp.concat([a.x1, a.y1, x, y, a.x2, a.y2]); + } + + dot.animate({cy: y}, + settings.animation.speed, + settings.animation.easing); + + // new popup data + o.info[i] = { + x: x, + y: y, + data: table.data[i], + label: table.labels[i], + line1: table.lines1[i], + line2: table.lines2[i] + }; + } + + // animate paths + p = p.concat([x, y, x, y]); + bgpp = bgpp.concat([x, y, x, y, "L", x, height - gutter.bottom, "z"]); + o.path.animate({path: p}, + settings.animation.speed, + settings.animation.easing); + o.bgp.animate({path: bgpp}, + settings.animation.speed, + settings.animation.easing); + + // update x axis labels + if (settings.x_labels_step) { + helpers.drawXLabels(element, table.labels); + } + + // draw y axis labels + if (settings.y_labels_count) { + helpers.drawYLabels(element, max); + } + } + + }; + + // private methods + var helpers = { + extend: function () { // copied from jQuery source + // copy reference to target object + var target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false, + options, name, src, copy; + + // Handle a deep copy situation + if (typeof target === "boolean") { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if (typeof target !== "object" && typeof target !== "function") { + target = {}; + } + + // extend myself if only one argument is passed + if (length === i) { + target = this; + --i; + } + + for (; i < length; i++) { + // Only deal with non-null/undefined values + if ((options = arguments[i]) !== null) { + // Extend the base object + for (name in options) { + if (options.hasOwnProperty(name)) + { + src = target[name]; + copy = options[name]; + + // Prevent never-ending loop + if (target === copy) { + continue; + } + + // Recurse if we're merging object literal values or arrays + if (deep && copy && (copy.constructor == Object || copy.constructor == Array)) { + var clone = src && (src.constructor == Object || src.constructor == Array) ? src : copy.constructor == Array ? [] : {}; + + // Never move original objects, clone them + target[name] = helpers.extend(deep, clone, copy); + + // Don't bring in undefined values + } else if (copy !== undefined) { + target[name] = copy; + } + } + } + } + } + + // Return the modified object + return target; + }, + + getAnchors: function(p1x, p1y, p2x, p2y, p3x, p3y) { + var l1 = (p2x - p1x) / 2, + l2 = (p3x - p2x) / 2, + a = Math.atan((p2x - p1x) / Math.abs(p2y - p1y)), + b = Math.atan((p3x - p2x) / Math.abs(p2y - p3y)), + dx1 = dy1 = dx2 = dy2 = 0, + alpha; + + a = p1y < p2y ? Math.PI - a: a; + b = p3y < p2y ? Math.PI - b: b; + alpha = Math.PI / 2 - ((a + b) % (Math.PI * 2)) / 2; + dx1 = l1 * Math.sin(alpha + a); + dx2 = l2 * Math.sin(alpha + b); + if (p1y != p2y) { + dy1 = l1 * Math.cos(alpha + a); + } + if (p2y != p3y) { + dy2 = l2 * Math.cos(alpha + b); + } + + return { + x1: p2x - dx1, + y1: p2y + dy1, + x2: p2x + dx2, + y2: p2y + dy2 + }; + }, + + getTable: function(elm, o, obj, table_elm) { + if (obj) { + // handle multiple data rows + if (obj.data[0].constructor == Array) { + o.dataArray = obj; + var one = {}; + one.labels = obj.labels; + one.data = obj.data[0]; + one.lines1 = obj.lines1[0]; + one.lines2 = obj.lines2[0]; + return one; + } + else { + return obj; + } + } + else { + return helpers.loadTableData(elm, table_elm); + } + }, + + loadTableData: function(elm, table_elm) { + var settings = elm.lineChart.settings, + table = (table_elm && table_elm.constructor == String) ? document.getElementById(table_elm) : table_elm, + res = { + labels: [], + data: [], + lines1: [], + lines2: [] + }, + tds = {}, + curr, td, i, j; + + if (table) { + // find elements to collect + for (i=0; i < table.childNodes.length; i++, curr = null, td = 'td') { + if (table.childNodes[i].tagName == 'TFOOT') { + curr = 'labels'; + td = 'th'; + } + else if (table.childNodes[i].tagName == 'TBODY') { + if (table.childNodes[i].className == settings.table_classes.data) { + curr = 'data'; + } + else if (table.childNodes[i].className == settings.table_classes.line1) { + curr = 'lines1'; + } + else if (table.childNodes[i].className == settings.table_classes.line2) { + curr = 'lines2'; + } + } + + if (curr) { + tds[curr] = table.childNodes[i].getElementsByTagName(td); + } + } + + // populate res + if (tds.labels && tds.data && tds.lines1 && tds.lines2) { + for (j=0; j < tds.labels.length; j++) { + res.labels.push(tds.labels[j].innerHTML); + } + for (j=0; j < tds.data.length; j++) { + res.data.push(tds.data[j].innerHTML); + } + for (j=0; j < tds.lines1.length; j++) { + res.lines1.push(tds.lines1[j].innerHTML); + } + for (j=0; j < tds.lines2.length; j++) { + res.lines2.push(tds.lines2[j].innerHTML); + } + } + return res; + } else { + return false; + } + }, + + bindHoverEvent: function(elm, i, dot, rect, frame, label) { + var settings = elm.lineChart.settings, + o = elm.customAttributes.lineChart, + f_in = function() { + var side = "right", + info = o.info[i], + x = info.x, + y = info.y; + + window.clearTimeout(elm.leave_timer); + if (x + frame.getBBox().width > settings.width) { + side = "left"; + } + var ppp = elm.popup(x, y, label, side, 1); + if (settings.mouse_coords == 'circle') { + frame.attr({ + path: ppp.path, + width: '200px' + }).show(); + label[0].attr({ + text: info.line1, + fill: settings.colors.line1, + translation: [ppp.dx, ppp.dy] + }).show(); + label[1].attr({ + text: info.line2, + fill: settings.colors.line2, + translation: [ppp.dx, ppp.dy] + }).show(); + } else if (settings.mouse_coords == 'rect') { + frame.show().stop().animate({ + path: ppp.path + }, + 200 * o.is_label_visible); + label[0].attr({ + text: info.line1 + }).show().stop().animateWith(frame, { + translation: [ppp.dx, ppp.dy] + }, + 200 * o.is_label_visible); + label[1].attr({ + text: info.line2 + }).show().stop().animateWith(frame, { + translation: [ppp.dx, ppp.dy] + }, + 200 * o.is_label_visible); + } + frame.toFront(); + label[0].toFront(); + label[1].toFront(); + this.toFront(); + dot.attr("r", 6); + o.is_label_visible = true; + }, + f_out = function() { + dot.attr("r", 4); + + elm.leave_timer = window.setTimeout(function() { + frame.hide(); + label[0].hide(); + label[1].hide(); + o.is_label_visible = false; + }, + 1); + }; + + rect.hover(f_in, f_out); + }, + + drawXLabels: function(elm, labels) { + var settings = elm.lineChart.settings, + o = elm.customAttributes.lineChart, + x = (settings.width - o.gutter.left) / o.size, + y = settings.height - o.gutter.bottom + 18, + step = settings.x_labels_step, + style = settings.text.axis_labels, + i; + + // reset old labels + if (o.XLabels.length) { + for (i = 0; i < o.XLabels.length; i++) { + o.XLabels[i].remove(); + } + } + + o.XLabels = []; + for (i = 0; i < o.size; i++) { + var label_x = Math.round(o.gutter.left + x * (i + 0.5)); + + if (i % step === 0) { + var l = elm.text(label_x, y, labels[i]) + .attr(style).toBack(); + o.XLabels.push(l); + } + } + }, + + drawYLabels: function(elm, max) { + var settings = elm.lineChart.settings, + o = elm.customAttributes.lineChart, + x = o.labelGutter + 20, + y = o.gutter.bottom, + top = o.gutter.top, + height = settings.height, + count = settings.y_labels_count, + step = Math.round(max / count), + labelHeight = (height - top - y) / count; + + // reset old labels + if (o.YLabels.length) { + for (var i = 0; i < o.YLabels.length; i++) { + o.YLabels[i].remove(); + } + } + + + o.YLabels = []; + for (var j = 0; j <= count; j++) { + var txt = (j * (max/count)), + l; + + l = elm + .text(x, height - y - (j*labelHeight), + settings.y_labels_format(txt, max, count)) + .attr(settings.text.axis_labels); + o.YLabels.push(l); + + } + }, + + error: function(message) { + if (console && console.error) { + console.error('lineChart Error: ' + message); + } + return false; + } + }; + + // go go go! + if (methods[method]) { + return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); + } else if (typeof method === 'object' || !method) { + return methods.init.apply(this, arguments); + } else { + return helpers.error('Method "' + method + '" not found.'); + } +}; + +Raphael.fn.lineChart.defaults = { + data_holder: null, // table element holding the data to display + data: null, // alternatively, supply a data object + width: 500, // chart width + height: 250, // chart height + gutter: { // gutter dimensions + top: 20, + right: 0, + bottom: 50, + left: 30 + }, + show_area: false, // whether to fill the area below the line + mouse_coords: 'rect', // way to capture mouse events + no_grid: false, // whether to display background grid + x_labels_step: false, // X axis: either false or a step integer + y_labels_count: false, // Y axis: either false or a labels count + y_labels_format: function(txt, max, count) { // function to handle display of Y labels + if (max > count) { + txt = Math.floor(txt) + ''; + } + else { + txt = txt + ''; + } + txt = txt.replace(/\.(\d{3})\d*/, '.$1'); + txt = txt.replace(/(\d{1,3})(?=(?:\d{3})+$)/g,"$1,"); + return txt; + }, + animation: { // animation (on data source change) settings + speed: 600, + easing: "backOut" + }, + colors: { // color settings + master: '#01A8F0', + line1: '#000000', + line2: '#01A8F0' + }, + text: { // text style settings + axis_labels: { + font: '10px Helvetica, Arial', + fill: "#000000" + }, + popup_line1: { + font: 'bold 11px Helvetica, Arial', + fill: "#000000" + }, + popup_line2: { + font: 'bold 10px Helvetica, Arial', + fill: "#000000" + } + }, + table_classes: { + data: 'data', + line1: 'line1', + line2: 'line2' + } +}; + +})(); + |
