g.raphael-rails 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +3 -0
- data/Rakefile +14 -0
- data/graphael-rails.gemspec +25 -0
- data/lib/graphael-rails.rb +6 -0
- data/lib/graphael/rails/version.rb +5 -0
- data/vendor/assets/javascripts/graphael-all.js +5 -0
- data/vendor/assets/javascripts/graphael-bar.js +674 -0
- data/vendor/assets/javascripts/graphael-dot.js +258 -0
- data/vendor/assets/javascripts/graphael-line.js +489 -0
- data/vendor/assets/javascripts/graphael-pie.js +296 -0
- data/vendor/assets/javascripts/graphael.js +861 -0
- metadata +100 -0
| @@ -0,0 +1,296 @@ | |
| 1 | 
            +
            /*!
         | 
| 2 | 
            +
             * g.Raphael 0.51 - Charting library, based on Raphaël
         | 
| 3 | 
            +
             *
         | 
| 4 | 
            +
             * Copyright (c) 2009-2012 Dmitry Baranovskiy (http://g.raphaeljs.com)
         | 
| 5 | 
            +
             * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
         | 
| 6 | 
            +
             */
         | 
| 7 | 
            +
             | 
| 8 | 
            +
             /*
         | 
| 9 | 
            +
             * piechart method on paper
         | 
| 10 | 
            +
             */
         | 
| 11 | 
            +
            /*\
         | 
| 12 | 
            +
             * Paper.piechart
         | 
| 13 | 
            +
             [ method ]
         | 
| 14 | 
            +
             **
         | 
| 15 | 
            +
             * Creates a pie chart
         | 
| 16 | 
            +
             **
         | 
| 17 | 
            +
             > Parameters
         | 
| 18 | 
            +
             **
         | 
| 19 | 
            +
             - cx (number) x coordinate of the chart
         | 
| 20 | 
            +
             - cy (number) y coordinate of the chart
         | 
| 21 | 
            +
             - r (integer) radius of the chart
         | 
| 22 | 
            +
             - values (array) values used to plot
         | 
| 23 | 
            +
             - opts (object) options for the chart
         | 
| 24 | 
            +
             o {
         | 
| 25 | 
            +
             o minPercent (number) minimal percent threshold which will have a slice rendered. Sliced corresponding to data points below this threshold will be collapsed into 1 additional slice. [default `1`]
         | 
| 26 | 
            +
             o maxSlices (number) a threshold for how many slices should be rendered before collapsing all remaining slices into 1 additional slice (to focus on most important data points). [default `100`]
         | 
| 27 | 
            +
             o stroke (string) color of the circle stroke in HTML color format [default `"#FFF"`]
         | 
| 28 | 
            +
             o strokewidth (integer) width of the chart stroke [default `1`]
         | 
| 29 | 
            +
             o init (boolean) whether or not to show animation when the chart is ready [default `false`]
         | 
| 30 | 
            +
             o colors (array) colors be used to plot the chart
         | 
| 31 | 
            +
             o href (array) urls to to set up clicks on chart slices
         | 
| 32 | 
            +
             o legend (array) array containing strings that will be used in a legend. Other label options work if legend is defined.
         | 
| 33 | 
            +
             o legendcolor (string) color of text in legend [default `"#000"`]
         | 
| 34 | 
            +
             o legendothers (string) text that will be used in legend to describe options that are collapsed into 1 slice, because they are too small to render [default `"Others"`]
         | 
| 35 | 
            +
             o legendmark (string) symbol used as a bullet point in legend that has the same colour as the chart slice [default `"circle"`]
         | 
| 36 | 
            +
             o legendpos (string) position of the legend on the chart [default `"east"`]. Other options are `"north"`, `"south"`, `"west"`
         | 
| 37 | 
            +
             o }
         | 
| 38 | 
            +
             **
         | 
| 39 | 
            +
             = (object) path element of the popup
         | 
| 40 | 
            +
             > Usage
         | 
| 41 | 
            +
             | r.piechart(cx, cy, r, values, opts)
         | 
| 42 | 
            +
             \*/
         | 
| 43 | 
            +
             
         | 
