Moving API to some stable point.
authorDmitry Baranovskiy <dbaranovskiy@Fresh-Air.local>
Wed, 5 Aug 2009 06:55:13 +0000 (16:55 +1000)
committerDmitry Baranovskiy <dbaranovskiy@Fresh-Air.local>
Wed, 5 Aug 2009 06:55:13 +0000 (16:55 +1000)
g.bar.js
g.dot.js [new file with mode: 0644]
g.line.js [new file with mode: 0644]
g.pie.js
g.raphael.js
test.html
test2.html

index 45b3e65..812d387 100644 (file)
--- a/g.bar.js
+++ b/g.bar.js
@@ -1,3 +1,10 @@
+/*
+ * g.Raphael 0.2 - 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.
+ */
+
 Raphael.fn.g.barchart = function (x, y, width, height, values, isVertical, opts) {
     opts = opts || {};
     var type = {round: "round", sharp: "sharp", soft: "soft"}[opts.type] || "square",
@@ -10,9 +17,9 @@ Raphael.fn.g.barchart = function (x, y, width, height, values, isVertical, opts)
         stacktotal = [],
         paper = this,
         multi = 0,
-        colors = opts.colors || Raphael.fn.g.colors,
+        colors = opts.colors || this.g.colors,
         len = values.length;
-    if (this.g.isArray(values[0])) {
+    if (this.raphael.isArray(values[0])) {
         total = [];
         multi = len;
         len = 0;
@@ -58,7 +65,7 @@ Raphael.fn.g.barchart = function (x, y, width, height, values, isVertical, opts)
                 var h = Math.round((multi ? values[j][i] : values[i]) * Y),
                     top = y + height - barvgutter - h,
                     bar;
-                bars.push(bar = this.g.finger(Math.round(X + barwidth / 2), top + h, barwidth, opts.init ? 0 : h, true, type).attr({stroke: "none", fill: colors[multi > 1 ? j : i]}));
+                bars.push(bar = this.g.finger(Math.round(X + barwidth / 2), top + h, barwidth, opts.init ? 0 : h, true, type).attr({stroke: "none", fill: colors[multi ? j : i]}));
                 bar.y = top;
                 bar.x = Math.round(X + barwidth / 2);
                 bar.w = barwidth;
@@ -127,7 +134,7 @@ Raphael.fn.g.barchart = function (x, y, width, height, values, isVertical, opts)
                         tot += multi ? values[j][i] : values[i];
                         if (j == multi - 1) {
                             var label = paper.g.labelise(labels[i], tot, total);
-                            L = paper.text(bars[i * (multi || 1) + j].x, y + height - barvgutter / 2, label).insertBefore(covers[i * (multi || 1) + j]);
+                            L = paper.g.text(bars[i * (multi || 1) + j].x, y + height - barvgutter / 2, label).insertBefore(covers[i * (multi || 1) + j]);
                             var bb = L.getBBox();
                             if (bb.x - 7 < l) {
                                 L.remove();
@@ -142,7 +149,7 @@ Raphael.fn.g.barchart = function (x, y, width, height, values, isVertical, opts)
                 for (var i = 0; i < len; i++) {
                     for (var j = 0; j < multi; j++) {
                         var label = paper.g.labelise(multi ? labels[j] && labels[j][i] : labels[i], multi ? values[j][i] : values[i], total);
-                        L = paper.text(bars[i * (multi || 1) + j].x, isBottom ? y + height - barvgutter / 2 : bars[i * (multi || 1) + j].y - 10, label).insertBefore(covers[i * (multi || 1) + j]);
+                        L = paper.g.text(bars[i * (multi || 1) + j].x, isBottom ? y + height - barvgutter / 2 : bars[i * (multi || 1) + j].y - 10, label).insertBefore(covers[i * (multi || 1) + j]);
                         var bb = L.getBBox();
                         if (bb.x - 7 < l) {
                             L.remove();
@@ -224,7 +231,7 @@ Raphael.fn.g.barchart = function (x, y, width, height, values, isVertical, opts)
                     var X = isRight ? bars[i * (multi || 1) + j].x - barheight / 2 + 3 : x + 5,
                         A = isRight ? "end" : "start",
                         L;
-                    this.labels.push(L = paper.text(X, bars[i * (multi || 1) + j].y, label).attr({"text-anchor": A}).insertBefore(covers[0]));
+                    this.labels.push(L = paper.g.text(X, bars[i * (multi || 1) + j].y, label).attr({"text-anchor": A}).insertBefore(covers[0]));
                     if (L.getBBox().x < x + 5) {
                         L.attr({x: x + 5, "text-anchor": "start"});
                     } else {
@@ -239,29 +246,30 @@ Raphael.fn.g.barchart = function (x, y, width, height, values, isVertical, opts)
         covers2.hide();
         covers.show();
         fout = fout || function () {};
-        var that = this;
-        for (var i = 0, ii = covers.length; i < ii; i++) {
-            covers[i].mouseover(fin).mouseout(fout);
-        }
+        covers.mouseover(fin).mouseout(fout);
         return this;
     };
     chart.hoverColumn = function (fin, fout) {
         covers.hide();
         covers2.show();
         fout = fout || function () {};
-        var that = this;
-        for (var i = 0, ii = covers2.length; i < ii; i++) {
-            covers2[i].mouseover(fin).mouseout(fout);
-        }
+        covers2.mouseover(fin).mouseout(fout);
+        return this;
+    };
+    chart.click = function (f) {
+        covers2.hide();
+        covers.show();
+        covers.click(f);
+        return this;
+    };
+    chart.clickColumn = function (f) {
+        covers.hide();
+        covers2.show();
+        covers2.click(f);
         return this;
     };
-    chart.push(bars);
+    chart.push(bars, covers, covers2);
     chart.bars = bars;
     chart.covers = covers;
-    chart.remove = function () {
-        chart.bars.remove();
-        chart.labels && chart.labels.remove();
-        chart.covers.remove();
-    };
     return chart;
 };
\ No newline at end of file
diff --git a/g.dot.js b/g.dot.js
new file mode 100644 (file)
index 0000000..d0255a2
--- /dev/null
+++ b/g.dot.js
@@ -0,0 +1,100 @@
+/*
+ * g.Raphael 0.2 - 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.
+ */
+
+Raphael.fn.g.dotchart = function (x, y, width, height, valuesx, valuesy, size, opts) {
+    function drawAxis(ax) {
+        +ax[0] && (ax[0] = paper.g.axis(x + gutter, y + gutter, width - 2 * gutter, minx, maxx, opts.axisxstep || Math.floor((width - 2 * gutter) / 20), 2, opts.axisxlabels || null, opts.axisxtype || "t"));
+        +ax[1] && (ax[1] = paper.g.axis(x + width - gutter, y + height - gutter, height - 2 * gutter, miny, maxy, opts.axisystep || Math.floor((height - 2 * gutter) / 20), 3, opts.axisylabels || null, opts.axisytype || "t"));
+        +ax[2] && (ax[2] = paper.g.axis(x + gutter, y + height - gutter + maxR, width - 2 * gutter, minx, maxx, opts.axisxstep || Math.floor((width - 2 * gutter) / 20), 0, opts.axisxlabels || null, opts.axisxtype || "t"));
+        +ax[3] && (ax[3] = paper.g.axis(x + gutter - maxR, y + height - gutter, height - 2 * gutter, miny, maxy, opts.axisystep || Math.floor((height - 2 * gutter) / 20), 1, opts.axisylabels || null, opts.axisytype || "t"));
+    }
+    opts = opts || {};
+    var xdim = this.g.snapEnds(Math.min.apply(Math, valuesx), Math.max.apply(Math, valuesx), valuesx.length - 1),
+        minx = xdim.from,
+        maxx = xdim.to,
+        gutter = opts.gutter || 10,
+        ydim = this.g.snapEnds(Math.min.apply(Math, valuesy), Math.max.apply(Math, valuesy), valuesy.length - 1),
+        miny = ydim.from,
+        maxy = ydim.to,
+        len = Math.max(valuesx.length, valuesy.length, size.length),
+        symbol = this.g.markers[opts.symbol] || "disc",
+        res = this.set(),
+        series = this.set(),
+        max = opts.max || 100,
+        top = Math.max.apply(Math, size),
+        R = [],
+        paper = this,
+        k = Math.sqrt(top / Math.PI) * 2 / max;
+
+    for (var i = 0; i < len; i++) {
+        R[i] = Math.min(Math.sqrt(size[i] / Math.PI) * 2 / k, max);
+    }
+    gutter = Math.max.apply(Math, R.concat(gutter));
+    var axis = this.set(),
+        maxR = Math.max.apply(Math, R);
+    if (opts.axis) {
+        var ax = (opts.axis + "").split(/[,\s]+/);
+        drawAxis(ax);
+        var g = [], b = [];
+        for (var i = 0, ii = ax.length; i < ii; i++) {
+            var bb = ax[i].all ? ax[i].all.getBBox()[["height", "width"][i % 2]] : 0;
+            g[i] = bb + gutter;
+            b[i] = bb;
+        }
+        gutter = Math.max.apply(Math, g.concat(gutter));
+        for (var i = 0, ii = ax.length; i < ii; i++) if (ax[i].all) {
+            ax[i].remove();
+            ax[i] = 1;
+        }
+        drawAxis(ax);
+        for (var i = 0, ii = ax.length; i < ii; i++) if (ax[i].all) {
+            axis.push(ax[i].all);
+        }
+        res.axis = axis;
+    }
+    var kx = (width - gutter * 2) / ((maxx - minx) || 1),
+        ky = (height - gutter * 2) / ((maxy - miny) || 1);
+    for (var i = 0, ii = valuesy.length; i < ii; i++) {
+        var sym = this.raphael.isArray(symbol) ? symbol[i] : symbol,
+            X = x + gutter + (valuesx[i] - minx) * kx,
+            Y = y + height - gutter - (valuesy[i] - miny) * ky;
+        sym && R[i] && series.push(this.g[sym](X, Y, R[i]).attr({fill: opts.heat ? this.g.colorValue(R[i], maxR) : Raphael.fn.g.colors[0], "fill-opacity": opts.opacity ? R[i] / max : 1, stroke: "none"}));
+    }
+    var covers = this.set();
+    for (var i = 0, ii = valuesy.length; i < ii; i++) {
+        var X = x + gutter + (valuesx[i] - minx) * kx,
+            Y = y + height - gutter - (valuesy[i] - miny) * ky;
+        covers.push(this.circle(X, Y, maxR).attr({fill: "#000", stroke: "none", opacity: 0}));
+        opts.href && opts.href[i] && covers[i].attr({href: opts.href[i]});
+        covers[i].r = +R[i].toFixed(3);
+        covers[i].x = +X.toFixed(3);
+        covers[i].y = +Y.toFixed(3);
+        covers[i].X = valuesx[i];
+        covers[i].Y = valuesy[i];
+        covers[i].value = size[i] || 0;
+        covers[i].dot = series[i];
+    }
+    res.covers = covers;
+    res.series = series;
+    res.push(series, axis, covers);
+    res.hover = function (fin, fout) {
+        covers.mouseover(fin).mouseout(fout);
+        return this;
+    };
+    res.click = function (f) {
+        covers.click(f);
+        return this;
+    };
+    res.href = function (map) {
+        for (var i = covers.length; i--;) {
+            if (covers[i].X == map.x && covers[i].Y == map.y && covers[i].value == map.value) {
+                covers[i].attr({href: map.href});
+            }
+        }
+    };
+    return res;
+};
diff --git a/g.line.js b/g.line.js
new file mode 100644 (file)
index 0000000..abaeaa4
--- /dev/null
+++ b/g.line.js
@@ -0,0 +1,196 @@
+/*
+ * g.Raphael 0.2 - 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.
+ */
+
+Raphael.fn.g.linechart = function (x, y, width, height, valuesx, valuesy, opts) {
+    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;
+    }
+    opts = opts || {};
+    if (!this.raphael.isArray(valuesx[0])) {
+        valuesx = [valuesx];
+    }
+    if (!this.raphael.isArray(valuesy[0])) {
+        valuesy = [valuesy];
+    }
+    var allx = Array.prototype.concat.apply([], valuesx),
+        ally = Array.prototype.concat.apply([], valuesy),
+        xdim = this.g.snapEnds(Math.min.apply(Math, allx), Math.max.apply(Math, allx), valuesx[0].length - 1),
+        minx = xdim.from,
+        maxx = xdim.to,
+        gutter = opts.gutter || 10,
+        kx = (width - gutter * 2) / (maxx - minx),
+        ydim = this.g.snapEnds(Math.min.apply(Math, ally), Math.max.apply(Math, ally), valuesy[0].length - 1),
+        miny = ydim.from,
+        maxy = ydim.to,
+        ky = (height - gutter * 2) / (maxy - miny),
+        len = Math.max(valuesx[0].length, valuesy[0].length),
+        symbol = opts.symbol || "",
+        colors = opts.colors || Raphael.fn.g.colors,
+        that = this,
+        columns = null,
+        dots = null,
+        chart = this.set(),
+        path = [];
+
+    for (var i = 0, ii = valuesy.length; i < ii; i++) {
+        len = Math.max(len, valuesy[i].length);
+    }
+    var shades = this.set();
+    for (var i = 0, ii = valuesy.length; i < ii; i++) {
+        if (opts.shade) {
+            shades.push(this.path({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 axis = this.set();
+    if (opts.axis) {
+        var ax = (opts.axis + "").split(/[,\s]+/);
+        +ax[0] && axis.push(this.g.axis(x + gutter, y + gutter, width - 2 * gutter, minx, maxx, opts.axisxstep || Math.floor((width - 2 * gutter) / 20), 2));
+        +ax[1] && axis.push(this.g.axis(x + width - gutter, y + height - gutter, height - 2 * gutter, miny, maxy, opts.axisystep || Math.floor((height - 2 * gutter) / 20), 3));
+        +ax[2] && axis.push(this.g.axis(x + gutter, y + height - gutter, width - 2 * gutter, minx, maxx, opts.axisxstep || Math.floor((width - 2 * gutter) / 20), 0));
+        +ax[3] && axis.push(this.g.axis(x + gutter, y + height - gutter, height - 2 * gutter, miny, maxy, opts.axisystep || Math.floor((height - 2 * gutter) / 20), 1));
+    }
+    var lines = this.set(),
+        symbols = this.set(),
+        line;
+    for (var i = 0, ii = valuesy.length; i < ii; i++) {
+        if (!opts.nostroke) {
+            lines.push(line = this.path({
+                stroke: colors[i],
+                "stroke-width": opts.width || 2,
+                "stroke-linejoin": "round",
+                "stroke-linecap": "round",
+                "stroke-dasharray": opts.dash || ""
+            }));
+        }
+        var sym = this.raphael.isArray(symbol) ? symbol[i] : symbol;
+        path = [];
+        for (var j = 0, jj = valuesy[i].length; j < jj; j++) {
+            var X = x + gutter + ((valuesx[i] || valuesx[0])[j] - minx) * kx;
+            var Y = y + height - gutter - (valuesy[i][j] - miny) * ky;
+            (Raphael.isArray(sym) ? sym[j] : sym) && symbols.push(this.g[Raphael.fn.g.markers[this.raphael.isArray(sym) ? sym[j] : sym]](X, Y, (opts.width || 2) * 3).attr({fill: colors[i], stroke: "none"}));
+            path = path.concat([j ? "L" : "M", X, Y]);
+        }
+        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() {
+        // 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 (var 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 = that.set();
+        for (var 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;
+            cvrs.push(C = that.rect(X - 1, y, w + 1, height).attr({stroke: "none", fill: "#000", opacity: 0}));
+            C.values = [];
+            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);
+                    }
+                }
+            }
+        }
+        columns = cvrs;
+    }
+    function createDots() {
+        var cvrs = that.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;
+                cvrs.push(C = that.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.axis = (valuesx[i] || valuesx[0])[j];
+            }
+        }
+        dots = cvrs;
+    }
+    chart.push(axis, columns, dots, lines, shades, symbols);
+    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 = that.raphael.isArray(arguments[0]) ? 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 (var i = 0, ii = hrefs.length; i < ii; i++) {
+            columns[i] && columns[i].attr("href", hrefs[i]);
+        }
+        return this;
+    };
+    chart.hoverDot = function (fin, fout) {
+        !dots && createDots();
+        dots.mouseover(fin).mouseout(fout);
+        return this;
+    };
+    chart.clickDot = function (f) {
+        !dots && createDots();
+        dots.click(f);
+        return this;
+    };
+    return chart;
+};
index ce21a21..e5a9539 100644 (file)
--- a/g.pie.js
+++ b/g.pie.js
@@ -1,9 +1,17 @@
+/*
+ * g.Raphael 0.2 - 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.
+ */
+
 Raphael.fn.g.piechart = function (cx, cy, r, values, opts) {
     opts = opts || {};
     var paper = this,
         sectors = [],
-        covers = [],
+        covers = this.set(),
         chart = this.set(),
+        series = this.set(),
         order = [],
         len = values.length,
         angle = 0,
@@ -13,13 +21,12 @@ Raphael.fn.g.piechart = function (cx, cy, r, values, opts) {
         defcut = true;
     chart.covers = covers;
     if (len == 1) {
-        chart.push(paper.circle(cx, cy, r).attr({fill: Raphael.fn.g.colors[0], stroke: opt.stroke || "#fff", "stroke-width": opts.strokewidth == null ? 1 : opts.strokewidth}));
-        covers.push(paper.circle(cx, cy, r).attr({fill: "#000", opacity: 0, "stroke-width": 3}));
-        chart.push(covers[0]);
+        series.push(this.circle(cx, cy, r).attr({fill: this.g.colors[0], stroke: opt.stroke || "#fff", "stroke-width": opts.strokewidth == null ? 1 : opts.strokewidth}));
+        covers.push(this.circle(cx, cy, r).attr({fill: "#000", opacity: 0, "stroke-width": 3}));
         total = values[0];
         values[0] = {value: values[0], order: 0, valueOf: function () { return this.value; }};
-        chart[0].middle = {x: cx, y: cy};
-        chart[0].mangle = 180;
+        series[0].middle = {x: cx, y: cy};
+        series[0].mangle = 180;
     } else {
         function sector(cx, cy, r, startAngle, endAngle, fill) {
             var rad = Math.PI / 180,
@@ -64,12 +71,12 @@ Raphael.fn.g.piechart = function (cx, cy, r, values, opts) {
                 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 = this.path({fill: opts.colors && opts.colors[i] || Raphael.fn.g.colors[i] || "#666", stroke: opts.stroke || "#fff", "stroke-width": opts.strokewidth == null ? 1 : opts.strokewidth, "stroke-linejoin": "round"}, opts.init ? ipath : path.join(","));
+            var p = this.path({fill: opts.colors && opts.colors[i] || this.g.colors[i] || "#666", stroke: opts.stroke || "#fff", "stroke-width": opts.strokewidth == null ? 1 : opts.strokewidth, "stroke-linejoin": "round"}, opts.init ? ipath : path.join(","));
             p.value = values[i];
             p.middle = path.middle;
             p.mangle = mangle;
             sectors.push(p);
-            chart.push(p);
+            series.push(p);
             opts.init && p.animate({path: path.join(",")}, (+opts.init - 1) || 1000, ">");
         }
         for (var i = 0; i < len; i++) {
@@ -77,17 +84,10 @@ Raphael.fn.g.piechart = function (cx, cy, r, values, opts) {
             opts.href && opts.href[i] && p.attr({href: opts.href[i]});
             p.attr = function () {};
             covers.push(p);
-            chart.push(p);
+            series.push(p);
         }
     }
 
-    chart.color = function (colorarray) {
-        var arr = colorarray || arguments;
-        for (var i = 0, ii = len; i < ii; i++) {
-            this[i].attr({fill: arr[i] || Raphael.fn.g.colors[i]});
-        }
-        return this;
-    };
     chart.hover = function (fin, fout) {
         fout = fout || function () {};
         var that = this;
@@ -111,7 +111,29 @@ Raphael.fn.g.piechart = function (cx, cy, r, values, opts) {
                 }).mouseout(function () {
                     fout.call(o);
                 });
-            })(this[i], covers[i], i);
+            })(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;
     };
@@ -127,14 +149,14 @@ Raphael.fn.g.piechart = function (cx, cy, r, values, opts) {
         mark = paper.g.markers[mark && mark.toLowerCase()] || "disc";
         chart.labels = paper.set();
         for (var i = 0; i < len; i++) {
-            var clr = chart[i].attr("fill"),
+            var clr = series[i].attr("fill"),
                 j = values[i].order,
                 txt;
             values[i].others && (labels[j] = otherslabel || "Others");
             labels[j] = paper.g.labelise(labels[j], values[i], total);
             chart.labels.push(paper.set());
             chart.labels[i].push(paper.g[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({font: opts.legendfont || '10px "Arial"', fill: opts.legendcolor || "#000", "text-anchor": "start"}));
+            chart.labels[i].push(txt = paper.text(x + 20, h, labels[j] || values[j]).attr(paper.g.txtattr).attr({fill: opts.legendcolor || "#000", "text-anchor": "start"}));
             covers[i].label = chart.labels[i];
             h += txt.getBBox().height * 1.2;
         }
@@ -151,5 +173,8 @@ Raphael.fn.g.piechart = function (cx, cy, r, values, opts) {
     if (opts.legend) {
         legend(opts.legend, opts.legendothers, opts.legendmark, opts.legendpos);
     }
+    chart.push(series, covers);
+    chart.series = series;
+    chart.covers = covers;
     return chart;
 };
index 497b91e..4ea11ec 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * g.Raphael 0.2 - Charting library on Raphaël
+ * g.Raphael 0.2 - Charting library, based on Raphaël
  *
- * Copyright (c) 2009 Dmitry Baranovskiy (http://raphaeljs.com)
+ * Copyright (c) 2009 Dmitry Baranovskiy (http://g.raphaeljs.com)
  * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
  */
 (function () {
@@ -22,6 +22,7 @@
         arrow: "arrow",
         "->": "arrow"
     };
+    Raphael.fn.g.txtattr = {font: "12px Arial, sans-serif"};
     Raphael.fn.g.colors = [];
     var hues = [.6, .2, .05, .1333, .75, 0];
     for (var i = 0; i < 10; i++) {
@@ -31,6 +32,9 @@
             Raphael.fn.g.colors.push("hsb(" + hues[i - hues.length] + ", 1, .5)");
         }
     }
+    Raphael.fn.g.text = function (x, y, text) {
+        return this.text(x, y, text).attr(this.g.txtattr);
+    };
     Raphael.fn.g.labelise = function (label, val, total) {
         if (label) {
             return (label + "").replace(/(##+(?:\.#+)?)|(%%+(?:\.%+)?)/g, function (all, value, percent) {
         }
     };
 
-    Raphael.fn.g.linechart = function (x, y, width, height, valuesx, valuesy, opts) {
-        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;
-        }
-        opts = opts || {};
-        if (!this.g.isArray(valuesx[0])) {
-            valuesx = [valuesx];
-        }
-        if (!this.g.isArray(valuesy[0])) {
-            valuesy = [valuesy];
-        }
-        var allx = Array.prototype.concat.apply([], valuesx),
-            ally = Array.prototype.concat.apply([], valuesy),
-            xdim = snapEnds(Math.min.apply(Math, allx), Math.max.apply(Math, allx), valuesx[0].length - 1),
-            minx = xdim.from,
-            maxx = xdim.to,
-            gutter = opts.gutter || 10,
-            kx = (width - gutter * 2) / (maxx - minx),
-            ydim = snapEnds(Math.min.apply(Math, ally), Math.max.apply(Math, ally), valuesy[0].length - 1),
-            miny = ydim.from,
-            maxy = ydim.to,
-            ky = (height - gutter * 2) / (maxy - miny),
-            len = Math.max(valuesx[0].length, valuesy[0].length),
-            symbol = opts.symbol || "",
-            colors = opts.colors || Raphael.fn.g.colors,
-            that = this,
-            path = [];
-
-        for (var i = 0, ii = valuesy.length; i < ii; i++) {
-            len = Math.max(len, valuesy[i].length);
-        }
-        var shades = this.set();
-        for (var i = 0, ii = valuesy.length; i < ii; i++) {
-            if (opts.shade) {
-                shades.push(this.path({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 axis = this.set();
-        if (opts.axis) {
-            var ax = (opts.axis + "").split(/[,\s]+/);
-            +ax[0] && axis.push(this.g.axis(x + gutter, y + gutter, width - 2 * gutter, minx, maxx, opts.axisxstep || Math.floor((width - 2 * gutter) / 20), 2));
-            +ax[1] && axis.push(this.g.axis(x + width - gutter, y + height - gutter, height - 2 * gutter, miny, maxy, opts.axisystep || Math.floor((height - 2 * gutter) / 20), 3));
-            +ax[2] && axis.push(this.g.axis(x + gutter, y + height - gutter, width - 2 * gutter, minx, maxx, opts.axisxstep || Math.floor((width - 2 * gutter) / 20), 0));
-            +ax[3] && axis.push(this.g.axis(x + gutter, y + height - gutter, height - 2 * gutter, miny, maxy, opts.axisystep || Math.floor((height - 2 * gutter) / 20), 1));
-        }
-        var lines = this.set(),
-            symbols = this.set(),
-            line;
-        for (var i = 0, ii = valuesy.length; i < ii; i++) {
-            if (!opts.nostroke) {
-                lines.push(line = this.path({
-                    stroke: colors[i],
-                    "stroke-width": opts.width || 2,
-                    "stroke-linejoin": "round",
-                    "stroke-linecap": "round",
-                    "stroke-dasharray": opts.dash || ""
-                }));
-            }
-            var sym = this.g.isArray(symbol) ? symbol[i] : symbol;
-            path = [];
-            for (var j = 0, jj = valuesy[i].length; j < jj; j++) {
-                var X = x + gutter + ((valuesx[i] || valuesx[0])[j] - minx) * kx;
-                var Y = y + height - gutter - (valuesy[i][j] - miny) * ky;
-                (this.g.isArray(sym) ? sym[j] : sym) && symbols.push(this.g[this.g.isArray(sym) ? sym[j] : sym](X, Y, (opts.width || 2) * 3).attr({fill: colors[i], stroke: "none"}));
-                path = path.concat([j ? "L" : "M", X, Y]);
-            }
-            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(",")});
-        }
-        return {
-            axis: axis,
-            lines: lines,
-            symbols: symbols,
-            shades: shades,
-            remove: function () {
-                axis.remove();
-                lines.remove();
-                shades.remove();
-                symbols.remove();
-            },
-            hide: function () {
-                axis.hide();
-                lines.hide();
-                shades.hide();
-                symbols.hide();
-            },
-            show: function () {
-                axis.show();
-                lines.show();
-                shades.show();
-                symbols.show();
-            },
-            hoverColumn: function (fin, fout) {
-                // 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 (var 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 = that.set();
-                for (var 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;
-                    cvrs.push(C = that.rect(X - 1, y, w + 1, height).attr({stroke: "none", fill: "#000", opacity: 0}));
-                    C.values = [];
-                    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);
-                            }
-                        }
-                    }
-                }
-                cvrs.mouseover(fin).mouseout(fout);
-                return this;
-            },
-            hoverDot: function (fin, fout) {
-                var cvrs = that.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;
-                        cvrs.push(C = that.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.axis = (valuesx[i] || valuesx[0])[j];
-                    }
-                }
-                cvrs.mouseover(fin).mouseout(fout);
-                return this;
-            }
-        };
-    };
-    Raphael.fn.g.dotchart = function (x, y, width, height, valuesx, valuesy, size, opts) {
-        function drawAxis(ax) {
-            +ax[0] && (ax[0] = paper.g.axis(x + gutter, y + gutter, width - 2 * gutter, minx, maxx, opts.axisxstep || Math.floor((width - 2 * gutter) / 20), 2, opts.axisxlabels || null, opts.axisxtype || "t"));
-            +ax[1] && (ax[1] = paper.g.axis(x + width - gutter, y + height - gutter, height - 2 * gutter, miny, maxy, opts.axisystep || Math.floor((height - 2 * gutter) / 20), 3, opts.axisylabels || null, opts.axisytype || "t"));
-            +ax[2] && (ax[2] = paper.g.axis(x + gutter, y + height - gutter + maxR, width - 2 * gutter, minx, maxx, opts.axisxstep || Math.floor((width - 2 * gutter) / 20), 0, opts.axisxlabels || null, opts.axisxtype || "t"));
-            +ax[3] && (ax[3] = paper.g.axis(x + gutter - maxR, y + height - gutter, height - 2 * gutter, miny, maxy, opts.axisystep || Math.floor((height - 2 * gutter) / 20), 1, opts.axisylabels || null, opts.axisytype || "t"));
-        }
-        opts = opts || {};
-        var xdim = snapEnds(Math.min.apply(Math, valuesx), Math.max.apply(Math, valuesx), valuesx.length - 1),
-            minx = xdim.from,
-            maxx = xdim.to,
-            gutter = opts.gutter || 10,
-            ydim = snapEnds(Math.min.apply(Math, valuesy), Math.max.apply(Math, valuesy), valuesy.length - 1),
-            miny = ydim.from,
-            maxy = ydim.to,
-            len = Math.max(valuesx.length, valuesy.length, size.length),
-            symbol = this.g.markers[opts.symbol] || "",
-            res = this.set(),
-            max = opts.max || 100,
-            top = Math.max.apply(Math, size),
-            R = [],
-            paper = this,
-            k = Math.sqrt(top / Math.PI) * 2 / max;
-
-        for (var i = 0; i < len; i++) {
-            R[i] = Math.min(Math.sqrt(size[i] / Math.PI) * 2 / k, max);
-        }
-        gutter = Math.max.apply(Math, R.concat(gutter));
-        var axis = this.set(),
-            maxR = Math.max.apply(Math, R);
-        if (opts.axis) {
-            var ax = (opts.axis + "").split(/[,\s]+/);
-            drawAxis(ax);
-            var g = [], b = [];
-            for (var i = 0, ii = ax.length; i < ii; i++) {
-                var bb = ax[i].all ? ax[i].all.getBBox()[["height", "width"][i % 2]] : 0;
-                g[i] = bb + gutter;
-                b[i] = bb;
-            }
-            gutter = Math.max.apply(Math, g.concat(gutter));
-            for (var i = 0, ii = ax.length; i < ii; i++) if (ax[i].all) {
-                ax[i].remove();
-                ax[i] = 1;
-            }
-            drawAxis(ax);
-            for (var i = 0, ii = ax.length; i < ii; i++) if (ax[i].all) {
-                axis.push(ax[i].all);
-            }
-            res.axis = axis;
-        }
-        var kx = (width - gutter * 2) / ((maxx - minx) || 1),
-            ky = (height - gutter * 2) / ((maxy - miny) || 1);
-        for (var i = 0, ii = valuesy.length; i < ii; i++) {
-            var sym = this.g.isArray(symbol) ? symbol[i] : symbol,
-                X = x + gutter + (valuesx[i] - minx) * kx,
-                Y = y + height - gutter - (valuesy[i] - miny) * ky;
-            sym && R[i] && res.push(this.g[sym](X, Y, R[i]).attr({fill: opts.heat ? this.g.colorValue(R[i], maxR) : Raphael.fn.g.colors[0], "fill-opacity": opts.opacity ? R[i] / max : 1, stroke: "none"}));
-        }
-        var covers = this.set();
-        for (var i = 0, ii = valuesy.length; i < ii; i++) {
-            var X = x + gutter + (valuesx[i] - minx) * kx,
-                Y = y + height - gutter - (valuesy[i] - miny) * ky;
-            covers.push(this.circle(X, Y, maxR).attr({fill: "#000", stroke: "none", opacity: 0}));
-            covers[i].r = +R[i].toFixed(3);
-            covers[i].x = +X.toFixed(3);
-            covers[i].y = +Y.toFixed(3);
-            covers[i].value = size[i] || 0;
-            covers[i].dot = res[i];
-        }
-        res.covers = covers;
-        res.hover = function (fin, fout) {
-            for (var i = 0, ii = valuesy.length; i < ii; i++) {
-                covers[i].mouseover(fin).mouseout(fout);
-            }
-            return this;
-        };
-        return res;
-    };
-
-
     Raphael.fn.g.finger = function (x, y, width, height, dir, ending, isPath) {
         // dir 0 for horisontal and 1 for vertical
         if ((dir && !height) || (!dir && !width)) {
         }
     };
 
+    // Symbols
     Raphael.fn.g.disc = function (cx, cy, r) {
         return this.circle(cx, cy, r);
     };
         return this.path({}, "M".concat(cx, ",", cy - r / 2, "l", [0, -r, r * 1.5, r * 1.5, -r * 1.5, r * 1.5, 0, -r, -r, 0, 0, -r], "z"));
     };
 
+    // Tooltips
     Raphael.fn.g.tag = function (x, y, text, angle, r) {
         angle = angle || 0;
         r = r == null ? 5 : r;
         text = text == null ? "$9.99" : text;
-        var res = this.set(),
+        var R = .5522 * r,
+            res = this.set(),
             d = 3;
         res.push(this.path({fill: "#000", stroke: "none"}));
-        res.push(this.text(x, y, text).attr({"font-size": 12, fill: "#fff"}));
+        res.push(this.text(x, y, text).attr(this.g.txtattr).attr({fill: "#fff"}));
         res.update = function () {
             this.rotate(0, x, y);
             var bb = this[1].getBBox();
                 this[0].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 {
                 var dx = Math.sqrt(Math.pow(r + d, 2) - Math.pow(bb.height / 2 + d, 2));
-                this[0].attr({path: ["M", x, y + r, "a", r, r, 0, 1, 1, 0, -r * 2, r, r, 0, 1, 1, 0, r * 2, "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(",")});
+                // ["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]
+                // "a", r, r, 0, 1, 1, 0, -r * 2, r, r, 0, 1, 1, 0, r * 2,
+                this[0].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(",")});
             }
             this[1].attr({x: x + r + d + bb.width / 2, y: y});
             angle = (360 - angle) % 360;
         res.update();
         return res;
     };
-
     Raphael.fn.g.popupit = function (x, y, set, dir, size) {
         dir = dir == null ? 2 : dir;
         size = size || 5;
                 "l", -Math.max(w - size, 0), 0, "z"].join(","),
             xy = [{x: x, y: y + size * 2 + h}, {x: x - size * 2 - w, y: y}, {x: x, y: y - size * 2 - h}, {x: x + size * 2 + w, y: y}][dir];
         set.translate(xy.x - w - bb.x, xy.y - h - bb.y);
-        return this.path({fill: "#000", stroke: "none"}, p).insertBefore(set[0]);
+        return this.path({fill: "#000", stroke: "none"}, p).insertBefore(set.node ? set : set[0]);
     };
     Raphael.fn.g.popup = function (x, y, text, dir, size) {
         dir = dir == null ? 2 : dir;
         var res = this.set(),
             d = 3;
         res.push(this.path({fill: "#000", stroke: "none"}));
-        res.push(this.text(x, y, text).attr({"font-size": 12, fill: "#fff"}));
+        res.push(this.text(x, y, text).attr(this.g.txtattr).attr({fill: "#fff"}));
         res.update = function (X, Y, withAnimation) {
             X = X || x;
             Y = Y || y;
         var res = this.set(),
             d = 3;
         res.push(this.path({fill: "#000", stroke: "none"}));
-        res.push(this.text(x, y, text).attr({"font-size": 12, fill: "#fff"}));
+        res.push(this.text(x, y, text).attr(this.g.txtattr).attr({fill: "#fff"}));
         res.update = function (x, y) {
             this.rotate(0, x, y);
             var bb = this[1].getBBox(),
     Raphael.fn.g.label = function (x, y, text) {
         var res = this.set();
         res.push(this.rect(x, y, 10, 10).attr({stroke: "none", fill: "#000"}));
-        res.push(this.text(x, y, text).attr({fill: "#fff"}));
+        res.push(this.text(x, y, text).attr(this.g.txtattr).attr({fill: "#fff"}));
         res.update = function () {
             var bb = this[1].getBBox(),
                 r = Math.min(bb.width + 10, bb.height + 10) / 2;
         var res = this.set();
         res.push(this.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", rotation: [22.5 - angle, x, y]}));
         angle = (angle + 90) * Math.PI / 180;
-        res.push(this.text(x + size * Math.sin(angle), y + size * Math.cos(angle), text).attr({"font-size": size * 12 / 30, fill: "#fff"}));
+        res.push(this.text(x + size * Math.sin(angle), y + size * Math.cos(angle), text).attr(this.g.txtattr).attr({"font-size": size * 12 / 30, fill: "#fff"}));
         res.drop = res[0];
         res.text = res[1];
         return res;
             fontSize = size * 12 / 12;
         var res = this.set();
         res.push(this.path({fill: "#000", stroke: "none"}));
-        res.push(this.text(x + size * Math.sin((angle) * rad), y + size * Math.cos((angle) * rad) - fontSize / 2, text).attr({"font-size": fontSize, fill: "#fff"}));
+        res.push(this.text(x + size * Math.sin((angle) * rad), y + size * Math.cos((angle) * rad) - fontSize / 2, text).attr(this.g.txtattr).attr({"font-size": fontSize, fill: "#fff"}));
         res.update = function (X, Y, withAnimation) {
             X = X || x;
             Y = Y || y;
         res.update(x, y);
         return res;
     };
+
     Raphael.fn.g.colorValue = function (value, total, s, b) {
         return "hsb(" + [Math.min((1 - value / total) * .4, 1), s || .75, b || .75] + ")";
     };
 
-    Raphael.fn.g.isArray = function (arr) {
-        return Object.prototype.toString.call(arr) == "[object Array]";
-    };
-    function snapEnds(from, to, steps) {
+    Raphael.fn.g.snapEnds = function (from, to, steps) {
         var f = from,
             t = to;
         if (f == t) {
         }
         var f = round((from - (i > 0 ? 0 : .5)) * Math.pow(10, i)) / Math.pow(10, i);
         return {from: f, to: t, power: i};
-    }
+    };
     Raphael.fn.g.axis = function (x, y, length, from, to, steps, orientation, labels, type, dashsize) {
         dashsize = dashsize == null ? 2 : dashsize;
         type = type || "t";
         steps = steps || 10;
         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 = snapEnds(from, to, steps),
+            ends = this.g.snapEnds(from, to, steps),
             f = ends.from,
             t = ends.to,
             i = ends.power,
                 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(this.text(x + addon, Y, (labels && labels[j++]) || (Math.round(label) == label ? label : +label.toFixed(rnd))).attr({"text-anchor": orientation - 1 ? "start" : "end"}));
+                text.push(this.text(x + addon, Y, (labels && labels[j++]) || (Math.round(label) == label ? label : +label.toFixed(rnd))).attr(this.g.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(this.text(x + addon, y - length, (labels && labels[j]) || (Math.round(label) == label ? label : +label.toFixed(rnd))).attr({"text-anchor": orientation - 1 ? "start" : "end"}));
+                text.push(this.text(x + addon, y - length, (labels && labels[j]) || (Math.round(label) == label ? label : +label.toFixed(rnd))).attr(this.g.txtattr).attr({"text-anchor": orientation - 1 ? "start" : "end"}));
             }
         } else {
             var X = x,
                 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 = this.text(X, y + addon, (labels && labels[j++]) || (Math.round(label) == label ? label : +label.toFixed(rnd))));
+                text.push(txt = this.text(X, y + addon, (labels && labels[j++]) || (Math.round(label) == label ? label : +label.toFixed(rnd))).attr(this.g.txtattr));
                 var bb = txt.getBBox();
                 if (prev >= bb.x - 5) {
                     text.pop(text.length - 1).remove();
             }
             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(this.text(x + length, y + addon, (labels && labels[j]) || (Math.round(label) == label ? label : +label.toFixed(rnd))));
+                text.push(this.text(x + length, y + addon, (labels && labels[j]) || (Math.round(label) == label ? label : +label.toFixed(rnd))).attr(this.g.txtattr));
             }
         }
         var res = this.path({}, path);
index 99e2172..287be9b 100644 (file)
--- a/test.html
+++ b/test.html
             var _7 = {"seriesLabels":["CLOV","contrib","FE"],"categoryLabels":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"data":[[71,359,243,393,288,252,48],[2,9,5,5,2,4,1],[18,46,53,50,32,57,2]]};
             window.onload = function () {
                 var r = Raphael(10, 10, 1200, 800);
+                r.g.txtattr.font = "12px 'Fontin Sans'";
+                r.g.colors = ["#468cc8", "#76960f", "#d7551e", "#d7e62d", "#0c4382", "#5fbe41", "#f5822d", "#edf000", "#0c87c8", "#ad2814", "#afbe46"];
+                
+                
+                r.g.disc(50, 50, 20);
+                r.g.line(100, 50, 20);
+                r.g.square(150, 50, 20);
+                r.g.triangle(200, 50, 20);
+                r.g.star(250, 50, 20);
+                r.g.cross(300, 50, 20);
+                r.g.plus(350, 50, 20);
+                r.g.arrow(400, 50, 20);
+                
+                r.g.tag(50, 100, "$9.99", 130);
+                r.g.popup(100, 100, "$9.99");
+                r.g.flag(150, 100, "$9.99", 45);
+                r.g.label(200, 100, "$9.99");
+                r.g.drop(250, 100, "$10");
+                r.g.blob(300, 100, "$9.99");
                 // r.rect(10, 10, 50, 50).attr({fill: "#000", stroke: "none"});
                 // r.path({fill: "#000", stroke: "none"}, "M70,10l50,0,0,50-50,0z")
                 var inited = false;
-                var pie = r.g.piechart(320, 240, 100, [55, 20, 13, 32, 5, 1, 2, 10], {legend: ["%%.%% – jQuery users", "EMACS users"], legendfont: '12px "Fontin Sans"', legendpos: "west", href: ["http://raphaeljs.com", "#tre"], colors: ["#468cc8", "#76960f", "#d7551e", "#d7e62d", "#0c4382", "#5fbe41", "#f5822d", "#edf000", "#0c87c8", "#ad2814", "#afbe46"], legendmark: "t"});
+                var pie = r.g.piechart(320, 440, 100, [55, 20, 13, 32, 5, 1, 2, 10], {legend: ["%%.%% – jQuery users", "EMACS users"], legendpos: "west", href: ["http://raphaeljs.com", "#tre"]});
                 pie.hover(function () {
                     this.sector.stop();
                     this.sector.scale(1.1, 1.1, this.cx, this.cy);
                     }
                 });
                 // pie.attr({opacity: .5});
-
-
-                // var b = r.g.barchart(600, 10, 320, 50, [[55], [10], [12]], 1, {type: "square", init: 0, stacked: 1});
-                r.g.label(320, 240, "Raphaël").attr({font: "20px Fontin"}).update();
-                // var b = r.g.barchart(600, 10, 320, 400, [[55, 20, 13, 32, 5, 1, 2, 10], [10, 2, 1, 5, 32, 13, 20, 55], [12, 20, 30]], false, {type: "square", stacked: 1}).hover(function () {
-                //     if (inited) {
-                //         pop.attr({text: this.bar.value}).update(this.bar.x, this.bar.y, 1);
-                //     } else {
-                //         pop.attr({text: this.bar.value, opacity: 1}).update(this.bar.x, this.bar.y).toFront();
-                //         inited = true;
-                //     }
-                // });//.label();
-                
-                var val52 = [];
-                // for (var i = 0, ii = _52.length; i < ii; i++) {
-                //     val52[i] = [];
-                //     for (var j = 0, jj = _52[i][1].length; j < jj; j++) {
-                //         val52[i][j] = _52[i][1][j][1];
-                //     }
-                // }
-                
-                val52 = _52.data;
                 
-                var val7 = [[912, 815, 106, 569, 57, 148, 487], [711, 674, 28, 70, 866, 494, 297]];
-                var val18 = [[3326, 3589, 6453, 3969, 750, 1021, 3946, 4161, 6499, 4109, 1031, 3155, 6991, 5322, 5733, 2313, 132, 8142], [3184, 1674, 3204, 9154, 679, 1862, 824, 2982, 2291, 5753, 8667, 2410, 8142, 3704, 5107, 4709, 1397, 8259]];
-                // r.rect(600, 420, 276, 32).attr({stroke: "none", fill: "#ccc"});
-                var clr = ["#d7561f", "#dee439", "#769810"];
-                r.g.barchart(600, 10, 276, 32, val52, false, {stacked: 1, vgutter: 0, colors: clr});
-                r.g.barchart(600, 52, 276, 70, val52, false, {stacked: 1, vgutter: 0, colors: clr});
-                r.g.barchart(600, 132, 276, 70, _7.data, false, {stacked: 1, vgutter: 15, colors: clr}).label(_7.categoryLabels);
-                r.g.linechart(600, 212, 276, 130, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17], val18, {axis: "0 0 0 1", axisxstep: 17, colors: ["#d7561f", "#769810"], width: 1});
-                r.g.barchart(610, 352, 256, 70, _18.data, false, {stacked: 1, vgutter: 15, colors: clr}).label(_18.categoryLabels);
+                // var b = r.g.barchart(600, 10, 320, 50, [[55], [10], [12]], 1, {type: "square", init: 0, stacked: 1});
+                // r.g.label(320, 240, "Raphaël").attr({font: "20px Myriad Pro"}).update();
+                var b = r.g.barchart(600, 10, 320, 400, [[55, 20, 13, 32, 5, 1, 2, 10], [10, 2, 1, 5, 32, 13, 20, 55], [12, 20, 30]], 1, {type: "round", stacked: 1});
                 
-                var s = r.set();
-                s.push(r.text(100, 30, "234").attr({fill: "#d7561f", "font-weight": 800}));
-                s.push(r.text(100, 45, "12").attr({fill: "#dee439", "font-weight": 800}));
-                s.push(r.text(100, 60, "0").attr({fill: "#769810", "font-weight": 800}));
-                r.g.labelit(s);
-                // r.g.barchart(600, 420, 320, 200, [[55, 20, 13, 32, 5, 1, 2, 10]], 0, {init: 1}).hover(function () {
-                //     this.flag = r.g.blob(this.bar.x + this.bar.w / 2, this.bar.y, this.bar.value || "0", 30);
-                // }, function () {
-                //     this.flag.animate({opacity: 0}, 100, function () {this.remove();});
-                // }).label([["Big (##)", "Small"]], 1);
+                r.g.barchart(600, 420, 320, 200, [[55, 20, 13, 32, 5, 1, 2, 10]]).hover(function () {
+                    this.flag = r.g.blob(this.bar.x + this.bar.w / 2, this.bar.y, this.bar.value || "0", 30);
+                }, function () {
+                    this.flag.animate({opacity: 0}, 100, function () {this.remove();});
+                }).label([["Big (##)", "Small"]], 1);
 
 
             };
index 0190ef6..474c100 100644 (file)
@@ -6,6 +6,8 @@
         <script src="../jquery.js" type="text/javascript" charset="utf-8"></script>
         <script src="../raphael.js" type="text/javascript" charset="utf-8"></script>
         <script src="g.raphael.js" type="text/javascript" charset="utf-8"></script>
+        <script src="g.dot.js" type="text/javascript" charset="utf-8"></script>
+        <script src="g.line.js" type="text/javascript" charset="utf-8"></script>
         <script type="text/javascript" charset="utf-8">
             window.onload = function () {
                 var data = [],
@@ -32,6 +34,7 @@
                 }
 
                 var r = Raphael("holder", 1200, 800);
+                r.g.txtattr.font = "11px 'Fontin Sans'";
                 var x = [], y = [], y2 = [], y3 = [];
                 for (var i = 0; i < 500; i++) {
                     x[i] = i * 10;
                     y2[i] = (y2[i - 1] || 150) + (Math.random() * 7) - 3.5;
                     y3[i] = (y3[i - 1] || 300) + (Math.random() * 7) - 4;
                 }
-                r.g.dotchart(10, 10, 800, 300, xs, ys, data, {symbol: "o", max: 15, heat: true, axis: "0 0 1 1", axisxstep: 23, axisystep: 6, axisxlabels: axisx, axisxtype: " ", axisytype: " ", axisylabels: axisy.reverse()}).hover(function () {
+                r.g.dotchart(10, 10, 800, 300, xs, ys, data, {max: 15, heat: true, axis: "0 0 1 1", axisxstep: 23, axisystep: 6, axisxlabels: axisx, axisxtype: " ", axisytype: " ", axisylabels: axisy.reverse()}).hover(function () {
                     this.tag = this.tag || r.g.tag(this.x, this.y, this.value, 0, this.r + 2).insertBefore(this);
                     this.tag.show();
                 }, function () {
                     this.tag && this.tag.hide();
-                }).axis.attr({font: "12px 'Fontin'"});
+                }).axis.attr({font: "12px Fontin"});
 
                 r.g.linechart(10, 400, 400, 300, x, [y, y2, y3], {nostroke: false, shade: true, axis: "1 1 1 1", axisxstep: 10});
                 var tag;
-                r.g.linechart(440, 400, 400, 300, [[1, 2, 3, 4, 5, 6, 7],[3.5, 4.5, 5.5, 6.5, 7, 8]], [[12, 32, 23, 15, 17, 27, 22], [10, 20, 30, 25, 15, 28]], {nostroke: false, axis: "0 0 1 1", symbol: "disc"}).hoverColumn(function () {
+                r.g.linechart(440, 400, 400, 300, [[1, 2, 3, 4, 5, 6, 7],[3.5, 4.5, 5.5, 6.5, 7, 8]], [[12, 32, 23, 15, 17, 27, 22], [10, 20, 30, 25, 15, 28]], {nostroke: false, axis: "0 0 1 1", symbol: "o"}).hoverColumn(function () {
                     for (var i = 0, ii = this.y.length; i < ii; i++) {
                         r.g.tag(this.x, this.y[i], this.values[i], 0, 9).insertBefore(this);
                     }