Juan Pablo Ugas Juan Pablo Ugas - 5 months ago 21
jQuery Question

Run jQuery Coffeescript on input change

I have a jQuery Coffeescript function that runs on page load. The functions grabs a table row then it's price, quantity and discounts and processes the values to determine a total for the row.

I currently run the function on page load but would also like it to run anytime that the form input values change. Please Note, this form is used on a rails f.fields_for which generates multiple forms and also additional dynamically generated forms.

What would be the most DRY way to do this?

$('tr.order-item').each ->
q = $(this).find('.quantity_input')
.val()
quantity = parseInt(q)
p = $(this).find('.price').text().replace("$", "")
price = parseFloat(p.replace(/,/g, ''), 10)
d = $(this).find('.discount_input').val()
discount = parseFloat(d)
total = price * quantity - discount
total_price = "$"+ parseFloat(total, 10).toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, "$1,").toString()
$(this).find('.item-total').text(total_price)


form_for fields

<tr class="order-item">
<td>
<div class="btn-group">
<button type="button" class="btn-u dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-angle-down"></i>
</button>
<ul class="dropdown-menu" role="menu">
<li>
</li>
<%= f.hidden_field :_destroy %>
<%= link_to "Remove Item", '#', class: "remove_fields btn btn-link" %>
<li><button class="btn btn-link">Add Custom Item</button></li>
<li><button class="btn btn-link">Remove Item</button></li>
</ul>
</div>
</td>
<td>
<h5 class="product"><%= f.object.product.name %></h5>
<%= f.hidden_field :product_id, class:"product-id" %>
<%= f.hidden_field :id, class:"id" %>
</td>
<td>
<h5 class="text-right"><span style="color: green" class="price"><%= number_to_currency f.object.unit_price %></span></h5>
</td>
<td>
<%= f.number_field :quantity, min: 1, hide_label: true, class:"quantity_input" %>
</td>
<td>
<%= f.text_field :discount, hide_label: true, class:"discount_input" %>
</td>
<td>
<h5 class="text-right"><span style="color: green" class="item-total"></span></h5>
</td>



Answer

An approach would be to listen for the keyup event in any input field and then update the values:

updateOrderItems = ->
  $(document).find('tr.order-item').each ->
    q = $(this).find('.quantity_input').val()
    quantity = parseInt(q)
    p = $(this).find('.price_value').text()
    price = parseFloat(p)
    d = $(this).find('.discount_input').val()
    discount = parseFloat(d)
    total_price = price * quantity - discount
    $(this).find('.item-total').text("$"+ parseFloat(total_price).toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, "$1,").toString())

updateOrderItems()
$(document).on 'keyup', 'tr.order-item input', ->
  updateOrderItems()

Passing the selector to .on() will fix your ajax issue.

To run your code on page load as well as on keyup

Declare a function, run it on page load, as well as on your keyup event.

As an alternative you might want to give your users the possibility to update the information that is displayed, by triggering your code upon a click on a button.

<button class="update-table">Update</button>

$('.update-table').on 'click', ->
  updateOrderItems()