javascript - 使用复选框作为按钮来自动计算 jquery 中的总数?

标签 javascript html jquery

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

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

我使用了以下 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. 如果用户点击“喝一杯”按钮,然后立即点击“喝两杯”按钮,价格只会增加“喝两杯”的值(value)并减去“喝一杯”的值(value)。 “三杯酒”等也是如此。

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

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

最佳答案

问题涉及在不引发 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”,并且所有选项都绑定(bind)了一个处理程序。

演示:

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


替代方法

与其在 float 价格中增加和减少,不如考虑仅将选定的选项添加到固定基价。每次饮料选项发生变化时,通过增加所选选项的基本价格来重新计算总价。

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

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

关于javascript - 使用复选框作为按钮来自动计算 jquery 中的总数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64827135/

相关文章:

php - jQuery - 找不到 ajax url

javascript - 如何从 Date() 和 toISOString 获取格式为 "2016-07-06T10:57Z"的字符串日期

android - Android:不会生成很大的html(> 25k行)到pdf

javascript - 根据第一个下拉选择 jquery 显示第二个下拉选项

javascript - jQuery 中的切换功能

python - 来自来源 'null' 已被 CORS 策略 : No 'Access-Control-Allow-Origin' header is present on the requested resource 阻止

javascript - 在调整大小时操作 jquery 菜单以实现响应式布局

javascript - 如何将输入给出的文本存储到 JSON 文件

javascript - 在 html 中显示 javascript 函数输出

html - CSS 网格布局被隐藏的 child 破坏了