Evaluate sum of values without clicking a button

I really don't know how to program in Javascript, yet I've tried to do some stuff. I have values to be summed if some are selected. The following function does sum operation and show result at once without clicking a button only for checkbox fields, not for the dropdown list and text fields.

However, I need to involve the selected values as well from the dropdown lists and entered both text fields in the same manner of the checkboxes and their immediate responses(output).

I think change method can be used in the same manner.

@Edit:

Sorry, I forgot the tell but, I need to multiply the m2 entered value by before summing with 3134,204499 and Bina Yasi with -566,2202888.

function calcAndShowTotal() {
  var total = 55435.04798; // it is constant value which must be the beginning value.
  $('#housepriceguesslist :checkbox:checked').each(function() {
    total += parseFloat($(this).attr('price')) || 0;
  });
  $('#total').val(total);
}

$('#housepriceguesslist :checkbox').change(calcAndShowTotal).change();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="housepriceguesslist">


  <select id="ilce">
    <option value="0">Choose a state</option>
    <option value="63999.50712318567">Adalar</option>
    <option value="6259.918435398593">Ataşehir</option>
    <option value="46285.35729304834">Beykoz</option>
    <option value="54258.92953697798">Kadıköy</option>
    <option value="-3500.620905653726">Kartal</option>
    <option value="12889.41219909602">Maltepe</option>
    <option value="-33711.83156847153">Pendik</option>
    <option value="-34577.42485251657">Sancaktepe</option>
    <option value="-52183.1608811019">Sultanbeyli</option>
    <option value="-34760.71735007784">Tuzla</option>
    <option value="-27379.87966213786">Çekmeköy</option>
    <option value="-5332.203990418937">Ümraniye</option>
    <option value="26485.33532820411">Üsküdar</option>
    <option value="-18732.62070553167">Şile</option>
  </select>

  <select id="odasalon">
    <option value="0">Choose room number</option>
    <option value="5940.027623576261">1+0</option>
    <option value="-1399.625767475593">1+1</option>
    <option value="-3033.638999060459">2+1</option>
    <option value="11519.83954756076">3+1</option>
    <option value="-7018.52116545078">4+1</option>
    <option value="-6008.081239150166">5+1</option>
  </select>

  m2: <input type="text" id="m2" /> Bina Yasi: <input type="text" id="binayasi" />



  <br/>
  <br/> Features:

  <br/>
  <br/>
  <input type="checkbox" id="Bati" value="Bati" price="-783.4452683566533" /> <label for="Bati">Bati</label>
  <br/>
  <input type="checkbox" id="Dogu" value="Dogu" price="-4895.732009084263" /> <label for="Dogu">Dogu</label>
  <br/>
  <input type="checkbox" id="Guney" value="Guney" price="-2599.001349652765" /> <label for="Guney">Guney</label>
  <br/>
  <input type="checkbox" id="Kuzey" value="Kuzey" price="3832.013070771234" /> <label for="Kuzey">Kuzey</label>
  <br/>
  <input type="checkbox" id="Amerikan Mutfak" value="Amerikan Mutfak" price="2346.347889828301" /> <label for="Amerikan Mutfak">Amerikan Mutfak</label>
  <br/>
  <input type="checkbox" id="Dusakabin" value="Dusakabin" price="-176.5092353740256" /> <label for="Dusakabin">Dusakabin</label>
  <br/>
  <input type="checkbox" id="Akilli Ev" value="Akilli Ev" price="-4756.206384200719" /> <label for="Akilli Ev">Akilli Ev</label>
  <br/>
  <input type="checkbox" id="Ebeveyn Banyosu" value="Ebeveyn Banyosu" price="10135.50644456019" /> <label for="Ebeveyn Banyosu">Ebeveyn Banyosu</label>
  <br/>
  <input type="checkbox" id="Kiler" value="Kiler" price="-10693.49979821809" /> <label for="Kiler">Kiler</label>
  <br/>
  <input type="checkbox" id="Kuvet" value="Kuvet" price="-941.0629741243247" /> <label for="Kuvet">Kuvet</label>
  <br/>
  <input type="checkbox" id="Parke Zemin" value="Parke Zemin" price="-8453.847199707092" /> <label for="Parke Zemin">Parke Zemin</label>
  <br/>
  <input type="checkbox" id="Seramik Zemin" value="Seramik Zemin" price="1545.025601000643" /> <label for="Seramik Zemin">Seramik Zemin</label>
  <br/>
  <input type="checkbox" id="Sauna" value="Sauna" price="8677.708176289747" /> <label for="Sauna">Sauna</label>
  <br/>
  <input type="checkbox" id="Spor Salonu" value="Spor Salonu" price="1159.884679563385" /> <label for="Spor Salonu">Spor Salonu</label>
  <br/>
  <input type="checkbox" id="Tenis Kortu" value="Tenis Kortu" price="16065.26794172257" /> <label for="Tenis Kortu">Tenis Kortu</label>
  <br/>