| 44 | 
            +
            (function () {
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                function Piechart(paper, cx, cy, r, values, opts) {
         | 
| 47 | 
            +
                    opts = opts || {};
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                    var chartinst = this,
         | 
| 50 | 
            +
                        sectors = [],
         | 
| 51 | 
            +
                        covers = paper.set(),
         | 
| 52 | 
            +
                        chart = paper.set(),
         | 
| 53 | 
            +
                        series = paper.set(),
         | 
| 54 | 
            +
                        order = [],
         | 
| 55 | 
            +
                        len = values.length,
         | 
| 56 | 
            +
                        angle = 0,
         | 
| 57 | 
            +
                        total = 0,
         | 
| 58 | 
            +
                        others = 0,
         | 
| 59 | 
            +
                        cut = opts.maxSlices || 100,
         | 
| 60 | 
            +
                        minPercent = parseFloat(opts.minPercent) || 1,
         | 
| 61 | 
            +
                        defcut = Boolean( minPercent );
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                    function sector(cx, cy, r, startAngle, endAngle, fill) {
         | 
| 64 | 
            +
                        var rad = Math.PI / 180,
         | 
| 65 | 
            +
                            x1 = cx + r * Math.cos(-startAngle * rad),
         | 
| 66 | 
            +
                            x2 = cx + r * Math.cos(-endAngle * rad),
         | 
| 67 | 
            +
                            xm = cx + r / 2 * Math.cos(-(startAngle + (endAngle - startAngle) / 2) * rad),
         | 
| 68 | 
            +
                            y1 = cy + r * Math.sin(-startAngle * rad),
         | 
| 69 | 
            +
                            y2 = cy + r * Math.sin(-endAngle * rad),
         | 
| 70 | 
            +
                            ym = cy + r / 2 * Math.sin(-(startAngle + (endAngle - startAngle) / 2) * rad),
         | 
| 71 | 
            +
                            res = [
         | 
| 72 | 
            +
                                "M", cx, cy,
         | 
| 73 | 
            +
                                "L", x1, y1,
         | 
| 74 | 
            +
                                "A", r, r, 0, +(Math.abs(endAngle - startAngle) > 180), 1, x2, y2,
         | 
| 75 | 
            +
                                "z"
         | 
| 76 | 
            +
                            ];
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                        res.middle = { x: xm, y: ym };
         | 
| 79 | 
            +
                        return res;
         | 
| 80 | 
            +
                    }
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                    chart.covers = covers;
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                    if (len == 1) {
         | 
| 85 | 
            +
                        series.push(paper.circle(cx, cy, r).attr({ fill: opts.colors && opts.colors[0] || chartinst.colors[0], stroke: opts.stroke || "#fff", "stroke-width": opts.strokewidth == null ? 1 : opts.strokewidth }));
         | 
| 86 | 
            +
                        covers.push(paper.circle(cx, cy, r).attr(chartinst.shim));
         | 
| 87 | 
            +
                        total = values[0];
         | 
| 88 | 
            +
                        values[0] = { value: values[0], order: 0, valueOf: function () { return this.value; } };
         | 
| 89 | 
            +
                        opts.href && opts.href[0] && covers[0].attr({ href: opts.href[0] });
         | 
| 90 | 
            +
                        series[0].middle = {x: cx, y: cy};
         | 
| 91 | 
            +
                        series[0].mangle = 180;
         | 
| 92 | 
            +
                    } else {
         | 
| 93 | 
            +
                        for (var i = 0; i < len; i++) {
         | 
| 94 | 
            +
                            total += values[i];
         | 
| 95 | 
            +
                            values[i] = { value: values[i], order: i, valueOf: function () { return this.value; } };
         | 
| 96 | 
            +
                        }
         | 
| 97 | 
            +
                        
         | 
| 98 | 
            +
                        //values are sorted numerically
         | 
| 99 | 
            +
                        values.sort(function (a, b) {
         | 
| 100 | 
            +
                            return b.value - a.value;
         | 
| 101 | 
            +
                        });
         | 
| 102 | 
            +
                        
         | 
| 103 | 
            +
                        for (i = 0; i < len; i++) {
         | 
| 104 | 
            +
                            if (defcut && values[i] * 100 / total < minPercent) {
         | 
| 105 | 
            +
                                cut = i;
         | 
| 106 | 
            +
                                defcut = false;
         | 
| 107 | 
            +
                            }
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                            if (i > cut) {
         | 
| 110 | 
            +
                                defcut = false;
         | 
| 111 | 
            +
                                values[cut].value += values[i];
         | 
| 112 | 
            +
                                values[cut].others = true;
         | 
| 113 | 
            +
                                others = values[cut].value;
         | 
| 114 | 
            +
                            }
         | 
| 115 | 
            +
                        }
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                        len = Math.min(cut + 1, values.length);
         | 
| 118 | 
            +
                        others && values.splice(len) && (values[cut].others = true);
         | 
| 119 | 
            +
             | 
| 120 | 
            +
                        for (i = 0; i < len; i++) {
         | 
| 121 | 
            +
                            var mangle = angle - 360 * values[i] / total / 2;
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                            if (!i) {
         | 
| 124 | 
            +
                                angle = 90 - mangle;
         | 
| 125 | 
            +
                                mangle = angle - 360 * values[i] / total / 2;
         | 
| 126 | 
            +
                            }
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                            if (opts.init) {
         | 
| 129 | 
            +
                                var ipath = sector(cx, cy, 1, angle, angle - 360 * values[i] / total).join(",");
         | 
| 130 | 
            +
                            }
         | 
| 131 | 
            +
             | 
| 132 | 
            +
                            var path = sector(cx, cy, r, angle, angle -= 360 * values[i] / total);
         | 
| 133 | 
            +
                            var j = (opts.matchColors && opts.matchColors == true) ? values[i].order : i;
         | 
| 134 | 
            +
                            var p = paper.path(opts.init ? ipath : path).attr({ fill: opts.colors && opts.colors[j] || chartinst.colors[j] || "#666", stroke: opts.stroke || "#fff", "stroke-width": (opts.strokewidth == null ? 1 : opts.strokewidth), "stroke-linejoin": "round" });
         | 
| 135 | 
            +
             | 
| 136 | 
            +
                            p.value = values[i];
         | 
| 137 | 
            +
                            p.middle = path.middle;
         | 
| 138 | 
            +
                            p.mangle = mangle;
         | 
| 139 | 
            +
                            sectors.push(p);
         | 
| 140 | 
            +
                            series.push(p);
         | 
| 141 | 
            +
                            opts.init && p.animate({ path: path.join(",") }, (+opts.init - 1) || 1000, ">");
         | 
| 142 | 
            +
                        }
         | 
| 143 | 
            +
             | 
| 144 | 
            +
                        for (i = 0; i < len; i++) {
         | 
| 145 | 
            +
                            p = paper.path(sectors[i].attr("path")).attr(chartinst.shim);
         | 
| 146 | 
            +
                            opts.href && opts.href[i] && p.attr({ href: opts.href[i] });
         | 
| 147 | 
            +
                            p.attr = function () {};
         | 
| 148 | 
            +
                            covers.push(p);
         | 
| 149 | 
            +
                            series.push(p);
         | 
| 150 | 
            +
                        }
         | 
| 151 | 
            +
                    }
         | 
| 152 | 
            +
             | 
| 153 | 
            +
                    chart.hover = function (fin, fout) {
         | 
| 154 | 
            +
                        fout = fout || function () {};
         | 
| 155 | 
            +
             | 
| 156 | 
            +
                        var that = this;
         | 
| 157 | 
            +
             | 
| 158 | 
            +
                        for (var i = 0; i < len; i++) {
         | 
| 159 | 
            +
                            (function (sector, cover, j) {
         | 
| 160 | 
            +
                                var o = {
         | 
| 161 | 
            +
                                    sector: sector,
         | 
| 162 | 
            +
                                    cover: cover,
         | 
| 163 | 
            +
                                    cx: cx,
         | 
| 164 | 
            +
                                    cy: cy,
         | 
| 165 | 
            +
                                    mx: sector.middle.x,
         | 
| 166 | 
            +
                                    my: sector.middle.y,
         | 
| 167 | 
            +
                                    mangle: sector.mangle,
         | 
| 168 | 
            +
                                    r: r,
         | 
| 169 | 
            +
                                    value: values[j],
         | 
| 170 | 
            +
                                    total: total,
         | 
| 171 | 
            +
                                    label: that.labels && that.labels[j]
         | 
| 172 | 
            +
                                };
         | 
| 173 | 
            +
                                cover.mouseover(function () {
         | 
| 174 | 
            +
                                    fin.call(o);
         | 
| 175 | 
            +
                                }).mouseout(function () {
         | 
| 176 | 
            +
                                    fout.call(o);
         | 
| 177 | 
            +
                                });
         | 
| 178 | 
            +
                            })(series[i], covers[i], i);
         | 
| 179 | 
            +
                        }
         | 
| 180 | 
            +
                        return this;
         | 
| 181 | 
            +
                    };
         | 
| 182 | 
            +
             | 
| 183 | 
            +
                    // x: where label could be put
         | 
| 184 | 
            +
                    // y: where label could be put
         | 
| 185 | 
            +
                    // value: value to show
         | 
| 186 | 
            +
                    // total: total number to count %
         | 
| 187 | 
            +
                    chart.each = function (f) {
         | 
| 188 | 
            +
                        var that = this;
         | 
| 189 | 
            +
             | 
| 190 | 
            +
                        for (var i = 0; i < len; i++) {
         | 
| 191 | 
            +
                            (function (sector, cover, j) {
         | 
| 192 | 
            +
                                var o = {
         | 
| 193 | 
            +
                                    sector: sector,
         | 
| 194 | 
            +
                                    cover: cover,
         | 
| 195 | 
            +
                                    cx: cx,
         | 
| 196 | 
            +
                                    cy: cy,
         | 
| 197 | 
            +
                                    x: sector.middle.x,
         | 
| 198 | 
            +
                                    y: sector.middle.y,
         | 
| 199 | 
            +
                                    mangle: sector.mangle,
         | 
| 200 | 
            +
                                    r: r,
         | 
| 201 | 
            +
                                    value: values[j],
         | 
| 202 | 
            +
                                    total: total,
         | 
| 203 | 
            +
                                    label: that.labels && that.labels[j]
         | 
| 204 | 
            +
                                };
         | 
| 205 | 
            +
                                f.call(o);
         | 
| 206 | 
            +
                            })(series[i], covers[i], i);
         | 
| 207 | 
            +
                        }
         | 
| 208 | 
            +
                        return this;
         | 
| 209 | 
            +
                    };
         | 
| 210 | 
            +
             | 
| 211 | 
            +
                    chart.click = function (f) {
         | 
| 212 | 
            +
                        var that = this;
         | 
| 213 | 
            +
             | 
| 214 | 
            +
                        for (var i = 0; i < len; i++) {
         | 
| 215 | 
            +
                            (function (sector, cover, j) {
         | 
| 216 | 
            +
                                var o = {
         | 
| 217 | 
            +
                                    sector: sector,
         | 
| 218 | 
            +
                                    cover: cover,
         | 
| 219 | 
            +
                                    cx: cx,
         | 
| 220 | 
            +
                                    cy: cy,
         | 
| 221 | 
            +
                                    mx: sector.middle.x,
         | 
| 222 | 
            +
                                    my: sector.middle.y,
         | 
| 223 | 
            +
                                    mangle: sector.mangle,
         | 
| 224 | 
            +
                                    r: r,
         | 
| 225 | 
            +
                                    value: values[j],
         | 
| 226 | 
            +
                                    total: total,
         | 
| 227 | 
            +
                                    label: that.labels && that.labels[j]
         | 
| 228 | 
            +
                                };
         | 
| 229 | 
            +
                                cover.click(function () { f.call(o); });
         | 
| 230 | 
            +
                            })(series[i], covers[i], i);
         | 
| 231 | 
            +
                        }
         | 
| 232 | 
            +
                        return this;
         | 
| 233 | 
            +
                    };
         | 
| 234 | 
            +
             | 
| 235 | 
            +
                    chart.inject = function (element) {
         | 
| 236 | 
            +
                        element.insertBefore(covers[0]);
         | 
| 237 | 
            +
                    };
         | 
| 238 | 
            +
             | 
| 239 | 
            +
                    var legend = function (labels, otherslabel, mark, dir) {
         | 
| 240 | 
            +
                        var x = cx + r + r / 5,
         | 
| 241 | 
            +
                            y = cy,
         | 
| 242 | 
            +
                            h = y + 10;
         | 
| 243 | 
            +
             | 
| 244 | 
            +
                        labels = labels || [];
         | 
| 245 | 
            +
                        dir = (dir && dir.toLowerCase && dir.toLowerCase()) || "east";
         | 
| 246 | 
            +
                        mark = paper[mark && mark.toLowerCase()] || "circle";
         | 
| 247 | 
            +
                        chart.labels = paper.set();
         | 
| 248 | 
            +
             | 
| 249 | 
            +
                        for (var i = 0; i < len; i++) {
         | 
| 250 | 
            +
                            var clr = series[i].attr("fill"),
         | 
| 251 | 
            +
                                j = values[i].order,
         | 
| 252 | 
            +
                                txt;
         | 
| 253 | 
            +
             | 
| 254 | 
            +
                            values[i].others && (labels[j] = otherslabel || "Others");
         | 
| 255 | 
            +
                            labels[j] = chartinst.labelise(labels[j], values[i], total);
         | 
| 256 | 
            +
                            chart.labels.push(paper.set());
         | 
| 257 | 
            +
                            chart.labels[i].push(paper[mark](x + 5, h, 5).attr({ fill: clr, stroke: "none" }));
         | 
| 258 | 
            +
                            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"}));
         | 
| 259 | 
            +
                            covers[i].label = chart.labels[i];
         | 
| 260 | 
            +
                            h += txt.getBBox().height * 1.2;
         | 
| 261 | 
            +
                        }
         | 
| 262 | 
            +
             | 
| 263 | 
            +
                        var bb = chart.labels.getBBox(),
         | 
| 264 | 
            +
                            tr = {
         | 
| 265 | 
            +
                                east: [0, -bb.height / 2],
         | 
| 266 | 
            +
                                west: [-bb.width - 2 * r - 20, -bb.height / 2],
         | 
| 267 | 
            +
                                north: [-r - bb.width / 2, -r - bb.height - 10],
         | 
| 268 | 
            +
                                south: [-r - bb.width / 2, r + 10]
         | 
| 269 | 
            +
                            }[dir];
         | 
| 270 | 
            +
             | 
| 271 | 
            +
                        chart.labels.translate.apply(chart.labels, tr);
         | 
| 272 | 
            +
                        chart.push(chart.labels);
         | 
| 273 | 
            +
                    };
         | 
| 274 | 
            +
             | 
| 275 | 
            +
                    if (opts.legend) {
         | 
| 276 | 
            +
                        legend(opts.legend, opts.legendothers, opts.legendmark, opts.legendpos);
         | 
| 277 | 
            +
                    }
         | 
| 278 | 
            +
             | 
| 279 | 
            +
                    chart.push(series, covers);
         | 
| 280 | 
            +
                    chart.series = series;
         | 
| 281 | 
            +
                    chart.covers = covers;
         | 
| 282 | 
            +
             | 
| 283 | 
            +
                    return chart;
         | 
| 284 | 
            +
                };
         | 
| 285 | 
            +
                
         | 
| 286 | 
            +
                //inheritance
         | 
| 287 | 
            +
                var F = function() {};
         | 
| 288 | 
            +
                F.prototype = Raphael.g;
         | 
| 289 | 
            +
                Piechart.prototype = new F;
         | 
| 290 | 
            +
                
         | 
| 291 | 
            +
                //public
         | 
| 292 | 
            +
                Raphael.fn.piechart = function(cx, cy, r, values, opts) {
         | 
| 293 | 
            +
                    return new Piechart(this, cx, cy, r, values, opts);
         | 
| 294 | 
            +
                }
         | 
| 295 | 
            +
                
         | 
| 296 | 
            +
            })();
         | 
