Need to total rows of input fields that are populated onClick from buttons with predefined values (html, css, js)

Viewed 25

Thanks for checking this out.

I am building a survey using rows of buttons that populate input fields onClick that rate something from 5 to -5.

The current code populates one of two input fields on either side of the row.

It's basically "populate, rinse and repeat" for each row, using the same code.

I now have multiple rows that need to be added together for a final total.

And some rows are now simply 1 thru 5, OR -1 thru -5.

I needed help with the solution I have, and cannot wrap my head around this one...

Any help is appreciated.

function changeValue(sender, value){
       var valueType1, valueType2, backgroundPlus, backgroundMinus, backgroundSelected, sibling, plusEls, minusEls;
       var row = sender.parentNode.parentNode;
       var parentDiv = row.closest('div');
       backgroundPlus = 'background-color:rgba(0,255,0,0.2);';
       backgroundMinus = 'background-color:rgba(255,0,0,0.2);';
       if (value > 0) {
           valueType1 = 'plus';
           valueType2 = 'minus';
           plusEls = row.querySelectorAll('.select-plus');
           minusEls = parentDiv.nextElementSibling.querySelectorAll('.select-minus');
           sibling = parentDiv.nextElementSibling;
           backgroundSelected = 'background-color:rgba(0,255,0);';
       } else {
           valueType1 = 'minus';
           valueType2 = 'plus';
           plusEls = parentDiv.previousElementSibling.querySelectorAll('.select-plus');
           minusEls = row.querySelectorAll('.select-minus');
           sibling = parentDiv.previousElementSibling;
           backgroundSelected = 'background-color:rgba(255,0,0); color:#fff;';
       }
       row.querySelector(".count-" + valueType1).value = 1*value;
       plusEls.forEach(function(el) {
           el.style.cssText = backgroundPlus;
       });
       minusEls.forEach(function(el) {
           el.style.cssText = backgroundMinus;
       });
       sender.style.cssText = backgroundSelected;
       sibling.querySelector(".count-" + valueType2).value = "";
   }
<style>
    body {
        display:block; width:100%; height:100%; min-height:1000px; margin:0 auto; padding:0; background-color:#fff; top:0; left:0;
        }
    .select-plus {
        display:block;
        float:left;
        height:40px; width:40px; margin:0 2px; border-radius:50%; background-color:rgba(0,255,0,0.2); color:#000; font-size:.85rem; font-weight:400;
    }
    .select-minus {
        height:40px; width:40px; margin:0 2px; border-radius:50%; background-color:rgba(255,0,0,0.2); color:#000; font-size:.85rem; font-weight:400;
    }
    .count-plus, .count-minus {
        height:40px; width:40px; margin:0 auto; text-align:center; font-size:1.1rem; font-weight:700; border:0; border-bottom:3px solid #000;
    }
    .count-plus {
        display:block;
        float:left;
        margin-right:10px;
        background:none;
    }
    .count-minus {
        display:block;
        float:right;
        margin-left:10px;
        background:none;
    }
    .bizModelRatingTableLabel {
        padding:0;
    }
    label {
        text-align:left;
        font-size:1rem;
    }
    table.bizModelRatingTable tbody tr td {
        margin:0;
        padding:0;
    }
</style>
<div style="display:block; float:left; width:50%;">
<table class="bizModelRatingTable" cellspacing="0" cellpadding="0" border="0">
  <tr>
    <td><input type="text" class="count-plus" value=""></td>
    <td><input class="select-plus" type="button" onclick="changeValue(this, 5)" value="5"></td>
    <td><input class="select-plus" type="button" onclick="changeValue(this, 4)" value="4"></td>
    <td><input class="select-plus" type="button" onclick="changeValue(this, 3)" value="3"></td>
    <td><input class="select-plus" type="button" onclick="changeValue(this, 2)" value="2"></td>
    <td><input class="select-plus" type="button" onclick="changeValue(this, 1)" value="1"></td>
  </tr>
</table>
</div>
<div style="display:block; float:left; width:50%;">
<table class="bizModelRatingTable" cellspacing="0" cellpadding="0" border="0">
  <tr>
    <td><input class="select-minus" type="button" onclick="changeValue(this, -1)" value="-1">
    <td><input class="select-minus" type="button" onclick="changeValue(this, -2)" value="-2">
    <td><input class="select-minus" type="button" onclick="changeValue(this, -3)" value="-3">
    <td><input class="select-minus" type="button" onclick="changeValue(this, -4)" value="-4">
    <td><input class="select-minus" type="button" onclick="changeValue(this, -5)" value="-5">
    <td><input type="text" class="count-minus" value="">
  </tr>
