Grz
Grz

Reputation: 39

Javascript & HTML unit converter - how to use one input field as constant

I am trying to convert a Python script into an HTML/Javascript web based converter. The script is very simple and I followed the steps at https://www.w3schools.com/howto/howto_js_length_converter.asp, which work great, if all fields are dynamic. In my case, I need one variable to not change. On an example: user provides the "AssayWeight" value and one of the following: PPM or Grav. After that, scripts calculates the other value from PPM/Grav that the user didn't provide. Here's the code I have so far:

<script>
function ppmtoGravConverter(source,valNum) {
  valNum = parseFloat(valNum);
  var inputPPMtoGrav = document.getElementById("inputPPMtoGrav");
  var inputAssayWeight = document.getElementById("inputAssayWeight");
  var inputGravtoPPM = document.getElementById("inputGravtoPPM");
  if (source=="inputPPMtoGrav") {
    inputGravtoPPM.value=(valNum*inputAssayWeight/1000).toFixed(4);
  }
  if (source=="inputGravtoPPM") {
    inputPPMtoGrav.value=(valNum*1000/inputAssayWeight).toFixed(4);
  }
}
</script>

and html from w3schools:

<label>Assay Weight</label>
<input id="inputAssayWeight" type="number" placeholder="Assay Weight" oninput="ppmtoGravConverter(this.id,this.value)" onchange="ppmtoGravConverter(this.id,this.value)">
<br><br>

<label>PPM</label>
<input id="inputPPMtoGrav" type="number" placeholder="PPM" oninput="ppmtoGravConverter(this.id,this.value)" onchange="ppmtoGravConverter(this.id,this.value)">

<label>Grav (mg)</label>
<input id="inputGravtoPPM" type="number" placeholder="Grav (mg)" oninput="ppmtoGravConverter(this.id,this.value)" onchange="ppmtoGravConverter(this.id,this.value)">

Please let me know what am I missing. This is my 2nd day looking at Javascript. Thanks!

Upvotes: 0

Views: 528

Answers (2)

zer00ne
zer00ne

Reputation: 43880

  1. Wrap everything in a <form> tag and give it an #id.

    <form id='main'><!-- EVERYTHING --></form>
    
  2. Bind "input" event to the <form> and call an event handler (i.e. a function to handle a triggered event). Refer to: JavaScript Event Handling

    document.forms.main.oninput = inputHandler;
    
  3. Define function inputHandler() -- remember to pass the Event Object

    function inputHandler(event) {...
    
  4. Define all variables -- refer to: Obtaining References to Forms and Form Elements in JavaScript

    // Collect all form controls into a NodeList
    const field = this.elements;
    
    // Find the element user interacted with
    const input = event.target;
    
    // Reference any form control by #id or [name] attribute by prefixing it with `field`
    const aW = field.assayWeight;
    
    // Assign a variable to form control values and convert them into a real Number
    let AWT = parseFloat(aW.value);
    
  5. Delegate "input" event by using if/else flow control statements. By explicitly allowing specific elements to react to an event and implicitly preventing other elements by simple omission is an important part of a programming paradigm called Event Delegation.

     if (input.matches('#assayWeight')) {...
    
  6. The HTML/CSS layout and styling features a toggling system in which it allows the user to enter "assay weight" and either "PPM" or "Grav". Hover over the titles and then click one and then the other to see the toggling. Refer to: Exposing Form Fields Via Checked Radio Buttons

     [name=conv],
     .mask {
       display: none
     }
    
     [name=conv]:checked + fieldset .mask {
       display: inline-block;
     }
    

Demo

document.forms.convPpmG.oninput = convert;

function convert(event) {
  const field = this.elements;
  const input = event.target;
  const awt = field.aWt;
  const ppm = field.pPM;
  const grv = field.grv;
  const gtp = field.gToP;
  const ptg = field.pToG;
  let AWT = parseFloat(awt.value);
  let PPMin = parseFloat(ppm.value);
  let GRVin = parseFloat(grv.value);

  if (input.matches('#aWt')) {
    // log(AWT, "Assay Weight");
  }

  if (input.matches('#pPM')) {
    // log(PPMin, "PPM Input");
    let GRVout = PPMin * AWT / 1000;
    // log(GRVout, "Grav Output");
    ptg.value = GRVout.toFixed(4);
  }

  if (input.matches('#grv')) {
    // log(GRVin, "Grav Input");
    let PPMout = GRVin * 1000 / AWT;
    // log(PPMout, "PPM Output");
    gtp.value = PPMout.toFixed(4);
  }
}

// A utility logger - not required
const log = (data, key = 'Field') => console.log(JSON.stringify(key + ': ' + data));
root,
body {
  font: 400 3vw/1.5 Consolas, monospace;
}

fieldset fieldset {
  min-height: 20vh;
}

input,
output {
  width: 10ch;
  margin-right: 5px;
  margin-bottom: 8px;
  font: inherit;
  text-align: right;
}

#aWt {
  display: inline-block;
}

[type=reset] {
  text-align: center;
}

.switch {
  padding: 3px 5px;
}

[type=reset]:hover,
.switch:hover {
  color: tomato;
  background: rgba(56, 87, 199, 0.4);
  cursor: pointer;
}

[name=conv],
.mask {
  display: none
}

[name=conv]:checked+fieldset .mask {
  display: inline-block;
}
<form id='convPpmG'>
  <fieldset>
    <legend>PPM / Grav Convertor</legend>
    <label>Assay Weight</label>
    <input id="aWt" type="number" min='0' value="0">
    <input type='reset'>
    <br>

    <input id='ppmToGrav' name='conv' type='radio'>
    <fieldset>
      <legend>
        <label for='ppmToGrav' class='switch'>PPM to Grav</label>
      </legend>
      <label class='mask'>
      PPM: <input id="pPM" type="number" min='0' value="0">
      to Grav: <output id='pToG'>0</output> mg
      </label>
    </fieldset>

    <hr>

    <input id='gravToPPM' name='conv' type='radio'>
    <fieldset>
      <legend>
        <label for='gravToPPM' class='switch'>Grav to PPM</label>
      </legend>
      <label class='mask'>
      Grav: <input id="grv" type="number" min='0' value="0">
      mg to PPM: <output id='gToP'>0</output>
      </label>
    </fieldset>

  </fieldset>
</form>

Upvotes: 1

dkapur17
dkapur17

Reputation: 516

The issue is that in your formula, you are using inputAssayWeight instead of actually taking its value and using it. Replace those two if conditions with

  if (source=="inputPPMtoGrav") {
    inputGravtoPPM.value=(valNum*parseFloat(inputAssayWeight.value)/1000).toFixed(4);
  }
  if (source=="inputGravtoPPM") {
    inputPPMtoGrav.value=(valNum*1000/parseFloat(inputAssayWeight.value)).toFixed(4);
  }

That should fix your issue.

Upvotes: 1

Related Questions