2
\$\begingroup\$

I am attempting to port a linear function that I designed in a spreadsheet into HTML and Javascript. It's based on linear least squares where I have to take a Matrix and multiply it by its transformation. At any rate. I am attempting to lay out a basic input system in Javascript/HTML where I can enter in variable data. I have to take in quite a few more inputs, so I am looking for a more maintainable code pattern with less duplication.

In the name of make it work, then make it better. I came up with the following code.

Very new to javascript and the scope is hurting my brain! I am thinking that a dictionary (or similar) where I can pass that to a function then iterate over the values to update my HTML view. But again I am really new to Javascript.

The code also in JS BIN.

 

window.onload = function() {

    var EnameField = document.getElementById('EnameField');
    var ENameValue = undefined;
    var MnameField = document.getElementById('MnameField');
    var MNameValue = undefined;
    var CnameField = document.getElementById('CnameField');
    var CNameValue = undefined;
    var FnameField = document.getElementById('FnameField');
    var FNameValue = undefined;

    updateNameDisplay();

    setInterval(updateNameDisplay, 100);

    function updateNameDisplay() {
        var thisEValue = EnameField.value || " ";
        if (ENameValue != thisEValue) {
            document.getElementById('EnameDisplay').innerHTML = ENameValue = thisEValue;
        }


        var thisMValue = MnameField.value || " ";
        if (MNameValue != thisMValue) {
            document.getElementById('MnameDisplay').innerHTML = MNameValue = thisMValue;
        }


        var thisCValue = CnameField.value || " ";
        if (CNameValue != thisCValue) {
            document.getElementById('CnameDisplay').innerHTML = CNameValue = thisCValue;
        }


        var thisFValue = FnameField.value || " ";
        if (FNameValue != thisFValue) {
            document.getElementById('FnameDisplay').innerHTML = FNameValue = thisFValue;
        }

    }

};
<!DOCTYPE html>
<html>
   <head>
      <meta charset=utf-8 />
      <title>Test Page</title>
   </head>
   <body>
      <form>
         How many E's <input type='text' id='EnameField'><br>
         How many M's <input type='text' id='MnameField'><br>
         How many C's <input type='text' id='CnameField'><br>
         How many F's <input type='text' id='FnameField'><br>
      </form>
      <hr>
      E's: <span id='EnameDisplay'>??</span><br>
      M's:<span id='MnameDisplay'>??</span><br>
      C's: <span id='CnameDisplay'>??</span><br>
      F's: <span id='FnameDisplay'>??</span><br>
   </body>

\$\endgroup\$
0
\$\begingroup\$

Handling the Problem

To make this scalable you need to generate the HTML to fit however many items you want to include. To Render it this way you need a data structure to hold what you want to render.

First Think of the data structure then what functions you need to render this data.

My Solution

I picked the following data structure.

[{
  title: String
  value: Number
}]

Here is the list of render functions I picked.

  • renderForm -> Render just the form
  • renderResults -> Render just the results
  • render -> Render the entire screen

And finally, we will need to capture the data changes from the form to update the data structure and then call renderResults so I created the onFormChange function.

Code

// Code goes here

const data = [{
  title: 'E',
  value: 0
}, {
  title: 'M',
  value: 0
}, {
  title: 'C',
  value: 0
}, {
  title: 'F',
  value: 0
}]

function onFormChange (value, i) {
  data[i].value = value;
  renderResults();
}

function renderForm () {
  const elForm = document.getElementById('form');
  let html = '';
  elForm.innerHTML = '';
  data.forEach((d, i) => {
    html += `
      How many ${d.title}'s 
      <input type='text' value=${d.value} onchange="onFormChange( this.value, ${i})">
      <br>
    `;
  })
  elForm.innerHTML = html;
}
function  renderResults () {
  const elResults = document.getElementById('results');
  let html = '';
  elResults.innerHTML = '';
  // Render Each Element
  data.forEach((d, i) => {
    html += `
      ${d.title}: ${d.value}<br>
    `;
  })
  // Render Total
  let sum = 0;
  data.forEach((d) => {
   sum += Number(d.value) || 0
  })
  html += `
    <div>Total is ${sum}</div>
  `
  elResults.innerHTML = html;
}

function render () {
  renderForm()
  renderResults()
}

window.onload = render;
  
<!DOCTYPE html>
<html>
  <head>
  </head>

  <body>
    <form id="form">
    </form>
    <hr>
    <div id="results">
    </div>
  </body>

</html>

Final Thoughts

I did add a total div at the end of the results to show how you can also do some calculations on the entire data set when any of the values change.

Go ahead and add any additional data to the data array and have fun with it.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.