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 onLabelClickmuss 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 forAttribut des Etiketts , so dass der Browser nicht nicht den Fehler hat , erneut ausgelöst es und dann eine Verwendung setTimeoutvon 0msdem hinzufügen forAttribute zurück , sobald das Ereignis bis gesprudelt hat. Dies bedeutet, event.preventDefaultdass 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#preventDefaultder das forAttribut aufruft oder entfernt .
manageLabel
Die FunktionmanageLabelAkzeptiert 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 onLoadmuss beim Laden der Seite aufgerufen werden, damit die Funktion manageLabelzu 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 .