</table>
</div>
<div style="display:block; float:left; width:50%;">
<table class="bizModelRatingTable" cellspacing="0" cellpadding="0" border="0">
  <tr>
    <td><input type="text" class="count-plus" value=""></td>
    <td><input class="select-plus" type="button" onclick="changeValue(this, 5)" value="5"></td>
    <td><input class="select-plus" type="button" onclick="changeValue(this, 4)" value="4"></td>
    <td><input class="select-plus" type="button" onclick="changeValue(this, 3)" value="3"></td>
    <td><input class="select-plus" type="button" onclick="changeValue(this, 2)" value="2"></td>
    <td><input class="select-plus" type="button" onclick="changeValue(this, 1)" value="1"></td>
  </tr>
</table>
</div>
<div style="display:block; float:left; width:50%;">
<table class="bizModelRatingTable" cellspacing="0" cellpadding="0" border="0">
  <tr>
    <td><input class="select-minus" type="button" onclick="changeValue(this, -1)" value="-1">
    <td><input class="select-minus" type="button" onclick="changeValue(this, -2)" value="-2">
    <td><input class="select-minus" type="button" onclick="changeValue(this, -3)" value="-3">
    <td><input class="select-minus" type="button" onclick="changeValue(this, -4)" value="-4">
    <td><input class="select-minus" type="button" onclick="changeValue(this, -5)" value="-5">
    <td><input type="text" class="count-minus" value="">
  </tr>
</table>
</div>

1 Answers

You might just get all Elements, that store the Value of that row, in your case all elements with the class either .count-plus or .count-minus.

Iterate through all of them and sum their values. You might need to parseInt(StringVal) their Value, as those are mostly stored as a string.

Lastly you could then output it to a separate element. I've extended your Code with the functionality, by adding a Function to collect the sum and a function to output the result of that function to a new element.

Some References of used Methods:
Array.prototype.reduce()
Destructuring Assignment


function changeValue(sender, value){
       var valueType1, valueType2, backgroundPlus, backgroundMinus, backgroundSelected, sibling, plusEls, minusEls;
       var row = sender.parentNode.parentNode;
       var parentDiv = row.closest('div');
       backgroundPlus = 'background-color:rgba(0,255,0,0.2);';
       backgroundMinus = 'background-color:rgba(255,0,0,0.2);';
       if (value > 0) {
           valueType1 = 'plus';
           valueType2 = 'minus';
           plusEls = row.querySelectorAll('.select-plus');
           minusEls = parentDiv.nextElementSibling.querySelectorAll('.select-minus');
           sibling = parentDiv.nextElementSibling;
           backgroundSelected = 'background-color:rgba(0,255,0);';
       } else {
           valueType1 = 'minus';
           valueType2 = 'plus';
           plusEls = parentDiv.previousElementSibling.querySelectorAll('.select-plus');
           minusEls = row.querySelectorAll('.select-minus');
           sibling = parentDiv.previousElementSibling;
           backgroundSelected = 'background-color:rgba(255,0,0); color:#fff;';
       }
       row.querySelector(".count-" + valueType1).value = 1*value;
       plusEls.forEach(function(el) {
           el.style.cssText = backgroundPlus;
       });
       minusEls.forEach(function(el) {
           el.style.cssText = backgroundMinus;
       });
       sender.style.cssText = backgroundSelected;
       sibling.querySelector(".count-" + valueType2).value = "";
   }
   
   // A helper Function to store the result in a new Element
  function getTotalCount(){
    const sum = sumCounts();
    const resultEl = document.querySelector('#sumField');
    resultEl.innerText = sum;
  }

   // "Independant" Function to sum the Values
   function sumCounts(){
    // We get all Field with the classes either .count-plus or .count-minus by using a simple 
    // CSS-Selector. It returns a NodeList storing all matched elements.
    let fields = document.querySelectorAll('.count-plus,.count-minus');

    // I then need to transform this NodeList into a usual Array by using the destructuring 
    // assignment, which takes all elements of an Iteratable-List and storing them into a new 
    // Array.
    // With .reduce i iterate through the entire Array and reduce it to a single Value. In this 
    // case i iterate through all Elements and sum their value and return the new Sum for the 
    // next iteration.
    let sum = [...fields].reduce((sum, field) => {
      sum += parseInt(field.value) || 0;
      return sum;
    }, 0);
    
    // Lastly i just return the sum.
    return sum;
   }
