Javascript / jQuery - 价格计算

时间:2016-09-07 11:54:21

标签: javascript jquery html ruby-on-rails ruby

我正在使用Ruby on Rails构建一个事件应用程序。目前,希望预订活动的用户一次只能预订并支付一个空间。我需要提供设施让他们预订多个空间并支付适当的价格 - 所以5个空间,每个10英镑= 50英镑支付等。 我在RoR中寻找合适的解决方案来解决这个问题,但我正在打砖墙。 但是,我相信我可能以错误的方式接近这一点,并且使用javascript或jQuery的解决方案是最好的方法。 我在这两方面都非常新手,需要一些帮助来实现这一目标。

这是我的付款/预订页面 -

Booking page

我希望用户能够在第一个文本区域中放置空格数,并且相应地更改价格(总金额)。

这是我的其他相关代码 -

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

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

<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>

建立这个网站的一个方面我不理解在使用RoR时处理钱是多么困难和复杂。我收到的一些建议表明我应该使用货币化的宝石(我不是,我正在使用money-rails),再加上一些模型方法/ MVC魔术就可以实现这一点。但是,如果可以找到正确的解决方案,我想我更喜欢这条路线。

1 个答案:

答案 0 :(得分:0)

正如您所建议的,一种方法是使用JavaScript来计算总数。

您可以更改视图的此片段:

<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>

使用jQuery更容易定位并提供每个空间价格的引用。例如:

<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>

使用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);
}

将函数与事件侦听器分开意味着您也可以在页面加载时调用它,以便您具有起始值。

Here's a fiddle演示(假设@event.price为10)。

<强>更新

这里的关键是@event.price应该返回预订的单价。您的操作可以像这样简单:

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

另请注意,如果您要在quantity对象上存储total_amount和/或@booking,则应移动表单中的字段(simple_form_for)并进行调整标记,以便它们作为预订的一部分提交。像这样的东西:

<%= simple_form_for [@event, @booking], id: "new_booking" do |form| %>
  <%= f.input :quantity %>
  <%= f.input :total_amount %>
  ...

调整JavaScript以定位这些输入(而不是原始帖子中的inputspan)。