最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to calculate form field values both directions? - Stack Overflow

programmeradmin2浏览0评论

I try to build item's form where I can put different formulas to calculate certain fields.

Main problem: i'd like to have formulas working both ways, so for example

  • when user inputs item's price, form should calculate sum based on price (price * qty).
  • when user inputs sum, form should calculate item's price based on sum (sum / qty).

I found Calcx -- great and powerful jQuery plugin for building a calculation form and modified one of it's examples for my need, but did not figure out is there possible somehow to make it work like i wanted in description above.

There is some additional problems I did NOT found a solution:

  • fields with formulas and set readonly: false should be editable. Fields in my example with class .sum still don't are editable. Why?
  • I added + and - buttons around qty-field to incr/decr functionality, but to get them work properly I had to detach Calcx functionality and attach then again. Is there simpler way to achieve that?

Disclaimer the solution for my problem may involve other techologies besides Calcx, too. Maybe some plugin or framework has better tools for my needs.

For the history I add code example here too, but to play with it is maybe better to look in the JSfiddle

<!DOCTYPE html>
<html>
<head>
  <title>testc calcx</title>
  <meta charset=utf-8>
  <meta name=description content="testime">
  <script src="//ajax.googleapis/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
  <script type="text/javascript" src="/js/jquery-calx-1.1.9.js"></script>

<style type="text/css">
  .plusminus {
    font-weight: bold;
    font-family: monospace;
    font-size: 1.3em;
    border: 1px green solid;
    padding: 0px 5px;
  }
</style>

  <script>

  $(document).ready(function(){

      $('#itemlist').calx();

      $('.sum').calx({
        readonly: false
      });

      $('.plusminus').click( 
        function () {
          $('#itemlist').calx('detach');  

          var operation = $( this ).text();
          var row = $( this ).attr('id').split('_').slice(1);
          var qty = $( '#qty_' + row ).val();

          if ( operation == '+' ) {
            $( '#qty_' + row ).val( ++qty );
          } else if ( operation == '-' ) {
            $( '#qty_' + row ).val( --qty );
          } else {
            alert( "Something wrong! " + $( this ).attr('id') );
          }
          $('#itemlist').calx();  
          $('#itemlist').calx('refresh');
        }
      );
  });

  </script>
</head>
<body>

<form id="itemlist">

  <input type="text" placeholder="Item" id="A1" size="20" value="HDD Baracuda Black 2TB" />

    <span id="min_1" class="plusminus">-</span>
    <input type="text" placeholder="Qty" id="qty_1" value="1" size="2" data-format="0" />
    <span id="plus_1" class="plusminus" >+</span>

  <input type="text" placeholder="Price" id="C1" size="5" data-format="$ 0,0[.]00" />
  <input type="text" placeholder="Disc." id="D1" size="3" data-format="0[.]00 %" />
  <input type="text" placeholder="Sum" id="E1" size="6" class="sum" data-formula="($qty_1*$C1)*(1-$D1)" data-format="$ 0,0[.]00" />
  <br />

  <input type="text" placeholder="Item" id="A2" size="20" value="Motherboard ASus XYZ" />

    <span id="min_2" class="plusminus">-</span>
    <input type="text" placeholder="Qty" id="qty_2" value="1" size="2" data-format="0" />
    <span id="plus_2" class="plusminus" >+</span>

  <input type="text" placeholder="Price" id="C2" size="5" data-format="$ 0,0[.]00" />
  <input type="text" placeholder="Disc." id="D2" size="3" data-format="0[.]00 %" />
  <input type="text" placeholder="Sum" id="E2" size="6" class="sum" data-formula="($qty_2*$C2)*(1-$D2)" data-format="$ 0,0[.]00" />
  <br />

  <input type="text" placeholder="Item" id="A3" size="20" value="Memory Kingston DDR3 4GB" />

    <span id="min_3" class="plusminus">-</span>
    <input type="text" placeholder="Qty" id="qty_3" value="1" size="2" data-format="0" />
    <span id="plus_3" class="plusminus" >+</span>

  <input type="text" placeholder="Price" id="C3" size="5" data-format="$ 0,0[.]00" />
  <input type="text" placeholder="Disc." id="D3" size="3" data-format="0[.]00 %" />
  <input type="text" placeholder="Sum" id="E3" size="6" class="sum" data-formula="($qty_3*$C3)*(1-$D3)" data-format="$ 0,0[.]00" />
  <br />

  <input type="text" placeholder="" id="total_1" data-formula="SUM($E1,$E3)" data-format="$ 0,0[.]00" />
