Add inline +/- buttons for number inputs, hide default spinners

This commit is contained in:
Michael Winter 2026-04-09 11:07:18 +02:00
parent c217e04243
commit a08c944f34
2 changed files with 214 additions and 24 deletions

View file

@ -75,6 +75,16 @@
font-size: 14px;
}
/* Hide default number input spinners */
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
input[type="number"] {
-moz-appearance: textfield;
}
.form-group input:focus {
outline: none;
border-color: #444444;
@ -92,6 +102,33 @@
align-items: center;
}
/* Number input with inline +/- buttons */
.number-input-group {
display: inline-flex;
align-items: center;
}
.number-input-group input {
width: 50px;
text-align: center;
margin: 0 2px;
}
.number-btn {
width: 24px;
height: 24px;
padding: 0;
font-size: 14px;
cursor: pointer;
background: #0a0a0a;
color: #666666;
border: 1px solid #222222;
border-radius: 3px;
}
.number-btn:hover {
background: #151515;
color: #999999;
border-color: #444444;
}
.checkbox-group label {
margin-bottom: 0;
text-transform: none;
@ -214,15 +251,27 @@
<div class="form-row">
<div class="form-group">
<label>Dims</label>
<input type="number" id="dims" value="7" min="1" max="10">
<div class="number-input-group">
<button type="button" class="number-btn" onclick="adjustValue('dims', -1)"></button>
<input type="number" id="dims" value="7" min="1" max="10">
<button type="button" class="number-btn" onclick="adjustValue('dims', 1)">+</button>
</div>
</div>
<div class="form-group">
<label>Chord Size</label>
<input type="number" id="chordSize" value="3" min="1" max="10">
<div class="number-input-group">
<button type="button" class="number-btn" onclick="adjustValue('chordSize', -1)"></button>
<input type="number" id="chordSize" value="3" min="1" max="10">
<button type="button" class="number-btn" onclick="adjustValue('chordSize', 1)">+</button>
</div>
</div>
<div class="form-group">
<label>Max Path</label>
<input type="number" id="maxPath" value="50" min="1">
<div class="number-input-group">
<button type="button" class="number-btn" onclick="adjustValue('maxPath', -1)"></button>
<input type="number" id="maxPath" value="50" min="1">
<button type="button" class="number-btn" onclick="adjustValue('maxPath', 1)">+</button>
</div>
</div>
<div class="form-group">
<label>Seed (optional)</label>
@ -236,7 +285,11 @@
</div>
<div class="form-group">
<label>Fundamental (Hz)</label>
<input type="number" id="fundamental" value="55" step="any">
<div class="number-input-group">
<button type="button" class="number-btn" onclick="adjustValue('fundamental', -1)"></button>
<input type="number" id="fundamental" value="55" step="any">
<button type="button" class="number-btn" onclick="adjustValue('fundamental', 1)">+</button>
</div>
</div>
<div class="form-group">
<label>Transcribe Name</label>
@ -250,19 +303,35 @@
<div class="form-row">
<div class="form-group">
<label>Symdiff Min</label>
<input type="number" id="symdiffMin" value="2" min="0">
<div class="number-input-group">
<button type="button" class="number-btn" onclick="adjustValue('symdiffMin', -1)"></button>
<input type="number" id="symdiffMin" value="2" min="0">
<button type="button" class="number-btn" onclick="adjustValue('symdiffMin', 1)">+</button>
</div>
</div>
<div class="form-group">
<label>Symdiff Max</label>
<input type="number" id="symdiffMax" value="2" min="0">
<div class="number-input-group">
<button type="button" class="number-btn" onclick="adjustValue('symdiffMax', -1)"></button>
<input type="number" id="symdiffMax" value="2" min="0">
<button type="button" class="number-btn" onclick="adjustValue('symdiffMax', 1)">+</button>
</div>
</div>
<div class="form-group">
<label>Melodic Min</label>
<input type="number" id="melodicMin" value="0" min="0">
<div class="number-input-group">
<button type="button" class="number-btn" onclick="adjustValue('melodicMin', -1)"></button>
<input type="number" id="melodicMin" value="0" min="0">
<button type="button" class="number-btn" onclick="adjustValue('melodicMin', 1)">+</button>
</div>
</div>
<div class="form-group">
<label>Melodic Max</label>
<input type="number" id="melodicMax" value="500" min="0">
<div class="number-input-group">
<button type="button" class="number-btn" onclick="adjustValue('melodicMax', -1)"></button>
<input type="number" id="melodicMax" value="500" min="0">
<button type="button" class="number-btn" onclick="adjustValue('melodicMax', 1)">+</button>
</div>
</div>
</div>
</div>
@ -272,19 +341,35 @@
<div class="form-row">
<div class="form-group">
<label>Target Register (octaves)</label>
<input type="number" id="targetRegister" value="0" step="any">
<div class="number-input-group">
<button type="button" class="number-btn" onclick="adjustValue('targetRegister', -1)"></button>
<input type="number" id="targetRegister" value="0" step="any">
<button type="button" class="number-btn" onclick="adjustValue('targetRegister', 1)">+</button>
</div>
</div>
<div class="form-group">
<label>Target Register Power</label>
<input type="number" id="targetRegisterPower" value="1.0" step="any">
<div class="number-input-group">
<button type="button" class="number-btn" onclick="adjustValue('targetRegisterPower', -1)"></button>
<input type="number" id="targetRegisterPower" value="1.0" step="any">
<button type="button" class="number-btn" onclick="adjustValue('targetRegisterPower', 1)">+</button>
</div>
</div>
<div class="form-group">
<label>Oscillations</label>
<input type="number" id="targetRegisterOscillations" value="0" step="any">
<div class="number-input-group">
<button type="button" class="number-btn" onclick="adjustValue('targetRegisterOscillations', -1)"></button>
<input type="number" id="targetRegisterOscillations" value="0" step="any">
<button type="button" class="number-btn" onclick="adjustValue('targetRegisterOscillations', 1)">+</button>
</div>
</div>
<div class="form-group">
<label>Amplitude</label>
<input type="number" id="targetRegisterAmplitude" value="0.25" step="any">
<div class="number-input-group">
<button type="button" class="number-btn" onclick="adjustValue('targetRegisterAmplitude', -1)"></button>
<input type="number" id="targetRegisterAmplitude" value="0.25" step="any">
<button type="button" class="number-btn" onclick="adjustValue('targetRegisterAmplitude', 1)">+</button>
</div>
</div>
</div>
</div>
@ -312,37 +397,69 @@
<div class="form-row">
<div class="form-group">
<label>Weight Melodic</label>
<input type="number" id="weightMelodic" value="1" step="any">
<div class="number-input-group">
<button type="button" class="number-btn" onclick="adjustValue('weightMelodic', -1)"></button>
<input type="number" id="weightMelodic" value="1" step="any">
<button type="button" class="number-btn" onclick="adjustValue('weightMelodic', 1)">+</button>
</div>
</div>
<div class="form-group">
<label>Weight Contrary Motion</label>
<input type="number" id="weightContraryMotion" value="0" step="any">
<div class="number-input-group">
<button type="button" class="number-btn" onclick="adjustValue('weightContraryMotion', -1)"></button>
<input type="number" id="weightContraryMotion" value="0" step="any">
<button type="button" class="number-btn" onclick="adjustValue('weightContraryMotion', 1)">+</button>
</div>
</div>
<div class="form-group">
<label>Weight DCA Hamiltonian</label>
<input type="number" id="weightDcaHamiltonian" value="1" step="any">
<div class="number-input-group">
<button type="button" class="number-btn" onclick="adjustValue('weightDcaHamiltonian', -1)"></button>
<input type="number" id="weightDcaHamiltonian" value="1" step="any">
<button type="button" class="number-btn" onclick="adjustValue('weightDcaHamiltonian', 1)">+</button>
</div>
</div>
<div class="form-group">
<label>Weight DCA Voice Movement</label>
<input type="number" id="weightDcaVoiceMovement" value="1" step="any">
<div class="number-input-group">
<button type="button" class="number-btn" onclick="adjustValue('weightDcaVoiceMovement', -1)"></button>
<input type="number" id="weightDcaVoiceMovement" value="1" step="any">
<button type="button" class="number-btn" onclick="adjustValue('weightDcaVoiceMovement', 1)">+</button>
</div>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label>Weight RGR Voice Movement</label>
<input type="number" id="weightRgrVoiceMovement" value="0" step="any">
<div class="number-input-group">
<button type="button" class="number-btn" onclick="adjustValue('weightRgrVoiceMovement', -1)"></button>
<input type="number" id="weightRgrVoiceMovement" value="0" step="any">
<button type="button" class="number-btn" onclick="adjustValue('weightRgrVoiceMovement', 1)">+</button>
</div>
</div>
<div class="form-group">
<label>RGR Threshold</label>
<input type="number" id="rgrVoiceMovementThreshold" value="5" min="1">
<div class="number-input-group">
<button type="button" class="number-btn" onclick="adjustValue('rgrVoiceMovementThreshold', -1)"></button>
<input type="number" id="rgrVoiceMovementThreshold" value="5" min="1">
<button type="button" class="number-btn" onclick="adjustValue('rgrVoiceMovementThreshold', 1)">+</button>
</div>
</div>
<div class="form-group">
<label>Weight Harmonic Compactness</label>
<input type="number" id="weightHarmonicCompactness" value="0" step="any">
<div class="number-input-group">
<button type="button" class="number-btn" onclick="adjustValue('weightHarmonicCompactness', -1)"></button>
<input type="number" id="weightHarmonicCompactness" value="0" step="any">
<button type="button" class="number-btn" onclick="adjustValue('weightHarmonicCompactness', 1)">+</button>
</div>
</div>
<div class="form-group">
<label>Weight Target Register</label>
<input type="number" id="weightTargetRegister" value="1" step="any">
<div class="number-input-group">
<button type="button" class="number-btn" onclick="adjustValue('weightTargetRegister', -1)"></button>
<input type="number" id="weightTargetRegister" value="1" step="any">
<button type="button" class="number-btn" onclick="adjustValue('weightTargetRegister', 1)">+</button>
</div>
</div>
</div>
</div>
@ -378,6 +495,16 @@
</div>
<script>
function adjustValue(id, delta) {
const input = document.getElementById(id);
const min = parseFloat(input.min) || -Infinity;
const max = parseFloat(input.max) || Infinity;
const step = parseFloat(input.step) || 1;
let val = parseFloat(input.value) || 0;
val = Math.max(min, Math.min(max, val + (delta * step)));
input.value = step % 1 !== 0 ? parseFloat(val.toFixed(2)) : Math.round(val);
}
function getFormData() {
return {
dims: parseInt(document.getElementById('dims').value) || 7,

View file

@ -263,6 +263,16 @@
border-radius: 4px;
}
/* Hide default number input spinners */
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
input[type="number"] {
-moz-appearance: textfield;
}
.file-select {
padding: 8px;
background: #0a0a0a;
@ -271,6 +281,33 @@
border-radius: 4px;
margin-left: 10px;
}
/* Number input with inline +/- buttons */
.number-input-group {
display: inline-flex;
align-items: center;
}
.number-input-group input {
width: 50px;
text-align: center;
margin: 0 2px;
}
.number-btn {
width: 24px;
height: 24px;
padding: 0;
font-size: 14px;
cursor: pointer;
background: #0a0a0a;
color: #666666;
border: 1px solid #222222;
border-radius: 3px;
}
.number-btn:hover {
background: #151515;
color: #999999;
border-color: #444444;
}
</style>
</head>
<body>
@ -282,13 +319,29 @@
<input type="text" id="filepathInput" value="output/output_chords.json" style="width: 250px;">
<button id="loadFileBtn">Load</button>
<span style="margin-left: 20px;">Fundamental (Hz):</span>
<input type="number" id="fundamentalInput" value="110" style="width: 60px;">
<div class="number-input-group">
<button type="button" class="number-btn" onclick="adjustValue('fundamentalInput', -1)"></button>
<input type="number" id="fundamentalInput" value="110" style="width: 60px;">
<button type="button" class="number-btn" onclick="adjustValue('fundamentalInput', 1)">+</button>
</div>
<span style="margin-left: 15px;">Octave:</span>
<input type="number" id="octaveInput" value="2" style="width: 40px;">
<div class="number-input-group">
<button type="button" class="number-btn" onclick="adjustValue('octaveInput', -1)"></button>
<input type="number" id="octaveInput" value="2" style="width: 40px;">
<button type="button" class="number-btn" onclick="adjustValue('octaveInput', 1)">+</button>
</div>
<span style="margin-left: 15px;">Ramp (s):</span>
<input type="number" id="rampDuration" value="3" step="0.1" style="width: 60px;">
<div class="number-input-group">
<button type="button" class="number-btn" onclick="adjustValue('rampDuration', -1)"></button>
<input type="number" id="rampDuration" value="3" step="0.1" style="width: 60px;">
<button type="button" class="number-btn" onclick="adjustValue('rampDuration', 1)">+</button>
</div>
<span style="margin-left: 10px;">Exponent:</span>
<input type="number" id="rampExponent" value="1" min="0.1" max="5" step="0.1" style="width: 50px;">
<div class="number-input-group">
<button type="button" class="number-btn" onclick="adjustValue('rampExponent', -1)"></button>
<input type="number" id="rampExponent" value="1" min="0.1" max="5" step="0.1" style="width: 50px;">
<button type="button" class="number-btn" onclick="adjustValue('rampExponent', 1)">+</button>
</div>
<span style="margin-left: 15px;">Siren IP:</span>
<input type="text" id="sirenIp" value="192.168.4.200" style="width: 100px;">
<button id="toggleUnitBtn" style="margin-left: 15px;">Show: Cents</button>
@ -328,6 +381,16 @@
let allGraphsData = null;
let displayMode = 'cents';
function adjustValue(id, delta) {
const input = document.getElementById(id);
const min = parseFloat(input.min) || -Infinity;
const max = parseFloat(input.max) || Infinity;
const step = parseFloat(input.step) || 1;
let val = parseFloat(input.value) || 0;
val = Math.max(min, Math.min(max, val + (delta * step)));
input.value = step % 1 !== 0 ? parseFloat(val.toFixed(2)) : Math.round(val);
}
// Parse fraction string like "3/2" or "1" into a number
function parseFraction(fracStr) {
if (!fracStr || fracStr === "1") return 1;