Public
Edited
Jun 20, 2023
Insert cell
md`# Drivetrain Picker`
Insert cell
picker = {
return Preact.render(htm`<${DrivetrainPicker} page="All" />`)
}
Insert cell
class DrivetrainPicker extends Preact.Component {
constructor(){
super([]);
this.state = {wheel: 680, crank: 170};
}
handleSubmit(evt){
evt.preventDefault();

var event = new Event('addDrivetrain');
console.log(this.state.label)
if(!this.state.label || this.state.label === ''){
const co = this.state.cassetteOut;
const label = `${this.state.chainringOut.join('-')}T : ${co[0]}-${co[co.length - 1]}T`
this.setState({label: label})
}
event['drivetrain'] = this.state;

this.setState({label: null, cassetteOut: null, chainringOut: null, cassetteSearch: null, chainringSearch: null});

this.base.dispatchEvent(event);

}
handleLabel(evt){
this.setState({label: evt.target.value});
}
handleWheel(evt){
this.setState({wheel: evt.target.value});
}
handleCrank(evt){
this.setState({crank: evt.target.value});
}
handleManualCassette(evt){

const input = evt.target.value.replace(/[^\d,-]/g, '').split(/[,-]+/).sort(d3.ascending);
this.setState({cassetteOut: input, cassetteSearch: null});
}
handleManualChainring(evt){
const input = evt.target.value.replace(/[^\d,-]/g, '').split(/[,-]+/).sort(d3.descending);
this.setState({chainringOut: input, chainringSearch: null});
}
handleCassetteChange(evt) {
const match = cassette.find(d => `${d.seriesName}: ${d.name}` === evt.target.value)
this.setState({cassetteOut: match.sprockets, cassetteSearch: evt.target.value});
}
handleChainringChange(evt) {
const match = chainrings.find(d => `${d.seriesName}: ${d.chainring}` === evt.target.value)
this.setState({chainringOut: match.chainring.replace('T','').split(/[,-]+/).map(d => +d),
chainringSearch: evt.target.value});
}
render({page}, {todos = []}) {
return htm`
<div class="picker">
<form onSubmit=${(e) => this.handleSubmit(e)}>
<div class="input-group">
<label for="cassette-in">Cassette</label>
<input placeholder="Search..." name="cassette-in" type="text" list="cassette-dl" onChange=${(e) => this.handleCassetteChange(e)} value="${this.state.cassetteSearch}"></input>
<input placeholder="Enter manually (comma delimited)" name="cassette-out" type="text" value="${this.state.cassetteOut}" onChange=${(e) => this.handleManualCassette(e)} required></input>
<datalist id="cassette-dl">
${cassette.map(d => htm`
<option value="${d.seriesName}: ${d.name}"></option>
`)}
</datalist>
</div>
<div class="input-group">
<label for="chainring-in">Chainrings</label>
<input placeholder="Search..." name="chainring-in" type="text" list="chainring-dl" onChange=${(e) => this.handleChainringChange(e)} value=${this.state.chainringSearch}></input>
<input placeholder="Enter manually (comma delimited)" name="chainring-out" type="text" value="${this.state.chainringOut}" onChange="${(e) => this.handleManualChainring(e)}" required></input>
<datalist id="chainring-dl">
${chainrings.map(d => htm`
<option>${d.seriesName}: ${d.chainring}</option>
`)}
</datalist>
</div>
<div class="input-group">
<label for="name-in">Label</label>
<input name="label-in" type="text" onChange=${(e) => this.handleLabel(e)} value="${this.state.label}"></input>
</div>
<div class="input-group il">
<label for="wheel-in">Wheel diameter (mm)</label>
<input name="wheel-in" type="number" style="width: 100px" onChange=${(e) => this.handleWheel(e)} value=${this.state.wheel}></input>
</div>
<div class="input-group il">
<label for="wheel-in">Crank length (mm)</label>
<input name="crank-in" type="number" style="width: 100px" onChange=${(e) => this.handleCrank(e)} value=${this.state.crank}></input>
</div>
<div class="input-group">
<input type="submit" value="Add Drivetrain"></input>
</div>
</form>
</div>
`;
}
}
Insert cell
Insert cell
pickerStyle = {
return html`<style>
.input-group{
margin: .25em;
}
.il{
display: inline-block;
margin-right: 1em;
}
.input-group > input[type="submit"]{
font-size: 25px;
margin-bottom: .5em;
}
.input-group > label{
font-family: Helvetica;
font-size: 14px;
font-weight: bold;
display: block;
}
</style>
`
}
Insert cell
Insert cell
cassettesRaw = d3.tsv('https://raw.githubusercontent.com/tysonanderson/drivetrain/master/cassettes.csv')
Insert cell
cranksetsRaw = d3.tsv('https://raw.githubusercontent.com/tysonanderson/drivetrain/master/cranksets.csv')
Insert cell
d3 = require('d3@5');
Insert cell
htm = (await require("htm@2/dist/htm.umd.js")).bind(Preact.h)
Insert cell
Preact = require("preact@8/dist/preact.min.js").catch(() => window.preact)
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