Введение
Хотя я специально указал в вопросе, что ответ не должен включать JavaScript, все ответы работали с JavaScript.
Поскольку это, похоже, ошибка Firefox, и большинство ответов, представленных на этом этапе, потребуют от меня и остальной части моего кода, я решил создать сценарий, который можно запустить один раз, который будет обрабатывать все метки независимо от того, когда они добавляются в домен и будут оказывать наименьшее влияние на другие мои сценарии.
Решение - Пример
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>
объяснение
onLabelClick
Функция onLabelClick
должна вызываться при каждом нажатии метки, она проверит, имеет ли метка соответствующий элемент ввода. Если это произойдет, это вызовет его, удалить for
атрибут этикетки , так что браузеры не ошибка не будет повторно вызвать его , а затем использовать setTimeout
из 0ms
для добавления for
атрибута обратно после того , как событие пузырилось. Это означает, event.preventDefault
что не нужно вызывать и, следовательно, никакие другие действия / события не будут отменены. Также, если мне нужно переопределить эту функцию, мне просто нужно добавить прослушиватель событий, который вызывает Event#preventDefault
или удаляет for
атрибут.
manageLabel
ФункцияmanageLabel
принимает метку, проверяет, был ли уже добавлен прослушиватель событий, чтобы избежать его повторного добавления, добавляет прослушиватель, если он еще не был добавлен, и добавляет его в список управляемых меток.
onLoad
Функция onLoad
должна вызываться при загрузке страницы, чтобы в этот момент ее manageLabel
можно было вызывать для всех меток в DOM. Функция также использует MutationObserver для перехвата любых добавляемых меток после того, как загрузка была запущена (и скрипт был запущен).
Код, представленный выше, был оптимизирован Мартином Баркером .