Найти html-метку, связанную с заданным вводом
-
08-07-2019 - |
Вопрос
Допустим, у меня есть html-форма.Каждое поле ввода / выбора / textarea будет иметь соответствующее <label>
с помощью for
атрибут, равный идентификатору его компаньона.В этом случае я знаю, что каждый входной сигнал будет иметь только одну метку.
Учитывая элемент ввода в javascript — например, через событие onkeyup - каков наилучший способ найти связанную с ним метку?
Решение
Сначала отсканируйте страницу на наличие меток и назначьте ссылку на метку из фактического элемента формы:
var labels = document.getElementsByTagName('LABEL');
for (var i = 0; i < labels.length; i++) {
if (labels[i].htmlFor != '') {
var elem = document.getElementById(labels[i].htmlFor);
if (elem)
elem.label = labels[i];
}
}
Тогда вы можете просто пойти:
document.getElementById('MyFormElem').label.innerHTML = 'Look ma this works!';
Нет необходимости в поисковом массиве:)
Другие советы
Если вы используете jQuery, вы можете сделать что-то вроде этого
$('label[for="foo"]').hide ();
Если вы не используете jQuery, вам придется искать ярлык. Вот функция, которая принимает элемент в качестве аргумента и возвращает связанную метку
function findLableForControl(el) {
var idVal = el.id;
labels = document.getElementsByTagName('label');
for( var i = 0; i < labels.length; i++ ) {
if (labels[i].htmlFor == idVal)
return labels[i];
}
}
В стандарт HTML5 , который указывает на метки, связанные с элементом ввода.
Таким образом, вы можете использовать что-то вроде этого (поддержка нативного свойства <=>, но с запасным вариантом для извлечения меток на случай, если браузер его не поддерживает) ...
var getLabelsForInputElement = function(element) {
var labels = [];
var id = element.id;
if (element.labels) {
return element.labels;
}
id && Array.prototype.push
.apply(labels, document.querySelector("label[for='" + id + "']"));
while (element = element.parentNode) {
if (element.tagName.toLowerCase() == "label") {
labels.push(element);
}
}
return labels;
};
// ES6
var getLabelsForInputElement = (element) => {
let labels;
let id = element.id;
if (element.labels) {
return element.labels;
}
if (id) {
labels = Array.from(document.querySelector(`label[for='${id}']`)));
}
while (element = element.parentNode) {
if (element.tagName.toLowerCase() == "label") {
labels.push(element);
}
}
return labels;
};
Еще проще, если вы используете jQuery ...
var getLabelsForInputElement = function(element) {
var labels = $();
var id = element.id;
if (element.labels) {
return element.labels;
}
id && (labels = $("label[for='" + id + "']")));
labels = labels.add($(element).parents("label"));
return labels;
};
Я немного удивлен, что, похоже, никто не знает, что ты вполне допустимо делать:
<label>Put your stuff here: <input value="Stuff"></label>
Который не будет подхвачен ни одним из предложенных ответов, но будет правильно обозначьте входные данные.
Вот некоторый код, который учитывает этот случай:
$.fn.getLabels = function() {
return this.map(function() {
var labels = $(this).parents('label');
if (this.id) {
labels.add('label[for="' + this.id + '"]');
}
return labels.get();
});
};
Использование:
$('#myfancyinput').getLabels();
Некоторые заметки:
- Код был написан для наглядности, а не для производительности.Могут быть доступны более эффективные альтернативы.
- Этот код поддерживает получение меток нескольких элементов за один раз.Если это не то, чего вы хотите, адаптируйтесь по мере необходимости.
- Это по-прежнему не заботится о таких вещах, как
aria-labelledby
если бы вы использовали это (оставлено в качестве упражнения для читателя). - Использование нескольких меток - сложное дело, когда речь заходит о поддержке в различных пользовательских агентах и вспомогательных технологиях, поэтому хорошо тестируйте и используйте на свой страх и риск и т.д.и т.д.
- Да, вы также могли бы реализовать это без использования jQuery.:-)
Раньше...
var labels = document.getElementsByTagName("LABEL"),
lookup = {},
i, label;
for (i = 0; i < labels.length; i++) {
label = labels[i];
if (document.getElementById(label.htmlFor)) {
lookup[label.htmlFor] = label;
}
}
Позже...
var myLabel = lookup[myInput.id];
Язвительный комментарий:Да, вы также можете сделать это с помощью jQuery.:-)
с помощью jquery вы можете сделать что-то вроде
var nameOfLabel = someInput.attr('id');
var label = $("label[for='" + nameOfLabel + "']");
document.querySelector (" метка [for = " + vHtmlInputElement.id + "] ");
Это отвечает на вопрос самым простым и простым способом. Он использует ванильный JavaScript и работает во всех основных браузерах основного потока.
Если вы хотите использовать querySelector (и вы можете, даже вплоть до IE9, а иногда и IE8!), Другой метод становится жизнеспособным.
Если у поля формы есть идентификатор, а вы используете атрибут for
метки, это становится довольно просто в современном JavaScript:
var form = document.querySelector('.sample-form');
var formFields = form.querySelectorAll('.form-field');
[].forEach.call(formFields, function (formField) {
var inputId = formField.id;
var label = form.querySelector('label[for=' + inputId + ']');
console.log(label.textContent);
});
Некоторые отметили несколько ярлыков; если все они используют одно и то же значение для атрибута querySelectorAll
, просто используйте querySelector
вместо <=> и выполните цикл, чтобы получить все необходимое.
$("label[for='inputId']").text()
Это помогло мне получить метку элемента ввода, используя его идентификатор. Р>
Ответ от Gijs был наиболее ценным для меня, но, к сожалению, расширение не работает.
Вот переписанное расширение, которое работает, оно может кому-то помочь:
jQuery.fn.getLabels = function () {
return this.map(function () {
var parentLabels = $(this).parents('label').get();
var associatedLabels = this.id ? associatedLabels = $("label[for='" + this.id + "']").get() : [];
return parentLabels.concat(associatedLabels);
});
};
На самом деле гораздо проще добавить идентификатор к метке в самой форме, например:
<label for="firstName" id="firstNameLabel">FirstName:</label>
<input type="text" id="firstName" name="firstName" class="input_Field"
pattern="^[a-zA-Z\s\-]{2,25}$" maxlength="25"
title="Alphabetic, Space, Dash Only, 2-25 Characters Long"
autocomplete="on" required
/>
Затем вы можете просто использовать что-то вроде этого:
if (myvariableforpagelang == 'es') {
// set field label to spanish
document.getElementById("firstNameLabel").innerHTML = "Primer Nombre:";
// set field tooltip (title to spanish
document.getElementById("firstName").title = "Alfabética, espacio, guión Sólo, 2-25 caracteres de longitud";
}
Javascript должен быть в функции загрузки тела.
Просто мысль, прекрасно работает для меня.
Как уже упоминалось, (на данный момент) рейтинг с наивысшим рейтингом не учитывает возможность встраивания ввода в метку.
Поскольку никто не опубликовал ответ без JQuery, вот мой:
var labels = form.getElementsByTagName ('label');
var input_label = {};
for (var i = 0 ; i != labels.length ; i++)
{
var label = labels[i];
var input = label.htmlFor
? document.getElementById(label.htmlFor)
: label.getElementsByTagName('input')[0];
input_label[input.outerHTML] =
(label.innerText || label.textContent); // innerText for IE8-
}
В этом примере для простоты таблица поиска напрямую индексируется входными элементами HTML. Это вряд ли эффективно, и вы можете адаптировать его так, как вам нравится.
Вы можете использовать форму в качестве базового элемента или весь документ, если хотите получить метки для нескольких форм одновременно.
Не выполняется проверка на неправильный HTML (множественные или отсутствующие входные данные внутри меток, отсутствующие входные данные с соответствующим идентификатором htmlFor и т. д.), но вы можете добавить их.
Возможно, вы захотите обрезать тексты меток, поскольку при вводе в метку вводимые пробелы часто присутствуют.
пытались ли вы использовать document.getElementbyID ('id'), где id - это идентификатор метки или ситуация, в которой вы не знаете, какую именно вы ищете
Используйте селектор JQuery:
$("label[for="+inputElement.id+"]")
Для будущих поисковиков...Ниже приведена адаптированная к jQuery версия принятого ответа FlySwat от FlySwat:
var labels = $("label");
for (var i = 0; i < labels.length; i++) {
var fieldId = labels[i].htmlFor;
if (fieldId != "") {
var elem = $("#" + fieldId);
if (elem.length != 0) {
elem.data("label", $(labels[i]));
}
}
}
Используя:
$("#myFormElemId").data("label").css("border","3px solid red");
Я знаю, что это старо, но у меня были проблемы с некоторыми решениями, и я собрал их вместе. Я проверил это на Windows (Chrome, Firefox и MSIE) и OS X (Chrome и Safari) и считаю, что это самое простое решение. Он работает с этими тремя стилями прикрепления метки.
<label><input type="checkbox" class="c123" id="cb1" name="item1">item1</label>
<input type="checkbox" class="c123" id="cb2" name="item2">item2</input>
<input type="checkbox" class="c123" id="cb3" name="item3"><label for="cb3">item3</label>
Использование jQuery:
$(".c123").click(function() {
$cb = $(this);
$lb = $(this).parent();
alert( $cb.attr('id') + ' = ' + $lb.text() );
});
Мой JSFiddle: http://jsfiddle.net/pnosko/6PQCw/
Я сделал для себя, может быть кому-нибудь пригодится: JSFIDDLE р>
$("input").each(function () {
if ($.trim($(this).prev('label').text()) != "") {
console.log("\nprev>children:");
console.log($.trim($(this).prev('label').text()));
} else {
if ($.trim($(this).parent('label').text()) != "") {
console.log("\nparent>children:");
console.log($.trim($(this).parent('label').text()));
} else {
if ($.trim($(this).parent().prev('label').text()) != "") {
console.log("\nparent>prev>children:");
console.log($.trim($(this).parent().prev('label').text()));
} else {
console.log("NOTFOUND! So set your own condition now");
}
}
}
});
Я немного удивлен, что никто не предлагает использовать метод отношений CSS?
в таблице стилей вы можете ссылаться на метку из селектора элемента:
<style>
//for input element with class 'YYY'
input.YYY + label {}
</style>
если флажок имеет идентификатор «XXX» тогда метка будет найдена через jQuery:
$('#XXX + label');
Вы также можете применить .find ('+ label'), чтобы вернуть метку из элемента флажка jQuery, т.е. полезно при зацикливании:
$('input[type=checkbox]').each( function(){
$(this).find('+ label');
});
Все остальные ответы чрезвычайно устарели !!
Все, что вам нужно сделать, это:
input.labels
HTML5 уже много лет поддерживается всеми основными браузерами. Нет абсолютно никаких причин, по которым вам придется делать это с нуля самостоятельно или заполнять это! Буквально просто используйте input.labels
, и это решит все ваши проблемы.
Лучший ответ работает отлично, но в большинстве случаев перебор всех элементов label
неэффективен.
Вот эффективная функция для получения input
, которая идет с элементом <=>:
function getLabelForInput(id)
{
var el = document.getElementById(id);
if (!el)
return null;
var elPrev = el.previousElementSibling;
var elNext = el.nextElementSibling;
while (elPrev || elNext)
{
if (elPrev)
{
if (elPrev.htmlFor === id)
return elPrev;
elPrev = elPrev.previousElementSibling;
}
if (elNext)
{
if (elNext.htmlFor === id)
return elNext;
elNext = elNext.nextElementSibling;
}
}
return null;
}
Для меня этой одной строки кода было достаточно:
el = document.getElementById(id).previousElementSibling;
В большинстве случаев <=> будет очень близко или рядом с входом, что означает, что цикл в вышеприведенной функции должен повторяться очень небольшое количество раз.
Действительно краткое решение, использующее функции ES6, такие как деструктурирование и неявные возвраты, чтобы превратить его в удобный однострочник, было бы:
const getLabels = ({ labels, id }) => labels || document.querySelectorAll(`label[for=${id}]`)
Или просто получить один ярлык, а не NodeList:
const getFirstLabel = ({ labels, id }) => labels && labels[0] || document.querySelector(`label[for=${id}]`)