| @@ -0,0 +1,861 @@ | |
| 1 | 
            +
            /*!
         | 
| 2 | 
            +
             * g.Raphael 0.51 - Charting library, based on Raphaël
         | 
| 3 | 
            +
             *
         | 
| 4 | 
            +
             * Copyright (c) 2009-2012 Dmitry Baranovskiy (http://g.raphaeljs.com)
         | 
| 5 | 
            +
             * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
         | 
| 6 | 
            +
             */
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            /*
         | 
| 9 | 
            +
             * Tooltips on Element prototype
         | 
| 10 | 
            +
             */
         | 
| 11 | 
            +
            /*\
         | 
| 12 | 
            +
             * Element.popup
         | 
| 13 | 
            +
             [ method ]
         | 
| 14 | 
            +
             **
         | 
| 15 | 
            +
             * Puts the context Element in a 'popup' tooltip. Can also be used on sets.
         | 
| 16 | 
            +
             **
         | 
| 17 | 
            +
             > Parameters
         | 
| 18 | 
            +
             **
         | 
| 19 | 
            +
             - dir (string) location of Element relative to the tail: `'down'`, `'left'`, `'up'` [default], or `'right'`.
         | 
| 20 | 
            +
             - size (number) amount of bevel/padding around the Element, as well as half the width and height of the tail [default: `5`]
         | 
| 21 | 
            +
             - x (number) x coordinate of the popup's tail [default: Element's `x` or `cx`]
         | 
| 22 | 
            +
             - y (number) y coordinate of the popup's tail [default: Element's `y` or `cy`]
         | 
| 23 | 
            +
             **
         | 
| 24 | 
            +
             = (object) path element of the popup
         | 
| 25 | 
            +
             \*/
         | 
| 26 | 
            +
            Raphael.el.popup = function (dir, size, x, y) {
         | 
| 27 | 
            +
                var paper = this.paper || this[0].paper,
         | 
| 28 | 
            +
                    bb, xy, center, cw, ch;
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                if (!paper) return;
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                switch (this.type) {
         | 
| 33 | 
            +
                    case 'text':
         | 
| 34 | 
            +
                    case 'circle':
         | 
| 35 | 
            +
                    case 'ellipse': center = true; break;
         | 
| 36 | 
            +
                    default: center = false;
         | 
| 37 | 
            +
                }
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                dir = dir == null ? 'up' : dir;
         | 
| 40 | 
            +
                size = size || 5;
         | 
| 41 | 
            +
                bb = this.getBBox();
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                x = typeof x == 'number' ? x : (center ? bb.x + bb.width / 2 : bb.x);
         | 
| 44 | 
            +
                y = typeof y == 'number' ? y : (center ? bb.y + bb.height / 2 : bb.y);
         | 
| 45 | 
            +
                cw = Math.max(bb.width / 2 - size, 0);
         | 
| 46 | 
            +
                ch = Math.max(bb.height / 2 - size, 0);
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                this.translate(x - bb.x - (center ? bb.width / 2 : 0), y - bb.y - (center ? bb.height / 2 : 0));
         | 
| 49 | 
            +
                bb = this.getBBox();
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                var paths = {
         | 
| 52 | 
            +
                    up: [
         | 
| 53 | 
            +
                        'M', x, y,
         | 
| 54 | 
            +
                        'l', -size, -size, -cw, 0,
         | 
| 55 | 
            +
                        'a', size, size, 0, 0, 1, -size, -size,
         | 
| 56 | 
            +
                        'l', 0, -bb.height,
         | 
| 57 | 
            +
                        'a', size, size, 0, 0, 1, size, -size,
         | 
| 58 | 
            +
                        'l', size * 2 + cw * 2, 0,
         | 
| 59 | 
            +
                        'a', size, size, 0, 0, 1, size, size,
         | 
| 60 | 
            +
                        'l', 0, bb.height,
         | 
| 61 | 
            +
                        'a', size, size, 0, 0, 1, -size, size,
         | 
| 62 | 
            +
                        'l', -cw, 0,
         | 
| 63 | 
            +
                        'z'
         | 
| 64 | 
            +
                    ].join(','),
         | 
| 65 | 
            +
                    down: [
         | 
| 66 | 
            +
                        'M', x, y,
         | 
| 67 | 
            +
                        'l', size, size, cw, 0,
         | 
| 68 | 
            +
                        'a', size, size, 0, 0, 1, size, size,
         | 
| 69 | 
            +
                        'l', 0, bb.height,
         | 
| 70 | 
            +
                        'a', size, size, 0, 0, 1, -size, size,
         | 
| 71 | 
            +
                        'l', -(size * 2 + cw * 2), 0,
         | 
| 72 | 
            +
                        'a', size, size, 0, 0, 1, -size, -size,
         | 
| 73 | 
            +
                        'l', 0, -bb.height,
         | 
| 74 | 
            +
                        'a', size, size, 0, 0, 1, size, -size,
         | 
| 75 | 
            +
                        'l', cw, 0,
         | 
| 76 | 
            +
                        'z'
         | 
| 77 | 
            +
                    ].join(','),
         | 
| 78 | 
            +
                    left: [
         | 
| 79 | 
            +
                        'M', x, y,
         | 
| 80 | 
            +
                        'l', -size, size, 0, ch,
         | 
| 81 | 
            +
                        'a', size, size, 0, 0, 1, -size, size,
         | 
| 82 | 
            +
                        'l', -bb.width, 0,
         | 
| 83 | 
            +
                        'a', size, size, 0, 0, 1, -size, -size,
         | 
| 84 | 
            +
                        'l', 0, -(size * 2 + ch * 2),
         | 
| 85 | 
            +
                        'a', size, size, 0, 0, 1, size, -size,
         | 
| 86 | 
            +
                        'l', bb.width, 0,
         | 
| 87 | 
            +
                        'a', size, size, 0, 0, 1, size, size,
         | 
| 88 | 
            +
                        'l', 0, ch,
         | 
| 89 | 
            +
                        'z'
         | 
| 90 | 
            +
                    ].join(','),
         | 
| 91 | 
            +
                    right: [
         | 
| 92 | 
            +
                        'M', x, y,
         | 
| 93 | 
            +
                        'l', size, -size, 0, -ch,
         | 
| 94 | 
            +
                        'a', size, size, 0, 0, 1, size, -size,
         | 
| 95 | 
            +
                        'l', bb.width, 0,
         | 
| 96 | 
            +
                        'a', size, size, 0, 0, 1, size, size,
         | 
| 97 | 
            +
                        'l', 0, size * 2 + ch * 2,
         | 
| 98 | 
            +
                        'a', size, size, 0, 0, 1, -size, size,
         | 
| 99 | 
            +
                        'l', -bb.width, 0,
         | 
| 100 | 
            +
                        'a', size, size, 0, 0, 1, -size, -size,
         | 
| 101 | 
            +
                        'l', 0, -ch,
         | 
| 102 | 
            +
                        'z'
         | 
| 103 | 
            +
                    ].join(',')
         | 
| 104 | 
            +
                };
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                xy = {
         | 
| 107 | 
            +
                    up: { x: -!center * (bb.width / 2), y: -size * 2 - (center ? bb.height / 2 : bb.height) },
         | 
| 108 | 
            +
                    down: { x: -!center * (bb.width / 2), y: size * 2 + (center ? bb.height / 2 : bb.height) },
         | 
| 109 | 
            +
                    left: { x: -size * 2 - (center ? bb.width / 2 : bb.width), y: -!center * (bb.height / 2) },
         | 
| 110 | 
            +
                    right: { x: size * 2 + (center ? bb.width / 2 : bb.width), y: -!center * (bb.height / 2) }
         | 
| 111 | 
            +
                }[dir];
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                this.translate(xy.x, xy.y);
         | 
| 114 | 
            +
                return paper.path(paths[dir]).attr({ fill: "#000", stroke: "none" }).insertBefore(this.node ? this : this[0]);
         | 
| 115 | 
            +
            };
         | 
| 116 | 
            +
             | 
| 117 | 
            +
            /*\
         | 
| 118 | 
            +
             * Element.tag
         | 
| 119 | 
            +
             [ method ]
         | 
| 120 | 
            +
             **
         | 
| 121 | 
            +
             * Puts the context Element in a 'tag' tooltip. Can also be used on sets.
         | 
| 122 | 
            +
             **
         | 
| 123 | 
            +
             > Parameters
         | 
| 124 | 
            +
             **
         | 
| 125 | 
            +
             - angle (number) angle of orientation in degrees [default: `0`]
         | 
| 126 | 
            +
             - r (number) radius of the loop [default: `5`]
         | 
| 127 | 
            +
             - x (number) x coordinate of the center of the tag loop [default: Element's `x` or `cx`]
         | 
| 128 | 
            +
             - y (number) y coordinate of the center of the tag loop [default: Element's `x` or `cx`]
         | 
| 129 | 
            +
             **
         | 
| 130 | 
            +
             = (object) path element of the tag
         | 
| 131 | 
            +
             \*/
         | 
