【问题标题】:jQuery Checkboxs as radio buttons with ability to uncheck alljQuery Checkboxes 作为单选按钮,能够取消选中所有
【发布时间】:2019-05-22 14:47:18
【问题描述】:

我有一系列充当单选按钮的复选框。这些需要保留复选框而不是单选按钮,以与相同形式的其他复选框保持一致。问题是当用户在做出选择后想要取消选中所有选项时该怎么做。我的解决方案不允许这样做。单击选定的复选框只会保持选中状态。 [编辑} 由于短语“取消选中所有”似乎引起了一些混乱,让我试着更好地解释一下。使用我现在的代码,如下所示,如果用户选择一个复选框,然后选择另一个复选框,则该用户的第一个选择将取消选中。问题是,如果现在用户决定取消选中他们的(当前选中的)第二个选择,这将使所有复选框都处于未选中状态,他们不能这样做,因为一旦选中一个框,您就不能取消选中它,除非选中另一个框.

$(".OverLen").on("click", function()
{
    Current = this.id;
    if($("#"+Current).prop("checked", true))
    {
        $(".OverLen").prop("checked", false);
        $("#"+Current).prop("checked", true);
    }
});

[编辑] 到目前为止,我发现的唯一解决方案是设置一个全局变量。但这似乎是一个尴尬的解决方案:

页面加载时:

OverLenID = ''; // 用于保存选中的 OverLen id

然后我把函数改成:

  $(".OverLen").on("click", function()
  {
     var Current = this.id;
     if($("#"+Current).is(':checked'))
     {
        if(Current == OverLenID)
        {
           $("#"+Current).prop("checked", false);
           OverLenID = '';
        }
        else
        {
           $(".OverLen").not(this).prop("checked", false);
           OverLenID = Current;
        }
     }
     else
     {
        OverLenID = '';
     }
  });

HTML 既然是请求的,这里是 HTML 的基础知识。 所有复选框都包含在一个 div 中。 div 没有什么特别之处,只是该 div 中包含 3 个 div,每个 div 都支持多行复选框。一个普通的复选框如下所示:

<input type="checkbox" id="ThisCheckboxID" name="Acc[]" value="ThisValue" />
<label for="ThisCheckboxID">CheckboxLabelName</label><br />

具有“OverLen”类的复选框如下所示:

<input class="OverLen" type="checkbox" id="OLA" name="Acc[]" value="OLA" />
<label for="OLA">Label Text A</label>
<div class="ANote">Info Text</div>
<input class="OverLen" type="checkbox" id="OLB" name="Acc[]" value="OLB" />
<label for="OLB">Label text B</label>
<div class="ANote">Info Text')</div>
<input class="OverLen" type="checkbox" id="OLC" name="Acc[]" value="OLC" />
<label for="OLC">Label Text C</label>
<div class="ANote">Info Text</div>

【问题讨论】:

  • $(".OverLen").not(this).prop("checked", false);
  • @bassxzero 对不起 - 我误解了。那并不能解决问题。虽然,谢谢,它确实消除了一行代码。也许我应该使用 onchange ...
  • @RationalRabbit 请发布 HTML,您曾提到还有其他组的复选框。盲目地写代码是浪费时间。
  • @zer00ne - 尊敬的,这无关紧要。复选框是复选框。唯一相关的因素是每个人都有一个唯一的 ID,他们确实这样做了。
  • @RationalRabbit 然后我假设每个复选框都由一个匹配的标签进行。每个复选框/标签对后跟一个 br。整组复选框/标签对嵌套在一个字段集中,而该字段集中又嵌套在一个表单中。该组的取消选中/选中所有复选框(及其标签)嵌套在图例中。你的问题的措辞有点难以理解——提到“取消选中所有”,这意味着你指的是每个复选框的切换行为你有(或需要)取消选中/选中所有主复选框(嵌套在图例中的那个).. 不确定。

标签: jquery checkbox


【解决方案1】:

type = "radio" 是你的朋友

  • 省去麻烦,使用&lt;input type="radio"&gt;,因为它们是为互斥选择行为而设计的(即在一个组中只能选中一个)。
  • 确保每个组共享相同的[name] 属性值。在演示中,每个组的名称都是cg,后缀为它的索引号。
  • 所有无线电都有唯一的#ids 和&lt;label for= 无线电ID &gt;...。将所有收音机设置为display: none(或不碍事并隐藏)和style the &lt;label&gt;s to appear as checkboxes

只需单独执行这 3 个步骤,您就不再需要在 jQuery/JavaScript 中实现该行为。扩展很容易,只需更改其他组的名称和 ID 中的单个字母(如果动态生成则更容易)。

最后一个要求是每个复选框都需要具有类似于复选框的切换行为(即用户可以通过单击直接选中/取消选中)。这是通过简单的 Vanilla JavaScript 完成的。为了将来的扩展,稳定、简单和可维护的代码将所有内容包装在&lt;form&gt; 标记中并使用HTMLFormElement API。更多细节在演示中注释。

// Register the click event to the <form>
var form = document.forms[0].onclick = fauxChx;

// Pass the Event Object (e)
function fauxChx(e) {
  /*
  Reference the clicked element's adjacent tag before it
  e.target is the clicked tag and .pES is the radio
  */
  const node = e.target.previousElementSibling;
  // if clicked tag is a label...
  if (e.target.matches('label')) {
    // and if the radio is checked...
    if (node.checked) {
      // uncheck it...
      node.checked = false;
    } else {
      // otherwise check it
      node.checked = true;
    }
  }
  /*
  By closing function the event no longer bubbles to 
  trigger anything else and by focusing on the label
  and excluding all other tags, we have isolated the
  event and as a result there are no conflicts. This
  programming pattern is called Event Delegation.
  */
  return false;
}
:root {
  font: 700 16px/1.25 Verdana;
}

