Calendar View
Colors by Cynthia Brewer. Layout inspired by Rick Wicklin and Robert Allison. Dow Jones historical data copyright Yahoo! Finance or independent data provider; fair use for educational purposes.
Source Code
1 var w = 960,
2 pw = 14,
3 z = ~~((w - pw * 2) / 53),
4 ph = z >> 1,//padding height
5 h = z * 7,
6 type = Raphael.svg ? "svg" : "xml";
7
8 //From: http://www.hunlock.com/blogs/Totally_Pwn_CSS_with_Javascript#quickIDX1
9 function getCSSRule(ruleName, deleteFlag) { // Return requested style obejct
10 if (document.styleSheets) { // If browser can play with stylesheets
11 for (var i=0; i<document.styleSheets.length; i++) { // For each stylesheet
12 var styleSheet=document.styleSheets[i]; // Get the current Stylesheet
13 var ii=0; // Initialize subCounter.
14 var cssRule=false; // Initialize cssRule.
15 do { // For each rule in stylesheet
16 if (styleSheet.cssRules) { // Browser uses cssRules?
17 cssRule = styleSheet.cssRules[ii]; // Yes --Mozilla Style
18 } else { // Browser usses rules?
19 cssRule = styleSheet.rules[ii]; // Yes IE style.
20 } // End IE check.
21 if (cssRule) { // If we found a rule...
22 if (cssRule.selectorText==ruleName) { // match ruleName?
23 if (deleteFlag=='delete') { // Yes. Are we deleteing?
24 if (styleSheet.cssRules) { // Yes, deleting...
25 styleSheet.deleteRule(ii); // Delete rule, Moz Style
26 } else { // Still deleting.
27 styleSheet.removeRule(ii); // Delete rule IE style.
28 } // End IE check.
29 return true; // return true, class deleted.
30 } else { // found and not deleting.
31 return cssRule; // return the style object.
32 } // End delete Check
33 } // End found rule name
34 } // end found cssRule
35 ii++; // Increment sub-counter
36 } while (cssRule) // end While loop
37 } // end For loop
38 } // end styleSheet ability check
39 return false; // we found NOTHING!
40 } // end getCSSRule
41
42 Raphael.st.addClass = function(addClass, parentSelector) {
43 //Simple set Attribute class if SVG
44 if (Raphael.svg) {
45 for (var i = 0; i < this.length; i++) {
46 this[i].addClass(addClass)
47 };
48 }
49 //For IE
50 else {
51 var sel = '.' + addClass;
52 sel = parentSelector ? parentSelector + ' ' + sel : sel;
53 var attributes = getCSSAttributes(sel);
54 for (var i = 0; i < this.length; i++) {
55 this[i].attr(attributes);
56 }
57 }
58 }
59
60 Raphael.el.addClass = function(addClass, parentSelector) {
61 //easily add class
62 if (Raphael.svg) {
63 var cssClass = this.node.getAttribute('class') !== null ? this.node.getAttribute('class') + ' ' + addClass : addClass;
64 this.node.setAttribute('class', cssClass);
65 }
66 //must extract CSS requirements
67 else {
68 var sel = '.' + addClass;
69 sel = parentSelector ? parentSelector + ' ' + sel : sel;
70
71 var attributes = getCSSAttributes(sel);
72 this.attr(attributes);
73 }
74 }
75
76 function getCSSAttributes(selector) {
77 var rules = getCSSRule(selector),
78 attributes = {};
79 if (!rules) return false;
80 rules = rules.style.cssText.split(';');
81 for (var i = 0; i < rules.length; i++) {
82 var rule = rules[i].split(':');
83 if (rule[0] !== undefined && rule[1] !== undefined)
84 var key = rule[0].replace(' ',''),
85 value = rule[1].replace(' ','');
86 attributes[key] = value;
87 }
88 return attributes;
89 }
90
91
92 var papers = [],
93 boxes = [],
94 paper_i = -1,
95 year_range = d3.range(1990, 1991);
96 var test;
97 vis = d3.select("#chart")
98 .selectAll(type)
99 .data(year_range)
100 .enter().select(function(data ,i) {
101 var paper = Raphael(this, w, h + ph *2);
102 papers.push(paper);
103 //accessible paper array for later
104
105 return paper.canvas;
106 });
107
108 vis.select(function(data, i){
109 var text = papers[i].text(6, (h/2+ph), data)
110 .attr('text-anchor', 'middle')
111 .rotate(-90);
112 return text.node;
113 });
114
115
116 d3.csv("dji.csv", function(csv) {
117 var data = d3.nest()
118 .key(function(d) { return d.Date; })
119 .rollup(function(d) { return (d[0].Close - d[0].Open) / d[0].Open; })
120 .map(csv);
121
122 var color = d3.scale.quantize()
123 .domain([-.05, .05])
124 .range(d3.range(9));
125
126 //Days Rectangles
127 vis.selectAll(Raphael.svg ? 'rect' : 'v:rect')
128 .data(calendar.dates)
129 .enter().select(function(d, i) {
130 var rect;
131 //setup for each year: Raphael sets
132 if (i === 0) {
133 paper_i++;
134 boxes.push(papers[paper_i].set());
135 if(paper_i > 0) boxes[paper_i-1].addClass('day');
136 }
137 rect = papers[paper_i]
138 .rect(d.week * z + pw, d.day * z, z, z);
139
140 rect.addClass("q" + color(data[d.Date]) + "-9", '.RdYlGn');
141 boxes[paper_i].push(rect);
142
143 return rect.node;
144 });//end data, last one
145 boxes[paper_i].addClass('day');
146 paper_i = -1;
147
148
149 //Months Path
150 var months = [];
151 vis.selectAll(Raphael.svg ? 'path' : 'v:path')
152 .data(calendar.months)
153 .enter().select(function(d, i) {
154 var path;
155 //set paper & add month class to sets
156 if (i === 0) {
157 paper_i++;
158 months.push(papers[paper_i].set());
159 if(paper_i > 0) months[paper_i].addClass('month');
160 }
161
162 //draw month path
163 path = papers[paper_i].path(
164 "M" + (d.firstWeek + 1) * z + "," + d.firstDay * z
165 + "H" + d.firstWeek * z
166 + "V" + 7 * z
167 + "H" + d.lastWeek * z
168 + "V" + (d.lastDay + 1) * z
169 + "H" + (d.lastWeek + 1) * z
170 + "V" + 0
171 + "H" + (d.firstWeek + 1) * z
172 + "Z"
173 ).translate(pw,0);
174 months[paper_i].push(path);
175
176 return path.node;
177 });//end data, last month set
178 months[paper_i].addClass('month');
179 paper_i = -1;
180 //--- END MONTH ---
181 });
182
183 //Final Safari forced-rendering
184 for (var i = 0; i < papers.length; i++) {
185 papers[i].safari();
186 }