Вступ
Хоча я спеціально зазначив у запитанні, що відповідь не повинен включати 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 для лову будь-яких міток, які додаються, після запуску завантаження (і сценарій запущений).
Код, відображений вище, був оптимізований Мартіном Баркером .