</div>
<input type="text" id="total" value="0" />

Upvotes: 0

Views: 672

Answers (3)

Teocci
Teocci

Reputation: 8955

This solution is simple, just the get the list of all the inputs (i.e. checkbox, and dropdown) using the .find() method and the selector 'input:checkbox, input:text, select'. Then verify if each one of these inputs elements has the attribute checked or select for the checkbox and select input types respectively, or it is a multiplier for the text inputs. This verification ca be done inside of the each() method callback. Finally, just convert then the value to a number, using the parseFloat() method and add it to the total accumulator.

Finally, sum the value to the total input. Like this:

let container;
let inputs;
let total;

function calcAndShowTotal() {
  let sum = 55435.04798; // it is constant value which must be the beginning value.
  let value;
  inputs.each(function() {
    if ($(this).is('input:checkbox:checked')) {
      // If is a checkbox
      value = parseFloat($(this).attr('price')) || 0;
      sum += value;
    } else if ($(this).is('input:text:not(#total)')) {
      // If is a text wait until you move to another element
      let factor = 1;
      if (this.id == 'm2') {
        factor = 3134.204499;
      } else if (this.id == 'binayasi') {
        factor = -566.2202888;
      }

      value = parseFloat($(this).val()) * factor || 0;
      sum += value;
    } else if ($(this).is('select')) {
      // If is a option from the select element
      value = parseFloat($('option:selected', this).val()) || 0;
      sum += value;
    }
  });
  total.val(sum);
}

function initHandlers() {
  inputs.on('keydown', function(e) {
    let focusable, next;
    if (e.keyCode == 13) {
      focusable = inputs.filter(':visible');
      next = focusable.eq(focusable.index(this) + 1);
      if (next.length) {
        next.focus();
      }
      return false;
    }
  });

  inputs.change(calcAndShowTotal);
  calcAndShowTotal();
}

$(function() {
  console.log('ready!');
  total = $('#total');
  container = $('#housepriceguesslist');
  inputs = container.find('input:checkbox, input:text, select');

  initHandlers();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="housepriceguesslist">
  Total: <input type="text" id="total" value="0" />
  <br/>
  <br/>
  <select id="ilce">
    <option value="0">Choose a state</option>
    <option value="63999.50712318567">Adalar</option>
    <option value="6259.918435398593">Ataşehir</option>
    <option value="46285.35729304834">Beykoz</option>
    <option value="54258.92953697798">Kadıköy</option>
    <option value="-3500.620905653726">Kartal</option>
    <option value="12889.41219909602">Maltepe</option>
    <option value="-33711.83156847153">Pendik</option>
    <option value="-34577.42485251657">Sancaktepe</option>
    <option value="-52183.1608811019">Sultanbeyli</option>
    <option value="-34760.71735007784">Tuzla</option>
    <option value="-27379.87966213786">Çekmeköy</option>
    <option value="-5332.203990418937">Ümraniye</option>
    <option value="26485.33532820411">Üsküdar</option>
    <option value="-18732.62070553167">Şile</option>
  </select>
  <select id="odasalon">
    <option value="0">Choose room number</option>
    <option value="5940.027623576261">1+0</option>
    <option value="-1399.625767475593">1+1</option>
    <option value="-3033.638999060459">2+1</option>
    <option value="11519.83954756076">3+1</option>
    <option value="-7018.52116545078">4+1</option>
    <option value="-6008.081239150166">5+1</option>
  </select>
  m2: <input type="text" id="m2" /> 
  Bina Yasi: <input type="text" id="binayasi" />
  <br/>
  <br/> Features:
  <br/>
  <br/>
  <input type="checkbox" id="Bati" value="Bati" price="-783.4452683566533" /> <label for="Bati">Bati</label>
  <br/>
  <input type="checkbox" id="Dogu" value="Dogu" price="-4895.732009084263" /> <label for="Dogu">Dogu</label>
  <br/>
  <input type="checkbox" id="Guney" value="Guney" price="-2599.001349652765" /> <label for="Guney">Guney</label>
  <br/>
  <input type="checkbox" id="Kuzey" value="Kuzey" price="3832.013070771234" /> <label for="Kuzey">Kuzey</label>
  <br/>
  <input type="checkbox" id="Amerikan Mutfak" value="Amerikan Mutfak" price="2346.347889828301" /> <label for="Amerikan Mutfak">Amerikan Mutfak</label>
  <br/>
  <input type="checkbox" id="Dusakabin" value="Dusakabin" price="-176.5092353740256" /> <label for="Dusakabin">Dusakabin</label>
  <br/>
  <input type="checkbox" id="Akilli Ev" value="Akilli Ev" price="-4756.206384200719" /> <label for="Akilli Ev">Akilli Ev</label>
  <br/>
  <input type="checkbox" id="Ebeveyn Banyosu" value="Ebeveyn Banyosu" price="10135.50644456019" /> <label for="Ebeveyn Banyosu">Ebeveyn Banyosu</label>
  <br/>
  <input type="checkbox" id="Kiler" value="Kiler" price="-10693.49979821809" /> <label for="Kiler">Kiler</label>
  <br/>
  <input type="checkbox" id="Kuvet" value="Kuvet" price="-941.0629741243247" /> <label for="Kuvet">Kuvet</label>
  <br/>
  <input type="checkbox" id="Parke Zemin" value="Parke Zemin" price="-8453.847199707092" /> <label for="Parke Zemin">Parke Zemin</label>
  <br/>
  <input type="checkbox" id="Seramik Zemin" value="Seramik Zemin" price="1545.025601000643" /> <label for="Seramik Zemin">Seramik Zemin</label>
  <br/>
  <input type="checkbox" id="Sauna" value="Sauna" price="8677.708176289747" /> <label for="Sauna">Sauna</label>
  <br/>
  <input type="checkbox" id="Spor Salonu" value="Spor Salonu" price="1159.884679563385" /> <label for="Spor Salonu">Spor Salonu</label>
  <br/>
  <input type="checkbox" id="Tenis Kortu" value="Tenis Kortu" price="16065.26794172257" /> <label for="Tenis Kortu">Tenis Kortu</label>
  <br/>
</div>

Note:

Remember to round the numbers to get more precision. The text modification will apply after you tab, or move to another element. So I added an enter listener so when you press enter is gonna move to the next element like when you press tab. Also, I moved the total to the top so you can see the results in the preview.

Update:

I recommend you to use the $(function(){}); to get the document when is ready. Inside you can assign the values of your elements. I notice that there was a bug in my code whenever ever you uncheck a checked element the Total should be 55435.04798, but it shows the double it is because total is also a text input.

Upvotes: 1

Barmar
Barmar

Reputation: 782148

You can loop over all the <select> boxes and text inputs with:

function calcAndShowTotal() {
  var total = 55435.04798; // it is constant value which must be the beginning value.
  $('#housepriceguesslist :checkbox:checked').each(function() {
    total += parseFloat($(this).attr('price')) || 0;
  });
  $("#housepriceguesslist select, #housepriceguesslist :text").each(function() {
    let multiplier = 1;
    if (this.id == "m2") {
      multiplier = 3134.204499;
    }
    else if (this.id == "binayasi") {
      multiplier = -566.2202888;
    }
    if (this.value) {
      total += parseFloat(this.value) * multiplier;
    }
  });
  $('#total').val(total);
}

And if you change the checkboxes to use value instead of price, you can do them all in one loop:

function calcAndShowTotal() {
  var total = 55435.04798; // it is constant value which must be the beginning value.
  $('#housepriceguesslist :checkbox:checked').each(function() {
    total += parseFloat($(this).attr('price')) || 0;
  });
  $("#housepriceguesslist select, #housepriceguesslist :text, #housepriceguesslist :checkbox:checked").each(function() {
    let multiplier = 1;
    if (this.id == "m2") {
      multiplier = 3134.204499;
    else if (this.id == "binyasi") {
      multiplier = -566.2202888;
    }
    if (this.value) {
      total += parseFloat(this.value) * multiplier;
    }
  });
  $('#total').val(total);
}

And call the function when any of the inputs are changed:

$('#housepriceguesslist input, #housepriceguesslist select').change(calcAndShowTotal).change();

Upvotes: 2

Karl Bishop
Karl Bishop

Reputation: 401

Similar to Barmar's, I added all elements to the .each() loop but also added the .change() handler to all elements:

var context = $('#housepriceguesslist');
var elems = $('input:checkbox, input:text, select', context);

function calcAndShowTotal() {
  var total = 55435.04798; // it is constant value which must be the beginning value.
  elems.each(function() {
    if ( $(this).is('input:checkbox:checked') ) {
      total += parseFloat($(this).attr('price')) || 0;
    } else if ( $(this).is('#m2') ) {
      total += parseFloat($(this).val()) * 3134.204499 || 0;
    } else if ( $(this).is('#binayasi') ) {
      total += parseFloat($(this).val()) * -566.2202888 || 0;
    } else if ( $(this).is('select') ) {
      total += parseFloat($('option:selected',this).val()) || 0;
    }
  });
  $('#total').val(total);
}

elems.change(calcAndShowTotal); // handlers
calcAndShowTotal(); // first run

See example here: https://jsfiddle.net/qgvsern4/1/

Upvotes: 1

Related Questions