| 132 | 
            +
            Raphael.el.tag = function (angle, r, x, y) {
         | 
| 133 | 
            +
                var d = 3,
         | 
| 134 | 
            +
                    paper = this.paper || this[0].paper;
         | 
| 135 | 
            +
             | 
| 136 | 
            +
                if (!paper) return;
         | 
| 137 | 
            +
             | 
| 138 | 
            +
                var p = paper.path().attr({ fill: '#000', stroke: '#000' }),
         | 
| 139 | 
            +
                    bb = this.getBBox(),
         | 
| 140 | 
            +
                    dx, R, center, tmp;
         | 
| 141 | 
            +
             | 
| 142 | 
            +
                switch (this.type) {
         | 
| 143 | 
            +
                    case 'text':
         | 
| 144 | 
            +
                    case 'circle':
         | 
| 145 | 
            +
                    case 'ellipse': center = true; break;
         | 
| 146 | 
            +
                    default: center = false;
         | 
| 147 | 
            +
                }
         | 
| 148 | 
            +
             | 
| 149 | 
            +
                angle = angle || 0;
         | 
| 150 | 
            +
                x = typeof x == 'number' ? x : (center ? bb.x + bb.width / 2 : bb.x);
         | 
| 151 | 
            +
                y = typeof y == 'number' ? y : (center ? bb.y + bb.height / 2 : bb.y);
         | 
| 152 | 
            +
                r = r == null ? 5 : r;
         | 
| 153 | 
            +
                R = .5522 * r;
         | 
| 154 | 
            +
             | 
| 155 | 
            +
                if (bb.height >= r * 2) {
         | 
| 156 | 
            +
                    p.attr({
         | 
| 157 | 
            +
                        path: [
         | 
| 158 | 
            +
                            "M", x, y + r,
         | 
| 159 | 
            +
                            "a", r, r, 0, 1, 1, 0, -r * 2, r, r, 0, 1, 1, 0, r * 2,
         | 
| 160 | 
            +
                            "m", 0, -r * 2 -d,
         | 
| 161 | 
            +
                            "a", r + d, r + d, 0, 1, 0, 0, (r + d) * 2,
         | 
| 162 | 
            +
                            "L", x + r + d, y + bb.height / 2 + d,
         | 
| 163 | 
            +
                            "l", bb.width + 2 * d, 0, 0, -bb.height - 2 * d, -bb.width - 2 * d, 0,
         | 
| 164 | 
            +
                            "L", x, y - r - d
         | 
| 165 | 
            +
                        ].join(",")
         | 
| 166 | 
            +
                    });
         | 
| 167 | 
            +
                } else {
         | 
| 168 | 
            +
                    dx = Math.sqrt(Math.pow(r + d, 2) - Math.pow(bb.height / 2 + d, 2));
         | 
| 169 | 
            +
                    p.attr({
         | 
| 170 | 
            +
                        path: [
         | 
| 171 | 
            +
                            "M", x, y + r,
         | 
| 172 | 
            +
                            "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,
         | 
| 173 | 
            +
                            "M", x + dx, y - bb.height / 2 - d,
         | 
| 174 | 
            +
                            "a", r + d, r + d, 0, 1, 0, 0, bb.height + 2 * d,
         | 
| 175 | 
            +
                            "l", r + d - dx + bb.width + 2 * d, 0, 0, -bb.height - 2 * d,
         | 
| 176 | 
            +
                            "L", x + dx, y - bb.height / 2 - d
         | 
| 177 | 
            +
                        ].join(",")
         | 
| 178 | 
            +
                    });
         | 
| 179 | 
            +
                }
         | 
| 180 | 
            +
             | 
| 181 | 
            +
                angle = 360 - angle;
         | 
| 182 | 
            +
                p.rotate(angle, x, y);
         | 
| 183 | 
            +
             | 
| 184 | 
            +
                if (this.attrs) {
         | 
| 185 | 
            +
                    //elements
         | 
| 186 | 
            +
                    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);
         | 
| 187 | 
            +
                    this.rotate(angle, x, y);
         | 
| 188 | 
            +
                    angle > 90 && angle < 270 && this.attr(this.attrs.x ? 'x' : 'cx', x - r - d - (!center ? bb.width : bb.width / 2)).rotate(180, x, y);
         | 
| 189 | 
            +
                } else {
         | 
| 190 | 
            +
                    //sets
         | 
| 191 | 
            +
                    if (angle > 90 && angle < 270) {
         | 
| 192 | 
            +
                        this.translate(x - bb.x - bb.width - r - d, y - bb.y - bb.height / 2);
         | 
| 193 | 
            +
                        this.rotate(angle - 180, bb.x + bb.width + r + d, bb.y + bb.height / 2);
         | 
| 194 | 
            +
                    } else {
         | 
| 195 | 
            +
                        this.translate(x - bb.x + r + d, y - bb.y - bb.height / 2);
         | 
| 196 | 
            +
                        this.rotate(angle, bb.x - r - d, bb.y + bb.height / 2); 
         | 
| 197 | 
            +
                    }
         | 
| 198 | 
            +
                }
         | 
| 199 | 
            +
             | 
| 200 | 
            +
                return p.insertBefore(this.node ? this : this[0]);
         | 
| 201 | 
            +
            };
         | 
| 202 | 
            +
             | 
| 203 | 
            +
            /*\
         | 
| 204 | 
            +
             * Element.drop
         | 
| 205 | 
            +
             [ method ]
         | 
| 206 | 
            +
             **
         | 
| 207 | 
            +
             * Puts the context Element in a 'drop' tooltip. Can also be used on sets.
         | 
| 208 | 
            +
             **
         | 
| 209 | 
            +
             > Parameters
         | 
| 210 | 
            +
             **
         | 
| 211 | 
            +
             - angle (number) angle of orientation in degrees [default: `0`]
         | 
| 212 | 
            +
             - x (number) x coordinate of the drop's point [default: Element's `x` or `cx`]
         | 
| 213 | 
            +
             - y (number) y coordinate of the drop's point [default: Element's `x` or `cx`]
         | 
| 214 | 
            +
             **
         | 
| 215 | 
            +
             = (object) path element of the drop
         | 
| 216 | 
            +
             \*/
         | 
| 217 | 
            +
            Raphael.el.drop = function (angle, x, y) {
         | 
| 218 | 
            +
                var bb = this.getBBox(),
         | 
| 219 | 
            +
                    paper = this.paper || this[0].paper,
         | 
| 220 | 
            +
                    center, size, p, dx, dy;
         | 
| 221 | 
            +
             | 
| 222 | 
            +
                if (!paper) return;
         | 
| 223 | 
            +
             | 
| 224 | 
            +
                switch (this.type) {
         | 
| 225 | 
            +
                    case 'text':
         | 
| 226 | 
            +
                    case 'circle':
         | 
| 227 | 
            +
                    case 'ellipse': center = true; break;
         | 
| 228 | 
            +
                    default: center = false;
         | 
| 229 | 
            +
                }
         | 
| 230 | 
            +
             | 
| 231 | 
            +
                angle = angle || 0;
         | 
| 232 | 
            +
             | 
| 233 | 
            +
                x = typeof x == 'number' ? x : (center ? bb.x + bb.width / 2 : bb.x);
         | 
| 234 | 
            +
                y = typeof y == 'number' ? y : (center ? bb.y + bb.height / 2 : bb.y);
         | 
| 235 | 
            +
                size = Math.max(bb.width, bb.height) + Math.min(bb.width, bb.height);
         | 
| 236 | 
            +
                p = paper.path([
         | 
| 237 | 
            +
                    "M", x, y,
         | 
| 238 | 
            +
                    "l", size, 0,
         | 
| 239 | 
            +
                    "A", size * .4, size * .4, 0, 1, 0, x + size * .7, y - size * .7,
         | 
| 240 | 
            +
                    "z"
         | 
| 241 | 
            +
                ]).attr({fill: "#000", stroke: "none"}).rotate(22.5 - angle, x, y);
         | 
| 242 | 
            +
             | 
| 243 | 
            +
                angle = (angle + 90) * Math.PI / 180;
         | 
| 244 | 
            +
                dx = (x + size * Math.sin(angle)) - (center ? 0 : bb.width / 2);
         | 
| 245 | 
            +
                dy = (y + size * Math.cos(angle)) - (center ? 0 : bb.height / 2);
         | 
| 246 | 
            +
             | 
| 247 | 
            +
                this.attrs ?
         | 
| 248 | 
            +
                    this.attr(this.attrs.x ? 'x' : 'cx', dx).attr(this.attrs.y ? 'y' : 'cy', dy) :
         | 
| 249 | 
            +
                    this.translate(dx - bb.x, dy - bb.y);
         | 
| 250 | 
            +
             | 
| 251 | 
            +
                return p.insertBefore(this.node ? this : this[0]);
         | 
| 252 | 
            +
            };
         | 
| 253 | 
            +
             | 
| 254 | 
            +
            /*\
         | 
| 255 | 
            +
             * Element.flag
         | 
| 256 | 
            +
             [ method ]
         | 
| 257 | 
            +
             **
         | 
| 258 | 
            +
             * Puts the context Element in a 'flag' tooltip. Can also be used on sets.
         | 
| 259 | 
            +
             **
         | 
| 260 | 
            +
             > Parameters
         | 
| 261 | 
            +
             **
         | 
| 262 | 
            +
             - angle (number) angle of orientation in degrees [default: `0`]
         | 
| 263 | 
            +
             - x (number) x coordinate of the flag's point [default: Element's `x` or `cx`]
         | 
| 264 | 
            +
             - y (number) y coordinate of the flag's point [default: Element's `x` or `cx`]
         | 
| 265 | 
            +
             **
         | 
| 266 | 
            +
             = (object) path element of the flag
         | 
| 267 | 
            +
             \*/
         | 
