0

I have the following code that provides me with the calculation that I need, but I want it to work with multiple outputs.

For example, Part A and Part B would have the same jQuery, except Part B may have a different multiplier or calc3, etc.

I will have up to 50 parts and am trying to prevent from having to write 50 rows of jQuery. Is there a way to write this with the (this) variable instead of the ('#id') ?

In the Snippet below, if you add in the Qty, Width, Height, and Depth - you will see the calculation work for Part A, but not Part B because I am trying to make the jQuery calculations simple.

//part1
$("#part1d").keyup(function() {
  //part A
  $('#part1A').val($('#part1q').val() * 1);
  $('#part1AL').val($('#part1w').val() - $('#calc1').val());
  $('#part1AW').val($('#part1d').val() - $('#calc2').val());
  //part B
  $('#part1A').val($('#part1q').val() * 2);
  $('#part1AL').val($('#part1w').val() - $('#calc1').val());
  $('#part1AW').val($('#part1d').val() - $('#calc2').val());
});
* {
  margin: 0;
  padding: 0;
  float: left;
}

.wrap {
  width: 96%;
  margin: 2% 2% 500px 2%;
}

.partwrap {}

.partname {
  width: 20%;
  margin: 1% 20% 1% 0;
}

.partdata {
  width: 10%;
}

input {
  width: auto;
  float: none;
}

.sectiontitle {
  color: red
}

.partdescr {
  color: purple;
}

.parts {
  width: 150px;
}

.values {
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!--values-->
<input class="values" id="calc1" value="1.4375">
<input class="values" id="calc2" value=".25">

<div class="wrap">
  <!--part 1-->
  <!--part 1 input-->
  <div class="partwrap">
    <div class="partdescr">
      <div class="partname">Part Number: <input id="part1"></div>
      <div class="partdata">Qty <input id="part1q"></div>
      <div class="partdata">Width <input id="part1w"></div>
      <div class="partdata">Height <input id="part1h"></div>
      <div class="partdata">Depth <input id="part1d"></div>

    </div>
    <!--part 1 output-->
    <div class="partdescr">
      <div class="parts">Part Name</div>
      <div class="parts">Qty</div>
      <div class="parts">Length</div>
      <div class="parts">Width</div>
      <div class="parts">Height</div>
    </div>

    <div>
      <div class="parts">Part A</div>
      <input id="part1A" class="parts">
      <input id="part1AL" class="parts">
      <input id="part1AW" class="parts">
      <input id="part1AH" class="parts">
    </div>
    <div>
      <div class="parts">Part B</div>
      <input id="part1A" class="parts">
      <input id="part1AL" class="parts">
      <input id="part1AW" class="parts">
      <input id="part1AH" class="parts">
    </div>

  </div>
</div>
Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
AlwaysLearning
  • 197
  • 3
  • 5
  • 13
  • You have multiple elements with the same id in your HTML, which is a Bad Thing. Ids should be unique to the document. – Heretic Monkey Feb 12 '18 at 01:34
  • Thanks Mike, I have that on purpose to show that I am wanting Part B to have the same output ( I will change the ID's to part1B, part1BL, etc. ), but want to show that Part B will use the same jQuery as Part A, using (this) instead of each individual ID. That would be 50 duplicate jQuery inserts, with the exception of the ID's – AlwaysLearning Feb 12 '18 at 01:41

2 Answers2

0

First of all your HTML is not valid.

1) Don't use duplicate ID's use classes instead.

2) You've duplicate div closures </div> tags

Once you fix this you should have desired results but, for the overriding bit ie, clac3 or multiplexer you could add an unique IDto that part div and target a specific input

JS

//part1
$("#part1d,#part1q,part1w,part1h").keyup(function () {
//part A
    $('.part1A').val($('#part1q').val() * 1);
    $('.part1AL').val($('#part1w').val() - $('#calc1').val());
    $('.part1AW').val($('#part1d').val() - $('#calc2').val());    
//part B
//overriding
   $("#partB").find(".part1A").val($('#part1q').val() * 2);    
});

HTML

<input class="values" id="calc1" value="1.4375">
<input class="values" id="calc2" value=".25">

<div class="wrap">
  <!--part 1-->
  <!--part 1 input-->
  <div class="partwrap">
    <div class="partdescr">
      <div class="partname">Part Number: <input id="part1"></div>
      <div class="partdata">Qty <input id="part1q"></div>
      <div class="partdata">Width <input id="part1w"></div>
      <div class="partdata">Height <input id="part1h"></div>
      <div class="partdata">Depth <input id="part1d"></div>

    </div>
    <!--part 1 output-->
    <div class="partdescr">
      <div class="parts">Part Name</div>
      <div class="parts">Qty</div>
      <div class="parts">Length</div>
      <div class="parts">Width</div>
      <div class="parts">Height</div>
    </div>

    <div>
      <div class="parts" id="partA">Part A
      <input class="part1A" class="parts">
      <input class="part1AL" class="parts">
      <input class="part1AW" class="parts">
      <input class="part1AH" class="parts">
    </div>
    <div>
      <div class="parts" id="partB">Part B
      <input class="part1A" class="parts">
      <input class="part1AL" class="parts">
      <input class="part1AW" class="parts">
      <input class="part1AH" class="parts">
    </div>

  </div>
