Commit 5ada49cc authored by Kjetil Thuen's avatar Kjetil Thuen
Browse files

Namespaced timer, polished slider

parent 453dba0f
timebars = require './timebars.coffee'
nesstarloader = require './nesstarloader.coffee'
timeBarAnim = undefined
window.nesstartimebars = {}
window.nesstartimebars.main = (containerId, dataDesc) ->
......@@ -20,16 +19,6 @@ window.nesstartimebars.main = (containerId, dataDesc) ->
, dataDesc)
window.nesstartimebars.toggleAnimation = (containerId) ->
if timeBarAnim?
clearInterval timeBarAnim
timeBarAnim = undefined
document.getElementById(containerId + "playBtn")
.innerHTML = "<i class='fa fa-play'></i>"
else
timeBarAnim = setInterval ->
timebars.nextFrame containerId
, timebars.speed()
document.getElementById(containerId + "playBtn")
.innerHTML = "<i class='fa fa-pause'></i>"
timebars.toggleAnim(containerId)
undefined
......@@ -2,7 +2,8 @@ d3 = require 'd3-browserify'
lodash = require 'lodash'
dragDealer = require('dragdealer').Dragdealer
completeData = {}
# Holds all state and prepared data
chartState = {}
chartWidth = (chartId) ->
parseInt d3.select("#" + chartId).style "width"
......@@ -10,7 +11,7 @@ chartWidth = (chartId) ->
chartHeight = (chartId) -> 700
numBars = (chartId) ->
vals = lodash.first(lodash.values completeData[chartId].yearData)
vals = lodash.first(lodash.values chartState[chartId].yearData)
vals.length
horizMargin = (chartId) ->
......@@ -25,7 +26,7 @@ barThickness = (chartId) ->
Math.floor(chartHeight(chartId) / numBars(chartId)) - 2
maxValue = lodash.memoize (chartId) ->
years = lodash.values completeData[chartId].yearData
years = lodash.values chartState[chartId].yearData
lodash.reduce(years, (max, yearData) ->
Math.max max, lodash.reduce(yearData, (max, val) ->
Math.max max, Math.max(val.rvalue, val.lvalue)
......@@ -33,7 +34,7 @@ maxValue = lodash.memoize (chartId) ->
0)
maxAge = lodash.memoize (chartId) ->
years = lodash.values completeData[chartId].yearData
years = lodash.values chartState[chartId].yearData
lodash.reduce(years, (max, yearData) ->
Math.max max, lodash.reduce(yearData, (max, val) ->
Math.max max, val.age
......@@ -106,9 +107,9 @@ prepareMetadataDiv = (chartId, data, mapping) ->
for own field, name of fieldMapping
_results.push "<dt>"
_results.push "<i class='" +
completeData[chartId].displayDetails[field + "symbol"] +
chartState[chartId].displayDetails[field + "symbol"] +
"'></i> " +
completeData[chartId].displayDetails[field + "label"]
chartState[chartId].displayDetails[field + "label"]
_results.push "</dt>"
_results.push "<dd>"
_results.push data[name]
......@@ -120,7 +121,7 @@ prepareMetadataDiv = (chartId, data, mapping) ->
updateMetadata = (chartId, currentYear, ageGroup) ->
# FIXME: Add a delay to reduce flicker
data = lodash.filter completeData[chartId].yearData[currentYear],
data = lodash.filter chartState[chartId].yearData[currentYear],
{ 'birthyear': ageGroup }
d3.select "#" + chartId + " div.dataDetails"
.html prepareMetadataDiv chartId, data[0]
......@@ -136,15 +137,15 @@ unhoverBar = (chartId) ->
(data, index) ->
d3.selectAll "#" + chartId + " svg.chart g.valuepoint"
.classed "hovered", false
updateMetadata chartId, data.year, completeData[chartId].selectedYear
updateMetadata chartId, data.year, chartState[chartId].selectedYear
selectBar = (chartId) ->
(data, index) ->
completeData[chartId].selectedYear = data.birthyear
chartState[chartId].selectedYear = data.birthyear
#FIXME: Shouln't this be updated automatically when the backed data changes?
d3.selectAll "#" + chartId + " svg.chart g.valuepoint"
.classed "selected", (d) ->
d.birthyear is completeData[chartId].selectedYear
d.birthyear is chartState[chartId].selectedYear
updateMetadata chartId, "2015", data.birthyear
......@@ -159,7 +160,7 @@ addBar = (newBar, chartId) ->
.on "mouseout", unhoverBar chartId
.on "click", selectBar chartId
.classed "selected", (d) ->
d.birthyear is completeData[chartId].selectedYear
d.birthyear is chartState[chartId].selectedYear
barGroup.append('rect')
.attr 'class', 'click-capture'
......@@ -173,7 +174,7 @@ addBar = (newBar, chartId) ->
.attr "class", "right"
.attr "x", chartWidth(chartId) / 2 + horizMargin(chartId)
.attr "height", barThickness chartId
.attr "fill", completeData[chartId].displayDetails.rightcolor
.attr "fill", chartState[chartId].displayDetails.rightcolor
.attr "width", (d) -> xScaleRight(chartId)(d.rvalue)
barGroup.append "text"
......@@ -186,27 +187,27 @@ addBar = (newBar, chartId) ->
xScaleRight(chartId)(d.lvalue) - horizMargin(chartId)
.attr "width", (d) -> xScaleRight(chartId)(d.lvalue)
.attr "height", barThickness chartId
.attr "fill", completeData[chartId].displayDetails.leftcolor
.attr "fill", chartState[chartId].displayDetails.leftcolor
valuesFromFrame = (chartId, frameNum) ->
frameIndexes = lodash.keys(completeData[chartId].yearData)
completeData[chartId].yearData['' + frameIndexes[frameNum] + '']
frameIndexes = lodash.keys(chartState[chartId].yearData)
chartState[chartId].yearData['' + frameIndexes[frameNum] + '']
updateChart = (chartId, frameNum) ->
data = valuesFromFrame chartId, frameNum
chart = d3.select "#" + chartId + " svg.chart"
label = d3.select "#" + chartId + " span.yearLabel"
.html completeData[chartId].displayDetails.name +
.html chartState[chartId].displayDetails.name +
" <span class='year'>" +
lodash.keys(completeData[chartId].yearData)[frameNum] +
lodash.keys(chartState[chartId].yearData)[frameNum] +
"</span>"
valuepoints = chart.selectAll "g.valuepoint"
.data data, (d) -> d.birthyear
valuepoints.classed "selected", (d) ->
d.birthyear is completeData[chartId].selectedYear
d.birthyear is chartState[chartId].selectedYear
valuepoints.transition()
.attr "transform", (d, i) ->
......@@ -233,20 +234,70 @@ updateChart = (chartId, frameNum) ->
.remove()
updateMetadata chartId,
lodash.keys(completeData[chartId].yearData)[frameNum],
completeData[chartId].selectedYear
lodash.keys(chartState[chartId].yearData)[frameNum],
chartState[chartId].selectedYear
undefined
nextFrame = (chartId) ->
dataLength = lodash.keys(completeData[chartId].yearData).length
dataLength = lodash.keys(chartState[chartId].yearData).length
if dataLength > 0
num = completeData[chartId].currentFrame or -1
num = chartState[chartId].currentFrame or -1
num++
if num >= dataLength
num = 0
completeData[chartId].currentFrame = num
completeData[chartId].slider.setStep(num, 0, snap=true)
setFrame chartId, num
setFrame = (chartId, frame) ->
dataLength = lodash.keys(chartState[chartId].yearData).length
if frame <= dataLength
chartState[chartId].currentFrame = frame
chartState[chartId].slider.setStep(frame, 0, snap=true)
stopAnim = (chartId) ->
clearInterval chartState[chartId].timeBarAnim
chartState[chartId].timeBarAnim = undefined
document.getElementById(chartId + "playBtn")
.innerHTML = "<i class='fa fa-play'></i>"
startAnim = (chartId) ->
chartState[chartId].timeBarAnim = setInterval ->
nextFrame chartId
, speed()
document.getElementById(chartId + "playBtn")
.innerHTML = "<i class='fa fa-pause'></i>"
toggleAnim = (chartId) ->
if chartState[chartId].timeBarAnim?
stopAnim chartId
else
startAnim chartId
displayPoster = (chartId, icon, header, message) ->
container = d3.select "#" + chartId
container.html ""
poster = container.append "div"
.attr "class", "poster"
.style "min-height", -> chartHeight(chartId) / 2 + "px"
.style "margin-top", -> chartHeight(chartId) / 4 + "px"
if icon
poster.append "div"
.attr "class", "icon"
.append "i"
.attr "class", icon
if header
poster.append "h3"
.attr "class", "header"
.html header
if message
poster.append "div"
.attr "class", "message"
.html message
#Constructor.
#
......@@ -261,9 +312,9 @@ nextFrame = (chartId) ->
#displayDetails contain stuff like labels and colors
setupChart = (chartId, data, displayDetails) ->
if data
completeData[chartId] = {}
completeData[chartId].yearData = data
completeData[chartId].displayDetails = displayDetails or {
chartState[chartId] = {}
chartState[chartId].yearData = data
chartState[chartId].displayDetails = displayDetails or {
name: "Timebars",
leftsymbol: "fa fa-female",
rightsymbol: "fa fa-male",
......@@ -275,8 +326,8 @@ setupChart = (chartId, data, displayDetails) ->
birthyearlabel: "Birthyear"
}
if lodash.keys(completeData).length < 1 or
lodash.keys(completeData[chartId].yearData).length < 2
if lodash.keys(chartState).length < 1 or
lodash.keys(chartState[chartId].yearData).length < 2
displayPoster(chartId,
"fa fa-exclamation-triangle",
"Problems rendering chart",
......@@ -343,17 +394,17 @@ setupChart = (chartId, data, displayDetails) ->
.attr "class", "dataDetails"
container.append "div"
.attr "class", "leftLabel"
.attr "class", "inlineLabel left"
.html "<i class='" +
completeData[chartId].displayDetails.leftsymbol +
chartState[chartId].displayDetails.leftsymbol +
"'></i> " +
completeData[chartId].displayDetails.leftlabel
chartState[chartId].displayDetails.leftlabel
container.append "div"
.attr "class", "rightLabel"
.html completeData[chartId].displayDetails.rightlabel +
.attr "class", "inlineLabel right"
.html chartState[chartId].displayDetails.rightlabel +
" <i class='" +
completeData[chartId].displayDetails.rightsymbol +
chartState[chartId].displayDetails.rightsymbol +
"'></i>"
controls = container.append "div"
......@@ -372,46 +423,21 @@ setupChart = (chartId, data, displayDetails) ->
.append "div"
.attr "class", "handle red-bar"
completeData[chartId].slider = new dragDealer(chartId + "Slider", {
chartState[chartId].slider = new dragDealer(chartId + "Slider", {
steps: lodash.keys(data).length
animationCallback: ->
frame = completeData[chartId].currentFrame = @getStep()[0]
frame = @getStep()[0]
d3.select "#" + chartId + " .dragdealer .handle"
.html lodash.keys(completeData[chartId].yearData)[frame]
.html lodash.keys(chartState[chartId].yearData)[frame - 1]
callback: ->
completeData[chartId].currentFrame = @getStep()[0]
updateChart(chartId, completeData[chartId].currentFrame - 1)
chartState[chartId].currentFrame = @getStep()[0]
updateChart(chartId, chartState[chartId].currentFrame - 1)
})
nextFrame chartId
setFrame chartId, 0
window.onresize = -> setupChart chartId, data, displayDetails
displayPoster = (chartId, icon, header, message) ->
container = d3.select "#" + chartId
container.html ""
poster = container.append "div"
.attr "class", "poster"
.style "min-height", -> chartHeight(chartId) / 2 + "px"
.style "margin-top", -> chartHeight(chartId) / 4 + "px"
if icon
poster.append "div"
.attr "class", "icon"
.append "i"
.attr "class", icon
if header
poster.append "h3"
.attr "class", "header"
.html header
if message
poster.append "div"
.attr "class", "message"
.html message
exports.displayPoster = displayPoster
exports.setupChart = setupChart
exports.speed = speed
exports.nextFrame = nextFrame
exports.toggleAnim = toggleAnim
......@@ -17,6 +17,7 @@
.controls {
display: table;
border-spacing: 5px;
height: 45px;
button {
display: table-cell;
......@@ -25,23 +26,26 @@
.dragdealer {
@include rounded();
width: 100%;
font-size: 14px;
display: table-cell;
background: #e1e1e1;
position: relative;
.handle {
@include rounded();
padding-left: 1em;
padding-right: 1em;
height: 100%;
width: 75px;
background: #c00;
color: white;
font-weight: bold;
line-height: 30px;
position: absolute;
cursor: pointer;
text-align:center;
border:1px solid silver;
vertical-align:middle; //now we can center vertically like in a TD
line-height: 35px;
}
}
}
.axisLabels {
path, line {
display: none;
......@@ -119,19 +123,16 @@
}
}
.leftLabel {
font-size: 200%;
position: absolute;
left: 0.5em;
bottom: 2em;
}
.rightLabel {
.inlineLabel {
font-size: 200%;
position: absolute;
right: 1em;
bottom: 2em;
text-align: right;
bottom: 70px;
&.left {
left: 20px;
}
&.right {
right: 20px;
}
}
.poster {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment