diff options
Diffstat (limited to 'test/analytics')
| -rw-r--r-- | test/analytics/analytics.html | 96 | ||||
| -rw-r--r-- | test/analytics/analytics.js | 141 | ||||
| -rw-r--r-- | test/analytics/demo-print.css | 20 | ||||
| -rw-r--r-- | test/analytics/demo.css | 23 | ||||
| -rw-r--r-- | test/analytics/popup.js | 121 |
5 files changed, 401 insertions, 0 deletions
diff --git a/test/analytics/analytics.html b/test/analytics/analytics.html new file mode 100644 index 0000000..416d154 --- /dev/null +++ b/test/analytics/analytics.html @@ -0,0 +1,96 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="utf-8"> + <title>Raphaël · Analytics</title> + <link rel="stylesheet" href="demo.css" type="text/css" media="screen"> + <link rel="stylesheet" href="demo-print.css" type="text/css" media="print"> + <script src="raphael.js"></script> + <script src="popup.js"></script> + <script src="jquery.js"></script> + <script src="analytics.js"></script> + <style type="text/css" media="screen"> + #holder { + height: 250px; + margin: -125px 0 0 -400px; + width: 800px; + } + </style> + </head> + <body> + <table id="data"> + <tfoot> + <tr> + <th>1</th> + <th>2</th> + <th>3</th> + <th>4</th> + <th>5</th> + <th>6</th> + <th>7</th> + <th>8</th> + <th>9</th> + <th>10</th> + <th>11</th> + <th>12</th> + <th>13</th> + <th>14</th> + <th>15</th> + <th>16</th> + <th>17</th> + <th>18</th> + <th>19</th> + <th>19</th> + <th>20</th> + <th>22</th> + <th>23</th> + <th>24</th> + <th>25</th> + <th>26</th> + <th>27</th> + <th>28</th> + <th>29</th> + <th>30</th> + <th>31</th> + </tr> + </tfoot> + <tbody> + <tr> + <td>8</td> + <td>25</td> + <td>27</td> + <td>25</td> + <td>54</td> + <td>59</td> + <td>79</td> + <td>47</td> + <td>27</td> + <td>44</td> + <td>44</td> + <td>51</td> + <td>56</td> + <td>83</td> + <td>12</td> + <td>91</td> + <td>52</td> + <td>12</td> + <td>40</td> + <td>8</td> + <td>60</td> + <td>29</td> + <td>7</td> + <td>33</td> + <td>56</td> + <td>25</td> + <td>1</td> + <td>78</td> + <td>70</td> + <td>68</td> + <td>2</td> + </tr> + </tbody> + </table> + <div id="holder"></div> + <p id="copy">Demo of <a href="http://raphaeljs.com/">Raphaël</a>—JavaScript Vector Library</p> + </body> +</html> diff --git a/test/analytics/analytics.js b/test/analytics/analytics.js new file mode 100644 index 0000000..461a036 --- /dev/null +++ b/test/analytics/analytics.js @@ -0,0 +1,141 @@ +Raphael.fn.drawGrid = function (x, y, w, h, wv, hv, color) { + color = color || "#000"; + var path = ["M", Math.round(x) + .5, Math.round(y) + .5, "L", Math.round(x + w) + .5, Math.round(y) + .5, Math.round(x + w) + .5, Math.round(y + h) + .5, Math.round(x) + .5, Math.round(y + h) + .5, Math.round(x) + .5, Math.round(y) + .5], + rowHeight = h / hv, + columnWidth = w / wv; + for (var i = 1; i < hv; i++) { + path = path.concat(["M", Math.round(x) + .5, Math.round(y + i * rowHeight) + .5, "H", Math.round(x + w) + .5]); + } + for (i = 1; i < wv; i++) { + path = path.concat(["M", Math.round(x + i * columnWidth) + .5, Math.round(y) + .5, "V", Math.round(y + h) + .5]); + } + return this.path(path.join(",")).attr({stroke: color}); +}; + +$(function () { + $("#data").css({ + position: "absolute", + left: "-9999em", + top: "-9999em" + }); +}); + +window.onload = function () { + function getAnchors(p1x, p1y, p2x, p2y, p3x, p3y) { + var l1 = (p2x - p1x) / 2, + l2 = (p3x - p2x) / 2, + a = Math.atan((p2x - p1x) / Math.abs(p2y - p1y)), + b = Math.atan((p3x - p2x) / Math.abs(p2y - p3y)); + a = p1y < p2y ? Math.PI - a : a; + b = p3y < p2y ? Math.PI - b : b; + var alpha = Math.PI / 2 - ((a + b) % (Math.PI * 2)) / 2, + dx1 = l1 * Math.sin(alpha + a), + dy1 = l1 * Math.cos(alpha + a), + dx2 = l2 * Math.sin(alpha + b), + dy2 = l2 * Math.cos(alpha + b); + return { + x1: p2x - dx1, + y1: p2y + dy1, + x2: p2x + dx2, + y2: p2y + dy2 + }; + } + // Grab the data + var labels = [], + data = []; + $("#data tfoot th").each(function () { + labels.push($(this).html()); + }); + $("#data tbody td").each(function () { + data.push($(this).html()); + }); + + // Draw + var width = 800, + height = 250, + leftgutter = 30, + bottomgutter = 20, + topgutter = 20, + colorhue = .6 || Math.random(), + color = "hsl(" + [colorhue, .5, .5] + ")", + r = Raphael("holder", width, height), + txt = {font: '12px Helvetica, Arial', fill: "#fff"}, + txt1 = {font: '10px Helvetica, Arial', fill: "#fff"}, + txt2 = {font: '12px Helvetica, Arial', fill: "#000"}, + X = (width - leftgutter) / labels.length, + max = Math.max.apply(Math, data), + Y = (height - bottomgutter - topgutter) / max; + r.drawGrid(leftgutter + X * .5 + .5, topgutter + .5, width - leftgutter - X, height - topgutter - bottomgutter, 10, 10, "#000"); + var path = r.path().attr({stroke: color, "stroke-width": 4, "stroke-linejoin": "round"}), + bgp = r.path().attr({stroke: "none", opacity: .3, fill: color}), + label = r.set(), + lx = 0, ly = 0, + is_label_visible = false, + leave_timer, + blanket = r.set(); + label.push(r.text(60, 12, "24 hits").attr(txt)); + label.push(r.text(60, 27, "22 September 2008").attr(txt1).attr({fill: color})); + label.hide(); + var frame = r.popup(100, 100, label, "right").attr({fill: "#000", stroke: "#666", "stroke-width": 2, "fill-opacity": .7}).hide(); + + var p, bgpp; + for (var i = 0, ii = labels.length; i < ii; i++) { + var y = Math.round(height - bottomgutter - Y * data[i]), + x = Math.round(leftgutter + X * (i + .5)), + t = r.text(x, height - 6, labels[i]).attr(txt).toBack(); + if (!i) { + p = ["M", x, y, "C", x, y]; + bgpp = ["M", leftgutter + X * .5, height - bottomgutter, "L", x, y, "C", x, y]; + } + if (i && i < ii - 1) { + var Y0 = Math.round(height - bottomgutter - Y * data[i - 1]), + X0 = Math.round(leftgutter + X * (i - .5)), + Y2 = Math.round(height - bottomgutter - Y * data[i + 1]), + X2 = Math.round(leftgutter + X * (i + 1.5)); + var a = getAnchors(X0, Y0, x, y, X2, Y2); + p = p.concat([a.x1, a.y1, x, y, a.x2, a.y2]); + bgpp = bgpp.concat([a.x1, a.y1, x, y, a.x2, a.y2]); + } + var dot = r.circle(x, y, 4).attr({fill: "#333", stroke: color, "stroke-width": 2}); + blanket.push(r.rect(leftgutter + X * i, 0, X, height - bottomgutter).attr({stroke: "none", fill: "#fff", opacity: 0})); + var rect = blanket[blanket.length - 1]; + (function (x, y, data, lbl, dot) { + var timer, i = 0; + rect.hover(function () { + clearTimeout(leave_timer); + var side = "right"; + if (x + frame.getBBox().width > width) { + side = "left"; + } + var ppp = r.popup(x, y, label, side, 1), + anim = Raphael.animation({ + path: ppp.path, + transform: ["t", ppp.dx, ppp.dy] + }, 200 * is_label_visible); + lx = label[0].transform()[0][1] + ppp.dx; + ly = label[0].transform()[0][2] + ppp.dy; + frame.show().stop().animate(anim); + label[0].attr({text: data + " hit" + (data == 1 ? "" : "s")}).show().stop().animateWith(frame, anim, {transform: ["t", lx, ly]}, 200 * is_label_visible); + label[1].attr({text: lbl + " September 2008"}).show().stop().animateWith(frame, anim, {transform: ["t", lx, ly]}, 200 * is_label_visible); + dot.attr("r", 6); + is_label_visible = true; + }, function () { + dot.attr("r", 4); + leave_timer = setTimeout(function () { + frame.hide(); + label[0].hide(); + label[1].hide(); + is_label_visible = false; + }, 1); + }); + })(x, y, data[i], labels[i], dot); + } + p = p.concat([x, y, x, y]); + bgpp = bgpp.concat([x, y, x, y, "L", x, height - bottomgutter, "z"]); + path.attr({path: p}); + bgp.attr({path: bgpp}); + frame.toFront(); + label[0].toFront(); + label[1].toFront(); + blanket.toFront(); +};
\ No newline at end of file diff --git a/test/analytics/demo-print.css b/test/analytics/demo-print.css new file mode 100644 index 0000000..04c724b --- /dev/null +++ b/test/analytics/demo-print.css @@ -0,0 +1,20 @@ +body { + background: #fff; + color: #000; + font: 100.1% "Lucida Grande", Lucida, Verdana, sans-serif; +} +#holder { + height: 480px; + left: 50%; + margin: 0 0 0 -320px; + position: absolute; + top: 0; + width: 640px; +} +#copy { + bottom: 0; + font-size: .7em; + position: absolute; + right: 1em; + text-align: right; +} diff --git a/test/analytics/demo.css b/test/analytics/demo.css new file mode 100644 index 0000000..a7940af --- /dev/null +++ b/test/analytics/demo.css @@ -0,0 +1,23 @@ +body { + background: #333; + color: #fff; + font: 300 100.1% "Helvetica Neue", Helvetica, "Arial Unicode MS", Arial, sans-serif; +} +#holder { + height: 480px; + left: 50%; + margin: -240px 0 0 -320px; + position: absolute; + top: 50%; + width: 640px; +} +#copy { + bottom: 0; + font: 300 .7em "Helvetica Neue", Helvetica, "Arial Unicode MS", Arial, sans-serif; + position: absolute; + right: 1em; + text-align: right; +} +#copy a { + color: #fff; +} diff --git a/test/analytics/popup.js b/test/analytics/popup.js new file mode 100644 index 0000000..5fd722a --- /dev/null +++ b/test/analytics/popup.js @@ -0,0 +1,121 @@ +(function () { +var tokenRegex = /\{([^\}]+)\}/g, + objNotationRegex = /(?:(?:^|\.)(.+?)(?=\[|\.|$|\()|\[('|")(.+?)\2\])(\(\))?/g, // matches .xxxxx or ["xxxxx"] to run over object properties + replacer = function (all, key, obj) { + var res = obj; + key.replace(objNotationRegex, function (all, name, quote, quotedName, isFunc) { + name = name || quotedName; + if (res) { + if (name in res) { + res = res[name]; + } + typeof res == "function" && isFunc && (res = res()); + } + }); + res = (res == null || res == obj ? all : res) + ""; + return res; + }, + fill = function (str, obj) { + return String(str).replace(tokenRegex, function (all, key) { + return replacer(all, key, obj); + }); + }; + Raphael.fn.popup = function (X, Y, set, pos, ret) { + pos = String(pos || "top-middle").split("-"); + pos[1] = pos[1] || "middle"; + var r = 5, + bb = set.getBBox(), + w = Math.round(bb.width), + h = Math.round(bb.height), + x = Math.round(bb.x) - r, + y = Math.round(bb.y) - r, + gap = Math.min(h / 2, w / 2, 10), + shapes = { + top: "M{x},{y}h{w4},{w4},{w4},{w4}a{r},{r},0,0,1,{r},{r}v{h4},{h4},{h4},{h4}a{r},{r},0,0,1,-{r},{r}l-{right},0-{gap},{gap}-{gap}-{gap}-{left},0a{r},{r},0,0,1-{r}-{r}v-{h4}-{h4}-{h4}-{h4}a{r},{r},0,0,1,{r}-{r}z", + bottom: "M{x},{y}l{left},0,{gap}-{gap},{gap},{gap},{right},0a{r},{r},0,0,1,{r},{r}v{h4},{h4},{h4},{h4}a{r},{r},0,0,1,-{r},{r}h-{w4}-{w4}-{w4}-{w4}a{r},{r},0,0,1-{r}-{r}v-{h4}-{h4}-{h4}-{h4}a{r},{r},0,0,1,{r}-{r}z", + right: "M{x},{y}h{w4},{w4},{w4},{w4}a{r},{r},0,0,1,{r},{r}v{h4},{h4},{h4},{h4}a{r},{r},0,0,1,-{r},{r}h-{w4}-{w4}-{w4}-{w4}a{r},{r},0,0,1-{r}-{r}l0-{bottom}-{gap}-{gap},{gap}-{gap},0-{top}a{r},{r},0,0,1,{r}-{r}z", + left: "M{x},{y}h{w4},{w4},{w4},{w4}a{r},{r},0,0,1,{r},{r}l0,{top},{gap},{gap}-{gap},{gap},0,{bottom}a{r},{r},0,0,1,-{r},{r}h-{w4}-{w4}-{w4}-{w4}a{r},{r},0,0,1-{r}-{r}v-{h4}-{h4}-{h4}-{h4}a{r},{r},0,0,1,{r}-{r}z" + }, + offset = { + hx0: X - (x + r + w - gap * 2), + hx1: X - (x + r + w / 2 - gap), + hx2: X - (x + r + gap), + vhy: Y - (y + r + h + r + gap), + "^hy": Y - (y - gap) + + }, + mask = [{ + x: x + r, + y: y, + w: w, + w4: w / 4, + h4: h / 4, + right: 0, + left: w - gap * 2, + bottom: 0, + top: h - gap * 2, + r: r, + h: h, + gap: gap + }, { + x: x + r, + y: y, + w: w, + w4: w / 4, + h4: h / 4, + left: w / 2 - gap, + right: w / 2 - gap, + top: h / 2 - gap, + bottom: h / 2 - gap, + r: r, + h: h, + gap: gap + }, { + x: x + r, + y: y, + w: w, + w4: w / 4, + h4: h / 4, + left: 0, + right: w - gap * 2, + top: 0, + bottom: h - gap * 2, + r: r, + h: h, + gap: gap + }][pos[1] == "middle" ? 1 : (pos[1] == "top" || pos[1] == "left") * 2]; + var dx = 0, + dy = 0, + out = this.path(fill(shapes[pos[0]], mask)).insertBefore(set); + switch (pos[0]) { + case "top": + dx = X - (x + r + mask.left + gap); + dy = Y - (y + r + h + r + gap); + break; + case "bottom": + dx = X - (x + r + mask.left + gap); + dy = Y - (y - gap); + break; + case "left": + dx = X - (x + r + w + r + gap); + dy = Y - (y + r + mask.top + gap); + break; + case "right": + dx = X - (x - gap); + dy = Y - (y + r + mask.top + gap); + break; + } + out.translate(dx, dy); + if (ret) { + ret = out.attr("path"); + out.remove(); + return { + path: ret, + dx: dx, + dy: dy + }; + } + set.translate(dx, dy); + return out; + }; +})();
\ No newline at end of file |
