skip to Main Content

I have customer site with a set of customized procedures that I maintain. We have a process we use for converting energy for a specific calibration. We take a reading, multiply it by an offset, then enter the result into the test form. The page we have only has limited functionality so I am trying to use HTML form as well as JavaScript for the calculations.

Below is what I have but for some reason the result isn’t showing up to the right of each of the readings that get entered. I only dabble a little with coding so I’m probably missing something obvious.

<!DOCTYPE html>
<html>
<body>

<h2>OAI Offset Caclculation</h2>
<script>
    function oaicalc(offset, reading1, reading2, reading3, reading4, reading5) {
//value near 1.000  
        var offset = parseFloat(document.getElementById('offset').value); 
//Energy value in mj 200.0> value <1.000
        var r1 = parseFloat(document.getElementById('reading1').value); 
        var r2 = parseFloat(document.getElementById('reading2').value);
        var r3 = parseFloat(document.getElementById('reading3').value);
        var r4 = parseFloat(document.getElementById('reading4').value);
        var r5 = parseFloat(document.getElementById('reading5').value);

//Corrected Energy Values
        var o1 = offset * r1;
        var o2 = offset * r2;
        var o3 = offset * r3;
        var o4 = offset * r4;
        var o5 = offset * r5;

//Chage HTML form Output
        document.getElementById('output1').innerHTML = o1;
        document.getElementById('output2').innerHTML = o2;
        document.getElementById('output3').innerHTML = o3;
        document.getElementById('output4').innerHTML = o4;
        document.getElementById('output5').innerHTML = o5;
    }
</script>


<form id="oaioffsetform">
  <label for="offset">Offset:</label><br>
  <input type="number" id="offset" name="offset" value="0">
  <br>
  <br>
  <label for="reading1">OAI Reading 1:</label><br>
  <input type="number" id="reading1" name="reading1" value="0" oninput="oaicalc()">:  <output name="output1">0</output>
  <br>
  <br>
  <label for="reading2">OAI Reading 2:</label><br>
  <input type="number" id="reading2" name="reading2" value="0" oninput="oaicalc()">:  <output name="output2">0</output>
  <br>
  <br>
  <label for="reading3">OAI Reading 3:</label><br>
  <input type="number" id="reading3" name="reading3" value="0" oninput="oaicalc()">:  <output name="output3">0</output>
  <br>
  <br>
  <label for="reading4">OAI Reading 4:</label><br>
  <input type="number" id="reading4" name="reading4" value="0" oninput="oaicalc()">:  <output name="output4">0</output>
  <br>
  <br>
  <label for="reading5">OAI Reading 5:</label><br>
  <input type="number" id="reading5" name="reading5" value="0" oninput="oaicalc()">:  <output name="output5">0</output><br><br>
</form> 


</body>
</html>

2

