"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
});
}