</div>

Working Demo

Nishanth Matha
  • 5,993
  • 2
  • 19
  • 28
0

The actual equations didn't make any sense at all so I organized the data in simple categories. It's probably inaccurate but it can be tailored to your specific needs very easily. Each row of inputs results are displayed in 2 outputs. The 2 inputs on top applies to all of the rows 2 outputs. Note that binding the input event to the <form> is better than any keyboard event. The only work needed to be done is adding table rows which is easy since they are identical and even easier should they be dynamically appended (that's entirely a new question).

References

input event

<input type="number">

<output></output>

.valueAsNumber

.toFixed()

Ternary Condition Operator

Dereferencing jQuery Objects

.on()

.each()

.closest()

.find()


Details commented in Demo

Demo

/* Delegate the input event on the <form>
|| On each() output.G and output.O...
|| Find the <tr> they are in by using .closest()
|| Next store all the input valueAsNumber into variables
|| T1 and T2 variables value are determined by ternary
|| conditions (if(condition)) ?) true : false
|| Finally the totals are displayed in the outputs
*/
$("#invForm").on('input', function() {
  $('.G,.O').each(function(idx) {
    var row = $(this).closest('tr');
    var q = row.find('.Q')[0].valueAsNumber;
    var w = row.find('.W')[0].valueAsNumber;
    var h = row.find('.H')[0].valueAsNumber;
    var d = row.find('.D')[0].valueAsNumber;
    var m = $('#metric')[0].valueAsNumber;
    var i = $('#imperial')[0].valueAsNumber;
    var T1 = ($(this).hasClass('G')) ? 1 : 0.578036672;
    var T2 = ($(this).hasClass('O')) ? i : m;
    var t = (q * w * h * d * T1 * T2).toFixed(2);
    $(this).val(t);
  });
  
});
* {
  margin: 0;
  padding: 0;
}

.inventory {
  width: 96%;
  table-layout: fixed;
}

td {
  border: 1px solid #000
}

.name {
  width: 10%;
}

.data,
.total {
  width: 10%;
}

input {
  width: 12ch;
  display: inline-block;
}

input[type=number] {
  width: 8ch;
  text-align: right;
  padding: 0 2px 0 1px
}

output {
  text-align: right;
  display: inline-block;
  width: 6ch;
}


}
<!-- Use a <table> wrapped in a <form> -->
<!-- If data is numbers consider <input type='number'> -->
<!-- <output> tags can handle .val(), .text(), or .html()-->
<form id='invForm'>
  <label for='metric'>Metric</label>
  <input id="metric" value="1" type='number' step='.01'>
  <label for='imperial'>Imperial</label>
  <input id="imperial" value="1" type='number' step='.01'>

  <table class="inventory">
    <thead>
      <tr>
        <th class='name'>Part Name</th>
        <th class="name">Part Number</th>
        <th class="data">Qty</th>
        <th class="data">Width</th>
        <th class="data">Height</th>
        <th class="data">Depth</th>
        <th class="total">Total Grams</th>
        <th class='total'>Total Ounces</th>
      </tr>
    </thead>
    <tbody>
    <!--Each row is identical in layout #IDs are not necessary-->
      <tr>
        <td><input class='part P' value='ChemX'></td>
        <td><input class='part N' value='X2k9'></td>
        <td><input class='part Q' type='number' step='1' min='0'></td>
        <td><input class='part W' type='number' step='.01' min='0'></td>
        <td><input class='part H' type='number' step='.01' min='0'></td>
        <td><input class='part D' type='number' step='.01' min='0'></td>
        <td><output class='part G'></output></td>
        <td><output class='part O'></output></td>
      </tr>
     <!--End of first data row-->
      <tr>
        <td><input class='part P' value='ChemZ'></td>
        <td><input class='part N' value='Zi96u'></td>
        <td><input class='part Q' type='number' step='1' min='0'></td>
        <td><input class='part W' type='number' step='.01' min='0'></td>
        <td><input class='part H' type='number' step='.01' min='0'></td>
        <td><input class='part D' type='number' step='.01' min='0'></td>
        <td><output class='part G'></output></td>
        <td><output class='part O'></output></td>
      </tr>
    </tbody>
  </table>
</form>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Community
  • 1
  • 1
zer00ne
  • 41,936
  • 6
  • 41
  • 68