Rails|Javascript同步多个字段,避免无限循环



我必须将价格一分为二。因此,我得到了方程price_1 + price_2 = total_price。因为我很好,我会允许用户更改3个参数中的任何一个。我必须在我的前端轨道视图中反映这一点。

当然,在数据库方面,我只存储其中两个值:)price_1和total_price

所以在我看来:

<%= f.number_field :price_1, :step => 0.1, class: "form-control" %>
<%= f.number_field :total_price, :step => 0.1, class: "form-control" %>

我认为我可以为第三个做什么:

<input id="price_2" type:"number" step="0.1">

并与javascript同步。当然,问题是这3个输入是可编辑的。因此,假设编辑price_1应该只更改price_2,反之亦然,而更改total_price应该只更改price_one(如果某个聪明的用户将price_1设置为0并降低total_price,则可能会对price_2采取措施…)

我很少看到关于这个的问题(或者可能我找不到好的答案,因为关键字不好)。这是一个快速的解决方案,但肯定会失败:

var global_lock = true
$("#price_1").on("change"){
  global_lock = !global_lock  
  if(!global_lock){
    $("#price_2").attr("value", (Integer.parse($("total_price").attr("value")) - Integer.parse($("price_1").attr("value")))
  } 
}

有更好的吗?也许我可以使用rails助手轻松集成?

编辑:

让我们抽象一下:p。相反,我有一个随机方程f(price_1, price_2, total_price) = 0。因此,我的代码变成

var global_lock = 2
$("#price_1").on("change"){
      global_lock = (global_lock++) % 3;  
      if(global_lock == 0){
        //Jquery stuff that always modifies both price_2 and total_price
      } 
    }
//Similar for price_2 and total_price

我在rails应用程序中实现了类似的功能。

如果您想在视图中保留所有ruby,可以使用number_field标记。

<%= number_field_tag(:price_2,nil,:step => 0.1) %>

我对你正在努力实现的目标的理解是:

  1. 您目前有3个字段可供用户编辑,分别命名为price_1price_2total_price
  2. total_priceprice_1price_2的和
  3. 当3个字段中的任何一个发生更改时,您希望根据其他2个字段各自的方程式更新它们

方程式如下:

价格_1已更改:

price_2 = total_price - price_1

价格_2已更改:

price_1 = total_price - price_2

总计价格已更改:

如果total_price的变化大于原始总价格,则

price_1 = price_1 + (total_price - old_total_price)

如果变化小于原始总价格,则

if price_1 < (old_total_price - total_price) then
price_1 = 0 and price_2 = price_2 - ( (old_total_price - total_price) - price_1)
else
price_1 = price_1 - (old_total_price - total_price)

很明显,如果total_price被设置为0,那么一切都是0

如果我是对的,那么我会写这样的函数:

Javascript

我对你使用global_lock有点困惑,所以如果我偏离了轨道,请告诉我。我已经编写了3个与任何更改绑定的函数,每个字段一个。希望这就是你想要的

var price_1 = $("#price_1");
var price_2 = $("#price_2");
var total_price = $("#total_price");
price_1.bind("change", function () {
    var p1 = Number(price_1.val());
    var total = Number(total_price.val());
    switch (true){
        case (p1 > total ):
            price_1.val(total);
            price_2.val(0);
            break;
        case (p1 < 0 ):
            price_1.val(0);
            price_2.val(total);
            break;
        default:
            price_2.val(Math.round((total - p1)*100)/100);
            break;
    }

});
price_2.bind("change", function () {
    var p2 = Number(price_2.val());
    var total = Number(total_price.val());
    switch (true){
        case (p2 > total ):
            price_1.val(0);
            price_2.val(total);
            break;
        case (p2 < 0 ):
            price_2.val(0);
            price_1.val(total);
            break;
        default:
            price_1.val(Math.round((total - p2)*100)/100);
            break;
    }

});
total_price.bind("change", function () {
    var total = Number(total_price.val());
    if (total < 0) {total = 0}
    var old_total = Number(price_1.val()) + Number(price_2.val());
    var total_difference = old_total - total;
    var p1 = Number(price_1.val());
    var p2 = Number(price_2.val());
    switch (true){
        case (p1 < total_difference):
            price_1.val(0);
            price_2.val(p2 - (total_difference - p1));
            break;
        default:
            price_1.val(p1 - total_difference);
            break;
    }
});

最新更新