"use strict"; // variables var margin = { top: 0, right: 0, bottom: 0, left: 0 }, width = 700 - margin.left - margin.right, height = 380; var docMargin = { top: 30, right: 30, bottom: 30, left: 30 } var lineDrop = 20, quoteNum = 0; var playOn = true; // created manually based on image --> will need to improve this var stations = { "4th & King": 132, "22nd Street": 141, "Bayshore": 160, "South SF": 185, "San Bruno": 195, "Millbrae": 224, // confirm value for Broadway "Broadway": 230, "Burlingame": 245, "San Mateo": 277, "Hayward Park": 295, "Hillsdale": 308, "Belmont": 330, "San Carlos": 347, "Redwood City": 376, "Menlo Park": 422, "Palo Alto": 438, "California Ave": 459, "San Antonio": 493, "Mountain View": 516, "Sunnyvale": 551, "Lawrence": 576, "Santa Clara": 622, "College Park": 639, "San Jose": 655 } var stationList = [ "4th & King", "22nd Street", "Bayshore", "South SF", "San Bruno", "Millbrae", "Broadway", "Burlingame", "San Mateo", "Hayward Park", "Hillsdale", "Belmont", "San Carlos", "Redwood City", "Menlo Park", "Palo Alto", "California Ave", "San Antonio", "Mountain View", "Sunnyvale", "Lawrence", "Santa Clara", "College Park", "San Jose" ] var scales = { // todo - remove hardcode here dateScale: d3.time.scale() .domain([d3.time.format("%Y-%m-%d").parse("2015-01-01"), d3.time.format("%Y-%m-%d").parse("2015-02-19")]) .range([lineDrop, height - 30]) } var color = { north: "#FF6F00", south: "#E0009D", unknown: "#8d8d8d" } // standard svg starter var svg = d3.select('#svgDiv') .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 + ')'); // station line & dots var stationGroup = svg.append("g") stationGroup.append("line") .classed("stationLine", true) .attr("y1", lineDrop) .attr("y2", lineDrop) .attr("x1", 132 - docMargin.left) .attr("x2", 655 - docMargin.left) .attr("stroke", color.station); stationGroup.selectAll(".station") .data(stationList) .enter() .append("circle") .attr("class", "station") .attr("cy", lineDrop) .attr("r", 3) .attr("cx", function(d, i) { return stations[d] - docMargin.left }) .on("mouseover", function(d) { console.log(d) }); var intervalId = -1; function startInterval(data) { if (data != undefined) { intervalId = setInterval(function() { quoteNum = (quoteNum + 1) % data.length; setUp(quoteNum, data) }, 2000); } } function setUp(j, data) { updateText(data[j]); d3.selectAll(".bumps") .data(data) .classed("selected", function(d, i) { if (i == j) { return true } else { return false } }); selectStation(data[j]["Departure station "]); } // get bump data d3.csv("bikeCaltrain.csv", function(error, data){ setUpBumpCircles(data); setUp(quoteNum, data) startInterval(data); playPauseSetup(data); }) function setUpBumpCircles(data) { svg.selectAll(".bumps") .data(data) .enter() .append("circle") .attr("class", "bumps") .attr("cy", function(d) { return scales.dateScale(d3.time.format("%m/%d/%Y").parse(d["Date of bicycle bump(s) "])) }) .attr("cx", function(d) { return stations[d["Departure station "]] - docMargin.left }) .attr("r", function(d) { return Math.pow(d['Total number of bumped bikes '], .5) * 4 }) .attr("fill", function(d) { if (d['Travel direction'] == "North") { return color.north; } else if (d['Travel direction'] == "South"){ return color.south } else { return color.unknown } }) .on("mouseover", function(d) { var currentStation = d["Departure station "] updateText(d); d3.selectAll(".bumps").data(data).classed("selected", false) d3.select(this).classed("selected", true) selectStation(currentStation); clearInterval(intervalId); }) .on("mouseout", function(d) { updateText(d); d3.select(this).classed("selected", false) d3.selectAll(".station").data(stationList).attr("fill", color.station); if(playOn){ startInterval(data); } }) } function updateText(dataObj) { if (dataObj["Comments "] != undefined && dataObj["Comments "] != "") { console.log(dataObj["Comments "]) document.getElementById("quote").innerHTML = dataObj["Comments "] } else { document.getElementById("quote").innerHTML = "[no comment]" } if (dataObj["Scheduled departure time "] != "") { document.getElementById("date").innerHTML = d3.time.format("%a %B %d, %Y")( d3.time.format("%m/%d/%Y").parse(dataObj["Date of bicycle bump(s) "]) ) + " at " + dataObj["Scheduled departure time "] } else { document.getElementById("date").innerHTML = d3.time.format("%a %B %d, %Y")( d3.time.format("%m/%d/%Y").parse(dataObj["Date of bicycle bump(s) "])) } document.getElementById("numberBumped").innerHTML = "" + dataObj['Total number of bumped bikes '] + " people with bikes bumped" if (dataObj['Travel direction'] == "North") { var highlightColor = color.north; } else { highlightColor = color.south; } document.getElementById("location").innerHTML = "Traveling " + "" + dataObj['Travel direction'] + "" + " from " + dataObj['Departure station '] + ""; } function selectStation(name) { d3.selectAll(".station") .data(stationList) .classed("selected", function(d) { if (d == name) { return true } else { return false } }); } function playPauseUpdate(){ d3.selectAll(".play").classed("hidden", playOn); d3.selectAll(".pause").classed("hidden", !playOn); } function playPauseSetup(data) { // handle play/pause var circleCenter = { x: 16, y: 50 }; function switchOnOff() { playOn = !playOn; d3.selectAll(".play").classed("hidden", playOn); d3.selectAll(".pause").classed("hidden", !playOn); if(playOn == false){ console.log('clearing interval') clearInterval(intervalId) } else { console.log('starting interval') startInterval(data) } } var playPauseGroup = d3.select("#playPause") .append('svg') .attr('width', 32) .attr('height', 68) .on("click", switchOnOff); playPauseGroup.append('circle') .classed("playPauseCircle", true) .attr({ cx: circleCenter.x, cy: circleCenter.y, r: 15, fill: "#BBBABA" }) playPauseGroup.append('polygon') .classed("play", true) .classed("hidden", playOn) .attr("points", function() { return (circleCenter.x - 4) + "," + (circleCenter.y - 6) + " " + (circleCenter.x + 7) + "," + (circleCenter.y) + " " + (circleCenter.x - 4) + "," + (circleCenter.y + 6) }); playPauseGroup.append('line') .classed("pause", true) .classed("hidden", !playOn) .attr({ x1: circleCenter.x - 3, x2: circleCenter.x - 3, y1: circleCenter.y - 5, y2: circleCenter.y + 3 }); playPauseGroup.append('line') .classed("pause", true) .classed("hidden", !playOn) .attr({ x1: circleCenter.x + 4, x2: circleCenter.x + 4, y1: circleCenter.y - 5, y2: circleCenter.y + 3 }); }