如何通过选择首个复选框来获取已选中复选框的顺序

3

我想将选中的复选框存储在一个数组中,但是我希望它们按照选中的顺序排序。

例如,我有三个复选框 -

<label for="check-1">check 1</label>
<input type="checkbox" id="check-1" value="1" name="mycheck[]">

<label for="check-2">check 2</label>
<input type="checkbox" id="check-2" value="2" name="mycheck[]">

<label for="check-3">check 3</label>
<input type="checkbox" id="check-3" value="3" name="mycheck[]">

我选择了检查2,然后是检查3和检查1。

我希望结果以这样的数组形式呈现 ('2','3','1')

我使用了这个函数,但它没有按顺序获取它们。

var list = new Array();
    $('input[name="mycheck"]:checked').each(function() {
        list.push([$(this).val()]);
    });

console.log(list);

你的复选框为什么有相同的名称?单选按钮应该共享相同的名称,而不是复选框。 - j08691
@j08691 因为我想把它们放在数组中,[]。 - deverasha
在你的 console.log 之前简单地加上一个 list.sort((a, b) => a-b) - Andy
$('input[name="mycheck"]:checked') 按照 HTML 中存在的顺序获取元素。您可以更新某种 data-order 值,该值是它们被点击的顺序,然后在 .each 之前进行排序。 - Peter Krebs
生成的 JavaScript “用户检查顺序”数组是否需要与表单一起发送?还是您仅在此页面的 JavaScript 中使用该数组。 - bloodyKnuckles
如果您打算将此用于用户排序项目,请注意警告:顺序不可见,这是基本的可用性要求。还有其他更好的UI模式,例如优先级矩阵、选择元素以指示优先级或拖放解决方案。 - Andy
6个回答

0

如果您需要使用包含复选框的表单将订单数组数据发送到服务器,则以下是记录订单复选框被选中的另一种方法。

首先请注意,复选框名称已从name="mycheck"更改为name="mycheck[]",以利用服务器端数组创建/修改,例如PHP

有了这个设置,就可以使用querySelectorAll()forEach()来收集目标复选框,然后迭代集合以添加change事件侦听器。

使用change事件处理程序来捕获每个目标复选框的选中状态更改。在选中状态更改时,使用querySelectorAll()属性选择器以及修改器^=和伪类:checked计算已选中状态复选框的数量。将计数减少一次以确定下一个可用的数组索引。

如果选中状态更改为true,则将下一个可用的数组索引添加到复选框名称属性中。

如果选中状态更改为false,则捕获先前分配的目标复选框索引,更新复选框名称以删除索引,并更新其余选中复选框的索引以反映从选择顺序中减去一个的移除。只有索引大于目标索引的复选框需要更新。

match()正则表达式被用于捕获之前分配的索引,以便在未选中状态下(即复选框先前已选中),可以:1)捕获目标复选框索引以确定哪些已选中的复选框需要将其索引递减,2)循环已选中的复选框以递减所有索引大于目标索引的复选框。

// collect and loop inputs with name starting with "mycheck["
document.querySelectorAll('input[name^="mycheck["]').forEach(function (cbox_change) {

  // add a change event listener to each checkbox
  cbox_change.addEventListener("change", function ({target: cbox_order}) {

    // determine the next available index
    let idx_add = document.querySelectorAll('input[name^="mycheck["]:checked').length - 1;
  
    // if changed checkbox check state is true (checked)
    if ( cbox_order.checked ) {
      // add next index to name attribute
      cbox_order.name = "mycheck[" + (idx_add) + "]";
    }
    
    // if changed checkbox check state is false (unchecked)
    else {
      // get target index already assigned when changed to true
      let idx_remove = parseInt(cbox_order.name.match(/^mycheck\[([0-9]+)\]$/)[1]);
      // remove index from name
      cbox_order.name = "mycheck[]";
      // loop all checked checkboxes to update indexes greater than target index
      document.querySelectorAll('input[name^="mycheck["]:checked').forEach(function (cbox_update) {
        // capture index to update
        let idx_update = parseInt(cbox_update.name.match(/^mycheck\[([0-9]+)\]$/)[1]);
        // if greater than target index, reduce by one
        if (idx_remove < idx_update) {
          cbox_update.name = "mycheck[" + (idx_update - 1) + "]";
        }
      });
    }

    // show name of all "mycheck" checkboxes
    document.querySelectorAll('input[name^="mycheck["]').forEach(function (cbox) {
      console.log(cbox.name);
    });
  });
});
<label for="check-1">check 1</label>
<input type="checkbox" id="check-1" value="1" name="mycheck[]">

