Ported linecharts over to Raphael 2.0 and removed the g namespace
authorRichard Zurad <rzurad@gmail.com>
Sun, 23 Oct 2011 01:18:37 +0000 (01:18 +0000)
committerRichard Zurad <rzurad@gmail.com>
Tue, 25 Oct 2011 04:26:39 +0000 (04:26 +0000)
g.line.js
test/linechart.html [new file with mode: 0644]
test/test2.html [deleted file]

index 2267ac2..f0e2fae 100644 (file)
--- a/g.line.js
+++ b/g.line.js
@@ -4,15 +4,32 @@
  * 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 () {
+    var defcolors = (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;
+        })();
+
     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);
@@ -24,18 +41,22 @@ Raphael.fn.g.linechart = function (x, y, width, height, valuesx, valuesy, opts)
         }
         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,
@@ -43,212 +64,267 @@ Raphael.fn.g.linechart = function (x, y, width, height, valuesx, valuesy, opts)
             y2: p2y + dy2
         };
     }
-    opts = opts || {};
-    if (!this.raphael.is(valuesx[0], "array")) {
-        valuesx = [valuesx];
-    }
-    if (!this.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 || 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 (i = 0, ii = valuesy.length; i < ii; i++) {
-        if (opts.shade) {
-            shades.push(this.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;
+    Raphael.fn.linechart = function (x, y, width, height, valuesx, valuesy, opts) {
+
+        opts = opts || {};
+
+        if (!Raphael.is(valuesx[0], "array")) {
+            valuesx = [valuesx];
         }
-        if (valuesx[i] && valuesx[i].length > width - 2 * gutter) {
-            valuesx[i] = shrink(valuesx[i], width - 2 * gutter);
+
+        if (!Raphael.is(valuesy[0], "array")) {
+            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,
-        ydim = this.g.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 = 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 (i = 0, ii = valuesy.length; i < ii; i++) {
-        if (!opts.nostroke) {
-            lines.push(line = this.path().attr({
-                stroke: colors[i],
-                "stroke-width": opts.width || 2,
-                "stroke-linejoin": "round",
-                "stroke-linecap": "round",
-                "stroke-dasharray": opts.dash || ""
-            }));
+
+        var gutter = opts.gutter || 10,
+            len = Math.max(valuesx[0].length, valuesy[0].length),
+            symbol = opts.symbol || "",
+            colors = opts.colors || defcolors,
+            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 sym = this.raphael.is(symbol, "array") ? symbol[i] : symbol,
-            symset = this.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(this.g[Raphael.fn.g.markers[this.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;
-                    var 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]);
+
+        var shades = this.set();
+
+        for (i = 0, ii = valuesy.length; i < ii; i++) {
+            if (opts.shade) {
+                shades.push(this.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);
             }
         }
-        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);
+
+        var allx = Array.prototype.concat.apply([], valuesx),
+            ally = Array.prototype.concat.apply([], valuesy),
+            xdim = this.snapEnds(Math.min.apply(Math, allx), Math.max.apply(Math, allx), valuesx[0].length - 1),
+            minx = xdim.from,
+            maxx = xdim.to,
+            ydim = this.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 = this.set();
+
+        if (opts.axis) {
+            var ax = (opts.axis + "").split(/[,\s]+/);
+            +ax[0] && axis.push(this.axis(x + gutter, y + gutter, width - 2 * gutter, minx, maxx, opts.axisxstep || Math.floor((width - 2 * gutter) / 20), 2));
+            +ax[1] && axis.push(this.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.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.axis(x + gutter, y + height - gutter, height - 2 * gutter, miny, maxy, opts.axisystep || Math.floor((height - 2 * gutter) / 20), 1));
         }
-        Xs = Xs2;
-        ii = Xs.length;
-        var cvrs = f || that.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 = that.rect(X - 1, y, Math.max(w + 1, 1), height).attr({stroke: "none", fill: "#000", opacity: 0}));
-            C.values = [];
-            C.symbols = that.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]);
-                    }
-                }
+
+        var lines = this.set(),
+            symbols = this.set(),
+            line;
+
+        for (i = 0, ii = valuesy.length; i < ii; i++) {
+            if (!opts.nostroke) {
+                lines.push(line = this.path().attr({
+                    stroke: colors[i],
+                    "stroke-width": opts.width || 2,
+                    "stroke-linejoin": "round",
+                    "stroke-linecap": "round",
+                    "stroke-dasharray": opts.dash || ""
+                }));
             }
-            f && f.call(C);
-        }
-        !f && (columns = cvrs);
-    }
-    function createDots(f) {
-        var cvrs = f || that.set(),
-            C;
-        for (var i = 0, ii = valuesy.length; i < ii; i++) {
+
+            var sym = Raphael.is(symbol, "array") ? symbol[i] : symbol,
+                symset = this.set();
+
+            path = [];
+
             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 = 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.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);
+
+                (Raphael.is(sym, "array") ? sym[j] : sym) && symset.push(this[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(",") });
         }
-        !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 = that.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]);
+
+        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 || that.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 = that.rect(X - 1, y, Math.max(w + 1, 1), height).attr({ stroke: "none", fill: "#000", opacity: 0 }));
+                C.values = [];
+                C.symbols = that.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);
         }
-        !columns && createColumns();
-        for (i = 0, ii = hrefs.length; i < ii; i++) {
-            columns[i] && columns[i].attr("href", hrefs[i]);
+
+        function createDots(f) {
+            var cvrs = f || 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;
+
+                    f ? (C = {}) : 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.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);
         }
-        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;
+
+        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 = that.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;
     };
-    return chart;
-};
+})();
diff --git a/test/linechart.html b/test/linechart.html
new file mode 100644 (file)
index 0000000..185ede3
--- /dev/null
@@ -0,0 +1,67 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+"http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en">
+    <head>
+        <title>gRaphaël Line Charts</title>
+        <link rel="stylesheet" href="css/demo.css" type="text/css" media="screen" charset="utf-8">
+        <link rel="stylesheet" href="css/demo-print.css" type="text/css" media="print" charset="utf-8">
+        <script src="../raphael/raphael.js" type="text/javascript" charset="utf-8"></script>
+        <script src="../raphael/plugins/raphael.tooltips.js" type="text/javascript"></script>
+        <script src="../g.utils.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 r = Raphael("holder"),
+                    txtattr = { font: "12px 'Fontin Sans', Fontin-Sans, sans-serif" };
+                
+                var x = [], y = [], y2 = [], y3 = [];
+
+                for (var i = 0; i < 1e6; i++) {
+                    x[i] = i * 10;
+                    y[i] = (y[i - 1] || 0) + (Math.random() * 7) - 3;
+                    y2[i] = (y2[i - 1] || 150) + (Math.random() * 7) - 3.5;
+                    y3[i] = (y3[i - 1] || 300) + (Math.random() * 7) - 4;
+                }
+
+                r.text(160, 10, "Simple Line Chart (1000 points)").attr(txtattr);
+                r.text(480, 10, "shade = true (10,000 points)").attr(txtattr);;
+                r.text(160, 250, "shade = true & nostroke = true (1,000,000 points)").attr(txtattr);
+                r.text(480, 250, "Symbols, axis and hover effect").attr(txtattr);
+
+                r.linechart(10, 10, 300, 220, x, [y.slice(0, 1e3), y2.slice(0, 1e3), y3.slice(0, 1e3)]).hoverColumn(function () {
+                    this.set = r.set(
+                        r.circle(this.x, this.y[0]),
+                        r.circle(this.x, this.y[1]),
+                        r.circle(this.x, this.y[2])
+                    );
+                }, function () {
+                    this.set.remove();
+                });
+
+                r.linechart(330, 10, 300, 220, x, [y.slice(0, 1e4), y2.slice(0, 1e4), y3.slice(0, 1e4)], { shade: true });
+                r.linechart(10, 250, 300, 220, x, [y, y2, y3], { nostroke: true, shade: true });
+
+                var lines = r.linechart(330, 250, 300, 220, [[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: "circle", smooth: true }).hoverColumn(function () {
+                    this.tags = r.set();
+
+                    for (var i = 0, ii = this.y.length; i < ii; i++) {
+                        this.tags.push(r.tag(this.x, this.y[i], this.values[i], 160, 10).insertBefore(this).attr([{ fill: "#fff" }, { fill: this.symbols[i].attr("fill") }]));
+                    }
+                }, function () {
+                    this.tags && this.tags.remove();
+                });
+
+                lines.symbols.attr({ r: 6 });
+                // lines.lines[0].animate({"stroke-width": 6}, 1000);
+                // lines.symbols[0].attr({stroke: "#fff"});
+                // lines.symbols[0][1].animate({fill: "#f00"}, 1000);
+            };
+        </script>
+    </head>
+    <body class="raphael" id="g.raphael.dmitry.baranovskiy.com">
+        <div id="holder"></div>
+        <p>
+            Demo of <a href="http://g.raphaeljs.com/">gRaphaël</a> JavaScript library.
+        </p>
+    </body>
+</html>
diff --git a/test/test2.html b/test/test2.html
deleted file mode 100644 (file)
index f5ded7b..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
-"http://www.w3.org/TR/html4/strict.dtd">
-<html lang="en">
-    <head>
-        <title>gRaphaël Static Line Charts</title>
-        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-        <meta name="author" content="Dmitry Baranovskiy">
-        <meta name="description" content="Charting JavaScript Library">
-        <link rel="stylesheet" href="demo.css" type="text/css" media="screen" charset="utf-8">
-        <link rel="stylesheet" href="demo-print.css" type="text/css" media="print" charset="utf-8">
-        <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.line.js" type="text/javascript" charset="utf-8"></script>
-        <script type="text/javascript" charset="utf-8">
-            window.onload = function () {
-                var r = Raphael("holder");
-                r.g.txtattr.font = "12px 'Fontin Sans', Fontin-Sans, sans-serif";
-                
-                var x = [], y = [], y2 = [], y3 = [];
-                for (var i = 0; i < 500; i++) {
-                    x[i] = i * 10;
-                    y[i] = (y[i - 1] || 0) + (Math.random() * 7) - 3;
-                    y2[i] = (y2[i - 1] || 150) + (Math.random() * 7) - 3.5;
-                    y3[i] = (y3[i - 1] || 300) + (Math.random() * 7) - 4;
-                }
-
-                r.g.text(160, 10, "Simple Line Chart");
-                r.g.text(480, 10, "shade = true");
-                r.g.text(160, 250, "shade = true & nostroke = true");
-                r.g.text(480, 250, "Symbols, axis and hover effect");
-
-                r.g.linechart(10, 10, 300, 220, x, [y, y2, y3]);
-                r.g.linechart(330, 10, 300, 220, x, [y, y2, y3], {shade: true});
-                r.g.linechart(10, 250, 300, 220, x, [y, y2, y3], {nostroke: true, shade: true});
-                var lines = r.g.linechart(330, 250, 300, 220, [[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 () {
-                    this.tags = r.set();
-                    for (var i = 0, ii = this.y.length; i < ii; i++) {
-                        this.tags.push(r.g.tag(this.x, this.y[i], this.values[i], 160, 10).insertBefore(this).attr([{fill: "#fff"}, {fill: this.symbols[i].attr("fill")}]));
-                    }
-                }, function () {
-                    this.tags && this.tags.remove();
-                });
-                // lines.lines[0].animate({"stroke-width": 6}, 1000);
-                // lines.symbols[0].attr({stroke: "#fff"});
-                // lines.symbols[0][1].animate({fill: "#f00"}, 1000);
-            };
-        </script>
-    </head>
-    <body class="raphael" id="g.raphael.dmitry.baranovskiy.com">
-        <div id="holder"></div>
-        <p>
-            Demo of <a href="http://g.raphaeljs.com/">gRaphaël</a> JavaScript library.
-        </p>
-    </body>
-</html>