<style>
    body {
        display:block; width:100%; height:100%; min-height:1000px; margin:0 auto; padding:0; background-color:#fff; top:0; left:0;
        }
    .select-plus {
        display:block;
        float:left;
        height:40px; width:40px; margin:0 2px; border-radius:50%; background-color:rgba(0,255,0,0.2); color:#000; font-size:.85rem; font-weight:400;
    }
    .select-minus {
        height:40px; width:40px; margin:0 2px; border-radius:50%; background-color:rgba(255,0,0,0.2); color:#000; font-size:.85rem; font-weight:400;
    }
    .count-plus, .count-minus {
        height:40px; width:40px; margin:0 auto; text-align:center; font-size:1.1rem; font-weight:700; border:0; border-bottom:3px solid #000;
    }
    .count-plus {
        display:block;
        float:left;
        margin-right:10px;
        background:none;
    }
    .count-minus {
        display:block;
        float:right;
        margin-left:10px;
        background:none;
    }
    .bizModelRatingTableLabel {
        padding:0;
    }
    label {
        text-align:left;
        font-size:1rem;
    }
    table.bizModelRatingTable tbody tr td {
        margin:0;
        padding:0;
    }
</style>
<div style="display:block; float:left; width:50%;">
<table class="bizModelRatingTable" cellspacing="0" cellpadding="0" border="0">
  <tr>
    <td><input type="text" class="count-plus" value=""></td>
    <td><input class="select-plus" type="button" onclick="changeValue(this, 5)" value="5"></td>
    <td><input class="select-plus" type="button" onclick="changeValue(this, 4)" value="4"></td>
    <td><input class="select-plus" type="button" onclick="changeValue(this, 3)" value="3"></td>
    <td><input class="select-plus" type="button" onclick="changeValue(this, 2)" value="2"></td>
    <td><input class="select-plus" type="button" onclick="changeValue(this, 1)" value="1"></td>
  </tr>
</table>
</div>
<div style="display:block; float:left; width:50%;">
<table class="bizModelRatingTable" cellspacing="0" cellpadding="0" border="0">
  <tr>
    <td><input class="select-minus" type="button" onclick="changeValue(this, -1)" value="-1">
    <td><input class="select-minus" type="button" onclick="changeValue(this, -2)" value="-2">
    <td><input class="select-minus" type="button" onclick="changeValue(this, -3)" value="-3">
    <td><input class="select-minus" type="button" onclick="changeValue(this, -4)" value="-4">
    <td><input class="select-minus" type="button" onclick="changeValue(this, -5)" value="-5">
    <td><input type="text" class="count-minus" value="">
  </tr>
</table>
</div>
<div style="display:block; float:left; width:50%;">
<table class="bizModelRatingTable" cellspacing="0" cellpadding="0" border="0">
  <tr>
    <td><input type="text" class="count-plus" value=""></td>
    <td><input class="select-plus" type="button" onclick="changeValue(this, 5)" value="5"></td>
    <td><input class="select-plus" type="button" onclick="changeValue(this, 4)" value="4"></td>
    <td><input class="select-plus" type="button" onclick="changeValue(this, 3)" value="3"></td>
    <td><input class="select-plus" type="button" onclick="changeValue(this, 2)" value="2"></td>
    <td><input class="select-plus" type="button" onclick="changeValue(this, 1)" value="1"></td>
  </tr>
</table>
</div>
<div style="display:block; float:left; width:50%;">
<table class="bizModelRatingTable" cellspacing="0" cellpadding="0" border="0">
  <tr>
    <td><input class="select-minus" type="button" onclick="changeValue(this, -1)" value="-1">
    <td><input class="select-minus" type="button" onclick="changeValue(this, -2)" value="-2">
    <td><input class="select-minus" type="button" onclick="changeValue(this, -3)" value="-3">
    <td><input class="select-minus" type="button" onclick="changeValue(this, -4)" value="-4">
    <td><input class="select-minus" type="button" onclick="changeValue(this, -5)" value="-5">
    <td><input type="text" class="count-minus" value="">
  </tr>
</table>
<button onclick="getTotalCount()">Sum Counts</button>
<span id="sumField"></span>
</div>

Related