<label for="check-2">check 2</label>
<input type="checkbox" id="check-2" value="2" name="mycheck[]">

<label for="check-3">check 3</label>
<input type="checkbox" id="check-3" value="3" name="mycheck[]">

如果您正在服务器上使用PHP访问此数组,则只需:

<?php

// get checked order array
$mycheck = $_POST['mycheck'];
// sort by key
ksort($mycheck);

?>

如果你需要在浏览器中使用order数组,在表单上传之前:

let check_order = Array.from(document.querySelectorAll('input[name^="mycheck["]:checked'))
  .sort(function (aa, bb) {
    return aa.name.match(/^mycheck\[([0-9]+)\]$/)[1] - bb.name.match(/^mycheck\[([0-9]+)\]$/)[1];
  })
  .map(function (item) {
    return parseInt(item.value);
  })
;

console.log(check_order);
<label for="check-1">check 1</label>
<input type="checkbox" id="check-1" value="1" name="mycheck[2]" checked>

<label for="check-2">check 2</label>
<input type="checkbox" id="check-2" value="2" name="mycheck[0]" checked>

<label for="check-3">check 3</label>
<input type="checkbox" id="check-3" value="3" name="mycheck[1]" checked>


0
你可以使用这种方式。

    var list = new Array();
    $('input').on("click", function (e) {
        if ($(this).is(':checked')) {
            list.push([$(this).val()]);
        }
        console.log(list);

    })
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<label for="check-1">check 1</label>
    <input type="checkbox" id="check-1" value="1" name="mycheck">

    <label for="check-2">check 2</label>
    <input type="checkbox" id="check-2" value="2" name="mycheck">

    <label for="check-3">check 3</label>
    <input type="checkbox" id="check-3" value="3" name="mycheck">

希望它能工作 :)

1
好的答案应该对代码的作用进行一些解释。 - Sean
这只有在用户实际点击每个复选框时才能起作用,这对于一般状态来说是一个危险的假设。如果复选框被程序化地选中(JavaScript),在HTML中已经有了“checked”属性或者用户返回并且浏览器保持选中状态,则它不起作用。复选框也可以通过键盘选中,但这会起作用,因为它会触发“click”事件。 - Andy
所以这是一个好的开始。您需要决定如何处理已选中的复选框,其中您没有收到它们的“click”事件。并且要删除再次取消选中的复选框。 - Andy
1
由于问题要求捕获用户检查每个框的顺序,我认为单击事件满足要求。但是,此答案不允许用户在选中复选框后取消选择该框,并随后从“用户检查顺序”数组中删除该框。 - bloodyKnuckles

0

为每个复选框添加了类.chx,因为这是访问一组标签最简单的方法--我想不出你不应该这样做的原因。基本上,您需要使用事件处理程序来获取用户与复选框交互产生的值。

示例中已经注释了详细信息

// Define an empty array
let checks = [];

// Bind each checkbox to the change event
$('.chx').on('change', function() {
  // If the changed checkbox is checked
  if (this.checked) {
    // Add the checkbox's value to the array
    checks.push(+$(this).val());
  } else {
    // Otherwise add a negative value of the checkbox to the array
    checks.push(-$(this).val());
  }
  console.log(checks);
});
/* Added the negative numbers because there's two states a checkbox is in
and if it's important to know the order of what was checked then it's 
probably important to know what state each one is in as well.
*/
<label for="check-1">check 1</label>
<input type="checkbox" id="check-1" class='chx' value="1" name="mycheck[]">

<label for="check-2">check 2</label>
<input type="checkbox" id="check-2" class='chx' value="2" name="mycheck[]">

<label for="check-3">check 3</label>
<input type="checkbox" id="check-3" class='chx' value="3" name="mycheck[]">

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


当复选框未选中时,为什么我们应该添加负值? - Triet Doan
我只是在示例中添加了一个解释。 - zer00ne

0

本答案假设值是唯一的。

当选中时,将该值推送到数组中。 当取消选中时,从数组中删除它。

