summaryrefslogtreecommitdiff
path: root/test/when/when.js
diff options
context:
space:
mode:
Diffstat (limited to 'test/when/when.js')
-rw-r--r--test/when/when.js187
1 files changed, 187 insertions, 0 deletions
diff --git a/test/when/when.js b/test/when/when.js
new file mode 100644
index 0000000..4e0e6be
--- /dev/null
+++ b/test/when/when.js
@@ -0,0 +1,187 @@
+/*
+Tim Redfern Jan 2012 tim@eclectronics.org
+
+Animated graphing - Edmund Rice School Ties
+
+see analytics.js example
+
+http://net.tutsplus.com/tutorials/javascript-ajax/an-introduction-to-the-raphael-js-library/
+
+aim for today: have a few items that can be chosen
+
+1) switch items - multiple lines view .. x amount of lines + 'other'
+2) animate between views
+3) rollover points
+4) label axes
+*/
+
+var data,raphael,classOfRange,birthplaces,colleges,locations,fields;
+
+var graphData;
+
+var maxPaths;
+
+window.onload = function() {
+ loadData();
+ createMenu();
+ //alert(document.getElementById("holder").offsetWidth+","+document.getElementById("holder").offsetHeight);
+ //seems predictable, gives same result in chrome, firefox, mobile safari
+ var graph=document.getElementById('graph');
+ raphael = new Raphael(graph, graph.offsetWidth, graph.offsetHeight);
+ drawGraph();
+}
+
+function graphableData(name) {
+ //organises a range of data to graph against a variable value
+ this.name=name;
+ this.data={};
+ this.max=0;
+ this.addElement = function(element,value) {
+ if (element in this.data) {
+ if (value in this.data[element]) this.data[element][value]++;
+ else this.data[element][value]=1;
+ }
+ else {
+ this.data[element]={};
+ this.data[element][value]=1
+ }
+ if (this.data[element][value]>this.max) this.max=this.data[element][value];
+ }
+ this.getElement = function(element) {
+ if (element in this.data) return data[element]; //returns an associative array
+ }
+ this.summary = function() {
+ var s= ""+name+": "+Object.keys(this.data).length+" elements, max "+this.max+"\n";
+ var k=Object.keys(this.data);
+ //s+=k+":";
+ for (i in k) {
+ s+=k[i]+":";
+ var l=Object.keys(this.data[k[i]]);
+ for (j in l) s+=l[j]+"="+this.data[k[i]][l[j]]+",";
+ s+="\n";
+ }
+ return s+"\n";
+ }
+
+}
+
+function loadData() {
+ maxPaths=8;
+ //replace with json loader
+ fields=["Class size","Location","Birthplace","College","Career"];
+ fieldNames=["classSize","location","birthplace","college","career"];
+ //basic { name:"Joe", surname:"Murphy",school:"Dublin",classOf:"86",location:"Ireland",email:"joem20156@gmail.com"},
+ //extended { name:"Joe", surname:"Murphy",school:"Dublin",classOf:"86",location:"Ireland",email:"joem20156@gmail.com",birthplace:"Ireland",college:"UCD",career:"construction",sports:["soccer","hurling"],nickname:"Virgil"},
+ data = [
+ { school:"Dublin",classOf:"86",location:"Ireland",birthplace:"Ireland",college:"UCD",career:"construction",sports:["soccer","hurling"],nickname:"Virgil"},
+ { school:"Dublin",classOf:"87",location:"Ireland",birthplace:"Ireland",college:"NUIG",career:"law",sports:["soccer","gaelic"],nickname:"Con"},
+ { school:"Dublin",classOf:"86",location:"Ireland",birthplace:"Ireland",college:"TCD",career:"teaching",sports:["gaelic","hurling"],nickname:"Morty"},
+ { school:"Dublin",classOf:"88",location:"USA",birthplace:"UK",college:"UL",career:"army",sports:["soccer"],nickname:"Mick"},
+ { school:"Dublin",classOf:"87",location:"Ireland",birthplace:"Ireland",college:"UCD",career:"law",sports:["soccer","gaelic"],nickname:"Johnjoe"},
+ { school:"Dublin",classOf:"86",location:"UK",birthplace:"Ireland",college:"TCD",career:"teaching",sports:["handball","hurling"],nickname:"Mossy"},
+ { school:"Dublin",classOf:"89",location:"USA",birthplace:"UK",college:"UL",career:"army",sports:["soccer"],nickname:"Mick"},
+ { school:"Dublin",classOf:"90",location:"Ireland",birthplace:"Ireland",college:"UCD",career:"law",sports:["soccer","gaelic"],nickname:"Johnjoe"},
+ { school:"Dublin",classOf:"88",location:"Ireland",birthplace:"Ireland",college:"UCC",career:"teaching",sports:["handball","hurling"],nickname:"Mossy"},
+ ];
+ //analyse data to populate menus etc, this may be loaded direct from corresponding server data
+ classOfRange={};
+ classOfRange.start=3000;
+ classOfRange.end=0;
+ birthplaces={};
+ colleges={};
+ locations={};
+ for (var i in data) {
+ var year = parseInt(data[i].classOf);
+ classOfRange.start=Math.min(classOfRange.start,year);
+ classOfRange.end=Math.max(classOfRange.end,year);
+ if (data[i].birthplace in birthplaces) birthplaces[data[i].birthplace]++;
+ else birthplaces[data[i].birthplace]=1;
+ if (data[i].college in colleges) colleges[data[i].college]++;
+ else colleges[data[i].college]=1;
+ if (data[i].location in locations) locations[data[i].location]++;
+ else locations[data[i].location]=1;
+ }
+
+ var numYears=(classOfRange.end-classOfRange.start);
+
+ //prepare all data for graphing
+ graphData={};
+ for (i in fields) graphData[fields[i]]=new graphableData(fields[i]);
+ for (var i in data) {
+ var yearField
+ for (j in fields) {
+ if (fields[j]=="Class size") {
+ graphData[fields[j]].addElement("Class size",parseInt(data[i].classOf));
+ }
+ else graphData[fields[j]].addElement(data[i][fieldNames[j]],parseInt(data[i].classOf));
+ }
+ }
+
+ ///* test
+ var message="from "+classOfRange.start+" to "+classOfRange.end+"\n";
+ for (var i in graphData) message+=graphData[i].summary();
+ alert(message);
+ //*/
+}
+
+function drawGraph() {
+ var color = "hsl(" + [.6, .5, .5] + ")";
+ var numYears=(classOfRange.end-classOfRange.start);
+ var gutterX=10,
+ gutterY=16;
+ //draw grid
+ var gridX=(raphael.width-(gutterX*2))/numYears;
+ var gridY=(raphael.height-(gutterY*2));
+ raphael.drawGrid(gutterX, gutterY, raphael.width-(gutterX*2), raphael.height -(gutterY*2), numYears, 10, "#000");
+ //label axis
+ var txt = {font: '12px Helvetica, Arial', fill: "#fff"};
+ for (var i=0;i<=numYears;i++) raphael.text(gutterX+(i*gridX),raphael.height-gutterY+8,classOfRange.start+i).attr(txt).toBack();
+ //construct graph
+ var graph = raphael.path().attr({stroke: color, "stroke-width": 4, "stroke-linejoin": "round"}),
+ bgGraph = raphael.path().attr({stroke: "none", opacity: .3, fill: color});
+ //default graph is 'Class size'
+ //find largest class
+ var classSize=[];
+ for (var i=0;i<=numYears;i++) classSize[i]=0;
+ for (var i in data) {
+ classSize[parseInt(data[i].classOf)-classOfRange.start]++;
+ }
+ var classMax=0;
+ for (var i in classSize) classMax=Math.max(classMax,classSize[i]);
+ var path,bgPath;
+ var stepY=(gridY/classMax);
+ for (var i=0;i<=numYears;i++) {
+ var x=gutterX+(i*gridX),
+ y=raphael.height-gutterY-(stepY*classSize[i]);
+ if (!i) {
+ path=["M",x,y,"C",x,y];
+ bgPath=["M", gutterX , raphael.height - gutterY, "L", x, y, "C", x, y];
+ }
+ if (i&&i<numYears-1) {
+ var Y0 = Math.round(raphael.height - gutterY - (stepY*classSize[i-1])),
+ X0 = Math.round(gutterX + (gridX * (i - .5))),
+ Y2 = Math.round(raphael.height - gutterY - (stepY*classSize[i+1])),
+ X2 = Math.round(gutterX + (gridX * (i + 1.5)));
+ var a = getAnchors(X0, Y0, x, y, X2, Y2);
+ path = path.concat([a.x1, a.y1, x, y, a.x2, a.y2]);
+ bgPath = bgPath.concat([a.x1, a.y1, x, y, a.x2, a.y2]);
+ }
+ }
+ path = path.concat([x, y, x, y]);
+ bgPath = bgPath.concat([x, y, x, y, "L", x, raphael.height - gutterY, "z"]);
+ graph.attr({path: path});
+ bgGraph.attr({path: bgPath});
+}
+
+function createMenu() {
+ var menu="<select id='select' onchange='doGraph(this.selectedIndex)'>\n";
+ for (i in fields) menu+="<option>"+fields[i]+"</option>/n";
+ menu+="</select>\n";
+ document.getElementById("menus").innerHTML=menu;
+}
+
+function doGraph(which){
+ //draw 1 or multiple graphs. animate between items
+ //maximum number of graphs
+ alert(fields[which]);
+}