| 268 | 
            +
            Raphael.el.flag = function (angle, x, y) {
         | 
| 269 | 
            +
                var d = 3,
         | 
| 270 | 
            +
                    paper = this.paper || this[0].paper;
         | 
| 271 | 
            +
             | 
| 272 | 
            +
                if (!paper) return;
         | 
| 273 | 
            +
             | 
| 274 | 
            +
                var p = paper.path().attr({ fill: '#000', stroke: '#000' }),
         | 
| 275 | 
            +
                    bb = this.getBBox(),
         | 
| 276 | 
            +
                    h = bb.height / 2,
         | 
| 277 | 
            +
                    center;
         | 
| 278 | 
            +
             | 
| 279 | 
            +
                switch (this.type) {
         | 
| 280 | 
            +
                    case 'text':
         | 
| 281 | 
            +
                    case 'circle':
         | 
| 282 | 
            +
                    case 'ellipse': center = true; break;
         | 
| 283 | 
            +
                    default: center = false;
         | 
| 284 | 
            +
                }
         | 
| 285 | 
            +
             | 
| 286 | 
            +
                angle = angle || 0;
         | 
| 287 | 
            +
                x = typeof x == 'number' ? x : (center ? bb.x + bb.width / 2 : bb.x);
         | 
| 288 | 
            +
                y = typeof y == 'number' ? y : (center ? bb.y + bb.height / 2: bb.y);
         | 
| 289 | 
            +
             | 
| 290 | 
            +
                p.attr({
         | 
| 291 | 
            +
                    path: [
         | 
| 292 | 
            +
                        "M", x, y,
         | 
| 293 | 
            +
                        "l", h + d, -h - d, bb.width + 2 * d, 0, 0, bb.height + 2 * d, -bb.width - 2 * d, 0,
         | 
| 294 | 
            +
                        "z"
         | 
| 295 | 
            +
                    ].join(",")
         | 
| 296 | 
            +
                });
         | 
| 297 | 
            +
             | 
| 298 | 
            +
                angle = 360 - angle;
         | 
| 299 | 
            +
                p.rotate(angle, x, y);
         | 
| 300 | 
            +
             | 
| 301 | 
            +
                if (this.attrs) {
         | 
| 302 | 
            +
                    //elements
         | 
| 303 | 
            +
                    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);
         | 
| 304 | 
            +
                    this.rotate(angle, x, y);
         | 
| 305 | 
            +
                    angle > 90 && angle < 270 && this.attr(this.attrs.x ? 'x' : 'cx', x - h - d - (!center ? bb.width : bb.width / 2)).rotate(180, x, y);
         | 
| 306 | 
            +
                } else {
         | 
| 307 | 
            +
                    //sets
         | 
| 308 | 
            +
                    if (angle > 90 && angle < 270) {
         | 
| 309 | 
            +
                        this.translate(x - bb.x - bb.width - h - d, y - bb.y - bb.height / 2);
         | 
| 310 | 
            +
                        this.rotate(angle - 180, bb.x + bb.width + h + d, bb.y + bb.height / 2);
         | 
| 311 | 
            +
                    } else {
         | 
| 312 | 
            +
                        this.translate(x - bb.x + h + d, y - bb.y - bb.height / 2);
         | 
| 313 | 
            +
                        this.rotate(angle, bb.x - h - d, bb.y + bb.height / 2);
         | 
| 314 | 
            +
                    }
         | 
| 315 | 
            +
                }
         | 
| 316 | 
            +
             | 
| 317 | 
            +
                return p.insertBefore(this.node ? this : this[0]);
         | 
| 318 | 
            +
            };
         | 
| 319 | 
            +
             | 
| 320 | 
            +
            /*\
         | 
| 321 | 
            +
             * Element.label
         | 
| 322 | 
            +
             [ method ]
         | 
| 323 | 
            +
             **
         | 
| 324 | 
            +
             * Puts the context Element in a 'label' tooltip. Can also be used on sets.
         | 
| 325 | 
            +
             **
         | 
| 326 | 
            +
             = (object) path element of the label.
         | 
| 327 | 
            +
             \*/
         | 
| 328 | 
            +
            Raphael.el.label = function () {
         | 
| 329 | 
            +
                var bb = this.getBBox(),
         | 
| 330 | 
            +
                    paper = this.paper || this[0].paper,
         | 
| 331 | 
            +
                    r = Math.min(20, bb.width + 10, bb.height + 10) / 2;
         | 
| 332 | 
            +
             | 
| 333 | 
            +
                if (!paper) return;
         | 
| 334 | 
            +
             | 
| 335 | 
            +
                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]);
         | 
| 336 | 
            +
            };
         | 
| 337 | 
            +
             | 
| 338 | 
            +
            /*\
         | 
| 339 | 
            +
             * Element.blob
         | 
| 340 | 
            +
             [ method ]
         | 
| 341 | 
            +
             **
         | 
| 342 | 
            +
             * Puts the context Element in a 'blob' tooltip. Can also be used on sets.
         | 
| 343 | 
            +
             **
         | 
| 344 | 
            +
             > Parameters
         | 
| 345 | 
            +
             **
         | 
| 346 | 
            +
             - angle (number) angle of orientation in degrees [default: `0`]
         | 
| 347 | 
            +
             - x (number) x coordinate of the blob's tail [default: Element's `x` or `cx`]
         | 
| 348 | 
            +
             - y (number) y coordinate of the blob's tail [default: Element's `x` or `cx`]
         | 
| 349 | 
            +
             **
         | 
| 350 | 
            +
             = (object) path element of the blob
         | 
| 351 | 
            +
             \*/
         | 
| 352 | 
            +
            Raphael.el.blob = function (angle, x, y) {
         | 
| 353 | 
            +
                var bb = this.getBBox(),
         | 
| 354 | 
            +
                    rad = Math.PI / 180,
         | 
| 355 | 
            +
                    paper = this.paper || this[0].paper,
         | 
| 356 | 
            +
                    p, center, size;
         | 
| 357 | 
            +
             | 
| 358 | 
            +
                if (!paper) return;
         | 
| 359 | 
            +
             | 
| 360 | 
            +
                switch (this.type) {
         | 
| 361 | 
            +
                    case 'text':
         | 
| 362 | 
            +
                    case 'circle':
         | 
| 363 | 
            +
                    case 'ellipse': center = true; break;
         | 
| 364 | 
            +
                    default: center = false;
         | 
| 365 | 
            +
                }
         | 
| 366 | 
            +
             | 
| 367 | 
            +
                p = paper.path().attr({ fill: "#000", stroke: "none" });
         | 
| 368 | 
            +
                angle = (+angle + 1 ? angle : 45) + 90;
         | 
| 369 | 
            +
                size = Math.min(bb.height, bb.width);
         | 
| 370 | 
            +
                x = typeof x == 'number' ? x : (center ? bb.x + bb.width / 2 : bb.x);
         | 
| 371 | 
            +
                y = typeof y == 'number' ? y : (center ? bb.y + bb.height / 2 : bb.y);
         | 
| 372 | 
            +
             | 
| 373 | 
            +
                var w = Math.max(bb.width + size, size * 25 / 12),
         | 
| 374 | 
            +
                    h = Math.max(bb.height + size, size * 25 / 12),
         | 
| 375 | 
            +
                    x2 = x + size * Math.sin((angle - 22.5) * rad),
         | 
| 376 | 
            +
                    y2 = y + size * Math.cos((angle - 22.5) * rad),
         | 
| 377 | 
            +
                    x1 = x + size * Math.sin((angle + 22.5) * rad),
         | 
| 378 | 
            +
                    y1 = y + size * Math.cos((angle + 22.5) * rad),
         | 
| 379 | 
            +
                    dx = (x1 - x2) / 2,
         | 
| 380 | 
            +
                    dy = (y1 - y2) / 2,
         | 
| 381 | 
            +
                    rx = w / 2,
         | 
| 382 | 
            +
                    ry = h / 2,
         | 
| 383 | 
            +
                    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)),
         | 
| 384 | 
            +
                    cx = k * rx * dy / ry + (x1 + x2) / 2,
         | 
| 385 | 
            +
                    cy = k * -ry * dx / rx + (y1 + y2) / 2;
         | 
| 386 | 
            +
             | 
| 387 | 
            +
                p.attr({
         | 
| 388 | 
            +
                    x: cx,
         | 
| 389 | 
            +
                    y: cy,
         | 
| 390 | 
            +
                    path: [
         | 
| 391 | 
            +
                        "M", x, y,
         | 
| 392 | 
            +
                        "L", x1, y1,
         | 
| 393 | 
            +
                        "A", rx, ry, 0, 1, 1, x2, y2,
         | 
| 394 | 
            +
                        "z"
         | 
| 395 | 
            +
                    ].join(",")
         | 
| 396 | 
            +
                });
         | 
| 397 | 
            +
             | 
| 398 | 
            +
                this.translate(cx - bb.x - bb.width / 2, cy - bb.y - bb.height / 2);
         | 
| 399 | 
            +
             | 
| 400 | 
            +
                return p.insertBefore(this.node ? this : this[0]);
         | 
| 401 | 
            +
            };
         | 
| 402 | 
            +
             | 
| 403 | 
            +
            /*
         | 
| 404 | 
            +
             * Tooltips on Paper prototype
         | 
| 405 | 
            +
             */
         | 
| 406 | 
            +
            /*\
         | 
| 407 | 
            +
             * Paper.label
         | 
| 408 | 
            +
             [ method ]
         | 
| 409 | 
            +
             **
         | 
| 410 | 
            +
             * Puts the given `text` into a 'label' tooltip. The text is given a default style according to @g.txtattr. See @Element.label
         | 
| 411 | 
            +
             **
         | 
| 412 | 
            +
             > Parameters
         | 
| 413 | 
            +
             **
         | 
| 414 | 
            +
             - x (number) x coordinate of the center of the label
         | 
| 415 | 
            +
             - y (number) y coordinate of the center of the label
         | 
| 416 | 
            +
             - text (string) text to place inside the label
         | 
| 417 | 
            +
             **
         | 
| 418 | 
            +
             = (object) set containing the label path and the text element
         | 
| 419 | 
            +
             > Usage
         | 
| 420 | 
            +
             | paper.label(50, 50, "$9.99");
         | 
| 421 | 
            +
             \*/
         | 
