g.raphael-0.5/ 0000755 0001756 0001757 00000000000 11654171544 012270 5 ustar pravi pravi g.raphael-0.5/g.pie.js 0000644 0001756 0001757 00000021770 11654171544 013637 0 ustar pravi pravi /* * g.Raphael 0.5 - Charting library, based on Raphaël * * Copyright (c) 2009 Dmitry Baranovskiy (http://g.raphaeljs.com) * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. */ (function () { function Piechart(paper, cx, cy, r, values, opts) { opts = opts || {}; var chartinst = this, sectors = [], covers = paper.set(), chart = paper.set(), series = paper.set(), order = [], len = values.length, angle = 0, total = 0, others = 0, cut = 9, defcut = true; function sector(cx, cy, r, startAngle, endAngle, fill) { var rad = Math.PI / 180, x1 = cx + r * Math.cos(-startAngle * rad), x2 = cx + r * Math.cos(-endAngle * rad), xm = cx + r / 2 * Math.cos(-(startAngle + (endAngle - startAngle) / 2) * rad), y1 = cy + r * Math.sin(-startAngle * rad), y2 = cy + r * Math.sin(-endAngle * rad), ym = cy + r / 2 * Math.sin(-(startAngle + (endAngle - startAngle) / 2) * rad), res = [ "M", cx, cy, "L", x1, y1, "A", r, r, 0, +(Math.abs(endAngle - startAngle) > 180), 1, x2, y2, "z" ]; res.middle = { x: xm, y: ym }; return res; } chart.covers = covers; if (len == 1) { series.push(paper.circle(cx, cy, r).attr({ fill: chartinst.colors[0], stroke: opts.stroke || "#fff", "stroke-width": opts.strokewidth == null ? 1 : opts.strokewidth })); covers.push(paper.circle(cx, cy, r).attr(chartinst.shim)); total = values[0]; values[0] = { value: values[0], order: 0, valueOf: function () { return this.value; } }; series[0].middle = {x: cx, y: cy}; series[0].mangle = 180; } else { for (var i = 0; i < len; i++) { total += values[i]; values[i] = { value: values[i], order: i, valueOf: function () { return this.value; } }; } values.sort(function (a, b) { return b.value - a.value; }); for (i = 0; i < len; i++) { if (defcut && values[i] * 360 / total <= 1.5) { cut = i; defcut = false; } if (i > cut) { defcut = false; values[cut].value += values[i]; values[cut].others = true; others = values[cut].value; } } len = Math.min(cut + 1, values.length); others && values.splice(len) && (values[cut].others = true); for (i = 0; i < len; i++) { var mangle = angle - 360 * values[i] / total / 2; if (!i) { angle = 90 - mangle; mangle = angle - 360 * values[i] / total / 2; } if (opts.init) { var ipath = sector(cx, cy, 1, angle, angle - 360 * values[i] / total).join(","); } var path = sector(cx, cy, r, angle, angle -= 360 * values[i] / total); var p = paper.path(opts.init ? ipath : path).attr({ fill: opts.colors && opts.colors[i] || chartinst.colors[i] || "#666", stroke: opts.stroke || "#fff", "stroke-width": (opts.strokewidth == null ? 1 : opts.strokewidth), "stroke-linejoin": "round" }); p.value = values[i]; p.middle = path.middle; p.mangle = mangle; sectors.push(p); series.push(p); opts.init && p.animate({ path: path.join(",") }, (+opts.init - 1) || 1000, ">"); } for (i = 0; i < len; i++) { p = paper.path(sectors[i].attr("path")).attr(chartinst.shim); opts.href && opts.href[i] && p.attr({ href: opts.href[i] }); p.attr = function () {}; covers.push(p); series.push(p); } } chart.hover = function (fin, fout) { fout = fout || function () {}; var that = this; for (var i = 0; i < len; i++) { (function (sector, cover, j) { var o = { sector: sector, cover: cover, cx: cx, cy: cy, mx: sector.middle.x, my: sector.middle.y, mangle: sector.mangle, r: r, value: values[j], total: total, label: that.labels && that.labels[j] }; cover.mouseover(function () { fin.call(o); }).mouseout(function () { fout.call(o); }); })(series[i], covers[i], i); } return this; }; // x: where label could be put // y: where label could be put // value: value to show // total: total number to count % chart.each = function (f) { var that = this; for (var i = 0; i < len; i++) { (function (sector, cover, j) { var o = { sector: sector, cover: cover, cx: cx, cy: cy, x: sector.middle.x, y: sector.middle.y, mangle: sector.mangle, r: r, value: values[j], total: total, label: that.labels && that.labels[j] }; f.call(o); })(series[i], covers[i], i); } return this; }; chart.click = function (f) { var that = this; for (var i = 0; i < len; i++) { (function (sector, cover, j) { var o = { sector: sector, cover: cover, cx: cx, cy: cy, mx: sector.middle.x, my: sector.middle.y, mangle: sector.mangle, r: r, value: values[j], total: total, label: that.labels && that.labels[j] }; cover.click(function () { f.call(o); }); })(series[i], covers[i], i); } return this; }; chart.inject = function (element) { element.insertBefore(covers[0]); }; var legend = function (labels, otherslabel, mark, dir) { var x = cx + r + r / 5, y = cy, h = y + 10; labels = labels || []; dir = (dir && dir.toLowerCase && dir.toLowerCase()) || "east"; mark = paper[mark && mark.toLowerCase()] || "circle"; chart.labels = paper.set(); for (var i = 0; i < len; i++) { var clr = series[i].attr("fill"), j = values[i].order, txt; values[i].others && (labels[j] = otherslabel || "Others"); labels[j] = chartinst.labelise(labels[j], values[i], total); chart.labels.push(paper.set()); chart.labels[i].push(paper[mark](x + 5, h, 5).attr({ fill: clr, stroke: "none" })); chart.labels[i].push(txt = paper.text(x + 20, h, labels[j] || values[j]).attr(chartinst.txtattr).attr({ fill: opts.legendcolor || "#000", "text-anchor": "start"})); covers[i].label = chart.labels[i]; h += txt.getBBox().height * 1.2; } var bb = chart.labels.getBBox(), tr = { east: [0, -bb.height / 2], west: [-bb.width - 2 * r - 20, -bb.height / 2], north: [-r - bb.width / 2, -r - bb.height - 10], south: [-r - bb.width / 2, r + 10] }[dir]; chart.labels.translate.apply(chart.labels, tr); chart.push(chart.labels); }; if (opts.legend) { legend(opts.legend, opts.legendothers, opts.legendmark, opts.legendpos); } chart.push(series, covers); chart.series = series; chart.covers = covers; return chart; }; //inheritance var F = function() {}; F.prototype = Raphael.g; Piechart.prototype = new F; //public Raphael.fn.piechart = function(cx, cy, r, values, opts) { return new Piechart(this, cx, cy, r, values, opts); } })(); g.raphael-0.5/g.line.js 0000644 0001756 0001757 00000026356 11654171544 014016 0 ustar pravi pravi /*! * g.Raphael 0.5 - Charting library, based on Raphaël * * Copyright (c) 2009 Dmitry Baranovskiy (http://g.raphaeljs.com) * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. */ (function () { function shrink(values, dim) { var k = values.length / dim, j = 0, l = k, sum = 0, res = []; while (j < values.length) { l--; if (l < 0) { sum += values[j] * (1 + l); res.push(sum / k); sum = values[j++] * -l; l += k; } else { sum += values[j++]; } } return res; } function getAnchors(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)); a = p1y < p2y ? Math.PI - a : a; b = p3y < p2y ? Math.PI - b : b; var alpha = Math.PI / 2 - ((a + b) % (Math.PI * 2)) / 2, dx1 = l1 * Math.sin(alpha + a), dy1 = l1 * Math.cos(alpha + a), dx2 = l2 * Math.sin(alpha + b), dy2 = l2 * Math.cos(alpha + b); return { x1: p2x - dx1, y1: p2y + dy1, x2: p2x + dx2, y2: p2y + dy2 }; } function Linechart(paper, x, y, width, height, valuesx, valuesy, opts) { var chartinst = this; opts = opts || {}; if (!paper.raphael.is(valuesx[0], "array")) { valuesx = [valuesx]; } if (!paper.raphael.is(valuesy[0], "array")) { valuesy = [valuesy]; } var gutter = opts.gutter || 10, len = Math.max(valuesx[0].length, valuesy[0].length), symbol = opts.symbol || "", colors = opts.colors || chartinst.colors, columns = null, dots = null, chart = paper.set(), path = []; for (var i = 0, ii = valuesy.length; i < ii; i++) { len = Math.max(len, valuesy[i].length); } var shades = paper.set(); for (i = 0, ii = valuesy.length; i < ii; i++) { if (opts.shade) { shades.push(paper.path().attr({ stroke: "none", fill: colors[i], opacity: opts.nostroke ? 1 : .3 })); } if (valuesy[i].length > width - 2 * gutter) { valuesy[i] = shrink(valuesy[i], width - 2 * gutter); len = width - 2 * gutter; } if (valuesx[i] && valuesx[i].length > width - 2 * gutter) { valuesx[i] = shrink(valuesx[i], width - 2 * gutter); } } var allx = Array.prototype.concat.apply([], valuesx), ally = Array.prototype.concat.apply([], valuesy), xdim = chartinst.snapEnds(Math.min.apply(Math, allx), Math.max.apply(Math, allx), valuesx[0].length - 1), minx = xdim.from, maxx = xdim.to, ydim = chartinst.snapEnds(Math.min.apply(Math, ally), Math.max.apply(Math, ally), valuesy[0].length - 1), miny = ydim.from, maxy = ydim.to, kx = (width - gutter * 2) / ((maxx - minx) || 1), ky = (height - gutter * 2) / ((maxy - miny) || 1); var axis = paper.set(); if (opts.axis) { var ax = (opts.axis + "").split(/[,\s]+/); +ax[0] && axis.push(chartinst.axis(x + gutter, y + gutter, width - 2 * gutter, minx, maxx, opts.axisxstep || Math.floor((width - 2 * gutter) / 20), 2, paper)); +ax[1] && axis.push(chartinst.axis(x + width - gutter, y + height - gutter, height - 2 * gutter, miny, maxy, opts.axisystep || Math.floor((height - 2 * gutter) / 20), 3, paper)); +ax[2] && axis.push(chartinst.axis(x + gutter, y + height - gutter, width - 2 * gutter, minx, maxx, opts.axisxstep || Math.floor((width - 2 * gutter) / 20), 0, paper)); +ax[3] && axis.push(chartinst.axis(x + gutter, y + height - gutter, height - 2 * gutter, miny, maxy, opts.axisystep || Math.floor((height - 2 * gutter) / 20), 1, paper)); } var lines = paper.set(), symbols = paper.set(), line; for (i = 0, ii = valuesy.length; i < ii; i++) { if (!opts.nostroke) { lines.push(line = paper.path().attr({ stroke: colors[i], "stroke-width": opts.width || 2, "stroke-linejoin": "round", "stroke-linecap": "round", "stroke-dasharray": opts.dash || "" })); } var sym = Raphael.is(symbol, "array") ? symbol[i] : symbol, symset = paper.set(); path = []; for (var j = 0, jj = valuesy[i].length; j < jj; j++) { var X = x + gutter + ((valuesx[i] || valuesx[0])[j] - minx) * kx, Y = y + height - gutter - (valuesy[i][j] - miny) * ky; (Raphael.is(sym, "array") ? sym[j] : sym) && symset.push(paper[Raphael.is(sym, "array") ? sym[j] : sym](X, Y, (opts.width || 2) * 3).attr({ fill: colors[i], stroke: "none" })); if (opts.smooth) { if (j && j != jj - 1) { var X0 = x + gutter + ((valuesx[i] || valuesx[0])[j - 1] - minx) * kx, Y0 = y + height - gutter - (valuesy[i][j - 1] - miny) * ky, X2 = x + gutter + ((valuesx[i] || valuesx[0])[j + 1] - minx) * kx, Y2 = y + height - gutter - (valuesy[i][j + 1] - miny) * ky, a = getAnchors(X0, Y0, X, Y, X2, Y2); path = path.concat([a.x1, a.y1, X, Y, a.x2, a.y2]); } if (!j) { path = ["M", X, Y, "C", X, Y]; } } else { path = path.concat([j ? "L" : "M", X, Y]); } } if (opts.smooth) { path = path.concat([X, Y, X, Y]); } symbols.push(symset); if (opts.shade) { shades[i].attr({ path: path.concat(["L", X, y + height - gutter, "L", x + gutter + ((valuesx[i] || valuesx[0])[0] - minx) * kx, y + height - gutter, "z"]).join(",") }); } !opts.nostroke && line.attr({ path: path.join(",") }); } function createColumns(f) { // unite Xs together var Xs = []; for (var i = 0, ii = valuesx.length; i < ii; i++) { Xs = Xs.concat(valuesx[i]); } Xs.sort(); // remove duplicates var Xs2 = [], xs = []; for (i = 0, ii = Xs.length; i < ii; i++) { Xs[i] != Xs[i - 1] && Xs2.push(Xs[i]) && xs.push(x + gutter + (Xs[i] - minx) * kx); } Xs = Xs2; ii = Xs.length; var cvrs = f || paper.set(); for (i = 0; i < ii; i++) { var X = xs[i] - (xs[i] - (xs[i - 1] || x)) / 2, w = ((xs[i + 1] || x + width) - xs[i]) / 2 + (xs[i] - (xs[i - 1] || x)) / 2, C; f ? (C = {}) : cvrs.push(C = paper.rect(X - 1, y, Math.max(w + 1, 1), height).attr({ stroke: "none", fill: "#000", opacity: 0 })); C.values = []; C.symbols = paper.set(); C.y = []; C.x = xs[i]; C.axis = Xs[i]; for (var j = 0, jj = valuesy.length; j < jj; j++) { Xs2 = valuesx[j] || valuesx[0]; for (var k = 0, kk = Xs2.length; k < kk; k++) { if (Xs2[k] == Xs[i]) { C.values.push(valuesy[j][k]); C.y.push(y + height - gutter - (valuesy[j][k] - miny) * ky); C.symbols.push(chart.symbols[j][k]); } } } f && f.call(C); } !f && (columns = cvrs); } function createDots(f) { var cvrs = f || paper.set(), C; for (var i = 0, ii = valuesy.length; i < ii; i++) { for (var j = 0, jj = valuesy[i].length; j < jj; j++) { var X = x + gutter + ((valuesx[i] || valuesx[0])[j] - minx) * kx, nearX = x + gutter + ((valuesx[i] || valuesx[0])[j ? j - 1 : 1] - minx) * kx, Y = y + height - gutter - (valuesy[i][j] - miny) * ky; f ? (C = {}) : cvrs.push(C = paper.circle(X, Y, Math.abs(nearX - X) / 2).attr({ stroke: "none", fill: "#000", opacity: 0 })); C.x = X; C.y = Y; C.value = valuesy[i][j]; C.line = chart.lines[i]; C.shade = chart.shades[i]; C.symbol = chart.symbols[i][j]; C.symbols = chart.symbols[i]; C.axis = (valuesx[i] || valuesx[0])[j]; f && f.call(C); } } !f && (dots = cvrs); } chart.push(lines, shades, symbols, axis, columns, dots); chart.lines = lines; chart.shades = shades; chart.symbols = symbols; chart.axis = axis; chart.hoverColumn = function (fin, fout) { !columns && createColumns(); columns.mouseover(fin).mouseout(fout); return this; }; chart.clickColumn = function (f) { !columns && createColumns(); columns.click(f); return this; }; chart.hrefColumn = function (cols) { var hrefs = paper.raphael.is(arguments[0], "array") ? arguments[0] : arguments; if (!(arguments.length - 1) && typeof cols == "object") { for (var x in cols) { for (var i = 0, ii = columns.length; i < ii; i++) if (columns[i].axis == x) { columns[i].attr("href", cols[x]); } } } !columns && createColumns(); for (i = 0, ii = hrefs.length; i < ii; i++) { columns[i] && columns[i].attr("href", hrefs[i]); } return this; }; chart.hover = function (fin, fout) { !dots && createDots(); dots.mouseover(fin).mouseout(fout); return this; }; chart.click = function (f) { !dots && createDots(); dots.click(f); return this; }; chart.each = function (f) { createDots(f); return this; }; chart.eachColumn = function (f) { createColumns(f); return this; }; return chart; }; //inheritance var F = function() {}; F.prototype = Raphael.g; Linechart.prototype = new F; //public Raphael.fn.linechart = function(x, y, width, height, valuesx, valuesy, opts) { return new Linechart(this, x, y, width, height, valuesx, valuesy, opts); } })(); g.raphael-0.5/g.raphael.js 0000644 0001756 0001757 00000067016 11654171544 014501 0 ustar pravi pravi /*! * g.Raphael 0.5 - Charting library, based on Raphaël * * Copyright (c) 2009 Dmitry Baranovskiy (http://g.raphaeljs.com) * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. */ /* * Tooltips on Element prototype */ /*\ * Element.popup [ method ] ** * Puts the context Element in a 'popup' tooltip. Can also be used on sets. ** > Parameters ** - dir (string) location of Element relative to the tail: `'down'`, `'left'`, `'up'` [default], or `'right'`. - size (number) amount of bevel/padding around the Element, as well as half the width and height of the tail [default: `5`] - x (number) x coordinate of the popup's tail [default: Element's `x` or `cx`] - y (number) y coordinate of the popup's tail [default: Element's `y` or `cy`] ** = (object) path element of the popup > Usage | paper.circle(50, 50, 5).attr({ | stroke: "#fff", | fill: "0-#c9de96-#8ab66b:44-#398235" | }).popup(); \*/ Raphael.el.popup = function (dir, size, x, y) { var paper = this.paper || this[0].paper, bb, xy, center, cw, ch; if (!paper) return; switch (this.type) { case 'text': case 'circle': case 'ellipse': center = true; break; default: center = false; } dir = dir == null ? 'up' : dir; size = size || 5; bb = this.getBBox(); x = typeof x == 'number' ? x : (center ? bb.x + bb.width / 2 : bb.x); y = typeof y == 'number' ? y : (center ? bb.y + bb.height / 2 : bb.y); cw = Math.max(bb.width / 2 - size, 0); ch = Math.max(bb.height / 2 - size, 0); this.translate(x - bb.x - (center ? bb.width / 2 : 0), y - bb.y - (center ? bb.height / 2 : 0)); bb = this.getBBox(); var paths = { up: [ 'M', x, y, 'l', -size, -size, -cw, 0, 'a', size, size, 0, 0, 1, -size, -size, 'l', 0, -bb.height, 'a', size, size, 0, 0, 1, size, -size, 'l', size * 2 + cw * 2, 0, 'a', size, size, 0, 0, 1, size, size, 'l', 0, bb.height, 'a', size, size, 0, 0, 1, -size, size, 'l', -cw, 0, 'z' ].join(','), down: [ 'M', x, y, 'l', size, size, cw, 0, 'a', size, size, 0, 0, 1, size, size, 'l', 0, bb.height, 'a', size, size, 0, 0, 1, -size, size, 'l', -(size * 2 + cw * 2), 0, 'a', size, size, 0, 0, 1, -size, -size, 'l', 0, -bb.height, 'a', size, size, 0, 0, 1, size, -size, 'l', cw, 0, 'z' ].join(','), left: [ 'M', x, y, 'l', -size, size, 0, ch, 'a', size, size, 0, 0, 1, -size, size, 'l', -bb.width, 0, 'a', size, size, 0, 0, 1, -size, -size, 'l', 0, -(size * 2 + ch * 2), 'a', size, size, 0, 0, 1, size, -size, 'l', bb.width, 0, 'a', size, size, 0, 0, 1, size, size, 'l', 0, ch, 'z' ].join(','), right: [ 'M', x, y, 'l', size, -size, 0, -ch, 'a', size, size, 0, 0, 1, size, -size, 'l', bb.width, 0, 'a', size, size, 0, 0, 1, size, size, 'l', 0, size * 2 + ch * 2, 'a', size, size, 0, 0, 1, -size, size, 'l', -bb.width, 0, 'a', size, size, 0, 0, 1, -size, -size, 'l', 0, -ch, 'z' ].join(',') }; xy = { up: { x: -!center * (bb.width / 2), y: -size * 2 - (center ? bb.height / 2 : bb.height) }, down: { x: -!center * (bb.width / 2), y: size * 2 + (center ? bb.height / 2 : bb.height) }, left: { x: -size * 2 - (center ? bb.width / 2 : bb.width), y: -!center * (bb.height / 2) }, right: { x: size * 2 + (center ? bb.width / 2 : bb.width), y: -!center * (bb.height / 2) } }[dir]; this.translate(xy.x, xy.y); return paper.path(paths[dir]).attr({ fill: "#000", stroke: "none" }).insertBefore(this.node ? this : this[0]); }; /*\ * Element.tag [ method ] ** * Puts the context Element in a 'tag' tooltip. Can also be used on sets. ** > Parameters ** - angle (number) angle of orientation in degrees [default: `0`] - r (number) radius of the loop [default: `5`] - x (number) x coordinate of the center of the tag loop [default: Element's `x` or `cx`] - y (number) y coordinate of the center of the tag loop [default: Element's `x` or `cx`] ** = (object) path element of the tag > Usage | paper.circle(50, 50, 15).attr({ | stroke: "#fff", | fill: "0-#c9de96-#8ab66b:44-#398235" | }).tag(60); \*/ Raphael.el.tag = function (angle, r, x, y) { var d = 3, paper = this.paper || this[0].paper; if (!paper) return; var p = paper.path().attr({ fill: '#000', stroke: '#000' }), bb = this.getBBox(), dx, R, center, tmp; switch (this.type) { case 'text': case 'circle': case 'ellipse': center = true; break; default: center = false; } angle = angle || 0; x = typeof x == 'number' ? x : (center ? bb.x + bb.width / 2 : bb.x); y = typeof y == 'number' ? y : (center ? bb.y + bb.height / 2 : bb.y); r = r == null ? 5 : r; R = .5522 * r; if (bb.height >= r * 2) { p.attr({ path: [ "M", x, y + r, "a", r, r, 0, 1, 1, 0, -r * 2, r, r, 0, 1, 1, 0, r * 2, "m", 0, -r * 2 -d, "a", r + d, r + d, 0, 1, 0, 0, (r + d) * 2, "L", x + r + d, y + bb.height / 2 + d, "l", bb.width + 2 * d, 0, 0, -bb.height - 2 * d, -bb.width - 2 * d, 0, "L", x, y - r - d ].join(",") }); } else { dx = Math.sqrt(Math.pow(r + d, 2) - Math.pow(bb.height / 2 + d, 2)); p.attr({ path: [ "M", x, y + r, "c", -R, 0, -r, R - r, -r, -r, 0, -R, r - R, -r, r, -r, R, 0, r, r - R, r, r, 0, R, R - r, r, -r, r, "M", x + dx, y - bb.height / 2 - d, "a", r + d, r + d, 0, 1, 0, 0, bb.height + 2 * d, "l", r + d - dx + bb.width + 2 * d, 0, 0, -bb.height - 2 * d, "L", x + dx, y - bb.height / 2 - d ].join(",") }); } angle = 360 - angle; p.rotate(angle, x, y); if (this.attrs) { //elements this.attr(this.attrs.x ? 'x' : 'cx', x + r + d + (!center ? this.type == 'text' ? bb.width : 0 : bb.width / 2)).attr('y', center ? y : y - bb.height / 2); this.rotate(angle, x, y); angle > 90 && angle < 270 && this.attr(this.attrs.x ? 'x' : 'cx', x - r - d - (!center ? bb.width : bb.width / 2)).rotate(180, x, y); } else { //sets if (angle > 90 && angle < 270) { this.translate(x - bb.x - bb.width - r - d, y - bb.y - bb.height / 2); this.rotate(angle - 180, bb.x + bb.width + r + d, bb.y + bb.height / 2); } else { this.translate(x - bb.x + r + d, y - bb.y - bb.height / 2); this.rotate(angle, bb.x - r - d, bb.y + bb.height / 2); } } return p.insertBefore(this.node ? this : this[0]); }; /*\ * Element.drop [ method ] ** * Puts the context Element in a 'drop' tooltip. Can also be used on sets. ** > Parameters ** - angle (number) angle of orientation in degrees [default: `0`] - x (number) x coordinate of the drop's point [default: Element's `x` or `cx`] - y (number) y coordinate of the drop's point [default: Element's `x` or `cx`] ** = (object) path element of the drop > Usage | paper.circle(50, 50, 8).attr({ | stroke: "#fff", | fill: "0-#c9de96-#8ab66b:44-#398235" | }).drop(60); \*/ Raphael.el.drop = function (angle, x, y) { var bb = this.getBBox(), paper = this.paper || this[0].paper, center, size, p, dx, dy; if (!paper) return; switch (this.type) { case 'text': case 'circle': case 'ellipse': center = true; break; default: center = false; } angle = angle || 0; x = typeof x == 'number' ? x : (center ? bb.x + bb.width / 2 : bb.x); y = typeof y == 'number' ? y : (center ? bb.y + bb.height / 2 : bb.y); size = Math.max(bb.width, bb.height) + Math.min(bb.width, bb.height); p = paper.path([ "M", x, y, "l", size, 0, "A", size * .4, size * .4, 0, 1, 0, x + size * .7, y - size * .7, "z" ]).attr({fill: "#000", stroke: "none"}).rotate(22.5 - angle, x, y); angle = (angle + 90) * Math.PI / 180; dx = (x + size * Math.sin(angle)) - (center ? 0 : bb.width / 2); dy = (y + size * Math.cos(angle)) - (center ? 0 : bb.height / 2); this.attrs ? this.attr(this.attrs.x ? 'x' : 'cx', dx).attr(this.attrs.y ? 'y' : 'cy', dy) : this.translate(dx - bb.x, dy - bb.y); return p.insertBefore(this.node ? this : this[0]); }; /*\ * Element.flag [ method ] ** * Puts the context Element in a 'flag' tooltip. Can also be used on sets. ** > Parameters ** - angle (number) angle of orientation in degrees [default: `0`] - x (number) x coordinate of the flag's point [default: Element's `x` or `cx`] - y (number) y coordinate of the flag's point [default: Element's `x` or `cx`] ** = (object) path element of the flag > Usage | paper.circle(50, 50, 10).attr({ | stroke: "#fff", | fill: "0-#c9de96-#8ab66b:44-#398235" | }).flag(60); \*/ Raphael.el.flag = function (angle, x, y) { var d = 3, paper = this.paper || this[0].paper; if (!paper) return; var p = paper.path().attr({ fill: '#000', stroke: '#000' }), bb = this.getBBox(), h = bb.height / 2, center; switch (this.type) { case 'text': case 'circle': case 'ellipse': center = true; break; default: center = false; } angle = angle || 0; x = typeof x == 'number' ? x : (center ? bb.x + bb.width / 2 : bb.x); y = typeof y == 'number' ? y : (center ? bb.y + bb.height / 2: bb.y); p.attr({ path: [ "M", x, y, "l", h + d, -h - d, bb.width + 2 * d, 0, 0, bb.height + 2 * d, -bb.width - 2 * d, 0, "z" ].join(",") }); angle = 360 - angle; p.rotate(angle, x, y); if (this.attrs) { //elements this.attr(this.attrs.x ? 'x' : 'cx', x + h + d + (!center ? this.type == 'text' ? bb.width : 0 : bb.width / 2)).attr('y', center ? y : y - bb.height / 2); this.rotate(angle, x, y); angle > 90 && angle < 270 && this.attr(this.attrs.x ? 'x' : 'cx', x - h - d - (!center ? bb.width : bb.width / 2)).rotate(180, x, y); } else { //sets if (angle > 90 && angle < 270) { this.translate(x - bb.x - bb.width - h - d, y - bb.y - bb.height / 2); this.rotate(angle - 180, bb.x + bb.width + h + d, bb.y + bb.height / 2); } else { this.translate(x - bb.x + h + d, y - bb.y - bb.height / 2); this.rotate(angle, bb.x - h - d, bb.y + bb.height / 2); } } return p.insertBefore(this.node ? this : this[0]); }; /*\ * Element.label [ method ] ** * Puts the context Element in a 'label' tooltip. Can also be used on sets. ** = (object) path element of the label. > Usage | paper.circle(50, 50, 10).attr({ | stroke: "#fff", | fill: "0-#c9de96-#8ab66b:44-#398235" | }).label(); \*/ Raphael.el.label = function () { var bb = this.getBBox(), paper = this.paper || this[0].paper, r = Math.min(20, bb.width + 10, bb.height + 10) / 2; if (!paper) return; return paper.rect(bb.x - r / 2, bb.y - r / 2, bb.width + r, bb.height + r, r).attr({ stroke: 'none', fill: '#000' }).insertBefore(this.node ? this : this[0]); }; /*\ * Element.blob [ method ] ** * Puts the context Element in a 'blob' tooltip. Can also be used on sets. ** > Parameters ** - angle (number) angle of orientation in degrees [default: `0`] - x (number) x coordinate of the blob's tail [default: Element's `x` or `cx`] - y (number) y coordinate of the blob's tail [default: Element's `x` or `cx`] ** = (object) path element of the blob > Usage | paper.circle(50, 50, 8).attr({ | stroke: "#fff", | fill: "0-#c9de96-#8ab66b:44-#398235" | }).blob(60); \*/ Raphael.el.blob = function (angle, x, y) { var bb = this.getBBox(), rad = Math.PI / 180, paper = this.paper || this[0].paper, p, center, size; if (!paper) return; switch (this.type) { case 'text': case 'circle': case 'ellipse': center = true; break; default: center = false; } p = paper.path().attr({ fill: "#000", stroke: "none" }); angle = (+angle + 1 ? angle : 45) + 90; size = Math.min(bb.height, bb.width); x = typeof x == 'number' ? x : (center ? bb.x + bb.width / 2 : bb.x); y = typeof y == 'number' ? y : (center ? bb.y + bb.height / 2 : bb.y); var w = Math.max(bb.width + size, size * 25 / 12), h = Math.max(bb.height + size, size * 25 / 12), x2 = x + size * Math.sin((angle - 22.5) * rad), y2 = y + size * Math.cos((angle - 22.5) * rad), x1 = x + size * Math.sin((angle + 22.5) * rad), y1 = y + size * Math.cos((angle + 22.5) * rad), dx = (x1 - x2) / 2, dy = (y1 - y2) / 2, rx = w / 2, ry = h / 2, k = -Math.sqrt(Math.abs(rx * rx * ry * ry - rx * rx * dy * dy - ry * ry * dx * dx) / (rx * rx * dy * dy + ry * ry * dx * dx)), cx = k * rx * dy / ry + (x1 + x2) / 2, cy = k * -ry * dx / rx + (y1 + y2) / 2; p.attr({ x: cx, y: cy, path: [ "M", x, y, "L", x1, y1, "A", rx, ry, 0, 1, 1, x2, y2, "z" ].join(",") }); this.translate(cx - bb.x - bb.width / 2, cy - bb.y - bb.height / 2); return p.insertBefore(this.node ? this : this[0]); }; /* * Tooltips on Paper prototype */ /*\ * Paper.label [ method ] ** * Puts the given `text` into a 'label' tooltip. The text is given a default style according to @g.txtattr. See @Element.label ** > Parameters ** - x (number) x coordinate of the center of the label - y (number) y coordinate of the center of the label - text (string) text to place inside the label ** = (object) set containing the label path and the text element > Usage | paper.label(50, 50, "$9.99"); \*/ Raphael.fn.label = function (x, y, text) { var set = this.set(); text = this.text(x, y, text).attr(Raphael.g.txtattr); return set.push(text.label(), text); }; /*\ * Paper.popup [ method ] ** * Puts the given `text` into a 'popup' tooltip. The text is given a default style according to @g.txtattr. See @Element.popup * * Note: The `dir` parameter has changed from g.Raphael 0.4.1 to 0.5. The options `0`, `1`, `2`, and `3` has been changed to `'down'`, `'left'`, `'up'`, and `'right'` respectively. ** > Parameters ** - x (number) x coordinate of the popup's tail - y (number) y coordinate of the popup's tail - text (string) text to place inside the popup - dir (string) location of the text relative to the tail: `'down'`, `'left'`, `'up'` [default], or `'right'`. - size (number) amount of padding around the Element [default: `5`] ** = (object) set containing the popup path and the text element > Usage | paper.popup(50, 50, "$9.99", 'down'); \*/ Raphael.fn.popup = function (x, y, text, dir, size) { var set = this.set(); text = this.text(x, y, text).attr(Raphael.g.txtattr); return set.push(text.popup(dir, size), text); }; /*\ * Paper.tag [ method ] ** * Puts the given text into a 'tag' tooltip. The text is given a default style according to @g.txtattr. See @Element.tag ** > Parameters ** - x (number) x coordinate of the center of the tag loop - y (number) y coordinate of the center of the tag loop - text (string) text to place inside the tag - angle (number) angle of orientation in degrees [default: `0`] - r (number) radius of the loop [default: `5`] ** = (object) set containing the tag path and the text element > Usage | paper.tag(50, 50, "$9.99", 60); \*/ Raphael.fn.tag = function (x, y, text, angle, r) { var set = this.set(); text = this.text(x, y, text).attr(Raphael.g.txtattr); return set.push(text.tag(angle, r), text); }; /*\ * Paper.flag [ method ] ** * Puts the given `text` into a 'flag' tooltip. The text is given a default style according to @g.txtattr. See @Element.flag ** > Parameters ** - x (number) x coordinate of the flag's point - y (number) y coordinate of the flag's point - text (string) text to place inside the flag - angle (number) angle of orientation in degrees [default: `0`] ** = (object) set containing the flag path and the text element > Usage | paper.flag(50, 50, "$9.99", 60); \*/ Raphael.fn.flag = function (x, y, text, angle) { var set = this.set(); text = this.text(x, y, text).attr(Raphael.g.txtattr); return set.push(text.flag(angle), text); }; /*\ * Paper.drop [ method ] ** * Puts the given text into a 'drop' tooltip. The text is given a default style according to @g.txtattr. See @Element.drop ** > Parameters ** - x (number) x coordinate of the drop's point - y (number) y coordinate of the drop's point - text (string) text to place inside the drop - angle (number) angle of orientation in degrees [default: `0`] ** = (object) set containing the drop path and the text element > Usage | paper.drop(50, 50, "$9.99", 60); \*/ Raphael.fn.drop = function (x, y, text, angle) { var set = this.set(); text = this.text(x, y, text).attr(Raphael.g.txtattr); return set.push(text.drop(angle), text); }; /*\ * Paper.blob [ method ] ** * Puts the given text into a 'blob' tooltip. The text is given a default style according to @g.txtattr. See @Element.blob ** > Parameters ** - x (number) x coordinate of the blob's tail - y (number) y coordinate of the blob's tail - text (string) text to place inside the blob - angle (number) angle of orientation in degrees [default: `0`] ** = (object) set containing the blob path and the text element > Usage | paper.blob(50, 50, "$9.99", 60); \*/ Raphael.fn.blob = function (x, y, text, angle) { var set = this.set(); text = this.text(x, y, text).attr(Raphael.g.txtattr); return set.push(text.blob(angle), text); }; /** * Brightness functions on the Element prototype */ /*\ * Element.lighter [ method ] ** * Makes the context element lighter by increasing the brightness and reducing the saturation by a given factor. Can be called on Sets. ** > Parameters ** - times (number) adjustment factor [default: `2`] ** = (object) Element > Usage | paper.circle(50, 50, 20).attr({ | fill: "#ff0000", | stroke: "#fff", | "stroke-width": 2 | }).lighter(6); \*/ Raphael.el.lighter = function (times) { times = times || 2; var fs = [this.attrs.fill, this.attrs.stroke]; this.fs = this.fs || [fs[0], fs[1]]; fs[0] = Raphael.rgb2hsb(Raphael.getRGB(fs[0]).hex); fs[1] = Raphael.rgb2hsb(Raphael.getRGB(fs[1]).hex); fs[0].b = Math.min(fs[0].b * times, 1); fs[0].s = fs[0].s / times; fs[1].b = Math.min(fs[1].b * times, 1); fs[1].s = fs[1].s / times; this.attr({fill: "hsb(" + [fs[0].h, fs[0].s, fs[0].b] + ")", stroke: "hsb(" + [fs[1].h, fs[1].s, fs[1].b] + ")"}); return this; }; /*\ * Element.darker [ method ] ** * Makes the context element darker by decreasing the brightness and increasing the saturation by a given factor. Can be called on Sets. ** > Parameters ** - times (number) adjustment factor [default: `2`] ** = (object) Element > Usage | paper.circle(50, 50, 20).attr({ | fill: "#ff0000", | stroke: "#fff", | "stroke-width": 2 | }).darker(6); \*/ Raphael.el.darker = function (times) { times = times || 2; var fs = [this.attrs.fill, this.attrs.stroke]; this.fs = this.fs || [fs[0], fs[1]]; fs[0] = Raphael.rgb2hsb(Raphael.getRGB(fs[0]).hex); fs[1] = Raphael.rgb2hsb(Raphael.getRGB(fs[1]).hex); fs[0].s = Math.min(fs[0].s * times, 1); fs[0].b = fs[0].b / times; fs[1].s = Math.min(fs[1].s * times, 1); fs[1].b = fs[1].b / times; this.attr({fill: "hsb(" + [fs[0].h, fs[0].s, fs[0].b] + ")", stroke: "hsb(" + [fs[1].h, fs[1].s, fs[1].b] + ")"}); return this; }; /*\ * Element.resetBrightness [ method ] ** * Resets brightness and saturation levels to their original values. See @Element.lighter and @Element.darker. Can be called on Sets. ** = (object) Element > Usage | paper.circle(50, 50, 20).attr({ | fill: "#ff0000", | stroke: "#fff", | "stroke-width": 2 | }).lighter(6).resetBrightness(); \*/ Raphael.el.resetBrightness = function () { if (this.fs) { this.attr({ fill: this.fs[0], stroke: this.fs[1] }); delete this.fs; } return this; }; //alias to set prototype (function () { var brightness = ['lighter', 'darker', 'resetBrightness'], tooltips = ['popup', 'tag', 'flag', 'label', 'drop', 'blob']; for (var f in tooltips) (function (name) { Raphael.st[name] = function () { return Raphael.el[name].apply(this, arguments); }; })(tooltips[f]); for (var f in brightness) (function (name) { Raphael.st[name] = function () { for (var i = 0; i < this.length; i++) { this[i][name].apply(this[i], arguments); } return this; }; })(brightness[f]); })(); //chart prototype for storing common functions Raphael.g = { /*\ * g.shim [ object ] ** * An attribute object that charts will set on all generated shims (shims being the invisible objects that mouse events are bound to) ** > Default value | { stroke: 'none', fill: '#000', 'fill-opacity': 0 } \*/ shim: { stroke: 'none', fill: '#000', 'fill-opacity': 0 }, /*\ * g.txtattr [ object ] ** * An attribute object that charts and tooltips will set on any generated text ** > Default value | { font: '12px Arial, sans-serif', fill: '#fff' } \*/ txtattr: { font: '12px Arial, sans-serif', fill: '#fff' }, /*\ * g.colors [ array ] ** * An array of color values that charts will iterate through when drawing chart data values. ** \*/ colors: (function () { var hues = [.6, .2, .05, .1333, .75, 0], colors = []; for (var i = 0; i < 10; i++) { if (i < hues.length) { colors.push('hsb(' + hues[i] + ',.75, .75)'); } else { colors.push('hsb(' + hues[i - hues.length] + ', 1, .5)'); } } return colors; })(), snapEnds: function(from, to, steps) { var f = from, t = to; if (f == t) { return {from: f, to: t, power: 0}; } function round(a) { return Math.abs(a - .5) < .25 ? ~~(a) + .5 : Math.round(a); } var d = (t - f) / steps, r = ~~(d), R = r, i = 0; if (r) { while (R) { i--; R = ~~(d * Math.pow(10, i)) / Math.pow(10, i); } i ++; } else { while (!r) { i = i || 1; r = ~~(d * Math.pow(10, i)) / Math.pow(10, i); i++; } i && i--; } t = round(to * Math.pow(10, i)) / Math.pow(10, i); if (t < to) { t = round((to + .5) * Math.pow(10, i)) / Math.pow(10, i); } f = round((from - (i > 0 ? 0 : .5)) * Math.pow(10, i)) / Math.pow(10, i); return { from: f, to: t, power: i }; }, axis: function (x, y, length, from, to, steps, orientation, labels, type, dashsize, paper) { dashsize = dashsize == null ? 2 : dashsize; type = type || "t"; steps = steps || 10; paper = arguments[arguments.length-1] //paper is always last argument var path = type == "|" || type == " " ? ["M", x + .5, y, "l", 0, .001] : orientation == 1 || orientation == 3 ? ["M", x + .5, y, "l", 0, -length] : ["M", x, y + .5, "l", length, 0], ends = this.snapEnds(from, to, steps), f = ends.from, t = ends.to, i = ends.power, j = 0, txtattr = { font: "11px 'Fontin Sans', Fontin-Sans, sans-serif" }, text = paper.set(), d; d = (t - f) / steps; var label = f, rnd = i > 0 ? i : 0; dx = length / steps; if (+orientation == 1 || +orientation == 3) { var Y = y, addon = (orientation - 1 ? 1 : -1) * (dashsize + 3 + !!(orientation - 1)); while (Y >= y - length) { type != "-" && type != " " && (path = path.concat(["M", x - (type == "+" || type == "|" ? dashsize : !(orientation - 1) * dashsize * 2), Y + .5, "l", dashsize * 2 + 1, 0])); text.push(paper.text(x + addon, Y, (labels && labels[j++]) || (Math.round(label) == label ? label : +label.toFixed(rnd))).attr(txtattr).attr({ "text-anchor": orientation - 1 ? "start" : "end" })); label += d; Y -= dx; } if (Math.round(Y + dx - (y - length))) { type != "-" && type != " " && (path = path.concat(["M", x - (type == "+" || type == "|" ? dashsize : !(orientation - 1) * dashsize * 2), y - length + .5, "l", dashsize * 2 + 1, 0])); text.push(paper.text(x + addon, y - length, (labels && labels[j]) || (Math.round(label) == label ? label : +label.toFixed(rnd))).attr(txtattr).attr({ "text-anchor": orientation - 1 ? "start" : "end" })); } } else { label = f; rnd = (i > 0) * i; addon = (orientation ? -1 : 1) * (dashsize + 9 + !orientation); var X = x, dx = length / steps, txt = 0, prev = 0; while (X <= x + length) { type != "-" && type != " " && (path = path.concat(["M", X + .5, y - (type == "+" ? dashsize : !!orientation * dashsize * 2), "l", 0, dashsize * 2 + 1])); text.push(txt = paper.text(X, y + addon, (labels && labels[j++]) || (Math.round(label) == label ? label : +label.toFixed(rnd))).attr(txtattr)); var bb = txt.getBBox(); if (prev >= bb.x - 5) { text.pop(text.length - 1).remove(); } else { prev = bb.x + bb.width; } label += d; X += dx; } if (Math.round(X - dx - x - length)) { type != "-" && type != " " && (path = path.concat(["M", x + length + .5, y - (type == "+" ? dashsize : !!orientation * dashsize * 2), "l", 0, dashsize * 2 + 1])); text.push(paper.text(x + length, y + addon, (labels && labels[j]) || (Math.round(label) == label ? label : +label.toFixed(rnd))).attr(txtattr)); } } var res = paper.path(path); res.text = text; res.all = paper.set([res, text]); res.remove = function () { this.text.remove(); this.constructor.prototype.remove.call(this); }; return res; }, labelise: function(label, val, total) { if (label) { return (label + "").replace(/(##+(?:\.#+)?)|(%%+(?:\.%+)?)/g, function (all, value, percent) { if (value) { return (+val).toFixed(value.replace(/^#+\.?/g, "").length); } if (percent) { return (val * 100 / total).toFixed(percent.replace(/^%+\.?/g, "").length) + "%"; } }); } else { return (+val).toFixed(0); } } } g.raphael-0.5/test/ 0000755 0001756 0001757 00000000000 11654171544 013247 5 ustar pravi pravi g.raphael-0.5/test/linechart.html 0000644 0001756 0001757 00000006566 11654171544 016123 0 ustar pravi pravi
Demo of gRaphaël JavaScript library.
g.raphael-0.5/test/images/ 0000755 0001756 0001757 00000000000 11654171544 014514 5 ustar pravi pravi g.raphael-0.5/test/images/bgbg.png 0000644 0001756 0001757 00000004604 11654171544 016127 0 ustar pravi pravi PNG IHDR ( dS 0PLTEq tEXtSoftware Adobe ImageReadyqe<