const selections = [];
$('[name="mycheck[]"]').on('change', function (){
  // if checked, add it to the array
  if (this.checked) {
    selections.push(this.value);
  } else {
    // if not checked, remove the value from the array
    const index = selections.indexOf(this.value);
    if (index > -1) selections.splice(index, 1);
  }
  console.log(selections);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<label for="check-1">check 1</label>
<input type="checkbox" id="check-1" value="1" name="mycheck[]">

<label for="check-2">check 2</label>
<input type="checkbox" id="check-2" value="2" name="mycheck[]">

<label for="check-3">check 3</label>
<input type="checkbox" id="check-3" value="3" name="mycheck[]">


这是一个简单而有效的解决方案,如果除了直接用户交互之外的选框检查方式应该被忽略。 - Andy

0
使用jQuery on() 方法来捕获Javascript change 事件,当复选框的状态改变时,并使用push() 方法将复选框的值添加到list数组中(如果已选中),或使用grep() 方法删除复选框的值,对于在更改后未选中的复选框。

var list = new Array();
$('input').on("change", function(e) {
  let boxval = $(this).val();
  if ($(this).is(':checked')) {
    list.push(boxval);
  } 
  else {
    list = $.grep(list, function(item) {
     return boxval !== item;
    });
  }
  console.log(list);
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<label for="check-1">check 1</label>
<input type="checkbox" id="check-1" value="1" name="mycheck">

<label for="check-2">check 2</label>
<input type="checkbox" id="check-2" value="2" name="mycheck">

<label for="check-3">check 3</label>
<input type="checkbox" id="check-3" value="3" name="mycheck">

为了保险起见,这里还提供了一个纯JavaScript版本...

...使用querySelectorAll()来收集目标复选框,然后使用forEach()迭代集合以便为每个复选框添加change事件监听器。在change事件发生时,如果复选框的选中状态为true,则将复选框值push()list数组中;反之,如果复选框的选中状态为false,则从list数组中删除复选框值。使用数组方法filterlist数组中移除未选中的框值。

var list = [];
document.querySelectorAll('input[name="mycheck"]').forEach(function (box) {
  box.addEventListener("change", function (evt) {
    let boxval = evt.target.value;
    if ( true === box.checked ) {
      list.push(boxval);
    }
    else {
      list = list.filter(function(val) {
        return boxval !== val;
      });
    }
    console.log(list);
  });
});
<label for="check-1">check 1</label>
<input type="checkbox" id="check-1" value="1" name="mycheck">

<label for="check-2">check 2</label>
<input type="checkbox" id="check-2" value="2" name="mycheck">

<label for="check-3">check 3</label>
<input type="checkbox" id="check-3" value="3" name="mycheck">


-2

在编程方面要小心状态(state):用户交互仅是改变状态的一种方式,而且通常有更多种交互方式可能比你所想象的还要多。

经常被忽视的是通过程序设置状态,例如通过“全选”复选框和键盘交互。

因此,通常最好监听change事件而不是click事件,并在创建最终列表时使用实际状态。为了表示这一点,我创建了一个按钮。

此外,您需要考虑到用户可以取消勾选并重新勾选。

此处的方法是跟踪每个复选框被选中的顺序,最后根据它们在该类型日志中的位置对实际选中的复选框进行排序。

const checkedLog = [];

$('input[type="checkbox"]').on("change", function(e) {
  if (this.checked) {
    checkedLog.push(this.value);
  }
  // only track order in which they were checked, not unchecked
});

$('button').on('click', function() {
  // get all actually checked values
  const vals = [];
  $('input:checked').each(function() {
    vals.push(this.value);
  })

  // sort actually checked values by last log entry
  const reverseLog = 
  vals.sort((a, b) => checkedLog.lastIndexOf(a) - checkedLog.lastIndexOf(b));
  console.log(vals);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<label for="check-1">check 1</label>
<input type="checkbox" id="check-1" value="1" name="mycheck">

<label for="check-2">check 2</label>
<input type="checkbox" id="check-2" value="2" name="mycheck" checked>

<label for="check-3">check 3</label>
<input type="checkbox" id="check-3" value="3" name="mycheck">

<button>get sorted values</button>

这是使用 数组的排序方法 并使用检查事件的日志来比较哪个复选框应该先出现。

lastIndexOf 被用于因为最后一次勾选的时间是有意义的。

你也可以在复选框被取消勾选时从日志中移除它们,然后 lastIndex() 就足够了。

如果只有一个被勾选的框没有触发 change 事件,lastIndexOf() 将返回 -1,并且该值将排在列表的第一位。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接