let rawData = { "bounciness": 0.5, "gravity": -0.25, "friction": 1.2, "windVector": { "ang": 2.7314, "mag": 4.23 } }
let resultJson = document.querySelector('.result.json');
let resultBase64 = document.querySelector('.result.base64');
let elems = [ 'bounciness', 'gravity', 'friction', 'windVector-ang', 'windVector-mag' ]
.map(v => document.querySelector(`[name="${v}"]`));
let [ bElem, gElem, fElem, waElem, wmElem ] = elems;
let fullUpdate = () => {
if (document.querySelector(':invalid')) {
resultJson.innerHTML = 'Invalid input';
resultBase64.innerHTML = 'Invalid input';
return;
}
let json = JSON.stringify(rawData);
resultJson.innerHTML = json;
resultBase64.innerHTML = btoa(json);
};
let updateElem = (elem, obj, prop) => {
elem.value = obj[prop].toString();
elem.addEventListener('input', evt => {
if (elem.matches(':valid')) obj[prop] = parseFloat(elem.value, 10);
fullUpdate();
});
};
updateElem(bElem, rawData, 'bounciness');
updateElem(gElem, rawData, 'gravity');
updateElem(fElem, rawData, 'friction');
updateElem(waElem, rawData.windVector, 'ang');
updateElem(wmElem, rawData.windVector, 'mag');
fullUpdate();
input { display: block; }
input:valid { background-color: rgba(0, 150, 0, 0.2); }
input:invalid { background-color: rgba(150, 0, 0, 0.2); }
p { margin: 0; margin-top: 5px; }
.result {
font-family: monospace;
border: 2px solid #a0a0a0;
margin-top: 0;
overflow: hidden;
text-overflow: ellipsis;
}
<p>Bounciness</p>
<input type="text" pattern="[-+]?[0-9]+([.][0-9]+)?" name="bounciness" />
<p>Gravity</p>
<input type="text" pattern="[-+]?[0-9]+([.][0-9]+)?" name="gravity" />
<p>Friction</p>
<input type="text" pattern="[-+]?[0-9]+([.][0-9]+)?" name="friction" />
<p>Wind Angle</p>
<input type="text" pattern="[-+]?[0-9]+([.][0-9]+)?" name="windVector-ang" />
<p>Wind Magnitude</p>
<input type="text" pattern="[-+]?[0-9]+([.][0-9]+)?" name="windVector-mag" />
<p>JSON</p>
<p class="result json"></p>
<p>Base64</p>
<p class="result base64"></p>