admin管理员组文章数量:1289832
In the following example, when you click on the label, the input changes state.
document.querySelector("label").addEventListener("click", function() {
console.log("clicked label");
});
label {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
<input type="checkbox" id="1">
<label for="1">Label</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");
});
label {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
<input type="checkbox" id="1">
<label for="1">Label</label>
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.
- Press the button over the label
- Move the cursor around (even outside the label) while still holding the button
- Return the cursor back to the label
- Release the button
- In Chrome, when you move the cursor between the mousedown and mouseup events the input still gets triggered --> it's not the case for me on chrome and ot shouldn't be. a click = mousedown+mouseup .. related for some ideas: stackoverflow./a/51451218/8620333 – Temani Afif Commented Nov 15, 2019 at 19:16
- @TemaniAfif Is it the case for you on chrome now? (since I've clarified what it is that I'm doing). Or does it still not change the state of the checkbox? – nick zoum Commented Nov 15, 2019 at 19:49
- 1 If we keep the mouse over the label then it's ok. the move shouldn't affect this so I guess we are facing a Firefox bug – Temani Afif Commented Nov 15, 2019 at 19:53
- 2 this is a bug which is loged as UNCONFIRMED status in firfox bug portal, "A "click" event should only occur if the mousedown and mouseup were in the same location" you can check there bug url: bugzilla.mozilla/show_bug.cgi?id=319347 – Jadli Commented Nov 15, 2019 at 21:23
-
1
@TemaniAfif I agree, moving the cursor even
1px
will break the interaction. – nick zoum Commented Nov 16, 2019 at 14:51
5 Answers
Reset to default 3Introduction
Although I specifically stated in the question that the answer shouldn't involve JavaScript, all the answers worked with JavaScript.
Since this seems to be a Firefox bug and most of the answers submitted at this point would require me to also alter the rest of my code, I decided to create a script that can be run once, will deal with all the labels regardless of when they are added to the dom and will have the least impact on my other scripts.
Solution - Example
var mutationConfiguration = {
attributes: true,
childList: true
};
if (document.readyState === "plete") 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);
}
}
label {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
padding: 10px;
border: 1px solid black;
cursor: pointer;
}
<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>
Explanation
onLabelClick
The function onLabelClick
needs to get called whenever a label gets clicked, it will check if the label has a corresponding input element. If it does, it will trigger it, remove the for
attribute of the label so that the browsers don't have the bug won't re-trigger it and then use a setTimeout
of 0ms
to add the for
attribute back once the event has bubbled up. This means event.preventDefault
doesn't have to get called and thus no other actions/events will get cancelled. Also if I need to override this function I just have to add an event-listener that calls Event#preventDefault
or removes the for
attribute.
manageLabel
The function manageLabel
accepts a label checks if it has already been added an event listener to avoid re-adding it, adds the listener if it hasn't already been added, and adds it to the list of labels have been managed.
onLoad
The function onLoad
needs to get called when the page gets loaded so that the function manageLabel
can be called for all the labels on the DOM at that moment. The function also uses a MutationObserver to catch any labels that get added, after the load has been fired (and the script has been run).
The code displayed above was optimized by Martin Barker.
I know you did not want JS Event listeners, but im thinking you mean to identify the movement this does not but is using mousedown instead of click (mousedown followed by mouseup).
While this is a known bug in Firefox you could get around it by using the mousedown event
I have had to change your id to be a valid one id's must start with a character
document.querySelector("label").addEventListener("mousedown", function(evt) {
console.log("clicked label");
// if you want to to check the checkbox when it happens,
let elmId = evt.target.getAttribute("for")
let oldState = document.querySelector("#"+elmId).checked;
setTimeout(() => {
if(oldState == document.querySelector("#"+elmId).checked){
document.querySelector("#"+elmId).checked = !oldState;
}
}, 150)
});
label {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
<input type="checkbox" id="valid_1">
<label for="valid_1">Label</label>
No. This looks like a firefox bug and not an issue with your code. I don't believe there is a css workaround for this behavior.
You may be able to report it to Mozilla and get the issue fixed, but I wouldn't rely on that. https://bugzilla.mozilla/home
For a potential workaround I would suggested triggering the event on mouseup instead.
Without javascript, when you click the label that has its "for" value the same as an inputs "id" value then the input gets clicked, but this is not consistent amongst browsers.
If a browser does follow the above, then your javascript click event will cancel out the effect, which ends up doing nothing.
A solution
To have consistency amongst browsers you could adopt a different strategy: Onload dynamically change all the attribute 'for' for 'data-for', so it nulls the original browser affect. Then you can apply your click event to each label.
var replaceLabelFor = function () {
var $labels = document.querySelectorAll('label');
var arrLabels = Array.prototype.slice.call($labels);
arrLabels.forEach(function (item) {
var att = document.createAttribute('data-for');
att.value = String(this.for);
item.setAttributeNode(att);
item.removeAttribute('for')
});
}
var applyMyLabelClick() {
document.querySelector("label").addEventListener("click", function() {
console.log("clicked label");
});
}
// x-browser handle onload
document.attachEvent("onreadystatechange", function(){
if(document.readyState === "plete"){
document.detachEvent("onreadystatechange", arguments.callee);
replaceLabelFor();
applyMyLabelClick();
}
});
Attaching the event to the document and targeting the element you require in there ought to sort this issue.
$(document).on('click', '.item', function(event) {});
From reading on this topic in the past, it’s down to Firefox understanding your action as an attempt to drag the element however, since user select is none, it just prevents the default behaviour.
This is based on fairly limited knowledge but it seems to be a known bug/quirk and there is a few articles floating around supporting this.
本文标签:
版权声明:本文标题:javascript - HTML Label doesn't trigger the respective input if the mouse gets moved while clicking in Firefox - Stack O 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741487168a2381457.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论