| 422 | 
            +
            Raphael.fn.label = function (x, y, text) {
         | 
| 423 | 
            +
                var set = this.set();
         | 
| 424 | 
            +
             | 
| 425 | 
            +
                text = this.text(x, y, text).attr(Raphael.g.txtattr);
         | 
| 426 | 
            +
                return set.push(text.label(), text);
         | 
| 427 | 
            +
            };
         | 
| 428 | 
            +
             | 
| 429 | 
            +
            /*\
         | 
| 430 | 
            +
             * Paper.popup
         | 
| 431 | 
            +
             [ method ]
         | 
| 432 | 
            +
             **
         | 
| 433 | 
            +
             * Puts the given `text` into a 'popup' tooltip. The text is given a default style according to @g.txtattr. See @Element.popup
         | 
| 434 | 
            +
             *
         | 
| 435 | 
            +
             * 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.
         | 
| 436 | 
            +
             **
         | 
| 437 | 
            +
             > Parameters
         | 
| 438 | 
            +
             **
         | 
| 439 | 
            +
             - x (number) x coordinate of the popup's tail
         | 
| 440 | 
            +
             - y (number) y coordinate of the popup's tail
         | 
| 441 | 
            +
             - text (string) text to place inside the popup
         | 
| 442 | 
            +
             - dir (string) location of the text relative to the tail: `'down'`, `'left'`, `'up'` [default], or `'right'`.
         | 
| 443 | 
            +
             - size (number) amount of padding around the Element [default: `5`]
         | 
| 444 | 
            +
             **
         | 
| 445 | 
            +
             = (object) set containing the popup path and the text element
         | 
| 446 | 
            +
             > Usage
         | 
| 447 | 
            +
             | paper.popup(50, 50, "$9.99", 'down');
         | 
| 448 | 
            +
             \*/
         | 
| 449 | 
            +
            Raphael.fn.popup = function (x, y, text, dir, size) {
         | 
| 450 | 
            +
                var set = this.set();
         | 
| 451 | 
            +
             | 
| 452 | 
            +
                text = this.text(x, y, text).attr(Raphael.g.txtattr);
         | 
| 453 | 
            +
                return set.push(text.popup(dir, size), text);
         | 
| 454 | 
            +
            };
         | 
| 455 | 
            +
             | 
| 456 | 
            +
            /*\
         | 
| 457 | 
            +
             * Paper.tag
         | 
| 458 | 
            +
             [ method ]
         | 
| 459 | 
            +
             **
         | 
| 460 | 
            +
             * Puts the given text into a 'tag' tooltip. The text is given a default style according to @g.txtattr. See @Element.tag
         | 
| 461 | 
            +
             **
         | 
| 462 | 
            +
             > Parameters
         | 
| 463 | 
            +
             **
         | 
| 464 | 
            +
             - x (number) x coordinate of the center of the tag loop
         | 
| 465 | 
            +
             - y (number) y coordinate of the center of the tag loop
         | 
| 466 | 
            +
             - text (string) text to place inside the tag
         | 
| 467 | 
            +
             - angle (number) angle of orientation in degrees [default: `0`]
         | 
| 468 | 
            +
             - r (number) radius of the loop [default: `5`]
         | 
| 469 | 
            +
             **
         | 
| 470 | 
            +
             = (object) set containing the tag path and the text element
         | 
| 471 | 
            +
             > Usage
         | 
| 472 | 
            +
             | paper.tag(50, 50, "$9.99", 60);
         | 
| 473 | 
            +
             \*/
         | 
| 474 | 
            +
            Raphael.fn.tag = function (x, y, text, angle, r) {
         | 
| 475 | 
            +
                var set = this.set();
         | 
| 476 | 
            +
             | 
| 477 | 
            +
                text = this.text(x, y, text).attr(Raphael.g.txtattr);
         | 
| 478 | 
            +
                return set.push(text.tag(angle, r), text);
         | 
| 479 | 
            +
            };
         | 
| 480 | 
            +
             | 
| 481 | 
            +
            /*\
         | 
| 482 | 
            +
             * Paper.flag
         | 
| 483 | 
            +
             [ method ]
         | 
| 484 | 
            +
             **
         | 
| 485 | 
            +
             * Puts the given `text` into a 'flag' tooltip. The text is given a default style according to @g.txtattr. See @Element.flag
         | 
| 486 | 
            +
             **
         | 
| 487 | 
            +
             > Parameters
         | 
| 488 | 
            +
             **
         | 
| 489 | 
            +
             - x (number) x coordinate of the flag's point
         | 
| 490 | 
            +
             - y (number) y coordinate of the flag's point
         | 
| 491 | 
            +
             - text (string) text to place inside the flag
         | 
| 492 | 
            +
             - angle (number) angle of orientation in degrees [default: `0`]
         | 
| 493 | 
            +
             **
         | 
| 494 | 
            +
             = (object) set containing the flag path and the text element
         | 
| 495 | 
            +
             > Usage
         | 
| 496 | 
            +
             | paper.flag(50, 50, "$9.99", 60);
         | 
| 497 | 
            +
             \*/
         | 
| 498 | 
            +
            Raphael.fn.flag = function (x, y, text, angle) {
         | 
| 499 | 
            +
                var set = this.set();
         | 
| 500 | 
            +
             | 
| 501 | 
            +
                text = this.text(x, y, text).attr(Raphael.g.txtattr);
         | 
| 502 | 
            +
                return set.push(text.flag(angle), text);
         | 
| 503 | 
            +
            };
         | 
| 504 | 
            +
             | 
| 505 | 
            +
            /*\
         | 
| 506 | 
            +
             * Paper.drop
         | 
| 507 | 
            +
             [ method ]
         | 
| 508 | 
            +
             **
         | 
| 509 | 
            +
             * Puts the given text into a 'drop' tooltip. The text is given a default style according to @g.txtattr. See @Element.drop
         | 
| 510 | 
            +
             **
         | 
| 511 | 
            +
             > Parameters
         | 
| 512 | 
            +
             **
         | 
| 513 | 
            +
             - x (number) x coordinate of the drop's point
         | 
| 514 | 
            +
             - y (number) y coordinate of the drop's point
         | 
| 515 | 
            +
             - text (string) text to place inside the drop
         | 
| 516 | 
            +
             - angle (number) angle of orientation in degrees [default: `0`]
         | 
| 517 | 
            +
             **
         | 
| 518 | 
            +
             = (object) set containing the drop path and the text element
         | 
| 519 | 
            +
             > Usage
         | 
| 520 | 
            +
             | paper.drop(50, 50, "$9.99", 60);
         | 
| 521 | 
            +
             \*/
         | 
| 522 | 
            +
            Raphael.fn.drop = function (x, y, text, angle) {
         | 
| 523 | 
            +
                var set = this.set();
         | 
| 524 | 
            +
             | 
| 525 | 
            +
                text = this.text(x, y, text).attr(Raphael.g.txtattr);
         | 
| 526 | 
            +
                return set.push(text.drop(angle), text);
         | 
| 527 | 
            +
            };
         | 
| 528 | 
            +
             | 
| 529 | 
            +
            /*\
         | 
| 530 | 
            +
             * Paper.blob
         | 
| 531 | 
            +
             [ method ]
         | 
| 532 | 
            +
             **
         | 
| 533 | 
            +
             * Puts the given text into a 'blob' tooltip. The text is given a default style according to @g.txtattr. See @Element.blob
         | 
| 534 | 
            +
             **
         | 
| 535 | 
            +
             > Parameters
         | 
| 536 | 
            +
             **
         | 
| 537 | 
            +
             - x (number) x coordinate of the blob's tail
         | 
| 538 | 
            +
             - y (number) y coordinate of the blob's tail
         | 
| 539 | 
            +
             - text (string) text to place inside the blob
         | 
| 540 | 
            +
             - angle (number) angle of orientation in degrees [default: `0`]
         | 
| 541 | 
            +
             **
         | 
| 542 | 
            +
             = (object) set containing the blob path and the text element
         | 
| 543 | 
            +
             > Usage
         | 
| 544 | 
            +
             | paper.blob(50, 50, "$9.99", 60);
         | 
| 545 | 
            +
             \*/
         | 
| 546 | 
            +
            Raphael.fn.blob = function (x, y, text, angle) {
         | 
| 547 | 
            +
                var set = this.set();
         | 
| 548 | 
            +
             | 
| 549 | 
            +
                text = this.text(x, y, text).attr(Raphael.g.txtattr);
         | 
| 550 | 
            +
                return set.push(text.blob(angle), text);
         | 
| 551 | 
            +
            };
         | 
| 552 | 
            +
             | 
| 553 | 
            +
            /**
         | 
| 554 | 
            +
             * Brightness functions on the Element prototype
         | 
| 555 | 
            +
             */
         | 
| 556 | 
            +
            /*\
         | 
| 557 | 
            +
             * Element.lighter
         | 
| 558 | 
            +
             [ method ]
         | 
| 559 | 
            +
             **
         | 
| 560 | 
            +
             * Makes the context element lighter by increasing the brightness and reducing the saturation by a given factor. Can be called on Sets.
         | 
| 561 | 
            +
             **
         | 
| 562 | 
            +
             > Parameters
         | 
| 563 | 
            +
             **
         | 
| 564 | 
            +
             - times (number) adjustment factor [default: `2`]
         | 
| 565 | 
            +
             **
         | 
| 566 | 
            +
             = (object) Element
         | 
| 567 | 
            +
             > Usage
         | 
| 568 | 
            +
             | paper.circle(50, 50, 20).attr({
         | 
| 569 | 
            +
             |     fill: "#ff0000",
         | 
| 570 | 
            +
             |     stroke: "#fff",
         | 
| 571 | 
            +
             |     "stroke-width": 2
         | 
| 572 | 
            +
             | }).lighter(6);
         | 
| 573 | 
            +
             \*/
         | 
