Handler for bidirectional unit conversion form Building a form where values can be entered in either pounds or kilos.

Script is...

function onlyNumber(fld) {
     if(fld.value.match(/[^0-9.]/)) {
     fld.value=fld.value.replace(/[^0-9.]/g,'');
     }
}
function convertUnit(sense, value) {
    retValue = 0;
    if (isNaN (value)) { alert ('Non-numeric value');  return 0; }
    value = parseFloat (value);
    var factor = 0.4536;
    if (sense == 'kg2lb') {
         retValue = value/factor;
         retValue = Math.round(retValue);
    }
    else if (sense == 'lb2kg') {
         retValue = value*factor;
         retValue = Math.round(retValue);
    }
    return retValue;
}


Works fine but I have to repeat this on every input:

onblur="this.form.kg_va.value=convertUnit('lb2kg',this.value);"     
onkeyup="onlyNumber(this);" onfocus="if(this.value == '0') { this.value = ''; }" 


Is there some way to simplify the onblur code ?

For example, is there a way to have the function focus on the same var pairs? The var pair being lb_FOOBAR and kg_FOOBAR.

And what about the input functions that are exactly the same?

onkeyup="onlyNumber(this);" onfocus="if(this.value == '0') { this.value = ''; }"


Any way to avoid having to repeat them for each input? Form will have 12 fields.
Instead of inlining the script, use addEventListener instead. To retrieve the elements, you'd need something like getElementsByClassName or querySelectorAll to return an array-like structure of elements. You loop through them, and attach a listener each.

var formInputs = Array.prototype.slice.call(document.querySelectorAll('.form-input'));
formInputs.forEach(function(element){
  element.addEventListener('blur', function(){
    // blur code
  });
  element.addEventListener('keyup', function(){
    // blur code
  });
});


The Array.prototype.slice.call is to convert the array-like structure returned by querySelectorAll into a real array. That's so I can use forEach. But a regular for loop will do, since a NodeList (the array-like structure) has a length property.

Now instead of alert and return, why not throw an error instead?

if(isNaN(value)) throw new Error('Non-numeric value');


Also, instead of putting all your conversions in a single function and sending a "sense", why not create a function for each kind of conversion? It's more verbose, but you don't have to pile up everything in one function.