summaryrefslogtreecommitdiff
path: root/test/analytics
diff options
context:
space:
mode:
Diffstat (limited to 'test/analytics')
-rw-r--r--test/analytics/analytics.html96
-rw-r--r--test/analytics/analytics.js141
-rw-r--r--test/analytics/demo-print.css20
-rw-r--r--test/analytics/demo.css23
-rw-r--r--test/analytics/popup.js121
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