| 574 | 
            +
            Raphael.el.lighter = function (times) {
         | 
| 575 | 
            +
                times = times || 2;
         | 
| 576 | 
            +
             | 
| 577 | 
            +
                var fs = [this.attrs.fill, this.attrs.stroke];
         | 
| 578 | 
            +
             | 
| 579 | 
            +
                this.fs = this.fs || [fs[0], fs[1]];
         | 
| 580 | 
            +
             | 
| 581 | 
            +
                fs[0] = Raphael.rgb2hsb(Raphael.getRGB(fs[0]).hex);
         | 
| 582 | 
            +
                fs[1] = Raphael.rgb2hsb(Raphael.getRGB(fs[1]).hex);
         | 
| 583 | 
            +
                fs[0].b = Math.min(fs[0].b * times, 1);
         | 
| 584 | 
            +
                fs[0].s = fs[0].s / times;
         | 
| 585 | 
            +
                fs[1].b = Math.min(fs[1].b * times, 1);
         | 
| 586 | 
            +
                fs[1].s = fs[1].s / times;
         | 
| 587 | 
            +
             | 
| 588 | 
            +
                this.attr({fill: "hsb(" + [fs[0].h, fs[0].s, fs[0].b] + ")", stroke: "hsb(" + [fs[1].h, fs[1].s, fs[1].b] + ")"});
         | 
| 589 | 
            +
                return this;
         | 
| 590 | 
            +
            };
         | 
| 591 | 
            +
             | 
| 592 | 
            +
            /*\
         | 
| 593 | 
            +
             * Element.darker
         | 
| 594 | 
            +
             [ method ]
         | 
| 595 | 
            +
             **
         | 
| 596 | 
            +
             * Makes the context element darker by decreasing the brightness and increasing the saturation by a given factor. Can be called on Sets.
         | 
| 597 | 
            +
             **
         | 
| 598 | 
            +
             > Parameters
         | 
| 599 | 
            +
             **
         | 
| 600 | 
            +
             - times (number) adjustment factor [default: `2`]
         | 
| 601 | 
            +
             **
         | 
| 602 | 
            +
             = (object) Element
         | 
| 603 | 
            +
             > Usage
         | 
| 604 | 
            +
             | paper.circle(50, 50, 20).attr({
         | 
| 605 | 
            +
             |     fill: "#ff0000",
         | 
| 606 | 
            +
             |     stroke: "#fff",
         | 
| 607 | 
            +
             |     "stroke-width": 2
         | 
| 608 | 
            +
             | }).darker(6);
         | 
| 609 | 
            +
             \*/
         | 
| 610 | 
            +
            Raphael.el.darker = function (times) {
         | 
| 611 | 
            +
                times = times || 2;
         | 
| 612 | 
            +
             | 
| 613 | 
            +
                var fs = [this.attrs.fill, this.attrs.stroke];
         | 
| 614 | 
            +
             | 
| 615 | 
            +
                this.fs = this.fs || [fs[0], fs[1]];
         | 
| 616 | 
            +
             | 
| 617 | 
            +
                fs[0] = Raphael.rgb2hsb(Raphael.getRGB(fs[0]).hex);
         | 
| 618 | 
            +
                fs[1] = Raphael.rgb2hsb(Raphael.getRGB(fs[1]).hex);
         | 
| 619 | 
            +
                fs[0].s = Math.min(fs[0].s * times, 1);
         | 
| 620 | 
            +
                fs[0].b = fs[0].b / times;
         | 
| 621 | 
            +
                fs[1].s = Math.min(fs[1].s * times, 1);
         | 
| 622 | 
            +
                fs[1].b = fs[1].b / times;
         | 
| 623 | 
            +
             | 
| 624 | 
            +
                this.attr({fill: "hsb(" + [fs[0].h, fs[0].s, fs[0].b] + ")", stroke: "hsb(" + [fs[1].h, fs[1].s, fs[1].b] + ")"});
         | 
| 625 | 
            +
                return this;
         | 
| 626 | 
            +
            };
         | 
| 627 | 
            +
             | 
| 628 | 
            +
            /*\
         | 
| 629 | 
            +
             * Element.resetBrightness
         | 
| 630 | 
            +
             [ method ]
         | 
| 631 | 
            +
             **
         | 
| 632 | 
            +
             * Resets brightness and saturation levels to their original values. See @Element.lighter and @Element.darker. Can be called on Sets.
         | 
| 633 | 
            +
             **
         | 
| 634 | 
            +
             = (object) Element
         | 
| 635 | 
            +
             > Usage
         | 
| 636 | 
            +
             | paper.circle(50, 50, 20).attr({
         | 
| 637 | 
            +
             |     fill: "#ff0000",
         | 
| 638 | 
            +
             |     stroke: "#fff",
         | 
| 639 | 
            +
             |     "stroke-width": 2
         | 
| 640 | 
            +
             | }).lighter(6).resetBrightness();
         | 
| 641 | 
            +
             \*/
         | 
| 642 | 
            +
            Raphael.el.resetBrightness = function () {
         | 
| 643 | 
            +
                if (this.fs) {
         | 
| 644 | 
            +
                    this.attr({ fill: this.fs[0], stroke: this.fs[1] });
         | 
| 645 | 
            +
                    delete this.fs;
         | 
| 646 | 
            +
                }
         | 
| 647 | 
            +
                return this;
         | 
| 648 | 
            +
            };
         | 
| 649 | 
            +
             | 
| 650 | 
            +
            //alias to set prototype
         | 
| 651 | 
            +
            (function () {
         | 
| 652 | 
            +
                var brightness = ['lighter', 'darker', 'resetBrightness'],
         | 
| 653 | 
            +
                    tooltips = ['popup', 'tag', 'flag', 'label', 'drop', 'blob'];
         | 
| 654 | 
            +
             | 
| 655 | 
            +
                for (var f in tooltips) (function (name) {
         | 
| 656 | 
            +
                    Raphael.st[name] = function () {
         | 
| 657 | 
            +
                        return Raphael.el[name].apply(this, arguments);
         | 
| 658 | 
            +
                    };
         | 
| 659 | 
            +
                })(tooltips[f]);
         | 
| 660 | 
            +
             | 
| 661 | 
            +
                for (var f in brightness) (function (name) {
         | 
| 662 | 
            +
                    Raphael.st[name] = function () {
         | 
| 663 | 
            +
                        for (var i = 0; i < this.length; i++) {
         | 
| 664 | 
            +
                            this[i][name].apply(this[i], arguments);
         | 
| 665 | 
            +
                        }
         | 
| 666 | 
            +
             | 
| 667 | 
            +
                        return this;
         | 
| 668 | 
            +
                    };
         | 
| 669 | 
            +
                })(brightness[f]);
         | 
| 670 | 
            +
            })();
         | 
| 671 | 
            +
             | 
| 672 | 
            +
            //chart prototype for storing common functions
         | 
