Einführung
Obwohl ich in der Frage ausdrücklich angegeben habe, dass die Antwort kein JavaScript beinhalten sollte, funktionierten alle Antworten mit JavaScript.
Da dies ein Firefox-Fehler zu sein scheint und die meisten an dieser Stelle eingereichten Antworten erfordern würden, dass ich auch den Rest meines Codes ändere, habe ich beschlossen, ein Skript zu erstellen, das einmal ausgeführt werden kann und alle Labels unabhängig vom Zeitpunkt behandelt Sie werden dem Dom hinzugefügt und haben den geringsten Einfluss auf meine anderen Skripte.
Lösung - Beispiel
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);
}
}
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>
Erläuterung
onLabelClick
Die Funktion onLabelClick
muss aufgerufen werden, wenn auf eine Beschriftung geklickt wird. Sie prüft, ob die Beschriftung ein entsprechendes Eingabeelement enthält. Ist dies der Fall, wird es auslösen, das entfernen for
Attribut des Etiketts , so dass der Browser nicht nicht den Fehler hat , erneut ausgelöst es und dann eine Verwendung setTimeout
von 0ms
dem hinzufügen for
Attribute zurück , sobald das Ereignis bis gesprudelt hat. Dies bedeutet, event.preventDefault
dass Sie nicht aufgerufen werden müssen und somit keine anderen Aktionen / Ereignisse abgebrochen werden. Auch wenn ich diese Funktion überschreiben muss, muss ich nur einen Ereignis-Listener hinzufügen, Event#preventDefault
der das for
Attribut aufruft oder entfernt .
manageLabel
Die FunktionmanageLabel
Akzeptiert eine Beschriftung, prüft, ob bereits ein Ereignis-Listener hinzugefügt wurde, um ein erneutes Hinzufügen zu vermeiden, fügt den Listener hinzu, falls er noch nicht hinzugefügt wurde, und fügt ihn der Liste der verwalteten Beschriftungen hinzu.
onLoad
Die Funktion onLoad
muss beim Laden der Seite aufgerufen werden, damit die Funktion manageLabel
zu diesem Zeitpunkt für alle Beschriftungen im DOM aufgerufen werden kann. Die Funktion verwendet auch einen MutationObserver , um alle Labels abzufangen, die hinzugefügt werden, nachdem das Laden ausgelöst wurde (und das Skript ausgeführt wurde).
Der oben angezeigte Code wurde von Martin Barker optimiert .