[英]Javascript / jQuery - Price calculation
I'm building an events app using Ruby on Rails. 我正在使用Ruby on Rails构建事件应用程序。 At the moment a user who wishes to book onto an event can only book and pay for one space at a time. 目前,希望预订活动的用户一次只能预订并支付一个空间。 I need to offer the facility for them to book multiple spaces and pay the appropriate price - so 5 spaces for £10 each = £50 to pay etc. I've looked for appropriate solutions in RoR to sort this but I'm hitting a brick wall. 我需要为他们提供设施以预订多个空间并支付适当的价格-所以5个空间,每个空间10英镑=支付50英镑,等等。砖墙。 However, I believe I've perhaps approached this the wrong way and that a solution using javascript or jQuery is the best way forward. 但是,我相信我可能采用了错误的方法,使用javascript或jQuery的解决方案是最好的方法。 I'm very much a novice at both and need some assistance in achieving this objective. 我对这两者都是新手,因此在实现此目标方面需要一些帮助。
Here's my payment/booking page - 这是我的付款/预订页面-
I want a User to be able to place the number of spaces in the first text area and for the price (total amount) to change accordingly. 我希望用户能够将空格数放在第一个文本区域中,并且价格(总计)可以相应地更改。
Here's my other relevant code - 这是我的其他相关代码-
booking.rb - booking.rb-
class Booking < ActiveRecord::Base
belongs_to :event
belongs_to :user
def total_amount
#quantity.to_i * @price_currency.to_money
quantity.to_i * strip_currency(event.price)
end
private
def strip_currency(amount = '')
amount.to_s.gsub(/[^\D\.]/, '').to_f
end
end
bookings_controller.rb bookings_controller.rb
class BookingsController < ApplicationController
before_action :authenticate_user!
def new
# booking form
# I need to find the event that we're making a booking on
@event = Event.find(params[:event_id])
# and because the event "has_many :bookings"
@booking = @event.bookings.new(quantity: params[:quantity])
# which person is booking the event?
@booking.user = current_user
#@booking.quantity = @booking.quantity
@total_amount = @booking.quantity.to_f * @event.price.to_f
end
def create
# actually process the booking
@event = Event.find(params[:event_id])
@booking = @event.bookings.new(booking_params)
@booking.user = current_user
@price = price
@quantity = quantity
#@total_amount = @booking.quantity.to_f * @event.price.to_f
Booking.transaction do
@event.reload
if @event.bookings.count > @event.number_of_spaces
flash[:warning] = "Sorry, this event is fully booked."
raise ActiveRecord::Rollback, "event is fully booked"
end
end
if @booking.save
# CHARGE THE USER WHO'S BOOKED
# #{} == puts a variable into a string
Stripe::Charge.create(amount: @event.price_pennies, currency: "gbp",
card: @booking.stripe_token, description: "Booking number #{@booking.id}")
flash[:success] = "Your place on our event has been booked"
redirect_to event_path(@event)
else
flash[:error] = "Payment unsuccessful"
render "new"
end
if @event.is_free?
@booking.save!
flash[:success] = "Your place on our event has been booked"
redirect_to event_path(@event)
end
end
#def total_amount
#@total_amount = @booking.quantity * @event.price
#end
private
def booking_params
params.require(:booking).permit(:stripe_token, :quantity)
end
end
bookings.new.html.erb bookings.new.html.erb
<div class="col-md-6 col-md-offset-3" id="eventshow">
<div class="row">
<div class="panel panel-default">
<div class="panel-heading">
<h2>Confirm Your Booking</h2>
</div>
<div class="panel-body">
<p>Confirm number of spaces you wish to book here:
<input type="number" placeholder="1" min="1" value="1"></p>
<p>Total Amount £<%= @event.price %></p>
<%= simple_form_for [@event, @booking], id: "new_booking" do |form| %>
<span class="payment-errors"></span>
<div class="form-row">
<label>
<span>Card Number</span>
<input type="text" size="20" data-stripe="number"/>
</label>
</div>
<div class="form-row">
<label>
<span>CVC</span>
<input type="text" size="4" data-stripe="cvc"/>
</label>
</div>
<div class="form-row">
<label>
<span>Expiration (MM/YYYY)</span>
<input type="text" size="2" data-stripe="exp-month"/>
</label>
<span> / </span>
<input type="text" size="4" data-stripe="exp-year"/>
</div>
</div>
<div class="panel-footer">
<%= form.button :submit %>
</div>
<% end %>
<% end %>
</div>
</div>
</div>
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
<script type="text/javascript">
Stripe.setPublishableKey('<%= STRIPE_PUBLIC_KEY %>');
var stripeResponseHandler = function(status, response) {
var $form = $('#new_booking');
if (response.error) {
// Show the errors on the form
$form.find('.payment-errors').text(response.error.message);
$form.find('input[type=submit]').prop('disabled', false);
} else {
// token contains id, last4, and card type
var token = response.id;
// Insert the token into the form so it gets submitted to the server
$form.append($('<input type="hidden" name="booking[stripe_token]" />').val(token));
// and submit
$form.get(0).submit();
}
};
// jQuery(function($) { - changed to the line below
$(document).on("ready page:load", function () {
$('#new_booking').submit(function(event) {
var $form = $(this);
// Disable the submit button to prevent repeated clicks
$form.find('input[type=submit]').prop('disabled', true);
Stripe.card.createToken($form, stripeResponseHandler);
// Prevent the form from submitting with the default action
return false;
});
});
</script>
One aspect of building this site which I didn't appreciate is how difficult and complex it can be to deal with money when using RoR. 我不喜欢建立该站点的一个方面是,使用RoR处理资金有多么困难和复杂。 A few of the suggestions I've received stated I should be using the monetize gem (I'm not, I'm using money-rails) and this coupled with some model method/MVC magic would achieve this. 我收到的一些建议指出,我应该使用可货币化的宝石(我不是,我使用的是钱轨),并且结合一些模型方法/ MVC魔术可以达到此目的。 However, I think I'd prefer this route if the right solution can be found. 但是,如果可以找到正确的解决方案,我想我会选择这种方法。
As you suggest, one approach is to use JavaScript to calculate the total. 正如您所建议的,一种方法是使用JavaScript计算总数。
You could change this snippet of your view: 您可以更改以下视图片段:
<p>
Confirm number of spaces you wish to book here:
<input type="number" placeholder="1" min="1" value="1">
</p>
<p>Total Amount £<%= @event.price %></p>
to make it easier to target with jQuery and to provide a reference to the price per space. 使其更易于使用jQuery定位,并提供每个空间价格的参考。 For example: 例如:
<div class="calculate-total">
<p>
Confirm number of spaces you wish to book here:
<input type="number" placeholder="1" min="1" value="1">
</p>
<p>
Total Amount
£<span class="total" data-unit-cost="<%= @event.price %>">0</span>
</p>
</div>
Using JavaScript, you can listen for a keyup
event on the input field and perform the calculation. 使用JavaScript,您可以在输入字段上侦听keyup
事件并执行计算。
$('.calculate-total input').on('keyup', calculateBookingPrice);
function calculateBookingPrice() {
var unitCost = parseFloat($('.calculate-total .total').data('unit-cost')),
numSpaces = parseInt($('.calculate-total .num-spaces').val()),
total = (numSpaces * unitCost).toFixed(2);
if (isNaN(total)) {
total = 0;
}
$('.calculate-total span.total').text(total);
}
Having the function separated from the event listener means you could also call it when the page loads so that you have a starting value. 将函数与事件侦听器分开,意味着您也可以在页面加载时调用它,以便获得初始值。
Here's a fiddle to demonstrate (it assumes @event.price
is 10). 这是一个小提琴来演示(假设@event.price
为10)。
UPDATE 更新
The key here is that @event.price
should return the unit price of a booking. 这里的关键是@event.price
应该返回预订的单价。 Your new action can be as simple as this: 您的新动作可以像这样简单:
def new
# Find the event for the booking.
@event = Event.find(params[:event_id])
# @event.price should return the unit cost of a booking.
# Don't need to set attributes here -- you can add them in create.
@booking = @event.bookings.new
end
Also note that if you want to store quantity
and/or total_amount
on your @booking
object, you should move the fields inside your form ( simple_form_for
) and adjust the markup so they are submitted as part of the booking. 另请注意,如果要将quantity
和/或total_amount
存储在@booking
对象上,则应移动表单( simple_form_for
)内的字段并调整标记,以便将其作为预订的一部分提交。 something like this: 像这样的东西:
<%= simple_form_for [@event, @booking], id: "new_booking" do |form| %>
<%= f.input :quantity %>
<%= f.input :total_amount %>
...
And adjust your JavaScript to target these inputs (instead of the input
and span
in my original post). 并调整JavaScript以定位这些输入(而不是我原始帖子中的input
和span
)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.