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 }
Copyright © 2011 Mike Bostock
Fork me on GitHub