你能模糊一组复选框吗?

Can you onblur a set of checkboxes?

提问人:Levi Wallach 提问时间:9/1/2021 更新时间:9/9/2021 访问量:2358

问:

我有一组复选框和验证,以便在提交时至少需要选中其中一个复选框。但是我希望能够在用户模糊出复选框集时设置验证错误。问题是,如果我对最后一个进行模糊处理,它将不起作用,因为它们可能会将 Shift Tab 键切换到倒数第二个复选框。我试过但 fieldset 标签中的 onblur,但这根本没有触发模糊。这只是一个纯 html 和普通 JS 无法克服的限制吗?

JavaScript HTML 验证

评论

2赞 Henok Teklu 9/1/2021
你能提供一个最小的可重现的例子(代码片段)
0赞 Neil Gaetano Lindberg 9/1/2021
您可能想考虑使用CSS来创建自己的复选框?查找“纯 CSS 复选框”,您可以使用 CSS3 选择器做很多事情。此外,如果你想将验证与JS合并,你可以控制选择/有效、选择/无效和模糊的视觉效果,但即使这样,你也可以用一些HTML5 + CSS3来做到这一点。
0赞 epascarello 9/1/2021
不确定为什么他们需要重新创建一个复选框@NeilGuyLindberg......
0赞 epascarello 9/1/2021
因此,如果他们使用键盘进行导航,您的想法将起作用,但是如果他们是鼠标用户,它会有所帮助吗?对于您的想法,您可以查看活动元素是什么,并确定它是否在组之外。
1赞 Neil Gaetano Lindberg 9/1/2021
@epascarello它不是在重新创建。它是一种隐藏复选框元素本身的方法,使用 CSS 绘制自己的元素,并使用伪装选择器。您必须查找“纯CSS复选框”以获取任何进一步的知识,因为这不是一个需要解释的小过程。

答:

1赞 epascarello 9/1/2021 #1

您可以查看下一个聚焦的元素是什么,并确定它们是否属于同一分组。

document.querySelectorAll('input[type="checkbox"]').forEach((elem) => {
  elem.addEventListener("blur", function (event) {
    const nextElem = event.relatedTarget;
    const fieldSet = elem.closest('fieldset');
    const isValid = fieldSet.querySelector("input:checked") !== null;
    if (nextElem?.closest('fieldset') !== fieldSet) {
        fieldSet.classList.toggle("error", !isValid);
    } else if (isValid) {
        fieldSet.classList.remove("error");
    }
  });
});
.error {
  color: red;
}
<form>
  <fieldset>
    <legend>Pizza One</legend>

    <input type="checkbox" name="x1-1" id="x1-1">
    <label for="x1-1">Cheese</label>

    <input type="checkbox" name="x1-2" id="x1-2">
    <label for="x1-2">Peppers</label>

    <input type="checkbox" name="x1-3" id="x1-3">
    <label for="x1=3">Mushrooms</label>

  </fieldset>

  <fieldset>
    <legend>Pizza Two</legend>

    <input type="checkbox" name="x2-1" id="x2-1">
    <label for="x2-1">Cheese</label>

    <input type="checkbox" name="x2-2" id="x2-2">
    <label for="x2-2">Peppers</label>

    <input type="checkbox" name="x2-3" id="x2-3">
    <label for="x2-3">Mushrooms</label>

  </fieldset>

  <input type="submit" />
</form>

添加使用 HTML5 验证的技巧

document.querySelectorAll('input[type="checkbox"]').forEach((elem) => {
  elem.addEventListener("blur", function(event) {
    const nextElem = event.relatedTarget;
    const fieldSet = elem.closest('fieldset');
    const isValid = fieldSet.querySelector("input:checked") !== null;
    if (nextElem?.closest('fieldset') !== fieldSet) {
      fieldSet.classList.toggle("error", !isValid);
    }
  });

  elem.addEventListener("change", function(event) {
    const fieldSet = elem.closest('fieldset');
    const isValid = fieldSet.querySelector("input:checked") !== null;
    if (isValid) {
      fieldSet.classList.remove("error");
      fieldSet.querySelectorAll("input").forEach((cb) => {
        cb.removeAttribute("required");
      });
    } else {
      fieldSet.querySelectorAll("input").forEach((cb) => {
        cb.setAttribute("required", "required");
      });
    }
  });

  const changeEvt = document.createEvent("HTMLEvents");
  changeEvt.initEvent("change", false, true);
  elem.dispatchEvent(changeEvt);
});
.error {
  color: red;
}
<form>
  <fieldset>
    <legend>Pizza One</legend>

    <input type="checkbox" name="x1-1" id="x1-1">
    <label for="x1-1">Cheese</label>

    <input type="checkbox" name="x1-2" id="x1-2">
    <label for="x1-2">Peppers</label>

    <input type="checkbox" name="x1-3" id="x1-3">
    <label for="x1=3">Mushrooms</label>

  </fieldset>

  <fieldset>
    <legend>Pizza Two</legend>

    <input type="checkbox" name="x2-1" id="x2-1">
    <label for="x2-1">Cheese</label>

    <input type="checkbox" name="x2-2" id="x2-2">
    <label for="x2-2">Peppers</label>

    <input type="checkbox" name="x2-3" id="x2-3">
    <label for="x2-3">Mushrooms</label>

  </fieldset>

  <input type="submit" />
</form>

评论

0赞 Levi Wallach 9/9/2021
谢谢你的想法。我使用其中一些来构建一个更具体地针对我的情况的函数。请注意,您的 fieldSet.querySelector(“input:checked”) !== null;对我不起作用,我不得不使用 document.querySelector(“fieldset”).querySelectorAll(“input:checked”).length。
0赞 Levi Wallach 9/9/2021 #2

根据 epascarello 的建议,我能够创建一个函数,该函数提供与所提供的功能类似的功能。我在复选框下方有一个错误跨度。我想要的行为是,如果选中任何复选框,就会立即删除它,但只有在用户模糊了整套复选框时才添加错误范围。请注意,此页面上只有一个字段集,并且错误范围具有我可以引用的特定 ID。这是我开始工作的功能:

document.querySelectorAll('input[type="checkbox"]').forEach((elem) => {
            elem.addEventListener("blur", function (event) {
                var errorSpan = document.getElementById("checkboxesErrorSpan");
                var isValid = document.querySelector("fieldset").querySelectorAll("input:checked").length > 0;
                if (isValid) {
                    if ((errorSpan.style.display == "inline")) {
                        errorSpan.style.display = "none";
                    }
                }
                else {
                    if (event.relatedTarget.type != "checkbox") {
                        if ((errorSpan.style.display == "none")) {
                            errorSpan.style.display = "inline";
                        }
                    }
                }
                
            });
        });