body {
  overflow-y: scroll;
  overflow-x: hidden;
}

form {
  display: flex;
  justify-content: space-evenly;
  align-items: center;
}

fieldset {
  width: fit-content;
}

.chx {
  display: none;
}

label {
  position: relative;
  padding-left: 30px;
  cursor: pointer;
  margin-bottom: 9px;
  display: inline-block;
  font-size: 16px;
}

label::before {
  content: '';
  position: absolute;
  left: 0px;
  top: -3px;
  width: 20px;
  height: 20px;
  padding-left: 3px;
  padding-bottom: 3px;
  border: 1px groove #ccc;
  background: #fff;
  border-radius: 4px;
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, .1);
}

.chx:checked+label::before {
  content: '✔';
  font-size: 22px;
  line-height: 1.2;
  color: #09ad7e;
  transition: all .2s;
}

label::after {
  content: attr(for);
}
<form>
  <fieldset>
    <legend>fauxChx<br>Group 0</legend>
    <input id='cx0' name='cg0' class='chx' type='radio'>
    <label for='cx0'></label><br>
    <input id='cx1' name='cg0' class='chx' type='radio'>
    <label for='cx1'></label><br>
    <input id='cx2' name='cg0' class='chx' type='radio'>
    <label for='cx2'></label><br>
    <input id='cx3' name='cg0' class='chx' type='radio'>
    <label for='cx3'></label><br>
    <input id='cx4' name='cg0' class='chx' type='radio'>
    <label for='cx4'></label><br>
    <input id='cx5' name='cg0' class='chx' type='radio'>
    <label for='cx5'></label>
  </fieldset>

  <fieldset>
    <legend>fauxChx<br>Gruop 1</legend>
    <input id='cy0' name='cg1' class='chx' type='radio'>
    <label for='cy0'></label><br>
    <input id='cy1' name='cg1' class='chx' type='radio'>
    <label for='cy1'></label><br>
    <input id='cy2' name='cg1' class='chx' type='radio'>
    <label for='cy2'></label><br>
    <input id='cy3' name='cg1' class='chx' type='radio'>
    <label for='cy3'></label><br>
    <input id='cy4' name='cg1' class='chx' type='radio'>
    <label for='cy4'></label><br>
    <input id='cy5' name='cg1' class='chx' type='radio'>
    <label for='cy5'></label>
  </fieldset>

  <fieldset>
    <legend>fauxChx<br>Gruop 2</legend>
    <input id='cz0' name='cg2' class='chx' type='radio'>
    <label for='cz0'></label><br>
    <input id='cz1' name='cg2' class='chx' type='radio'>
    <label for='cz1'></label><br>
    <input id='cz2' name='cg2' class='chx' type='radio'>
    <label for='cz2'></label><br>
    <input id='cz3' name='cg2' class='chx' type='radio'>
    <label for='cz3'></label><br>
    <input id='cz4' name='cg2' class='chx' type='radio'>
    <label for='cz4'></label><br>
    <input id='cz5' name='cg2' class='chx' type='radio'>
    <label for='cz5'></label>
  </fieldset>
</form>

【讨论】:

  • 感谢您的出色解决方案。我相信它将来会派上用场。也喜欢您提供的链接。也就是说,我相信我会坚持使用全局变量的第二个解决方案(经过一番思考,我在我的问题中进行了编辑)。这些只是 30 个列表中的 5 个“非此即彼”复选框,我真的不想通过给它们一个不同的名称来改变它们在后端的处理方式。事实上,它们只是另一个具有不同类的复选框。
  • 不客气。当您获得更多经验时,您会倾向于 JavaScript 并减少使用 jQuery。 jQuery 方便且用途广泛,但另一方面,在表面之下还有很多事情要做,它会妨碍您。我相信这就是您现在遇到的问题。编码愉快!
【解决方案2】:

您可以使用此行取消选中同一类的所有其他复选框。

$(".OverLen").not(this).prop("checked", false);

所以你的函数看起来像这样。

$(".OverLen").on("change", function()
{
   var $this = $(this); // cache this; very minor speed opt. 

    if( $this.prop("checked", true) )
    {
        $(".OverLen").not(this).prop("checked", false);
    }
});

【讨论】:

  • 是的,正如我所说,这更简洁,但不能解决问题。不过,如果选中了一个复选框,您不能取消选中它,只能进行另一个选择。我能想到的唯一方法是设置一个全局页面加载,只有在选中一个框时才会更改。因此,您将始终知道选中了哪个复选框,如果再次选中则将其清除。
  • 我编辑了我的问题以显示全局变量的使用。这可行,但似乎必须有一种方法可以在没有全局的 jQuery 函数中执行此操作。
  • 我很抱歉。我不知道我在这个解决方案中缺少什么。这实际上工作得很好。我想我一定没有意识到这本身就是整个解决方案,并且还有其他代码妨碍了我。谢谢@bassxzero。
猜你喜欢
  • 1970-01-01
  • 2012-08-16
  • 2012-09-22
  • 2011-09-05
  • 1970-01-01
  • 2013-06-08
  • 2014-01-04
  • 1970-01-01
  • 2018-08-29
相关资源
最近更新 更多