faster replacement on unicode chars
[g.raphael] / g.pie.sector.js
1 /*
2  * g.Raphael 0.5 - Charting library, based on RaphaĆ«l
3  *
4  * Copyright (c) 2009 Dmitry Baranovskiy (http://g.raphaeljs.com)
5  * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
6  */
7 Raphael = typeof(Raphael) != 'undefined' ? Raphael :  (imports ? imports.seed.Raphael.Raphael : {});
8 Roo = typeof(Roo) != 'undefined' ? Roo:  (imports ? imports.seed.Roo.Roo: {});
9 //chartinst = typeof(chartinst) != 'undefined' ? chartinst:  (imports ? imports.chartinst.chartinst : {});
10  
11
12
13 (function () {
14
15     /**
16      * @param {Raphael} paper to draw on
17      * @param {int} cx - centre X
18      * @param {int} cy - centre Y
19      * @param {int} r - radius
20      * @param {Array} values
21      * @param {Object} opts options
22      *   cut : after this meany items - do not show a pie element?
23      *   
24      *   
25      * 
26      */
27
28     function Piesectorchart(paper, width, height, cx, cy, r, values, opts) {
29         
30         opts = opts || {};
31
32         var chartinst = this,
33             chart = paper.set(),
34             len = values.length,
35             angle = opts.start_angle || 90,
36             total = 0,
37             others = 0,
38             cut = opts.cut || 9,
39             defcut = true
40             lineheight = opts.lineheight || 30;
41         
42         opts.barwidth = opts.barwidth || 80;
43         
44         paper.rect(0, 0, width, height).attr({ stroke: "none", fill: (opts.background || "#F0F4F7") });
45         
46         paper.customAttributes.sector = function (cx, cy, startAngle, endAngle, color, R) {
47             
48             var rad = Math.PI / 180,
49                 x1 = cx + r * Math.cos(-startAngle * rad),
50                 x2 = cx + r * Math.cos(-endAngle * rad),
51                 y1 = cy + r * Math.sin(-startAngle * rad),
52                 y2 = cy + r * Math.sin(-endAngle * rad),
53                 path;
54         
55             path = [["M", x1, y1], ["A", R, R, 0, +(Math.abs(endAngle - startAngle) > 180), 1, x2, y2]];
56
57             return {path: path, stroke: color};
58         };
59         
60         if (len == 1) {
61             total = values[0];
62             paper.circle(cx, cy, r + opts.barwidth / 2).attr({ fill: opts.colors && opts.colors[0] || chartinst.colors[0] || "#3E66BC", "stroke": "#fff" });
63             paper.circle(cx, cy, r - opts.barwidth / 2).attr({ fill: opts.background || "#F0F4F7", "stroke": "#fff" });
64             
65         } else {
66             
67             for (var i = 0; i < len; i++) {
68                 total += values[i] * 1;
69                 values[i] = {
70                     value: values[i],
71                     valueOf: function () { return this.value; }
72                 };
73             }
74             
75             if (!opts.no_sort) {
76                 values.sort(function (a, b) {
77                     return b.value - a.value;
78                 });
79             }
80             
81             for (i = 0; i < len; i++) {
82                 if (defcut && values[i] * 360 / total <= 1.5) {
83                     cut = i;
84                     defcut = false;
85                 }
86
87                 if (i > cut) {
88                     defcut = false;
89                     values[cut].value += values[i];
90                     values[cut].others = true;
91                 }
92             }
93             
94             len = Math.min(cut + 1, values.length);
95             
96             for (i = 0; i < len; i++) {
97                 
98                 var p = paper.path().attr({
99                     "stroke": "#fff", 
100                     "stroke-width": opts.barwidth
101                 }).attr({sector: [cx, cy, angle, angle -= 360 * values[i] / total, opts.colors && opts.colors[i] || chartinst.colors[i], r]});
102             
103             }
104             
105         }
106         
107         var ix = cx + r + opts.barwidth / 2 + 30,
108             iy = cy - r - 30;
109         
110         for (var i = 0; i < len; i++) {
111             
112             paper.circle(ix, iy, 6).attr({ fill: opts.colors && opts.colors[i] || chartinst.colors[i] || "#3E66BC", "stroke": "#fff" });
113             
114             var text = (values[i].others) ? opts.others : opts.legend[i] || values[i];
115             
116             if(text.indexOf('#qty#') !== -1) {
117                 text = text.replace('#qty#', Math.round(values[i]));
118             }
119             
120             if(text.indexOf('#%#') !== -1) {
121                 text = text.replace('#%#', Math.round(values[i] / total * 100) + '%');
122             }
123             
124             paper.text(ix + 20, iy, text).attr({ 
125                 "font-size": "18",
126                 "font-family": "'Fontin Sans', Fontin-Sans, sans-serif",
127                 "text-anchor": "start",
128                 fill : "#0C014F"
129             });
130             
131             iy += lineheight;
132             
133         }
134
135         chart.cx = cx;
136         chart.cy = cy;
137         chart.r = r;
138         return chart;
139     };
140     
141     //inheritance
142     var F = function() {};
143     F.prototype = Raphael.g;
144     Piesectorchart.prototype = new F;
145     
146     //public
147     Raphael.fn.piesectorchart = function(width, height, cx, cy, r, values, opts) {
148         return new Piesectorchart(this, width, height, cx, cy, r, values, opts);
149     }
150     
151 })();