Public
Edited
Mar 1, 2024
Insert cell
Insert cell
Insert cell
Insert cell
<div id='content-wrapper'>
<div id='map'>
<div id='canvas-container'></div>
<div id='svg-container'></div>
</div>
<div id='data-table-wrapper'>
<button id='launch-button' disabled=true>Launch Dijkstra</button>
<table id='data-table'>
<thead>
<tr>
<th>Start Node</th>
<th>End Node</th>
</tr>
</thead>
<tbody id='data-table-body'>
<tr>
<td class="waiting-ui" id="waiting-ui-start">Select start node</td>
<td class="waiting-ui" id="waiting-ui-end">Select end node</td>
</tr>
<tr>
<th>Station</th>
<th>Distances</th>
<th>From</th>
</tr>
</tbody>
</table>
</div>
</div>
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
margin = ({ top: 20, bottom: 70, right: 30 })
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
setLabelInvisible = key => {
d3.select(`#station-label_${key}`)
.classed('visible', false)
.classed('invisible', true)
}
Insert cell
onSelectStartNode = key => {
d3.select(`#circ_${key}`)
.classed('selected-start-cir', true)
setLabelVisible(key)
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function onClickNode(event) {
const { id, name } = event.properties
if (state.mode === 'start') {
if (state.selectedStart === id) {
onDeselectStartNode(id)
} else {
state.selectedStart = id
d3.select('#waiting-ui-start').html(name)
onSelectStartNode(id)
state.mode = 'end'
}
}

else if (state.mode === 'end') {
if (state.selectedEnd === id) {
onDeselectEndNode(id)
d3.select('#waiting-ui-end').html('Select end node')
}

else if (state.selectedStart === id) {
state.selectedStart = ''
d3.select('#waiting-ui-start').html('Select start node')
onDeselectStartNode(id)
state.mode = 'start'
} else {
state.selectedEnd = id
onSelectEndNode(id)
d3.select('#waiting-ui-end').html(name)
d3.select('#launch-button').attr('disabled', null)
state.mode = 'ready'
}
}

else if (state.mode === 'ready') {
if (state.selectedEnd === id) {
state.selectedEnd = ''
onDeselectEndNode(id)
d3.select('#launch-button').attr('disabled', true)
d3.select('#waiting-ui-end').html('Select end node')
state.mode = 'end'
}
}
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function updateTable(key, distances, previousNodes) {

const sorted = Object.keys(distances).sort((a, b) => {
if (distances[a] < distances[b]) {
return -1
} else if (distances[b] > distances[a]) {
return 1
}
return 0
})

const d = []

sorted.forEach((k) => {
d.push(distances[k])
})

d3.selectAll('.data-rows')
.each(function (d, j) {
const row = d3.select(this)
row.selectAll('td')
.each(function (td, i) {
const cell = d3.select(this)
const key = sorted[j]
const distance = distances[key]
if (distance !== Infinity) {
if (i === 0) {
cell.text(stationNames[key])
}
if (i === 1) {
cell.text(distance.toFixed(2))
}

if (i === 2) {
cell.text(stationNames[previousNodes[key]])
}
}
})

})
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
anim_resetChart = function() {

d3.selectAll('.anim-path').remove()
d3.selectAll('.dist-label-g')
.style('opacity', 0)

//button
d3.select('#launch-button')
.html('Launch Dijkstra')
.attr('disabled', true)

// circles
d3.select('.highlighted-end-cir')
.classed('highlighted-end-cir', false)

d3.select('.highlighted-start-cir')
.classed('highlighted-start-cir', false)

d3.selectAll('.unvisited-cir')
.classed('unvisited-cir', false)
d3.selectAll('.selected-start-cir')
.classed('selected-start-cir', false)

d3.select('.selected-end-cir')
.classed('selected-end-cir', false)

d3.selectAll('.station-label')
.classed('visible', false)
.classed('invisible', true)


//table
d3.selectAll('.data-rows')
.each(function (d, j) {
d3.select(this)
.selectAll('td').text('')
})

d3.select('#waiting-ui-end').html('Select end node')
d3.select('#waiting-ui-start').html('Select start node')
//state
state.selectedStart = ''
state.selectedEnd = ''
state.mode = 'start'
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
<style>

#map {
position: relative;
flex: 0 0 auto;
}

#svg-container {
position: absolute;
top: 0;
left: 0;
}

#canvas-container {
width: 630px;
height: 670px;
}

.station-circle {
cursor: pointer;
}

.cont {
display: flex;
justify-content: baseline;
align-items: center;
}

#content-wrapper {
display: flex;
flex-wrap: wrap;
gap: 1.4rem;
}

#data-table-wrapper {
flex-grow: 1;
min-width: 300px;
}

.legend-piece {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: -6em;
}

.legend {
display: flex;
justify-content: flex-start;
align-items: flex-start;
flex-direction: column;
width: 100%;
}

.inputs {
display: flex;
align-items: center;
gap: 1.4rem;
}

.viz {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}

/*************************************************************/
/* Chart states */
/*************************************************************/

.distance-labels {
background-color: white;
}

.visible {
opacity: 1;
transition: opacity 200ms ease-in-out;
}

.invisible {
opacity: 0;
transition: opacity 200ms ease-in-out;
}

.unvisited-cir {
fill: blue;
transition: fill 200ms ease-in-out;
}

.current-cir {
fill: yellow;
transition: fill 200ms ease-in-out;
}

.selected-start-cir {
fill: green;
transition: fill 200ms ease-in-out;
}

.selected-end-cir {
fill: green;
transition: fill 200ms ease-in-out;
}

.station-circle {
/* fill: white; */
transition: fill 200ms ease-in-out;
}

/* hover interactions */
.highlighted-start-cir {
fill: green;
transition: fill 200ms ease-in-out;
}

.highlighted-end-cir {
fill: red;
transition: fill 200ms ease-in-out;
}

/*************************************************************/
/* Table */
/*************************************************************/

th {
text-align: left;
}

td {
/* width: 20ch; */
}
</style>
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more