| 673 | 
            +
            Raphael.g = {
         | 
| 674 | 
            +
                /*\
         | 
| 675 | 
            +
                 * g.shim
         | 
| 676 | 
            +
                 [ object ]
         | 
| 677 | 
            +
                 **
         | 
| 678 | 
            +
                 * An attribute object that charts will set on all generated shims (shims being the invisible objects that mouse events are bound to)
         | 
| 679 | 
            +
                 **
         | 
| 680 | 
            +
                 > Default value
         | 
| 681 | 
            +
                 | { stroke: 'none', fill: '#000', 'fill-opacity': 0 }
         | 
| 682 | 
            +
                 \*/
         | 
| 683 | 
            +
                shim: { stroke: 'none', fill: '#000', 'fill-opacity': 0 },
         | 
| 684 | 
            +
             | 
| 685 | 
            +
                /*\
         | 
| 686 | 
            +
                 * g.txtattr
         | 
| 687 | 
            +
                 [ object ]
         | 
| 688 | 
            +
                 **
         | 
| 689 | 
            +
                 * An attribute object that charts and tooltips will set on any generated text
         | 
| 690 | 
            +
                 **
         | 
| 691 | 
            +
                 > Default value
         | 
| 692 | 
            +
                 | { font: '12px Arial, sans-serif', fill: '#fff' }
         | 
| 693 | 
            +
                 \*/  
         | 
| 694 | 
            +
                txtattr: { font: '12px Arial, sans-serif', fill: '#fff' },
         | 
| 695 | 
            +
             | 
| 696 | 
            +
                /*\
         | 
| 697 | 
            +
                 * g.colors
         | 
| 698 | 
            +
                 [ array ]
         | 
| 699 | 
            +
                 **
         | 
| 700 | 
            +
                 * An array of color values that charts will iterate through when drawing chart data values.
         | 
| 701 | 
            +
                 **
         | 
| 702 | 
            +
                 \*/
         | 
| 703 | 
            +
                colors: (function () {
         | 
| 704 | 
            +
                        var hues = [.6, .2, .05, .1333, .75, 0],
         | 
| 705 | 
            +
                            colors = [];
         | 
| 706 | 
            +
             | 
| 707 | 
            +
                        for (var i = 0; i < 10; i++) {
         | 
| 708 | 
            +
                            if (i < hues.length) {
         | 
| 709 | 
            +
                                colors.push('hsb(' + hues[i] + ',.75, .75)');
         | 
| 710 | 
            +
                            } else {
         | 
| 711 | 
            +
                                colors.push('hsb(' + hues[i - hues.length] + ', 1, .5)');
         | 
| 712 | 
            +
                            }
         | 
| 713 | 
            +
                        }
         | 
| 714 | 
            +
             | 
| 715 | 
            +
                        return colors;
         | 
| 716 | 
            +
                })(),
         | 
| 717 | 
            +
                
         | 
| 718 | 
            +
                snapEnds: function(from, to, steps) {
         | 
| 719 | 
            +
                    var f = from,
         | 
| 720 | 
            +
                        t = to;
         | 
| 721 | 
            +
             | 
| 722 | 
            +
                    if (f == t) {
         | 
| 723 | 
            +
                        return {from: f, to: t, power: 0};
         | 
| 724 | 
            +
                    }
         | 
| 725 | 
            +
             | 
| 726 | 
            +
                    function round(a) {
         | 
| 727 | 
            +
                        return Math.abs(a - .5) < .25 ? ~~(a) + .5 : Math.round(a);
         | 
| 728 | 
            +
                    }
         | 
| 729 | 
            +
             | 
| 730 | 
            +
                    var d = (t - f) / steps,
         | 
| 731 | 
            +
                        r = ~~(d),
         | 
| 732 | 
            +
                        R = r,
         | 
| 733 | 
            +
                        i = 0;
         | 
| 734 | 
            +
             | 
| 735 | 
            +
                    if (r) {
         | 
| 736 | 
            +
                        while (R) {
         | 
| 737 | 
            +
                            i--;
         | 
| 738 | 
            +
                            R = ~~(d * Math.pow(10, i)) / Math.pow(10, i);
         | 
| 739 | 
            +
                        }
         | 
| 740 | 
            +
             | 
| 741 | 
            +
                        i ++;
         | 
| 742 | 
            +
                    } else {
         | 
| 743 | 
            +
                        if(d == 0 || !isFinite(d)) {
         | 
| 744 | 
            +
                            i = 1;
         | 
| 745 | 
            +
                        } else {
         | 
| 746 | 
            +
                            while (!r) {
         | 
| 747 | 
            +
                                i = i || 1;
         | 
| 748 | 
            +
                                r = ~~(d * Math.pow(10, i)) / Math.pow(10, i);
         | 
| 749 | 
            +
                                i++;
         | 
| 750 | 
            +
                            }
         | 
| 751 | 
            +
                        }
         | 
| 752 | 
            +
             | 
| 753 | 
            +
                        i && i--;
         | 
| 754 | 
            +
                    }
         | 
| 755 | 
            +
             | 
| 756 | 
            +
                    t = round(to * Math.pow(10, i)) / Math.pow(10, i);
         | 
| 757 | 
            +
             | 
| 758 | 
            +
                    if (t < to) {
         | 
| 759 | 
            +
                        t = round((to + .5) * Math.pow(10, i)) / Math.pow(10, i);
         | 
| 760 | 
            +
                    }
         | 
| 761 | 
            +
             | 
| 762 | 
            +
                    f = round((from - (i > 0 ? 0 : .5)) * Math.pow(10, i)) / Math.pow(10, i);
         | 
| 763 | 
            +
                    return { from: f, to: t, power: i };
         | 
| 764 | 
            +
                },
         | 
| 765 | 
            +
             | 
| 766 | 
            +
                axis: function (x, y, length, from, to, steps, orientation, labels, type, dashsize, paper) {
         | 
| 767 | 
            +
                    dashsize = dashsize == null ? 2 : dashsize;
         | 
| 768 | 
            +
                    type = type || "t";
         | 
| 769 | 
            +
                    steps = steps || 10;
         | 
| 770 | 
            +
                    paper = arguments[arguments.length-1] //paper is always last argument
         | 
| 771 | 
            +
             | 
| 772 | 
            +
                    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],
         | 
| 773 | 
            +
                        ends = this.snapEnds(from, to, steps),
         | 
| 774 | 
            +
                        f = ends.from,
         | 
| 775 | 
            +
                        t = ends.to,
         | 
| 776 | 
            +
                        i = ends.power,
         | 
| 777 | 
            +
                        j = 0,
         | 
| 778 | 
            +
                        txtattr = { font: "11px 'Fontin Sans', Fontin-Sans, sans-serif" },
         | 
| 779 | 
            +
                        text = paper.set(),
         | 
| 780 | 
            +
                        d;
         | 
| 781 | 
            +
             | 
| 782 | 
            +
                    d = (t - f) / steps;
         | 
| 783 | 
            +
             | 
| 784 | 
            +
                    var label = f,
         | 
| 785 | 
            +
                        rnd = i > 0 ? i : 0;
         | 
| 786 | 
            +
                        dx = length / steps;
         | 
| 787 | 
            +
             | 
| 788 | 
            +
                    if (+orientation == 1 || +orientation == 3) {
         | 
| 789 | 
            +
                        var Y = y,
         | 
| 790 | 
            +
                            addon = (orientation - 1 ? 1 : -1) * (dashsize + 3 + !!(orientation - 1));
         | 
| 791 | 
            +
             | 
| 792 | 
            +
                        while (Y >= y - length) {
         | 
| 793 | 
            +
                            type != "-" && type != " " && (path = path.concat(["M", x - (type == "+" || type == "|" ? dashsize : !(orientation - 1) * dashsize * 2), Y + .5, "l", dashsize * 2 + 1, 0]));
         | 
| 794 | 
            +
                            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" }));
         | 
| 795 | 
            +
                            label += d;
         | 
| 796 | 
            +
                            Y -= dx;
         | 
| 797 | 
            +
                        }
         | 
| 798 | 
            +
             | 
| 799 | 
            +
                        if (Math.round(Y + dx - (y - length))) {
         | 
| 800 | 
            +
                            type != "-" && type != " " && (path = path.concat(["M", x - (type == "+" || type == "|" ? dashsize : !(orientation - 1) * dashsize * 2), y - length + .5, "l", dashsize * 2 + 1, 0]));
         | 
| 801 | 
            +
                            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" }));
         | 
| 802 | 
            +
                        }
         | 
| 803 | 
            +
                    } else {
         | 
| 804 | 
            +
                        label = f;
         | 
| 805 | 
            +
                        rnd = (i > 0) * i;
         | 
| 806 | 
            +
                        addon = (orientation ? -1 : 1) * (dashsize + 9 + !orientation);
         | 
| 807 | 
            +
             | 
| 808 | 
            +
                        var X = x,
         | 
| 809 | 
            +
                            dx = length / steps,
         | 
| 810 | 
            +
                            txt = 0,
         | 
| 811 | 
            +
                            prev = 0;
         | 
| 812 | 
            +
             | 
| 813 | 
            +
                        while (X <= x + length) {
         | 
| 814 | 
            +
                            type != "-" && type != " " && (path = path.concat(["M", X + .5, y - (type == "+" ? dashsize : !!orientation * dashsize * 2), "l", 0, dashsize * 2 + 1]));
         | 
| 815 | 
            +
                            text.push(txt = paper.text(X, y + addon, (labels && labels[j++]) || (Math.round(label) == label ? label : +label.toFixed(rnd))).attr(txtattr));
         | 
| 816 | 
            +
             | 
| 817 | 
            +
                            var bb = txt.getBBox();
         | 
| 818 | 
            +
             | 
| 819 | 
            +
                            if (prev >= bb.x - 5) {
         | 
| 820 | 
            +
                                text.pop(text.length - 1).remove();
         | 
| 821 | 
            +
                            } else {
         | 
| 822 | 
            +
                                prev = bb.x + bb.width;
         | 
| 823 | 
            +
                            }
         | 
| 824 | 
            +
             | 
| 825 | 
            +
                            label += d;
         | 
| 826 | 
            +
                            X += dx;
         | 
| 827 | 
            +
                        }
         | 
| 828 | 
            +
             | 
| 829 | 
            +
                        if (Math.round(X - dx - x - length)) {
         | 
| 830 | 
            +
                            type != "-" && type != " " && (path = path.concat(["M", x + length + .5, y - (type == "+" ? dashsize : !!orientation * dashsize * 2), "l", 0, dashsize * 2 + 1]));
         | 
| 831 | 
            +
                            text.push(paper.text(x + length, y + addon, (labels && labels[j]) || (Math.round(label) == label ? label : +label.toFixed(rnd))).attr(txtattr));
         | 
| 832 | 
            +
                        }
         | 
| 833 | 
            +
                    }
         | 
| 834 | 
            +
             | 
| 835 | 
            +
                    var res = paper.path(path);
         | 
| 836 | 
            +
             | 
| 837 | 
            +
                    res.text = text;
         | 
| 838 | 
            +
                    res.all = paper.set([res, text]);
         | 
| 839 | 
            +
                    res.remove = function () {
         | 
| 840 | 
            +
                        this.text.remove();
         | 
| 841 | 
            +
                        this.constructor.prototype.remove.call(this);
         | 
| 842 | 
            +
                    };
         | 
| 843 | 
            +
             | 
| 844 | 
            +
                    return res;
         | 
| 845 | 
            +
                },
         | 
| 846 | 
            +
                
         | 
| 847 | 
            +
                labelise: function(label, val, total) {
         | 
| 848 | 
            +
                    if (label) {
         | 
| 849 | 
            +
                        return (label + "").replace(/(##+(?:\.#+)?)|(%%+(?:\.%+)?)/g, function (all, value, percent) {
         | 
| 850 | 
            +
                            if (value) {
         | 
| 851 | 
            +
                                return (+val).toFixed(value.replace(/^#+\.?/g, "").length);
         | 
| 852 | 
            +
                            }
         | 
| 853 | 
            +
                            if (percent) {
         | 
| 854 | 
            +
                                return (val * 100 / total).toFixed(percent.replace(/^%+\.?/g, "").length) + "%";
         | 
| 855 | 
            +
                            }
         | 
| 856 | 
            +
                        });
         | 
| 857 | 
            +
                    } else {
         | 
| 858 | 
            +
                        return (+val).toFixed(0);
         | 
| 859 | 
            +
                    }
         | 
| 860 | 
            +
                }
         | 
| 861 | 
            +
            }
         |