</form>

</body>
</html>

I try to build item's form where I can put different formulas to calculate certain fields.

Main problem: i'd like to have formulas working both ways, so for example

  • when user inputs item's price, form should calculate sum based on price (price * qty).
  • when user inputs sum, form should calculate item's price based on sum (sum / qty).

I found Calcx -- great and powerful jQuery plugin for building a calculation form and modified one of it's examples for my need, but did not figure out is there possible somehow to make it work like i wanted in description above.

There is some additional problems I did NOT found a solution:

  • fields with formulas and set readonly: false should be editable. Fields in my example with class .sum still don't are editable. Why?
  • I added + and - buttons around qty-field to incr/decr functionality, but to get them work properly I had to detach Calcx functionality and attach then again. Is there simpler way to achieve that?

Disclaimer the solution for my problem may involve other techologies besides Calcx, too. Maybe some plugin or framework has better tools for my needs.

For the history I add code example here too, but to play with it is maybe better to look in the JSfiddle

<!DOCTYPE html>
<html>
<head>
  <title>testc calcx</title>
  <meta charset=utf-8>
  <meta name=description content="testime">
  <script src="//ajax.googleapis./ajax/libs/jquery/1.9.1/jquery.min.js"></script>
  <script type="text/javascript" src="/js/jquery-calx-1.1.9.js"></script>

<style type="text/css">
  .plusminus {
    font-weight: bold;
    font-family: monospace;
    font-size: 1.3em;
    border: 1px green solid;
    padding: 0px 5px;
  }
</style>

  <script>

  $(document).ready(function(){

      $('#itemlist').calx();

      $('.sum').calx({
        readonly: false
      });

      $('.plusminus').click( 
        function () {
          $('#itemlist').calx('detach');  

          var operation = $( this ).text();
          var row = $( this ).attr('id').split('_').slice(1);
          var qty = $( '#qty_' + row ).val();

          if ( operation == '+' ) {
            $( '#qty_' + row ).val( ++qty );
          } else if ( operation == '-' ) {
            $( '#qty_' + row ).val( --qty );
          } else {
            alert( "Something wrong! " + $( this ).attr('id') );
          }
          $('#itemlist').calx();  
          $('#itemlist').calx('refresh');
        }
      );
  });

  </script>
</head>
<body>

<form id="itemlist">

  <input type="text" placeholder="Item" id="A1" size="20" value="HDD Baracuda Black 2TB" />

    <span id="min_1" class="plusminus">-</span>
    <input type="text" placeholder="Qty" id="qty_1" value="1" size="2" data-format="0" />
    <span id="plus_1" class="plusminus" >+</span>

  <input type="text" placeholder="Price" id="C1" size="5" data-format="$ 0,0[.]00" />
  <input type="text" placeholder="Disc." id="D1" size="3" data-format="0[.]00 %" />
  <input type="text" placeholder="Sum" id="E1" size="6" class="sum" data-formula="($qty_1*$C1)*(1-$D1)" data-format="$ 0,0[.]00" />
  <br />

  <input type="text" placeholder="Item" id="A2" size="20" value="Motherboard ASus XYZ" />

    <span id="min_2" class="plusminus">-</span>
    <input type="text" placeholder="Qty" id="qty_2" value="1" size="2" data-format="0" />
    <span id="plus_2" class="plusminus" >+</span>

  <input type="text" placeholder="Price" id="C2" size="5" data-format="$ 0,0[.]00" />
  <input type="text" placeholder="Disc." id="D2" size="3" data-format="0[.]00 %" />
  <input type="text" placeholder="Sum" id="E2" size="6" class="sum" data-formula="($qty_2*$C2)*(1-$D2)" data-format="$ 0,0[.]00" />
  <br />

  <input type="text" placeholder="Item" id="A3" size="20" value="Memory Kingston DDR3 4GB" />

    <span id="min_3" class="plusminus">-</span>
    <input type="text" placeholder="Qty" id="qty_3" value="1" size="2" data-format="0" />
    <span id="plus_3" class="plusminus" >+</span>

  <input type="text" placeholder="Price" id="C3" size="5" data-format="$ 0,0[.]00" />
  <input type="text" placeholder="Disc." id="D3" size="3" data-format="0[.]00 %" />
  <input type="text" placeholder="Sum" id="E3" size="6" class="sum" data-formula="($qty_3*$C3)*(1-$D3)" data-format="$ 0,0[.]00" />
  <br />

  <input type="text" placeholder="" id="total_1" data-formula="SUM($E1,$E3)" data-format="$ 0,0[.]00" />
