【问题标题】:Using checkboxes as buttons to auto calculate a total in jquery?使用复选框作为按钮在 jquery 中自动计算总数?
【发布时间】:2021-02-25 19:53:16
【问题描述】:

我有一个食物菜单表格,但我在带有复选框的部分遇到问题。

我想让表单更漂亮,所以我将复选框设置为按钮,以便在单击时选中该框。这很好用,但问题是当我从一个复选框移动到另一个而不取消选中第一个复选框时。它不会从我的总数中减去金额。

我使用了以下 jQuery 脚本:

$('.drinks').on('change', function() {

  $('.drinks').not(this).prop('checked', false);
  
});

自动从一个复选框切换到下一个复选框,以图形方式显示,但在我的控制台中,它实际上并没有取消选中其他复选框。

$(document).ready(function(){
   console.log("Jquery DOM ready.");
     let totalprice="200";
     $('#pricedisplay').html("$" + totalprice);

     $('input[name=drink-one]').change(function(){
        console.log("an input just changed.");
        $('input[name=drink-one]:checked').each(function(){
           let oneAddon = this.value;
           console.log(this.value);
           totalprice = parseFloat(totalprice) + parseFloat(oneAddon);
           console.log(totalprice);
        });
        $('input[name=drink-one]:not(:checked)').each(function (){
           let oneAddon = this.value;
           console.log(this.value);
           totalprice = parseFloat(totalprice) - parseFloat(oneAddon);
           console.log(totalprice);
        });
        $('#pricedisplay').html("$" + totalprice)
     });

     $('input[name=drink-two]').change(function(){
        console.log("an input just changed.");
        $('input[name=drink-two]:checked').each(function(){
           let twoAddon = this.value;
           console.log(this.value);
           totalprice = parseFloat(totalprice) + parseFloat(twoAddon);
           console.log(totalprice);
        });
        $('input[name=drink-two]:not(:checked)').each(function (){
           let twoAddon = this.value;
           console.log(this.value);
           totalprice = parseFloat(totalprice) - parseFloat(twoAddon);
           console.log(totalprice);
        });
        $('#pricedisplay').html("$" + totalprice)
     });

     $('input[name=drink-three]').change(function(){
        console.log("an input just changed.");
        $('input[name=drink-three]:checked').each(function(){
           let threeAddon = this.value;
           console.log(this.value);
           totalprice = parseFloat(totalprice) + parseFloat(threeAddon);
           console.log(totalprice);
        });
        $('input[name=drink-three]:not(:checked)').each(function (){
           let threeAddon = this.value;
           console.log(this.value);
           totalprice = parseFloat(totalprice) - parseFloat(threeAddon);
           console.log(totalprice);
        });
        $('#pricedisplay').html("$" + totalprice)
     });
     $('.drinks').on('change', function() {

       $('.drinks').not(this).prop('checked', false);

     });
   });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<body>
    <div class="chks">
        <div id="ck-button-one">
            <label>
                <input class="drinks" type="checkbox" name="drink-one" value="5"><span>One</span></input>
            </label>
        </div>
        <div id="ck-button-two">
            <label>
                <input class="drinks" type="checkbox" name="drink-two" value="10"><span>Two</span></input>
            </label>
        </div>
        <div id="ck-button-three">
            <label>
                <input class="drinks" type="checkbox" name="drink-three" value="20"><span>Three</span></input>
            </label>
        </div>
    </div>
    <div class="price">Purchase Price:
        <span id="pricedisplay"></span>
    </div>
</body>
</html>

当我点击按钮时,总价会正确添加。如果我单击同一个按钮,它会正确减去。如果我在取消单击上一个按钮之前单击另一个按钮,整个事情就会中断并继续添加,因为您无法返回之前单击的另一个按钮以撤消其值。

我需要帮助才能使此功能执行以下操作:

  1. 如果用户不想要任何额外的饮料,价格保持不变。

  2. 如果用户选择“喝一个”,价格会上涨 5。

  3. 如果用户再次点击“drink one's”按钮,价格会下降 5。

  4. 如果用户点击'drink one's'按钮,然后立即点击'drink one's'按钮,价格只会增加'drink one's'的价值并减去'drink one's'的价值。 'drink-three' 等也是如此。

  5. 一次只能检查一个按钮,或者一次不能检查任何按钮。

我尝试包含不同步骤的控制台日志以帮助调试。

【问题讨论】:

  • 你会考虑使用radio buttons吗?您需要为“无”添加一个按钮,但它可能会简化检查和取消选中按钮的逻辑。
  • 这只能处理饮料吗?或者你会有多组按钮用于不同的插件?例如,有人可以添加饮料和配菜,但不添加甜点吗?

标签: javascript html jquery


【解决方案1】:

问题涉及以编程方式取消检查输入而不引发change 事件。

解释:change 事件仅在“当用户通过单击或使用键盘提交对元素值的更改时……”并且“不一定针对每个更改元素的值” (MDN)。另见Changing .prop using jQuery does not trigger .change event

在你的情况下: 当一个选项被选中时,我们想取消选中其他选项。我们想要添加选中选项的价格并减去未选中选项的价格。然而:

  1. 为了减去未选中的选项,我们需要触发change 事件。

  2. 我们只想在一个选项被选中时取消选中其他选项。
    我们确实想在某个选项未选中时取消选中其他选项。

  3. 我们只想减去 从选中变为未选中的选项。
    我们不想减去已经取消选中的选项

所以,不要这样:

$('.drinks').on('change', function() {
  $('.drinks').not(this).prop('checked', false);
});