Answers


  1. As was mentioned in the comments, your form fields have name attributes but you are attempting to access them as if they had id attributes. You can access an element by its name attribute by using .querySelector().
    You really should strive to avoid using id attributes on elements as their use makes the solution brittle and causes problems with scaling an application down the line. In most cases, you can avoid them completely.

    Your HTML is not correct for a few reasons:

    • You don’t have a <head> element in your document.
    • The first heading in a document should be h1 and h2 would only
      then be used if you were trying to define a sub-section of that h1.
      Do not use heading elements because of the way they style the text,
      you can use CSS to alter the styling. Headings are for creating
      document structure that is used by those who rely on assistive
      technologies, like screen readers to help them navigate the page
      content.
    • You should not be using br elements to create visual alignment on
      the page. br elements are to be used solely to break up a line of
      block level content (i.e., paragraphs, divs, etc.) that must appear
      on the next line down. They should not be used to add white vertical
      space to a page. Again, use CSS for that.
    • You should be separating your JavaScript from your HTML and therefore
      not use inline event attributes like oninput in your HTML. Instead,
      do your event binding in JavaScript with .addEventListener().

    .innerHTML should be avoided whenever possible as there are security and performance implications to using it. Since the data you are working with doesn’t contain any HTML that needs to be parsed, you should use .textContent.

    See updated code below:

    div { margin-top:.5em; }
    <!DOCTYPE html>
    <html>
    <head>
      <title>Page title here</title>
    </head>
    <body>
    
    <h1>OAI Offset Calculation</h1>
    
    <form>
      <div>
        <!-- An alternate way to use <label> elements is to wrap them around the element
             that they are a label for. This way you don't need any ID's. -->
        <label>Offset:<br>
          <input type="number" name="offset" value="0">
        </label>
      </div>
      <div>
        <label>OAI Reading 1:<br>
          <input type="number" name="reading1" value="0">
        </label>
        :  <output name="output1">0</output>
      </div>
      <div>
        <label>OAI Reading 2:<br>
          <input type="number" name="reading2" value="0">
        </label>
        :  <output name="output2">0</output>
      </div>
      <div>
       <label>OAI Reading 3:<br>
         <input type="number" name="reading3" value="0">
       </label>
       :  <output name="output3">0</output>
      </div>
      <div>
        <label>OAI Reading 4:<br>
          <input type="number" name="reading4" value="0">   
        </label>
        :  <output name="output4">0</output> 
      </div>
    
      <div>
        <label>OAI Reading 5:<br>
          <input type="number" name="reading5" value="0">
        </label>
        :  <output name="output5">0</output>
      </div>
    </form> 
    
    <!-- Your <script> element should be the last thing in the <body> so that
         by the time the HTML parser reaches it, all the HTML elements will
         have been parsed into memory and will be available for use. -->
    <script>
      // Use const on element references
      // Get all your element references just once rather than every time the function runs
      // Don't set variables to the property of an element because if you ever want a different
      // proeprty value, you'd need to scan the document again for the same element.
      const r1 = document.querySelector("[name='reading1']"); 
      const r2 = document.querySelector("[name='reading2']");
      const r3 = document.querySelector("[name='reading3']");
      const r4 = document.querySelector("[name='reading4']");
      const r5 = document.querySelector("[name='reading5']");
      const offset = document.querySelector("[name='offset']"); 
      const o1 = document.querySelector("[name='output1']");
      const o2 = document.querySelector("[name='output2']");
      const o3 = document.querySelector("[name='output3']");
      const o4 = document.querySelector("[name='output4']");
      const o5 = document.querySelector("[name='output5']");  
      
      // Set your events up in JavaScript, not HTML
      r1.addEventListener("input", oaicalc);
      r2.addEventListener("input", oaicalc);
      r3.addEventListener("input", oaicalc);
      r4.addEventListener("input", oaicalc);
      r5.addEventListener("input", oaicalc);  
    
      // You aren't passing anything to this function and your elements are already
      // referenced, so you don't need any function arguments.
      function oaicalc() {
        // Now you only need to get the values and parse them
        let offsetValue = parseFloat(offset.value); 
    
        // Use .textContent when there is no HTML in the string you are working with
        o1.textContent = offsetValue * parseFloat(r1.value);
        o2.textContent = offsetValue * parseFloat(r2.value);
        o3.textContent = offsetValue * parseFloat(r3.value);
        o4.textContent = offsetValue * parseFloat(r4.value);
        o5.textContent = offsetValue * parseFloat(r5.value);   
      }
    </script>
    </body>
    </html>
    Login or Signup to reply.
  2. Here I created a general event listener for input on the form. The input element is the target on the event object. You don’t need to parse the value of the input, now that they have the type of number.

    If the offset is updated you need to run through all the input elements to calculate a new value.

    General comment: use the name attribute for both form and input elements. I makes if easy to find the right element.

    document.forms.oaioffsetform.addEventListener('input', e => {
      let form = e.target.form;
      if (e.target.dataset.id) {
        let outvalue = e.target.value * form.offset.value;
        form[`output${e.target.dataset.id}`].value = outvalue;
      }
      if (e.target.name == 'offset') {
        [...form.readings.querySelectorAll('input')].forEach(input => {
          let outvalue = input.value * form.offset.value;
          form[`output${input.dataset.id}`].value = outvalue;
        });
      }
    });
    fieldset {
      border: none;
      padding: 0;
    }
    <h2>OAI Offset Caclculation</h2>
    <form name="oaioffsetform">
      <label for="offset">Offset:</label><br>
      <input type="number" name="offset" value="0">
      <br>
      <br>
      <fieldset name="readings">
        <label for="reading1">OAI Reading 1:</label><br>
        <input type="number" name="reading1" data-id="1" value="0">: <output name="output1">0</output>
        <br>
        <br>
        <label for="reading2">OAI Reading 2:</label><br>
        <input type="number" name="reading2" data-id="2" value="0">: <output name="output2">0</output>
        <br>
        <br>
        <label for="reading3">OAI Reading 3:</label><br>
        <input type="number" name="reading3" data-id="3" value="0">: <output name="output3">0</output>
        <br>
        <br>
        <label for="reading4">OAI Reading 4:</label><br>
        <input type="number" name="reading4" data-id="4" value="0">: <output name="output4">0</output>
        <br>
        <br>
        <label for="reading5">OAI Reading 5:</label><br>
        <input type="number" name="reading5" data-id="5" value="0">: <output name="output5">0</output><br><br>
      </fieldset>
    </form>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search