</form>

</body>
</html>
Share Improve this question edited Apr 27, 2014 at 18:42 w.k asked Apr 27, 2014 at 16:12 w.kw.k 8,3865 gold badges35 silver badges62 bronze badges 5
  • 1 What is the question? The JSFiddle seems to work for me. – Sukima Commented Apr 27, 2014 at 16:16
  • @Sukima: Question: how to make form rows calculate other way too? If i enter SUM i want it to calculate UNIT PRICE. Now it works only other way. – w.k Commented Apr 27, 2014 at 16:51
  • @w.k:I am close to finding another solution tomorrow i'll try to refine the code and post the answer. – Devima Commented May 5, 2014 at 17:15
  • @w.k:haaa, now i understand your question (better late than never), i'm sorry for my post that is wrong. Now i try to improve it. – Devima Commented May 6, 2014 at 15:19
  • @w.k:now the script for me is Ok (but i'm going crazy), tomorrow i'll try to make a new version of the script with a few changes in the html code, thanks for the BIG GAME. – Devima Commented May 6, 2014 at 17:06
Add a ment  | 

5 Answers 5

Reset to default 8 +300

I reended you to use the library ractive.js. Take a look how simple and automatic is it's two way databinding: http://learn.ractivejs/two-way-binding/1/

<label>Enter your name: <input value='{{name}}'></label>
<p>Hello, {{name}}!</p>

So you could do this:

<label>Price: <input value='{{price}}'></label>
<label>Quantity: <input value='{{quantity}}'></label>
<label>Sum: <input value='{{price * quantity}}'></label>

In this simple way you can use expressions like {{price * quantity}} and save a lot of code. http://learn.ractivejs/expressions/2/

You can add js functions between {{ }} and events:

http://learn.ractivejs/event-proxies/1/

You can know how to setup ractive in 60 seconds: http://www.ractivejs/60-second-setup

And learn it easily in it's interactive tutorial: http://learn.ractivejs/hello-world/1/

Edit 1:

I added this jsfiddle as an example.

I don't like libraries, especially if I can avoid them. And you can clearly avoid them here.

I basically put all the data of each item in self-made

<row></row>

With that, I can use

$(this).parent();

On every input, and I immediately have the desired row. From there I'm going to find the other values.

jsFiddle

$(document).ready(function(){

    function calcTotal(){
        var items = $("#itemlist row").length;        
        var sums = $(".sum");

        var total = 0
        for(var i = 0; i < items; i++){
            if(sums.eq(i).val()){
                total += parseFloat(sums.eq(i).val());
            }
        }

        $("#total").val(parseFloat(total).toFixed(2));
    }

    function calcSum(object){
        var row = $(object).parent();                
        var qty = row.find(".qty");
        var prc = row.find(".prc");
        var sum = row.find(".sum");        
        var disc = row.find(".disc");

        var newSum = qty.val()*prc.val()*(1-disc.val()/100);

        sum.val(parseFloat(newSum).toFixed(2));

        calcTotal();
    }

    function calcPrice(object){
        var row = $(object).parent();                
        var qty = row.find(".qty");
        var prc = row.find(".prc");
        var sum = row.find(".sum");        
        var disc = row.find(".disc");

        var newPrice = -100*sum.val()/(disc.val()-100)/qty.val();

        prc.val(parseFloat(newPrice).toFixed(2));

        calcTotal();
    }


    $('.plusminus').click(function(){            
        var operator = parseFloat($(this).text()+"1");
        var row = $(this).parent();
        var qty = row.find(".qty");
        var qtyVal = parseFloat(qty.val());

        qty.val(parseFloat(qtyVal+operator));

        calcSum(this);
    });

    $(".prc, .disc, .qty").blur(function(){   
        calcSum(this);
    });

    $(".sum").blur(function(){
        calcPrice(this);
    });

});

<body>
<form id="itemlist">  
    <row>
    <input type="text" placeholder="Item" class="name" size="20" value="HDD Baracuda Black 2TB" />

    <span id="min_1" class="plusminus">-</span>
    <input type="text" placeholder="Qty" class="qty" value="1" size="2"/>
    <span id="plus_1" class="plusminus" >+</span>

  <input type="text" placeholder="Price" class="prc" size="5"/>
  <input type="text" placeholder="Disc." class="disc" size="3"/>
  <input type="text" placeholder="Sum" class="sum" size="6"/>
    </row>
    <row>
  <input type="text" placeholder="Item" class="name" size="20" value="Motherboard ASus XYZ" />

    <span id="min_1" class="plusminus">-</span>
    <input type="text" placeholder="Qty" class="qty" value="1" size="2"/>
    <span id="plus_1" class="plusminus" >+</span>

  <input type="text" placeholder="Price" class="prc" size="5"/>
  <input type="text" placeholder="Disc." class="disc" size="3"/>
  <input type="text" placeholder="Sum" class="sum" size="6"/>
    </row>
    <row>
  <input type="text" placeholder="Item" class="name" size="20" value="Memory Kingston DDR3 4GB" />

    <span id="min_1" class="plusminus">-</span>
    <input type="text" placeholder="Qty" class="qty" value="1" size="2"/>
    <span id="plus_1" class="plusminus">+</span>

  <input type="text" placeholder="Price" class="prc" size="5"/>
  <input type="text" placeholder="Disc." class="disc" size="3"/>
  <input type="text" placeholder="Sum" class="sum" size="6"/>
    </row>
  <input type="text" placeholder="Total" id="total"/>
</form>
</body>

Oh, and I revamped the plus-minus thing a bit, sorry.

Seems my question was not clear enough. I post my own solution for my problem. It is using just jQuery and is not so generic as it would be with some additional plugin. But it acts exactly as I want, furthermore I added functionality to have ranged subforms inside the same form. Here is jsFiddle version to play with, and below is solution as a whole.

Now is possible to change row sum so that price is calculated based on it, and vice versa too.

<!DOCTYPE html>
<html>
<head>
  <title>test calculated forms</title>
  <meta charset=utf-8>
  <script src="//ajax.googleapis./ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<style type="text/css">
  .plusminus {
    font-weight: bold;
    font-family: monospace;
    font-size: 1.3em;
    border: 1px green solid;
    padding: 0px 5px;
  }
</style>

  <script>

  $(document).ready(function(){
      $('.plusminus').click( 
        function () {

          var operation = $( this ).text();
          var attr = $( this ).attr('id').split('_');
          var cell_id = attr[0] + '_B_' + attr[2];
          var qty = $( '#' + cell_id ).val();

          if ( operation == '+' ) {
            $( '#' + cell_id ).val( ++qty );
          } else if ( operation == '-' ) {
            $( '#' + cell_id ).val( --qty );
          } else {
            alert( "Something wrong! " + $( this ).attr('id') );
          }
          recalculate_row_sum( cell_id );
        }
      );

      $( '.form_sum' ).on( 'change', function() {
        recalculate_unit_price( $( this ).attr('id') );
      });

      $( '.form_price' ).on( 'change', function() {
        recalculate_row_sum( $( this ).attr('id') );
      });

      $( '.form_discount' ).on( 'change', function() {
        recalculate_row_sum( $( this ).attr('id') );
      });

      $( '.form_qty' ).on( 'change', function() {
        recalculate_row_sum( $( this ).attr('id') );
      });

      init_ranges();
  });


  // you may have many independent ranges on same form, to init them on load is init_ranges-function
  function init_ranges () {
    var ranges = $( '#ranges' ).val().split( '-' );

    for (var i = ranges[0]; i <= ranges[1]; i++) {
      init_range_rows( i );
    }
  }

  function init_range_rows ( range ) {
    var edges = $( '#R' + range ).val().split( '-' );

    for (var i = edges[0]; i <= edges[1]; i++) {
      recalculate_row_sum( 'R' + range + '_C_' + i );
    }
  }


  function recalculate_unit_price ( cell_id, data ) {
    var row_data = get_row_data( cell_id, data );
    var unit_price = ( row_data.row_sum/(100 -row_data.discount)*100/row_data.qty ).toFixed(2);
    $( '#' + row_data.range + '_C_' + row_data.row ).val( unit_price );

    recalculate_range_total( cell_id, row_data );
  }

  function recalculate_row_sum ( cell_id, data ) {
    var row_data = get_row_data( cell_id, data );
    var sum = ( row_data.unit_price*(100 - row_data.discount)/100*row_data.qty ).toFixed(2);
    $( '#' + row_data.range + '_E_' + row_data.row ).val( sum );

    recalculate_range_total( cell_id, row_data );
  }

  function recalculate_range_total ( cell_id, data ) {
    var row_data = get_row_data( cell_id, data );
    var edges = $( '#' + row_data.range ).val().split( '-' );
    var total_amount = 0;

    for (var i = edges[0]; i <= edges[1]; i++) {
      total_amount += $( '#' + row_data.range + '_E_' + i ).val() * 1;
    }
    $( '#' + row_data.range + '_total' ).val( ( total_amount ).toFixed(2) );
  }

  function get_row_data ( cell_id, cached_data ) {
    if ( typeof cached_data === 'defined' ) {
      return cached_data; 
    }

    var row_info = cell_id.split( '_' );
    var data = {
      range: row_info[0],
      col: row_info[1],
      row: row_info[2],
      unit_price: $( '#' + row_info[0] + '_C_' + row_info[2] ).val() || 0 , 
      qty: $( '#' + row_info[0] + '_B_' + row_info[2] ).val() || 0, 
      discount: $( '#' + row_info[0] + '_D_' + row_info[2] ).val() || 0, 
      row_sum: $( '#' + row_info[0] + '_E_' + row_info[2] ).val() || 0
    };
    return data;
  }

  </script>
</head>
<body>

<form id="itemlist" method="post" enctype="multipart/form-data" >

  <input type="hidden" id="ranges" name="ranges" value="1-3" />

  <input type="text" placeholder="Item" id="R1_A_1" name="A_1" size="20" class="form_item" value="HDD Baracuda Black 2TB" />

    <span id="R1_min_1" class="plusminus">-</span>
    <input type="text" placeholder="Qty" id="R1_B_1" name="B_1" value="1" size="2" class="form_qty" />
    <span id="R1_plus_1" class="plusminus" >+</span>

  <input type="text" placeholder="Price" id="R1_C_1" name="C_1" size="5" class="form_price" value="27" />
  <input type="text" placeholder="Disc." id="R1_D_1" name="D_1" size="3" class="form_discount" />
  <input type="text" placeholder="Sum" id="R1_E_1" name="E_1" size="6" class="form_sum" />
  <br />

  <input type="text" placeholder="Item" id="R1_A_2" name="A_2" size="20" class="form_item" value="Motherboard ASus XYZ" />

    <span id="R1_min_2" class="plusminus">-</span>
    <input type="text" placeholder="Qty" id="R1_B_2" name="B_2" value="1" size="2" class="form_qty" />
    <span id="R1_plus_2" class="plusminus" >+</span>

  <input type="text" placeholder="Price" id="R1_C_2" name="C_2" size="5" class="form_price" value="46" />
  <input type="text" placeholder="Disc." id="R1_D_2" name="D_2" size="3" class="form_discount" />
  <input type="text" placeholder="Sum" id="R1_E_2" name="E_2" size="6" class="form_sum" />
  <br />

  <input type="text" placeholder="Item" id="R1_A_3" name="A_3" size="20" class="form_item" value="Memory Kingston DDR3 4GB" />

    <span id="R1_min_3" class="plusminus">-</span>
    <input type="text" placeholder="Qty" id="R1_B_3" name="B_3" value="1" size="2" class="form_qty" />
    <span id="R1_plus_3" class="plusminus" >+</span>

  <input type="text" placeholder="Price" id="R1_C_3" name="C_3" size="5" class="form_price" value="18" />
  <input type="text" placeholder="Disc." id="R1_D_3" name="D_3" size="3" class="form_discount" />
  <input type="text" placeholder="Sum" id="R1_E_3" name="E_3" size="6" class="form_sum" />
  <br />

  <input type="text" placeholder="Total Amount" id="R1_total" name="R1_total" />

  <br />
  <br />

  <input type="text" placeholder="Item" id="R2_A_4" name="A_4" size="20" class="form_item" value="Other foo" />

    <span id="R2_min_4" class="plusminus">-</span>
    <input type="text" placeholder="Qty" id="R2_B_4" name="B_4" value="1" size="2" class="form_qty" />
    <span id="R2_plus_4" class="plusminus" >+</span>

  <input type="text" placeholder="Price" id="R2_C_4" name="C_4" size="5" class="form_price" value="18" />
  <input type="text" placeholder="Disc." id="R2_D_4" name="D_4" size="3" class="form_discount" />
  <input type="text" placeholder="Sum" id="R2_E_4" name="E_4" size="6" class="form_sum" />
  <br />

  <input type="text" placeholder="Item" id="R2_A_5" name="A_5" size="20" class="form_item" value="Other bar" />

    <span id="R2_min_5" class="plusminus">-</span>
    <input type="text" placeholder="Qty" id="R2_B_5" name="B_5" value="1" size="2" class="form_qty" />
    <span id="R2_plus_5" class="plusminus" >+</span>

  <input type="text" placeholder="Price" id="R2_C_5" name="C_5" size="5" class="form_price" value="18" />
  <input type="text" placeholder="Disc." id="R2_D_5" name="D_5" size="3" class="form_discount" />
  <input type="text" placeholder="Sum" id="R2_E_5" name="E_5" size="6" class="form_sum" />
  <br />

  <input type="text" placeholder="Total Amount" id="R2_total" name="R2_total" />

  <br />
  <br />

  <input type="text" placeholder="Item" id="R3_A_6" name="A_6" size="20" class="form_item" value="Some X" />

    <span id="R3_min_6" class="plusminus">-</span>
    <input type="text" placeholder="Qty" id="R3_B_6" name="B_6" value="1" size="2" class="form_qty" />
    <span id="R3_plus_6" class="plusminus" >+</span>

  <input type="text" placeholder="Price" id="R3_C_6" name="C_6" size="5" class="form_price" value="18" />
  <input type="text" placeholder="Disc." id="R3_D_6" name="D_6" size="3" class="form_discount" />
  <input type="text" placeholder="Sum" id="R3_E_6" name="E_6" size="6" class="form_sum" />
  <br />

  <input type="text" placeholder="Item" id="R3_A_7" name="A_7" size="20" class="form_item" value="Some Y" />

    <span id="R3_min_7" class="plusminus">-</span>
    <input type="text" placeholder="Qty" id="R3_B_7" name="B_7" value="1" size="2" class="form_qty" />
    <span id="R3_plus_7" class="plusminus" >+</span>

  <input type="text" placeholder="Price" id="R3_C_7" name="C_7" size="5" class="form_price" value="18" />
  <input type="text" placeholder="Disc." id="R3_D_7" name="D_7" size="3" class="form_discount" />
  <input type="text" placeholder="Sum" id="R3_E_7" name="E_7" size="6" class="form_sum" />
  <br />

  <input type="text" placeholder="Item" id="R3_A_8" name="A_8" size="20" class="form_item" value="Some Z" />

    <span id="R3_min_8" class="plusminus">-</span>
    <input type="text" placeholder="Qty" id="R3_B_8" name="B_8" value="1" size="2" class="form_qty" />
    <span id="R3_plus_8" class="plusminus" >+</span>

  <input type="text" placeholder="Price" id="R3_C_8" name="C_8" size="5" class="form_price" value="18" />
  <input type="text" placeholder="Disc." id="R3_D_8" name="D_8" size="3" class="form_discount" />
  <input type="text" placeholder="Sum" id="R3_E_8" name="E_8" size="6" class="form_sum" />
  <br />

  <input type="text" placeholder="Item" id="R3_A_9" name="A_9" size="20" class="form_item" value="Some Õ" />

    <span id="R3_min_9" class="plusminus">-</span>
    <input type="text" placeholder="Qty" id="R3_B_9" name="B_9" value="1" size="2" class="form_qty" />
    <span id="R3_plus_9" class="plusminus" >+</span>

  <input type="text" placeholder="Price" id="R3_C_9" name="C_9" size="5" class="form_price" value="18" />
  <input type="text" placeholder="Disc." id="R3_D_9" name="D_9" size="3" class="form_discount" />
  <input type="text" placeholder="Sum" id="R3_E_9" name="E_9" size="6" class="form_sum" />
  <br />

  <input type="text" placeholder="Total Amount" id="R3_total" name="R3_total" />

  <input type="hidden" id="R1" name="R1" value="1-3" />
  <input type="hidden" id="R2" name="R2" value="4-5" />
  <input type="hidden" id="R3" name="R3" value="6-9" />

  <br />
  <br />

  <input type="submit" name="test" value="submit all forms" />

</form>

</body>
</html> 

I'd like still to see more general and effective solutions here!

You are not likely to find a ponent for that, because most workflows are optimized for one-way processing: having at least two parameters to define a result. Other directions are ambiguous. Take your example with unit price (UP), quantity (Q) and price (PR) where PR=UP*Q. There is no real "mon usecase" to enable PR editing; what would that mean: you need to calculate a new UP=PR/Q or a new Q=PR/UP? (If you can decide it now, that does not mean that there are not tasks where both of the choices, or only the other one is adequate. Having the 3 fields you have a=fn_a(b,c), b=fn_b(a,c) and c=fn_c(a,b) to calculate values. When one of them (say X) is edited, that obsoletes the X=fn_X... calculation, but you still have two others to choose from (and if a real change happened, then generally both will assign different values). The choice between the two formulas might depend on context and/or value entered and/or the order the controls were last used in. This simply is not a question of framework, but an integral part of the page's unique function. If you have designed how that should work then you may get some aid from a framework. AngularJS allows you to bind every control to a property of an object, and so the object can store the relevant state (e.g. the order in which the controls have been used) and alter its calculation behavior accordingly (e.g. always re-calculate the least recently entered parameter based on all more recent ones).

Modifying the html code i've create this script jQuery without external plugin.
Fiddle
This script putes tot-row, tot-group, price-per-unit, average-price, and shows the last value changed.
is possible to change row sum and price is recalculated.
Probably due to my ignorance I don't understand the question of ranges could you please give me some clarification?

<script type="text/javascript">
$(document).ready(function(){

     $('input.Row').each(function(){$(this).val('Row nuber: '+$(this).parent('div').find('div').length)})
     function calculateTot(elem){
         var ind=elem.parent().index()+1
         var totSum=0,averagePrice=0
         var collection1=elem.parents('div').find('input.sum')
         var collection2=elem.parents('div').find('input.price')
         for(i=0;i<collection1.length;i++){
              totSum+=parseFloat(collection1.get(i).value)
              averagePrice+=parseFloat(collection2.get(i).value)
              }
         elem.parents('div').find('input.Amount').val(totSum.toFixed(2))
         elem.parents('div').find('input.AvPrice').val((averagePrice/elem.parents('div').find('input.price').length).toFixed(2))
         elem.get(0).className==='plusminus'?elem.parents('div').find('input.Change').val('Changed: Qty row:'+ind):
         elem.parents('div').find('input.Change').val('Changed: '+elem.get(0).className+' row:'+ind)
     }

    function calculateScount(elem){
        var qty =parseInt(elem.parent().find('input.qty').val())
        var price=parseFloat(elem.parent().find('input.price').val())
        var thisVal=parseFloat(elem.val())
        var scount=(price*qty)/100*thisVal
        elem.parent().find('input.sum').val((price*qty-scount).toFixed(2))
        calculateTot(elem) 
     }

     function calculate(elem){
        var qty =parseInt(elem.parent().find('input.qty').val())
        var price=parseFloat(elem.parent().find('input.price').val())
        var scontValue=parseFloat(elem.parent().find('input.discount').val())
        elem.parent().find('input.sum').val((price*qty).toFixed(2));
        calculateTot(elem)
        if(scontValue>0){calculateScount(elem.parent().find('input.discount'))}
      }

      function retro(elem){
        var scontValue=parseFloat(elem.parent().find('input.discount').val())
        elem.parent().find('input.price').val(parseFloat(elem.val()/elem.parent().find('input.qty').val()).toFixed(2))
        calculateTot(elem)
        if(scontValue>0){calculateScount(elem.parent().find('input.discount'))} 
      }

      $('.plusminus').click(function(){
        var val=$(this).text()  
        if(val==='+'){
            var qty=parseInt($(this).prev().val())
            qty++
            $(this).prev().val(qty)
            calculate($(this))
        }

        if(val==='-'&&parseInt($(this).next().val())>=1){
            var qty=parseInt($(this).next().val())
            qty--
            $(this).next().val(qty)
            calculate($(this))
        }

       });
     $('input.qty,input.price').on('change',function(){calculate($(this))})  
     $('input.discount').on('change',function(){calculateScount($(this))})  
     $('input.sum').on('change',function(){retro($(this))})      
});
</script>
发布评论

评论列表(0)

  1. 暂无评论