move allmost everything into data object
[MojoFacets.git] / public / facet_graph.js
1 var data = {
2         x: {
3                 min: Number.MAX_VALUE,
4                 max: Number.MIN_VALUE,
5                 range: 0,
6                 inc: 0,
7                 data: [],
8                 px: [],
9         },
10         y: {
11                 min: Number.MAX_VALUE,
12                 max: Number.MIN_VALUE,
13                 range: 0,
14                 data: [],
15                 inc: 0,
16                 num_labels: 0,
17                 labels: [],
18         },
19         width: 600,
20         height: 400,
21 };
22
23 var ul = $('ul#facet');
24
25 ul.find('li label').each( function(){
26         var v = parseFloat( $(this).text() );
27         if ( isNaN(v) ) v = 0;
28         if ( v > data.x.max ) data.x.max = v;
29         if ( v < data.x.min ) data.x.min = v;
30         data.x.data.push( v );
31 });
32
33 ul.find('li span.count').each( function(){
34         var v = parseFloat( $(this).text() ); // FIXME not numeric!
35         if ( isNaN(v) ) v = 0;
36         if ( v > data.y.max ) data.y.max = v;
37         if ( v < data.y.min ) data.y.min = v;
38         data.y.data.push( v );
39 });
40
41 data.y.min = 0; // XXX force to 0, because it's count
42
43 data.x.range = data.x.max - data.x.min;
44 data.y.range = data.y.max - data.y.min;
45
46
47 var y_num_labels = Math.round( data.height / 20 ); // padding between vertical labels
48 data.y.inc = Math.ceil( data.y.range / y_num_labels );
49
50 var y_last_pos = Math.ceil( data.y.max - data.y.inc / 2 );
51 for( var y_pos = data.y.min; y_pos < y_last_pos; y_pos += data.y.inc ) {
52         data.y.labels.push( y_pos );
53 }
54 data.y.labels.push( data.y.max );
55
56 data.numeric = $('span#numeric').length;
57 data.x.inc = data.numeric
58         ? Math.round( data.width / data.x.range )
59         : data.width / data.x.data.length
60         ;
61
62 console.debug( 'data', data );
63
64 var canvas = $('<canvas/>');
65
66 canvas.attr({
67         width: data.width,
68         height: data.height,
69 });
70
71 var canvasContain = $('<div class="chart"></div>')
72         .css({ width: data.width, height: data.height })
73         .append( canvas )
74         .insertBefore( ul );
75
76 var ctx = canvas[0].getContext('2d');
77 ctx.translate( 0, data.height ); // start at bottom left
78 ctx.lineWidth = 2;
79 ctx.strokeStyle = '#ff8800';
80 ctx.fillStyle = '#ffcc88';
81
82 ctx.moveTo( 0, 0 );
83 ctx.beginPath();
84
85 for( var i in data.x.data ) {
86         var x = data.x.data[i];
87         if ( data.numeric ) x = Math.ceil( ( x - data.x.min ) / data.x.range * data.width  );
88         var y = Math.ceil( ( data.y.data[i] - data.y.min ) / data.y.range * data.height );
89         if ( data.numeric ) {
90                 ctx.lineTo( x, -y );
91                 data.x.px.push( x );
92         } else {
93                 var x_px = i * data.x.inc;
94                 console.debug( x_px, y );
95                 ctx.fillRect( x_px, 0, data.x.inc, -y );
96                 ctx.strokeRect( x_px, 0, data.x.inc, -y );
97         }
98 }
99
100 ctx.stroke();
101 ctx.closePath();
102
103 if ( data.numeric ) {
104
105 var labels_x = $('<ul class="labels-x"></ul>')
106         .css({ width: data.width, height: data.height, position: 'absolute' });
107
108 for( var x_pos = 0; x_pos < data.width; x_pos += data.x.inc ) {
109         var x_val = ( x_pos / data.width * data.x.range ) + data.x.min;
110         $('<li><span class="label">' + x_val + '</span></li>')
111                 .css({ left: x_pos })
112                 .appendTo(labels_x);
113 }
114
115 $('<li><span class="label">' + data.x.max + '</span></li>')
116                 .css({ right: 0 })
117                 .appendTo(labels_x);
118
119 labels_x.appendTo(canvasContain);
120
121 } // data.numeric
122
123 var labels_y = $('<ul class="labels-y"></ul>')
124         .css({ width: data.width, height: data.height, position: 'absolute' });
125
126 for( var i in data.y.labels ) {
127                 $('<li><span class="line"></span><span class="label">' + data.y.labels[i] + '</span></li>')
128                         .css({ bottom: Math.ceil( ( data.y.labels[i] - data.y.min ) / data.y.range * data.height ) })
129                         .appendTo(labels_y);
130 }
131 labels_y.appendTo(canvasContain);