我们可以使用这个:

$('.drinks').on('change', function() {
  if (this.checked) {
    $('.drinks:checked').not(this).prop('checked', false).trigger('change');
  }
}

下面,我合并了一些重复的代码,以尽量保持DRY。现在每个选项都具有相同的名称“drink”,并且所有选项都绑定了一个处理程序。

演示:

$(function() {

  const $priceDisplay = $('#pricedisplay');
  const $drinks = $('.drinks');
  let totalprice = 200;

  $priceDisplay.html("$" + totalprice);

  $drinks.on('change', function() {

    // if changed input is checked ...
    if (this.checked) {
      // for all checked except this, uncheck and trigger "change" event
      $drinks.filter(':checked').not(this).prop('checked', false).trigger('change');
    }

    // add or subtract price depending on checked state
    totalprice = this.checked
      ? totalprice + parseFloat(this.value)
      : totalprice - parseFloat(this.value);

    // update display
    $priceDisplay.html("$" + totalprice);

  });

});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!DOCTYPE html>

<div class="chks">
  <div id="ck-button-one">
    <label>
      <input class="drinks" type="checkbox" name="drink" value="5">
      <span>One</span>
    </label>
  </div>
  <div id="ck-button-two">
    <label>
      <input class="drinks" type="checkbox" name="drink" value="10">
      <span>Two</span>
    </label>
  </div>
  <div id="ck-button-three">
    <label>
      <input class="drinks" type="checkbox" name="drink" value="20">
      <span>Three</span>
    </label>
  </div>
</div>
<div class="price">Purchase Price:
  <span id="pricedisplay"></span>
</div>

替代方法

与其在浮动价格中加减,不如考虑仅将选定的期权添加到固定的基本价格中。每次更改饮品选项时,通过增加所选选项的基价来重新计算总价。

当饮品选项发生变化时,所选饮品的价格会添加到基本价格中。
如果未选择任何饮品,则基本价格不会增加任何内容。

$(function() {

  const basePrice = "200";
  const $priceDisplay = $('#pricedisplay');
  const $drinks = $('.drinks');

  $priceDisplay.html("$" + basePrice);

  $drinks.on('change', function() {

    let newPrice = parseFloat(basePrice);

    $drinks.not(this).prop('checked', false);

    $drinks.filter(':checked').each(function() {
      newPrice += parseFloat(this.value);
    });

    $priceDisplay.html("$" + newPrice);

  });

});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="chks">
  <div id="ck-button-one">
    <label>
      <input class="drinks" type="checkbox" name="drink" value="5">
      <span>One</span>
    </label>
  </div>
  <div id="ck-button-two">
    <label>
      <input class="drinks" type="checkbox" name="drink" value="10">
      <span>Two</span>
    </label>
  </div>
  <div id="ck-button-three">
    <label>
      <input class="drinks" type="checkbox" name="drink" value="20">
      <span>Three</span>
    </label>
  </div>
</div>
<div class="price">Purchase Price:
  <span id="pricedisplay"></span>
</div>

结构略有不同,这个概念可以扩展为处理多个选项组:

$(function() {

  const basePrice = "200";
  const $priceDisplay = $('#pricedisplay');
  const $options = $('.option');

  $priceDisplay.html("$" + basePrice);

  $options.on('change', function() {

    // define new price from base price
    let newPrice = parseFloat(basePrice);

    // uncheck other options in this group
    let $thisGroupOpts = $options.filter('[name=' + this.name + ']');
    $thisGroupOpts.not(this).prop('checked', false);

    // add prices for all checked options
    $options.filter(':checked').each(function() {
      newPrice += parseFloat(this.value);
    });

    // display total price
    $priceDisplay.html("$" + newPrice);

  });

});
.optionsPane {
  display: flex;
  flex-direction: row;
  margin: 0 0 2em;
}

.optionGroup {
  flex: 1 1 auto;
}

.optionGroup label {
  display: block;
}

#pricedisplay {
  font-weight: bold;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="optionsPane">
  <div class="optionGroup">
    <h2>Drinks</h2>
    <label>
      <input class="option" type="checkbox" name="drink" value="5">
      <span>One</span>
    </label>
    <label>
      <input class="option" type="checkbox" name="drink" value="10">
      <span>Two</span>
    </label>
    <label>
      <input class="option" type="checkbox" name="drink" value="20">
      <span>Three</span>
    </label>
  </div>
  <div class="optionGroup">
    <h2>Sides</h2>
    <label>
      <input class="option" type="checkbox" name="side" value="3">
      <span>One</span>
    </label>
    <label>
      <input class="option" type="checkbox" name="side" value="4">
      <span>Two</span>
    </label>
    <label>
      <input class="option" type="checkbox" name="side" value="5">
      <span>Three</span>
    </label>
  </div>
  <div class="optionGroup">
    <h2>Deserts</h2>
    <label>
      <input class="option" type="checkbox" name="desert" value="5">
      <span>One</span>
    </label>
    <label>
      <input class="option" type="checkbox" name="desert" value="7">
      <span>Two</span>
    </label>
    <label>
      <input class="option" type="checkbox" name="desert" value="10">
      <span>Three</span>
    </label>
  </div>
</div>
<div class="price">Purchase Price:
  <span id="pricedisplay"></span>
</div>

【讨论】:

  • 这可能是我在这里看到的问题的最佳解决方案。真正经过深思熟虑和乐于助人。谢谢。
猜你喜欢
  • 1970-01-01
  • 2011-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多