-
-
Save albersmc/7420524 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type | date | Line 1 | Line 2 | Line 3 | Line 4 | |
---|---|---|---|---|---|---|
val1 | 1/1/00 | 11.361 | 40.863 | 106.118 | 33.896 | |
val1 | 1/1/01 | 9.552 | 39.713 | 123.521 | 32.408 | |
val1 | 1/1/02 | 8.576 | 38.091 | 137.61 | 33.204 | |
val1 | 1/1/03 | 7.549 | 35.853 | 140.896 | 34.865 | |
val1 | 1/1/04 | 6.716 | 32.109 | 156.805 | 36.044 | |
val1 | 1/1/05 | 6.312 | 30.235 | 164.498 | 36.149 | |
val1 | 1/1/06 | 5.76 | 27.934 | 161.806 | 36.039 | |
val1 | 1/1/07 | 5.181 | 25.183 | 164.546 | 35.703 | |
val1 | 1/1/08 | 4.922 | 28.642 | 180.783 | 40.183 | |
val1 | 1/1/09 | 8.195 | 35.716 | 183.53 | 53.573 | |
val1 | 1/1/10 | 10.966 | 36.073 | 183.53 | 61.274 | |
val2 | 5/1/08 | 73.17096 | 73.8 | 70.86987 | 71.22524 | |
val2 | 6/1/08 | 73.40022 | 73.6 | 70.85164 | 71.10571 | |
val2 | 7/1/08 | 73.18956 | 73.5 | 70.68008 | 70.892 | |
val2 | 8/1/08 | 73.27032 | 73.5 | 70.78835 | 70.70468 | |
val2 | 9/1/08 | 73.1027 | 73.6 | 70.80603 | 70.50166 | |
val2 | 10/1/08 | 73.19533 | 73.5 | 70.84274 | 70.36867 | |
val2 | 11/1/08 | 72.95339 | 73.3 | 70.95702 | 69.93706 | |
val2 | 12/1/08 | 72.81297 | 73 | 70.65752 | 69.56481 | |
val2 | 1/1/09 | 72.46693 | 72.5 | 70.73147 | 69.04002 | |
val2 | 2/1/09 | 72.51446 | 72 | 70.46809 | 68.75864 | |
val2 | 3/1/09 | 72.12102 | 71.8 | 70.0565 | 68.25459 | |
val2 | 4/1/09 | 72.31942 | 71.7 | 70.01981 | 68.15527 | |
val2 | 5/1/09 | 72.07051 | 71.5 | 69.86392 | 67.79279 | |
val2 | 6/1/09 | 71.83347 | 71.2 | 69.81618 | 67.80988 | |
val2 | 7/1/09 | 71.84483 | 71.1 | 69.76656 | 67.67518 | |
val2 | 8/1/09 | 71.69344 | 71.1 | 70.02958 | 67.29216 | |
val2 | 9/1/09 | 71.75568 | 71.2 | 70.03351 | 66.8834 | |
val2 | 10/1/09 | 71.76352 | 71 | 69.97632 | 66.61176 | |
val2 | 11/1/09 | 71.9547 | 71.4 | 69.91604 | 66.69512 | |
val2 | 12/1/09 | 72.00006 | 71.2 | 69.9911 | 66.46241 | |
val2 | 1/1/10 | 72.16405 | 71.3 | 70.14699 | 66.76878 | |
val2 | 2/1/10 | 72.07063 | 71.4 | 70.10736 | 66.74509 | |
val2 | 3/1/10 | 72.01749 | 71.3 | 70.07778 | 66.75923 | |
val2 | 4/1/10 | 72.11574 | 71.6 | 69.92162 | 66.86999 | |
val2 | 5/1/10 | 71.99252 | 71.6 | 69.92286 | 66.76907 | |
val2 | 6/1/10 | 72.27586 | 71.7 | 69.87484 | 66.7173 | |
val2 | 7/1/10 | 72.30006 | 71.7 | 70.19234 | 66.6966 | |
val2 | 8/1/10 | 72.48346 | 71.7 | 70.23014 | 66.73079 | |
val2 | 9/1/10 | 72.63282 | 71.4 | 70.37191 | 66.64181 | |
val2 | 10/1/10 | 72.69502 | 71.6 | 70.26771 | 66.44191 | |
val2 | 11/1/10 | 72.846 | 71.7 | 70.16416 | 66.39793 | |
val2 | 12/1/10 | 72.98971 | 71.8 | 70.31656 | 66.51099 | |
val2 | 1/1/11 | 72.89347 | 72 | 70.43721 | 66.68821 | |
val2 | 2/1/11 | 72.83181 | 72 | 70.66043 | 66.63231 | |
val2 | 3/1/11 | 72.95651 | 71.9 | 71.00793 | 66.70368 | |
val2 | 4/1/11 | 72.77982 | 72 | 70.99963 | 66.59103 | |
val2 | 5/1/11 | 72.68517 | 72 | 71.04446 | 66.56474 | |
val2 | 6/1/11 | 72.80386 | 72 | 71.11172 | 66.41299 | |
val2 | 7/1/11 | 72.68908 | 72.1 | 70.92947 | 66.39697 | |
val2 | 8/1/11 | 72.65163 | 72.1 | 70.92245 | 66.6134 | |
val2 | 9/1/11 | 72.70605 | 72.1 | 70.47206 | 66.68613 | |
val2 | 10/1/11 | 72.60508 | 71.9 | 70.49169 | 66.63239 | |
val2 | 11/1/11 | 72.51452 | 71.8 | 70.57639 | 66.81437 | |
val2 | 12/1/11 | 72.19783 | 71.9 | 70.60051 | 66.8495 | |
val2 | 1/1/12 | 72.48839 | 71.9 | 70.27213 | 66.91769 | |
val2 | 2/1/12 | 72.2776 | 71.9 | 70.37115 | 66.99259 | |
val2 | 3/1/12 | 72.42102 | 72.1 | 70.24574 | 67.01841 | |
val2 | 4/1/12 | 72.49939 | 72.3 | 70.32284 | 66.9746 | |
val2 | 5/1/12 | 72.56266 | 72.2 | 70.3585 | 67.1202 | |
val2 | 6/1/12 | 72.3299 | 72.2 | 70.65968 | 67.11346 | |
val2 | 7/1/12 | 72.35701 | 72.1 | 70.69147 | 67.03298 | |
val2 | 8/1/12 | 72.22827 | 72.1 | 70.66949 | 66.96553 | |
val2 | 9/1/12 | 72.32135 | 72.3 | 70.65089 | 67.29552 | |
val2 | 10/1/12 | 72.25543 | 72.3 | 70.88633 | 67.43998 | |
val2 | 11/1/12 | 72.2934 | 72.5 | 70.94573 | 67.27721 | |
val2 | 12/1/12 | 72.19945 | 72.7 | 70.77234 | 67.30031 | |
val2 | 1/1/13 | 72.10005 | 72.5 | 71.13177 | 67.23456 | |
val2 | 2/1/13 | 72.40376 | 72.7 | 71.1607 | 67.27918 | |
val2 | 3/1/13 | 72.09074 | 72.4 | 71.35171 | 67.26635 | |
val3 | 5/1/08 | 107.4 | 107.1 | 101.7 | 110.9 | |
val3 | 6/1/08 | 107.7 | 107.9 | 102.2 | 112 | |
val3 | 7/1/08 | 107.6 | 108.2 | 102.4 | 112.6 | |
val3 | 8/1/08 | 107.4 | 108.1 | 102.7 | 112.2 | |
val3 | 9/1/08 | 107.7 | 108.2 | 102.7 | 112 | |
val3 | 10/1/08 | 107.6 | 107 | 102.6 | 110.9 | |
val3 | 11/1/08 | 107.3 | 106.7 | 101.7 | 108.8 | |
val3 | 12/1/08 | 107.1 | 105.9 | 101.3 | 107.6 | |
val3 | 1/1/09 | 106.6 | 105.6 | 100.7 | 108.1 | |
val3 | 2/1/09 | 107 | 106.4 | 100.4 | 108.7 | |
val3 | 3/1/09 | 107.2 | 106.6 | 100.7 | 108.9 | |
val3 | 4/1/09 | 107.4 | 106.5 | 100.8 | 109.2 | |
val3 | 5/1/09 | 107.7 | 107.2 | 100.6 | 109.5 | |
val3 | 6/1/09 | 107.6 | 107.6 | 100.4 | 110.4 | |
val3 | 7/1/09 | 107.3 | 107.2 | 100.1 | 110.3 | |
val3 | 8/1/09 | 107.7 | 107.2 | 100.4 | 110.5 | |
val3 | 9/1/09 | 107.8 | 107.2 | 100.4 | 110.6 | |
val3 | 10/1/09 | 107.8 | 107.1 | 100 | 110.7 | |
val3 | 11/1/09 | 108 | 107.7 | 99.8 | 110.8 | |
val3 | 12/1/09 | 108.2 | 107.3 | 99.6 | 110.6 | |
val3 | 1/1/10 | 107.9 | 107.6 | 99.7 | 111 | |
val3 | 2/1/10 | 108.1 | 108.1 | 99.6 | 111 | |
val3 | 3/1/10 | 109.3 | 108.1 | 99.9 | 111.4 | |
val3 | 4/1/10 | 109.6 | 108.4 | 100 | 111.6 | |
val3 | 5/1/10 | 109.7 | 108.7 | 99.9 | 111.7 | |
val3 | 6/1/10 | 109.7 | 108.6 | 99.7 | 111.6 | |
val3 | 7/1/10 | 109.3 | 109.2 | 99.1 | 111.6 | |
val3 | 8/1/10 | 109.5 | 109.1 | 99.3 | 111.8 | |
val3 | 9/1/10 | 109.8 | 109.3 | 99.5 | 111.9 | |
val3 | 10/1/10 | 110.1 | 109.7 | 99.8 | 112 | |
val3 | 11/1/10 | 110 | 109.8 | 99.5 | 112 | |
val3 | 12/1/10 | 110.7 | 109.8 | 99.2 | 112.2 | |
val3 | 1/1/11 | 110.6 | 110.1 | 99.1 | 112.8 | |
val3 | 2/1/11 | 111.4 | 110.4 | 99.1 | 113.3 | |
val3 | 3/1/11 | 112.7 | 111.6 | 99.4 | 114.4 | |
val3 | 4/1/11 | 113.2 | 112 | 99.5 | 115.2 | |
val3 | 5/1/11 | 113.3 | 112.7 | 99.5 | 115.7 | |
val3 | 6/1/11 | 113.3 | 112 | 99.3 | 115.6 | |
val3 | 7/1/11 | 113.1 | 112.2 | 99.3 | 115.7 | |
val3 | 8/1/11 | 113.3 | 112.5 | 99.5 | 116 | |
val3 | 9/1/11 | 113.8 | 112.7 | 99.5 | 116.2 | |
val3 | 10/1/11 | 113.9 | 112.9 | 99.6 | 115.9 | |
val3 | 11/1/11 | 114 | 113 | 99 | 115.8 | |
val3 | 12/1/11 | 114.2 | 112.4 | 99 | 115.6 | |
val3 | 1/1/12 | 113.7 | 112.8 | 99.2 | 116.1 | |
val3 | 2/1/12 | 114.2 | 113.3 | 99.4 | 116.6 | |
val3 | 3/1/12 | 115.4 | 113.8 | 99.9 | 117.5 | |
val3 | 4/1/12 | 115.8 | 114.2 | 100 | 117.8 | |
val3 | 5/1/12 | 115.7 | 114.1 | 99.7 | 117.7 | |
val3 | 6/1/12 | 115.8 | 113.7 | 99.2 | 117.5 | |
val3 | 7/1/12 | 115.5 | 113.6 | 98.9 | 117.3 | |
val3 | 8/1/12 | 115.8 | 113.9 | 99 | 118 | |
val3 | 9/1/12 | 116.8 | 114 | 99.2 | 118.5 | |
val3 | 10/1/12 | 117.1 | 114.2 | 99.2 | 118.4 | |
val3 | 11/1/12 | 117.2 | 114 | 98.8 | 117.9 | |
val3 | 12/1/12 | 117.4 | 113.3 | 98.9 | 117.6 | |
val3 | 1/1/13 | 116.7 | 113.4 | 98.9 | 117.9 | |
val3 | 2/1/13 | 117.1 | 114.7 | 98.8 | 118.9 | |
val3 | 3/1/13 | 118 | 114.9 | 99 | 119.2 | |
val4 | 4/1/08 | 0.322530177 | 0.487575577 | -1.211608 | 0.329393674 | |
val4 | 7/1/08 | 0.719161238 | 0.687349003 | -1.048973498 | -0.928590211 | |
val4 | 10/1/08 | -0.714621757 | -1.10731091 | -3.248118907 | -2.300768187 | |
val4 | 1/1/09 | 0.948890662 | -2.241384557 | -4.001615871 | -1.338921877 | |
val4 | 4/1/09 | 0.005347498 | -0.916059149 | 1.681314514 | -0.078672016 | |
val4 | 7/1/09 | 0.712367508 | 0.413730539 | 0.027603546 | 0.359814188 | |
val4 | 10/1/09 | 0.817646052 | 1.130675622 | 1.837807076 | 0.991629206 | |
val4 | 1/1/10 | 0.544772582 | 1.197893872 | 1.45349234 | 0.578726181 | |
val4 | 4/1/10 | 0.701573667 | 0.811817143 | 1.003532803 | 0.556087615 | |
val4 | 7/1/10 | 0.680793026 | 0.458490123 | 1.354243021 | 0.644413039 | |
val4 | 10/1/10 | 0.836913751 | 1.084675368 | -0.364925908 | 0.592971344 | |
val4 | 1/1/11 | -0.447146488 | 0.613821371 | -1.804990147 | 0.019725063 | |
val4 | 4/1/11 | 1.312298438 | -0.20943943 | -0.855743258 | 0.613631882 | |
val4 | 7/1/11 | 1.183831041 | 1.423050254 | 2.542266842 | 0.318137613 | |
val4 | 10/1/11 | 0.587360864 | 0.53251806 | 0.100300377 | 1.00774786 | |
val4 | 1/1/12 | 1.218325343 | 0.286423072 | 1.50181406 | 0.48657094 | |
val4 | 4/1/12 | 0.646755403 | 0.474190407 | -0.224074176 | 0.311704081 | |
val4 | 7/1/12 | 0.649948015 | 0.18293058 | -0.928727296 | 0.767612651 | |
val4 | 10/1/12 | 0.595724198 | 0.152856134 | 0.038731645 | 0.094488189 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<body> | |
<link href="stylesheet.css" rel="stylesheet" type="text/css"> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js" charset="utf-8"></script> | |
<script type="text/javascript" src="jquery.tipsy.js"></script> | |
<div id="container"> | |
<p id="headline" class="hed">Headline</p> | |
<p class="dek">dek</p> | |
<p class="dek">dek </p> | |
</div> | |
<p id="menu" class="menuchoice">Select series: <select> | |
<option value="val1">Value 1</option> | |
<option value="val2">Value 2</option> | |
<option value="val3">Value 3</option> | |
<option value="val4">Value 4</option> | |
</select> | |
<div id="graphic"> </div> | |
<script> | |
//set the margins | |
var margin = {top: 50, right: 160, bottom: 80, left: 50}, | |
width = 900 - margin.left - margin.right, | |
height = 500 - margin.top - margin.bottom; | |
//set dek and head to be as wide as SVG | |
d3.select('#dek') | |
.style('width', width+'px'); | |
d3.select('#headline') | |
.style('width',width+'px'); | |
//write out your source text here | |
var sourcetext= "Source: XXXXX"; | |
// set the type of number here, n is a number with a comma, .2% will get you a percent, .2f will get you 2 decimal points | |
var NumbType = d3.format(".2f"); | |
// color array | |
var bluescale4 = ["#8BA9D0", "#6A90C1", "#066CA9", "#004B8C"]; | |
//color function pulls from array of colors stored in color.js | |
var color = d3.scale.ordinal().range(bluescale4); | |
//define the approx. number of x scale ticks | |
var xscaleticks = 5; | |
//defines a function to be used to append the title to the tooltip. you can set how you want it to display here. | |
var maketip = function (d) { | |
var tip = '<p class="tip3">' + d.name + '<p class="tip1">' + NumbType(d.value) + '</p> <p class="tip3">'+ formatDate(d.date)+'</p>'; | |
return tip;} | |
//define your year format here, first for the x scale, then if the date is displayed in tooltips | |
var parseDate = d3.time.format("%m/%d/%y").parse; | |
var formatDate = d3.time.format("%b %d, '%y"); | |
//create an SVG | |
var svg = d3.select("#graphic").append("svg") | |
.attr("width", width + margin.left + margin.right) | |
.attr("height", height + margin.top + margin.bottom) | |
.append("g") | |
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
//make a rectangle so there is something to click on | |
svg.append("svg:rect") | |
.attr("width", width) | |
.attr("height", height) | |
.attr("class", "plot"); | |
//make a clip path for the graph | |
var clip = svg.append("svg:clipPath") | |
.attr("id", "clip") | |
.append("svg:rect") | |
.attr("x", 0) | |
.attr("y", 0) | |
.attr("width", width) | |
.attr("height", height); | |
// force data to update when menu is changed | |
var menu = d3.select("#menu select") | |
.on("change", change); | |
//suck in the data, store it in a value called formatted, run the redraw function | |
d3.csv("data.csv", function(data) { | |
formatted = data; | |
redraw(); | |
}); | |
d3.select(window) | |
.on("keydown", function() { altKey = d3.event.altKey; }) | |
.on("keyup", function() { altKey = false; }); | |
var altKey; | |
// set terms of transition that will take place | |
// when a new economic indicator is chosen | |
function change() { | |
d3.transition() | |
.duration(altKey ? 7500 : 1500) | |
.each(redraw); | |
} | |
// all the meat goes in the redraw function | |
function redraw() { | |
// create data nests based on economic indicator (series) | |
var nested = d3.nest() | |
.key(function(d) { return d.type; }) | |
.map(formatted) | |
// get value from menu selection | |
// the option values are set in HTML and correspond | |
//to the [type] value we used to nest the data | |
var series = menu.property("value"); | |
// only retrieve data from the selected series, using the nest we just created | |
var data = nested[series]; | |
// for object constancy we will need to set "keys", one for each type of data (column name) exclude all others. | |
color.domain(d3.keys(data[0]).filter(function(key) { return (key !== "date" && key !== "type"); })); | |
var linedata = color.domain().map(function(name) { | |
return {name: name, | |
values: data.map(function(d) { | |
return {name:name, date: parseDate(d.date), value: parseFloat(d[name],10)}; | |
}) | |
}; | |
}); | |
//make an empty variable to stash the last values into so i can sort the legend | |
var lastvalues=[]; | |
//setup the x and y scales | |
var x = d3.time.scale() | |
.domain([ | |
d3.min(linedata, function(c) { return d3.min(c.values, function(v) { return v.date; }); }), | |
d3.max(linedata, function(c) { return d3.max(c.values, function(v) { return v.date; }); }) | |
]) | |
.range([0, width]); | |
var y = d3.scale.linear() | |
.domain([ | |
d3.min(linedata, function(c) { return d3.min(c.values, function(v) { return v.value; }); }), | |
d3.max(linedata, function(c) { return d3.max(c.values, function(v) { return v.value; }); }) | |
]) | |
.range([height, 0]); | |
//will draw the line | |
var line = d3.svg.line() | |
.x(function(d) { return x(d.date); }) | |
.y(function(d) { return y(d.value); }); | |
//define the zoom | |
var zoom = d3.behavior.zoom() | |
.x(x) | |
.y(y) | |
.scaleExtent([1,8]) | |
.on("zoom", zoomed); | |
//call the zoom on the SVG | |
svg.call(zoom); | |
//create and draw the x axis | |
var xAxis = d3.svg.axis() | |
.scale(x) | |
.orient("bottom") | |
.tickPadding(8) | |
.ticks(xscaleticks); | |
svg.append("svg:g") | |
.attr("class", "x axis"); | |
//create and draw the y axis | |
var yAxis = d3.svg.axis() | |
.scale(y) | |
.orient("left") | |
.tickSize(0-width) | |
.tickPadding(8); | |
svg.append("svg:g") | |
.attr("class", "y axis"); | |
//bind the data | |
var thegraph = svg.selectAll(".thegraph") | |
.data(linedata) | |
//append a g tag for each line and set of tooltip circles and give it a unique ID based on the column name of the data | |
var thegraphEnter=thegraph.enter().append("g") | |
.attr("clip-path", "url(#clip)") | |
.attr("class", "thegraph") | |
.attr('id',function(d){ return d.name+"-line"; }) | |
.style("stroke-width",2.5) | |
.on("mouseover", function (d) { | |
d3.select(this) //on mouseover of each line, give it a nice thick stroke | |
.style("stroke-width",'6px'); | |
var selectthegraphs = $('.thegraph').not(this); //select all the rest of the lines, except the one you are hovering on and drop their opacity | |
d3.selectAll(selectthegraphs) | |
.style("opacity",0.2); | |
var getname = document.getElementById(d.name); //use get element cause the ID names have spaces in them | |
var selectlegend = $('.legend').not(getname); //grab all the legend items that match the line you are on, except the one you are hovering on | |
d3.selectAll(selectlegend) // drop opacity on other legend names | |
.style("opacity",.2); | |
d3.select(getname) | |
.attr("class", "legend-select"); //change the class on the legend name that corresponds to hovered line to be bolder | |
}) | |
.on("mouseout", function(d) { //undo everything on the mouseout | |
d3.select(this) | |
.style("stroke-width",'2.5px'); | |
var selectthegraphs = $('.thegraph').not(this); | |
d3.selectAll(selectthegraphs) | |
.style("opacity",1); | |
var getname = document.getElementById(d.name); | |
var getname2= $('.legend[fakeclass="fakelegend"]') | |
var selectlegend = $('.legend').not(getname2).not(getname); | |
d3.selectAll(selectlegend) | |
.style("opacity",1); | |
d3.select(getname) | |
.attr("class", "legend"); | |
}); | |
//actually append the line to the graph | |
thegraphEnter.append("path") | |
.attr("class", "line") | |
.style("stroke", function(d) { return color(d.name); }) | |
.attr("d", function(d) { return line(d.values[0]); }) | |
.transition() | |
.duration(2000) | |
.attrTween('d',function (d){ | |
var interpolate = d3.scale.quantile() | |
.domain([0,1]) | |
.range(d3.range(1, d.values.length+1)); | |
return function(t){ | |
return line(d.values.slice(0, interpolate(t))); | |
}; | |
}); | |
//then append some 'nearly' invisible circles at each data point | |
thegraph.selectAll("circle") | |
.data( function(d) {return(d.values);} ) | |
.enter() | |
.append("circle") | |
.attr("class","tipcircle") | |
.attr("cx", function(d,i){return x(d.date)}) | |
.attr("cy",function(d,i){return y(d.value)}) | |
.attr("r",12) | |
.style('opacity', 1e-6)//1e-6 | |
.attr ("title", maketip); | |
//append the legend | |
var legend = svg.selectAll('.legend') | |
.data(linedata); | |
var legendEnter=legend | |
.enter() | |
.append('g') | |
.attr('class', 'legend') | |
.attr('id',function(d){ return d.name; }) | |
.on('click', function (d) { //onclick function to toggle off the lines | |
if($(this).css("opacity") == 1){ //uses the opacity of the item clicked on to determine whether to turn the line on or off | |
var elemented = document.getElementById(this.id +"-line"); //grab the line that has the same ID as this point along w/ "-line" use get element cause ID has spaces | |
d3.select(elemented) | |
.transition() | |
.duration(1000) | |
.style("opacity",0) | |
.style("display",'none'); | |
d3.select(this) | |
.attr('fakeclass', 'fakelegend') | |
.transition() | |
.duration(1000) | |
.style ("opacity", .2); | |
} else { | |
var elemented = document.getElementById(this.id +"-line"); | |
d3.select(elemented) | |
.style("display", "block") | |
.transition() | |
.duration(1000) | |
.style("opacity",1); | |
d3.select(this) | |
.attr('fakeclass','legend') | |
.transition() | |
.duration(1000) | |
.style ("opacity", 1);} | |
}); | |
//create a scale to pass the legend items through | |
var legendscale= d3.scale.ordinal() | |
.domain(lastvalues) | |
.range([0,30,60,90,120,150,180,210]); | |
//actually add the circles to the created legend container | |
legendEnter.append('circle') | |
.attr('cx', width +20) | |
.attr('cy', function(d){return legendscale(d.values[d.values.length-1].value);}) | |
.attr('r', 7) | |
.style('fill', function(d) { | |
return color(d.name); | |
}); | |
//add the legend text | |
legendEnter.append('text') | |
.attr('x', width+35) | |
.attr('y', function(d){return legendscale(d.values[d.values.length-1].value);}) | |
.text(function(d){ return d.name; }); | |
// set variable for updating visualization | |
var thegraphUpdate = d3.transition(thegraph); | |
// change values of path and then the circles to those of the new series | |
thegraphUpdate.select("path") | |
.attr("d", function(d, i) { | |
//must be a better place to put this, but this works for now | |
lastvalues[i]=d.values[d.values.length-1].value; | |
lastvalues.sort(function (a,b){return b-a}); | |
legendscale.domain(lastvalues); | |
return line(d.values); }); | |
thegraphUpdate.selectAll("circle") | |
.attr ("title", maketip) | |
.attr("cy",function(d,i){return y(d.value)}) | |
.attr("cx", function(d,i){return x(d.date)}); | |
// and now for legend items | |
var legendUpdate=d3.transition(legend); | |
legendUpdate.select("circle") | |
.attr('cy', function(d, i){ | |
return legendscale(d.values[d.values.length-1].value);}); | |
legendUpdate.select("text") | |
.attr('y', function (d) {return legendscale(d.values[d.values.length-1].value);}); | |
// update the axes, | |
d3.transition(svg).select(".y.axis") | |
.call(yAxis); | |
d3.transition(svg).select(".x.axis") | |
.attr("transform", "translate(0," + height + ")") | |
.call(xAxis); | |
//make my tooltips work | |
$('circle').tipsy({opacity:.9, gravity:'n', html:true}); | |
//define the zoom function | |
function zoomed() { | |
svg.select(".x.axis").call(xAxis); | |
svg.select(".y.axis").call(yAxis); | |
svg.selectAll(".tipcircle") | |
.attr("cx", function(d,i){return x(d.date)}) | |
.attr("cy",function(d,i){return y(d.value)}); | |
svg.selectAll(".line") | |
.attr("class","line") | |
.attr("d", function (d) { return line(d.values)}); | |
} | |
//end of the redraw function | |
} | |
svg.append("svg:text") | |
.attr("text-anchor", "start") | |
.attr ("x", 0-margin.left) | |
.attr("y", height+margin.bottom-10) | |
.text (sourcetext) | |
.attr ("class","source"); | |
</script> | |
</body> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// tipsy, facebook style tooltips for jquery | |
// version 1.0.0a | |
// (c) 2008-2010 jason frame [[email protected]] | |
// released under the MIT license | |
(function($) { | |
function maybeCall(thing, ctx) { | |
return (typeof thing == 'function') ? (thing.call(ctx)) : thing; | |
} | |
// CAUTION the current implementation does not allow for tipsied elements to stay out of DOM (in between events) | |
// i.e. don't remove, store, then re-insert tipsied elements (and why would you want to do that anyway?) | |
var garbageCollect = (function() { | |
var currentInterval; | |
var to = null; | |
var tipsies = []; | |
function _do() { | |
for (var i = 0; i < tipsies.length;) { | |
var t = tipsies[i]; | |
// FIXME? the 2nd (non-paranoid) check is from the link below, it should be replaced if a better way is found | |
// http://stackoverflow.com/questions/4040715/check-if-cached-jquery-object-is-still-in-dom | |
if (t.options.gcInterval === 0 || t.$element.closest('body').length === 0) { | |
t.hoverState = 'out'; | |
t.hide(); | |
tipsies.splice(i,1); | |
} else { | |
i++; | |
} | |
} | |
} | |
function _loop() { | |
to = setTimeout(function() { _do(); _loop(); }, currentInterval); | |
} | |
return function(t) { | |
if (t.options.gcInterval === 0) return; | |
if (to && t.options.gcInterval < currentInterval) { | |
clearTimeout(to); to = null; | |
currentInterval = t.options.gcInterval; | |
} | |
tipsies.push(t); | |
if (!to) _loop(); | |
}; | |
})(); | |
function Tipsy(element, options) { | |
this.$element = $(element); | |
this.options = options; | |
this.enabled = true; | |
this.fixTitle(); | |
garbageCollect(this); | |
} | |
Tipsy.prototype = { | |
show: function() { | |
var title = this.getTitle(); | |
if (title && this.enabled) { | |
var $tip = this.tip(); | |
$tip.find('.tipsy-inner')[this.options.html ? 'html' : 'text'](title); | |
$tip[0].className = 'tipsy'; // reset classname in case of dynamic gravity | |
$tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).prependTo(document.body); | |
var pos = $.extend({}, this.$element.offset(), { | |
width: this.$element[0].offsetWidth || 0, | |
height: this.$element[0].offsetHeight || 0 | |
}); | |
if (typeof this.$element[0].nearestViewportElement == 'object') { | |
// SVG | |
var el = this.$element[0]; | |
var rect = el.getBoundingClientRect(); | |
pos.width = rect.width; | |
pos.height = rect.height; | |
} | |
var actualWidth = $tip[0].offsetWidth, | |
actualHeight = $tip[0].offsetHeight, | |
gravity = maybeCall(this.options.gravity, this.$element[0]); | |
var tp; | |
switch (gravity.charAt(0)) { | |
case 'n': | |
tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2}; | |
break; | |
case 's': | |
tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2}; | |
break; | |
case 'e': | |
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset}; | |
break; | |
case 'w': | |
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset}; | |
break; | |
} | |
if (gravity.length == 2) { | |
if (gravity.charAt(1) == 'w') { | |
tp.left = pos.left + pos.width / 2 - 15; | |
} else { | |
tp.left = pos.left + pos.width / 2 - actualWidth + 15; | |
} | |
} | |
$tip.css(tp).addClass('tipsy-' + gravity); | |
$tip.find('.tipsy-arrow')[0].className = 'tipsy-arrow tipsy-arrow-' + gravity.charAt(0); | |
if (this.options.className) { | |
$tip.addClass(maybeCall(this.options.className, this.$element[0])); | |
} | |
if (this.options.fade) { | |
$tip.stop().css({opacity: 0, display: 'block', visibility: 'visible'}).animate({opacity: this.options.opacity}); | |
} else { | |
$tip.css({visibility: 'visible', opacity: this.options.opacity}); | |
} | |
var t = this; | |
var set_hovered = function(set_hover){ | |
return function(){ | |
t.$tip.stop(); | |
t.tipHovered = set_hover; | |
if (!set_hover){ | |
if (t.options.delayOut === 0 && t.options.trigger != 'manual') { | |
t.hide(); | |
} else { | |
setTimeout(function() { | |
if (t.hoverState == 'out') t.hide(); }, t.options.delayOut); | |
} | |
} | |
}; | |
}; | |
$tip.hover(set_hovered(true), set_hovered(false)); | |
} | |
}, | |
hide: function() { | |
if (this.options.fade) { | |
this.tip().stop().fadeOut(function() { $(this).remove(); }); | |
} else { | |
this.tip().remove(); | |
} | |
}, | |
fixTitle: function() { | |
var $e = this.$element; | |
if ($e.attr('title') || typeof($e.attr('original-title')) != 'string') { | |
$e.attr('original-title', $e.attr('title') || '').removeAttr('title'); | |
} | |
if (typeof $e.context.nearestViewportElement == 'object'){ | |
if ($e.children('title').length){ | |
$e.append('<original-title>' + ($e.children('title').text() || '') + '</original-title>') | |
.children('title').remove(); | |
} | |
} | |
}, | |
getTitle: function() { | |
var title, $e = this.$element, o = this.options; | |
this.fixTitle(); | |
if (typeof o.title == 'string') { | |
var title_name = o.title == 'title' ? 'original-title' : o.title; | |
if ($e.children(title_name).length){ | |
title = $e.children(title_name).html(); | |
} else{ | |
title = $e.attr(title_name); | |
if (typeof title == 'undefined') title = '' | |
} | |
} else if (typeof o.title == 'function') { | |
title = o.title.call($e[0]); | |
} | |
title = ('' + title).replace(/(^\s*|\s*$)/, ""); | |
return title || o.fallback; | |
}, | |
tip: function() { | |
if (!this.$tip) { | |
this.$tip = $('<div class="tipsy"></div>').html('<div class="tipsy-arrow"></div><div class="tipsy-inner"></div>'); | |
} | |
return this.$tip; | |
}, | |
validate: function() { | |
if (!this.$element[0].parentNode) { | |
this.hide(); | |
this.$element = null; | |
this.options = null; | |
} | |
}, | |
enable: function() { this.enabled = true; }, | |
disable: function() { this.enabled = false; }, | |
toggleEnabled: function() { this.enabled = !this.enabled; } | |
}; | |
$.fn.tipsy = function(options) { | |
if (options === true) { | |
return this.data('tipsy'); | |
} else if (typeof options == 'string') { | |
$(this).each(function(i,el){ | |
if ($(el).data('tipsy')) { | |
tipsy = $(el).data('tipsy') | |
tipsy[options](); | |
} | |
}); | |
return this; | |
} | |
options = $.extend({}, $.fn.tipsy.defaults, options); | |
if (options.hoverlock && options.delayOut === 0) { | |
options.delayOut = 100; | |
} | |
function get(ele) { | |
var tipsy = $.data(ele, 'tipsy'); | |
if (!tipsy) { | |
tipsy = new Tipsy(ele, $.fn.tipsy.elementOptions(ele, options)); | |
$.data(ele, 'tipsy', tipsy); | |
} | |
return tipsy; | |
} | |
function enter() { | |
var tipsy = get(this); | |
tipsy.hoverState = 'in'; | |
if (options.delayIn === 0) { | |
tipsy.show(); | |
} else { | |
tipsy.fixTitle(); | |
setTimeout(function() { if (tipsy.hoverState == 'in') tipsy.show(); }, options.delayIn); | |
} | |
} | |
function leave() { | |
var tipsy = get(this); | |
tipsy.hoverState = 'out'; | |
if (options.delayOut === 0) { | |
tipsy.hide(); | |
} else { | |
var to = function() { | |
if (!tipsy.tipHovered || !options.hoverlock){ | |
if (tipsy.hoverState == 'out') tipsy.hide(); | |
} | |
}; | |
setTimeout(to, options.delayOut); | |
} | |
} | |
if (!options.live) this.each(function() { get(this); }); | |
if (options.trigger != 'manual') { | |
var binder = options.live ? 'live' : 'bind', | |
eventIn = options.trigger == 'hover' ? 'mouseenter' : 'focus', | |
eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur'; | |
this[binder](eventIn, enter)[binder](eventOut, leave); | |
} | |
return this; | |
}; | |
$.fn.tipsy.defaults = { | |
className: null, | |
delayIn: 0, | |
delayOut: 0, | |
fade: false, | |
fallback: '', | |
gcInterval: 0, | |
gravity: 'n', | |
html: false, | |
live: false, | |
offset: 0, | |
opacity: 0.8, | |
title: 'title', | |
trigger: 'hover', | |
hoverlock: false | |
}; | |
// Overwrite this method to provide options on a per-element basis. | |
// For example, you could store the gravity in a 'tipsy-gravity' attribute: | |
// return $.extend({}, options, {gravity: $(ele).attr('tipsy-gravity') || 'n' }); | |
// (remember - do not modify 'options' in place!) | |
$.fn.tipsy.elementOptions = function(ele, options) { | |
return $.metadata ? $.extend({}, options, $(ele).metadata()) : options; | |
}; | |
$.fn.tipsy.autoNS = function() { | |
return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n'; | |
}; | |
$.fn.tipsy.autoWE = function() { | |
return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w'; | |
}; | |
/** | |
* yields a closure of the supplied parameters, producing a function that takes | |
* no arguments and is suitable for use as an autogravity function like so: | |
* | |
* @param margin (int) - distance from the viewable region edge that an | |
* element should be before setting its tooltip's gravity to be away | |
* from that edge. | |
* @param prefer (string, e.g. 'n', 'sw', 'w') - the direction to prefer | |
* if there are no viewable region edges effecting the tooltip's | |
* gravity. It will try to vary from this minimally, for example, | |
* if 'sw' is preferred and an element is near the right viewable | |
* region edge, but not the top edge, it will set the gravity for | |
* that element's tooltip to be 'se', preserving the southern | |
* component. | |
*/ | |
$.fn.tipsy.autoBounds = function(margin, prefer) { | |
return function() { | |
var dir = {ns: prefer[0], ew: (prefer.length > 1 ? prefer[1] : false)}, | |
boundTop = $(document).scrollTop() + margin, | |
boundLeft = $(document).scrollLeft() + margin, | |
$this = $(this); | |
if ($this.offset().top < boundTop) dir.ns = 'n'; | |
if ($this.offset().left < boundLeft) dir.ew = 'w'; | |
if ($(window).width() + $(document).scrollLeft() - $this.offset().left < margin) dir.ew = 'e'; | |
if ($(window).height() + $(document).scrollTop() - $this.offset().top < margin) dir.ns = 's'; | |
return dir.ns + (dir.ew ? dir.ew : ''); | |
}; | |
}; | |
})(jQuery); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.plot{ | |
fill: #fff; | |
} | |
.axis path, | |
.axis line { | |
fill: none; | |
stroke: #AFBABF; | |
shape-rendering: crispEdges; | |
} | |
.axis text { | |
font-family: SourceSansPro-Bold; | |
font-size: 14px; | |
fill: #AFBABF; | |
} | |
.x.axis path { | |
display: none; | |
} | |
.y.axis path{ | |
display: none; | |
} | |
.line { | |
fill: none; | |
stroke: steelblue; | |
stroke-linejoin: round; | |
stroke-linecap:round; | |
} | |
.hed { | |
font-family: SourceSansPro-Bold; | |
font-size: 24pt; | |
margin-bottom:5px; | |
margin-top:0px; | |
} | |
.dek { | |
font-family: SourceSansPro-Light; | |
font-size: 12pt; | |
margin-bottom:0px; | |
margin-top:0px; | |
} | |
.menuchoice { | |
font-family: SourceSansPro-Light; | |
font-size: 10pt; | |
margin-bottom:0px; | |
fill: #231F20; | |
} | |
.legend { | |
font-family: SourceSansPro-Light; | |
font-size: 10pt; | |
margin-bottom:0px; | |
fill: #231F20; | |
} | |
.legend-off { | |
font-family: SourceSansPro-Light; | |
font-size: 10pt; | |
margin-bottom:0px; | |
fill: #231F20; | |
} | |
.legend-select { | |
font-family: SourceSansPro-Bold; | |
font-size: 10pt; | |
margin-bottom:0px; | |
fill: #231F20; | |
} | |
.tip1 { | |
font-family: SourceSansPro-Bold; | |
font-size: 14pt; | |
text-align: center; | |
margin-bottom:-12px; | |
margin-top:0px; | |
} | |
.tip2 { | |
font-family: SourceSansPro-ExtraLight; | |
font-size: 10pt; | |
text-align: center; | |
margin-bottom:-12px; | |
} | |
.tip3 { | |
font-family: SourceSansPro-ExtraLight; | |
font-size: 10pt; | |
text-align: center; | |
margin-bottom:0px; | |
} | |
@font-face { | |
font-family: 'SourceSansPro-ExtraLight'; | |
font-style: normal; | |
font-weight: 200; | |
src: local('Source Sans Pro ExtraLight'), local('SourceSansPro-ExtraLight'), url(http://themes.googleusercontent.com/static/fonts/sourcesanspro/v5/toadOcfmlt9b38dHJxOBGC-IiwWNzQT_LXAtr-Ee9Pw.woff) format('woff'); | |
} | |
@font-face { | |
font-family: 'SourceSansPro-Light'; | |
font-style: normal; | |
font-weight: 300; | |
src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), url(http://themes.googleusercontent.com/static/fonts/sourcesanspro/v5/toadOcfmlt9b38dHJxOBGMVNtom4QlEDNJaqqqzqdSs.woff) format('woff'); | |
} | |
@font-face { | |
font-family: 'SourceSansPro-Bold'; | |
font-style: normal; | |
font-weight: 700; | |
src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'), url(http://themes.googleusercontent.com/static/fonts/sourcesanspro/v5/toadOcfmlt9b38dHJxOBGIqjGYJUyOXcBwUQbRaNH6c.woff) format('woff'); | |
} | |
.tipsy { font-family:"Source Sans Pro"; font-size: 10px; position: absolute; padding: 5px; z-index: 100000; } | |
.tipsy-inner { background-color: #000; color: #FFF; max-width: 200px; padding: 0; text-align: left; padding:10px;} | |
/* Rounded corners */ | |
.tipsy-inner { border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; } | |
/* Uncomment for shadow */ | |
/*.tipsy-inner { box-shadow: 0 0 5px #000000; -webkit-box-shadow: 0 0 5px #000000; -moz-box-shadow: 0 0 5px #000000; }*/ | |
.tipsy-arrow { position: absolute; width: 0; height: 0; line-height: 0; border: 5px dashed #000; } | |
/* Rules to colour arrows */ | |
.tipsy-arrow-n { border-bottom-color: #000; } | |
.tipsy-arrow-s { border-top-color: #000; } | |
.tipsy-arrow-e { border-left-color: #FFF; } | |
.tipsy-arrow-w { border-right-color: #000; } | |
.tipsy-n .tipsy-arrow { top: 0px; left: 50%; margin-left: -5px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent; } | |
.tipsy-nw .tipsy-arrow { top: 0; left: 10px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent;} | |
.tipsy-ne .tipsy-arrow { top: 0; right: 10px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent;} | |
.tipsy-s .tipsy-arrow { bottom: 0; left: 50%; margin-left: -5px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; } | |
.tipsy-sw .tipsy-arrow { bottom: 0; left: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; } | |
.tipsy-se .tipsy-arrow { bottom: 0; right: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; } | |
.tipsy-e .tipsy-arrow { right: 0; top: 50%; margin-top: -5px; border-left-style: solid; border-right: none; border-top-color: transparent; border-bottom-color: transparent; } | |
.tipsy-w .tipsy-arrow { left: 0; top: 50%; margin-top: -5px; border-right-style: solid; border-left: none; border-top-color: transparent; border-bottom-color: transparent; } | |
.gravity { width: 100%; margin: 5px 0; border-spacing: 5px; } | |
.gravity td { text-align: center; vertical-align: middle; padding: 5px 0; background-color: #d0d0d0; width: 33%; } | |
.gravity a { } | |
.gravity a:hover { color: #505050; background: none; } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment