nic*_*oum 13 html javascript css label
In the following example, when you click on the label, the input changes state.
document.querySelector("label").addEventListener("click", function() {
console.log("clicked label");
});Run Code Online (Sandbox Code Playgroud)
label {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}Run Code Online (Sandbox Code Playgroud)
<input type="checkbox" id="1">
<label for="1">Label</label>Run Code Online (Sandbox Code Playgroud)
In Chrome, when you move the cursor between the mousedown and mouseup events the input still gets triggered, whereas in Firefox the checkbox doesn't change state.
Is there a way to fix this? (without using JavaScript event listeners)
Firefox version: 69.0.3 (64-bit)
Full set of actions when using chrome.
虽然我在问题中特别指出答案不应涉及 JavaScript,但所有答案都适用于 JavaScript。
由于这似乎是一个 Firefox 错误,并且此时提交的大多数答案都需要我更改其余代码,因此我决定创建一个可以运行一次的脚本,无论何时都会处理所有标签它们被添加到 dom 中,对我的其他脚本影响最小。
var mutationConfiguration = {
attributes: true,
childList: true
};
if (document.readyState === "complete") onLoad();
else addEventListener("load", onLoad);
var managingDoms = [];
function onLoad() {
document.querySelectorAll("label[for]").forEach(manageLabel);
if (typeof MutationObserver === "function") {
var observer = new MutationObserver(function(list) {
list.forEach(function(item) {
({
"attributes": function() {
if (!(item.target instanceof HTMLLabelElement)) return;
if (item.attributeName === "for") manageLabel(item.target);
},
"childList": function() {
item.addedNodes.forEach(function(newNode) {
if (!(newNode instanceof HTMLLabelElement)) return;
if (newNode.hasAttribute("for")) manageLabel(newNode);
});
}
}[item.type])();
});
});
observer.observe(document.body, mutationConfiguration);
}
}
function manageLabel(label) {
if (managingDoms.includes(label)) return;
label.addEventListener("click", onLabelClick);
managingDoms.push(label);
}
function onLabelClick(event) {
if (event.defaultPrevented) return;
var id = this.getAttribute("for");
var target = document.getElementById(id);
if (target !== null) {
this.removeAttribute("for");
var self = this;
target.click();
target.focus();
setTimeout(function() {
self.setAttribute("for", id);
}, 0);
}
}Run Code Online (Sandbox Code Playgroud)
label {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
padding: 10px;
border: 1px solid black;
cursor: pointer;
}Run Code Online (Sandbox Code Playgroud)
<input type="checkbox" id="a">
<input type="text" id="b">
<label for="a">A</label>
<script>
setTimeout(function() {
var label = document.createElement("label");
label.setAttribute("for", "b");
label.textContent = "b";
document.body.appendChild(label);
}, 3E3);
</script>Run Code Online (Sandbox Code Playgroud)
onLabelClickonLabelClick每当单击标签时都需要调用
该函数,它将检查标签是否具有相应的输入元素。如果确实如此,它将触发它,删除for标签的属性,以便浏览器没有错误,不会重新触发它,然后在事件冒泡后使用setTimeoutof0ms将属性添加回来。for这意味着event.preventDefault不必被调用,因此不会取消其他操作/事件。另外,如果我需要重写此函数,我只需添加一个调用Event#preventDefault或删除该for属性的事件侦听器。
manageLabel
该函数manageLabel接受标签检查是否已添加事件侦听器以避免重新添加它,如果尚未添加则添加侦听器,并将其添加到已管理的标签列表中。
onLoad
该函数onLoad需要在页面加载时调用,以便manageLabel此时可以为 DOM 上的所有标签调用该函数。该函数还使用MutationObserver来捕获在加载触发(并且脚本已运行)后添加的任何标签。
上面显示的代码由Martin Barker优化。