Найти метку HTML, связанную с заданным вводом

Допустим, у меня есть HTML-форма. Каждое поле ввода / выбора / текста будет иметь соответствующий <label> с атрибутом for, установленным на идентификатор его сопутствующего баннера. В этом случае я знаю, что у каждого входа будет только одна метка.

Учитывая элемент ввода в javascript - например, через событие onkeyup - как лучше всего найти связанный с ним ярлык?

Обратите внимание, что у элемента может быть более одной метки, я видел некоторые приложения (например, SAP), у которых есть несколько меток для каждого элемента.

Motti 08.07.2009 10:28
function getInputLabel(thisElement) { var theAssociatedLabel,elementID; elementID = thisElement.id; theAssociatedLabel = thisElement.parentNode.querySelector("label[for='" + elementID + "']"); console.info('theAssociatedLabel.htmlFor: ' + theAssociatedLabel.htmlFor); theAssociatedLabel.style.backgroundColor = "green";//Set the label background color to green };
Alan Wells 28.10.2016 06:02

или просто node.parentNode.querySelector ("label [for = '" + node.id + "']"). innerHTML; ржу не могу

Solomon P Byer 25.11.2019 07:42
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
116
3
176 846
21
Перейти к ответу Данный вопрос помечен как решенный

Ответы 21

пробовали ли вы использовать document.getElementbyID ('id'), где id - это идентификатор метки или ситуация, когда вы не знаете, какой из них вы ищете

Я знаю идентификатор входного элемента, но не идентификатор метки.

Joel Coehoorn 13.11.2008 01:11

нельзя ли установить соответствующий идентификатор для метки, например input id = 'test' и label id = 'lbl_test "

Josh Mein 13.11.2008 01:14

Ранее...

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. :-)

Хороший. Я немного реорганизую его, чтобы он создавал поиск при первом вызове метода, но он должен помочь.

Joel Coehoorn 13.11.2008 01:13

Я имел в виду, что вы создадите поиск только один раз.

Tomalak 13.11.2008 01:15

Имейте в виду, что в нем была небольшая ошибка: используйте свойство «htmlFor», а не «for», поскольку последнее является зарезервированным словом в JS. Я забываю, что при использовании объектов меток ... :-)

Tomalak 13.11.2008 01:18

У меня есть способ сделать это без массива поиска выше.

FlySwat 13.11.2008 01:25

Я имел в виду переместить код инициализации внутри метода, а не делать это только один раз :(

Joel Coehoorn 13.11.2008 05:48

Вы не упомянули ни одного «метода», и в настоящее время я даже не уверен, знаю ли я, что вы называете «кодом инициализации». Все, что я сказал, это то, что для одной страницы поисковый объект нужно создать только один раз. Где и когда вы делаете, это полностью ваше дело.

Tomalak 13.11.2008 12:21

Я думал, что использование слов «раньше» и «позже» дало бы понять, что первое произойдет при загрузке документа, а второе произойдет в любое время, когда вам это понадобится.

Tomalak 13.11.2008 12:32

Я думаю, что в строке 3 допущена опечатка: ";"

bogatyrjov 19.08.2013 17:53

И «label [i]» вместо «label» в строке 5

bogatyrjov 19.08.2013 18:01

@Jevgeni Ой, какое-то время это оставалось незамеченным. Спасибо, что предложили исправить. Я обновил весь код, чтобы он соответствовал последнему стилю JS, и также добавил проверку «если существует цель метки».

Tomalak 19.08.2013 18:13

Если вы используете 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];
   }
}

с jquery вы могли бы сделать что-то вроде

var nameOfLabel = someInput.attr('id');
var label = $("label[for='" + nameOfLabel + "']");

Потенциально пропускает ярлыки, которые являются предками.

alex 21.02.2017 13:34
Ответ принят как подходящий

Сначала просканируйте страницу на предмет ярлыков и назначьте ссылку на ярлык из фактического элемента формы:

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!';

Нет необходимости в поисковом массиве :)

Можете ли вы объяснить, чем ваше использование свойства expando отличается от моего? Я не использую никаких «массивов поиска», я использую объект со свойствами. Существует только синтаксическая разница между «element.label», «element ['label']» или «lookup ['elementId']». За кадром они тоже самое.

Tomalak 13.11.2008 12:28

Это лучше, потому что мне не нужно держать вокруг отдельный объект - связь сохраняется непосредственно с элементом ввода.

Joel Coehoorn 13.11.2008 17:07

Это должно выполняться браузером.

andho 25.01.2013 08:43

Используйте селектор JQuery:

$("label[for = "+inputElement.id+"]")

Для будущих искателей ... Ниже приведена версия принятого ответа FlySwat на основе jQuery:

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");

+1, но из того, что я вижу, нет причин использовать версию jQuery для первого блока: она не короче и не читабельнее, а простой javascript, вероятно, будет работать лучше. Тем не менее, неплохо иметь пример jQuery того, как его использовать после создания.

Joel Coehoorn 19.08.2011 17:12

Очевидно, что для многих из нас нет особой технической причины для такого подхода, скорее, причина, по крайней мере, в моем случае, связана с HR. Представьте, что у вас есть команда, в которую входят дизайнеры, интеграторы и даже младшие разработчики, которые, по вашему мнению, привыкли использовать jQuery. Использование парадигмы jQuery может помочь повысить продуктивность и уменьшить разочарование.

ObjectType 19.08.2011 19:53

Это не очень jQuery-ified. Почему for зацикливается на each()? Почему htmlFor вместо attr("for")?

alex 05.09.2013 14:24

Полагаю, это зависит от перспективы. Потребление было jQuery-ified, а не внутренним.

ObjectType 06.09.2013 15:10
$("label[for='inputId']").text()

Это помогло мне получить метку элемента ввода по его идентификатору.

Я немного удивлен, что, кажется, никто не знает, что вы вполне разрешено должны делать:

<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. :-)

Приятно видеть, что кто-то поднимает неявную ассоциацию меток, а не делает предположение, что в элементе for всегда будет атрибут label.

Josh Habdas 25.03.2014 05:47

Ответ от 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);
    });
};

В Стандарт HTML5 есть свойство labels, которое указывает на метки, связанные с элементом ввода.

Итак, вы можете использовать что-то вроде этого (поддержка собственного свойства labels, но с резервным вариантом для получения меток на случай, если браузер его не поддерживает) ...

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;
};

Не только в Chrome, это в стандарте HTML5.

Bergi 11.08.2013 19:57

Это должно быть скоро. Спасибо!

maxhm10 13.09.2017 23:45

На самом деле гораздо проще добавить идентификатор к метке в самой форме, например:

<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 id и т. д.) Не производятся, но вы можете их добавить.

Возможно, вы захотите обрезать тексты меток, поскольку конечные пробелы часто присутствуют, когда ввод встроен в метку.

Я знаю, что это устарело, но у меня были проблемы с некоторыми решениями, и я собрал это по кусочкам. Я тестировал это в 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/

На самом деле это не работает - он просто возвращает текст родительского элемента, который иногда бывает тем текстом, который вам нужен.

John Hascall 01.07.2016 08:40

Сделал для себя, может кому пригодится: JSFIDDLE

$("input").each(function () {
    if ($.trim($(this).prev('label').text()) != "") {
        console.info("\nprev>children:");
        console.info($.trim($(this).prev('label').text()));
    } else {
        if ($.trim($(this).parent('label').text()) != "") {
            console.info("\nparent>children:");
            console.info($.trim($(this).parent('label').text()));
        } else {
            if ($.trim($(this).parent().prev('label').text()) != "") {
                console.info("\nparent>prev>children:");
                console.info($.trim($(this).parent().prev('label').text()));
            } else {
                console.info("NOTFOUND! So set your own condition now");
            }
        }
    }
});

Если вы хотите использовать 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.info(label.textContent);
});

Некоторые отметили несколько ярлыков; если все они используют одно и то же значение для атрибута for, просто используйте querySelectorAll вместо querySelector и выполните цикл, чтобы получить все, что вам нужно.

Я немного удивлен, что никто не предлагает использовать метод отношений 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');
});

К сожалению, я должен отметить, что это зависит от метки, идущей непосредственно после элемента.

Gordon Rouse 28.09.2017 03:32

document.querySelector ("метка [для =" + vHtmlInputElement.id + "]");

Это дает самый простой и краткий ответ на вопрос. Это использует ванильный javascript и работает во всех основных браузерах.

Это не дает ответа на вопрос. Как только у вас будет достаточно репутация, вы сможете комментировать любой пост; вместо этого дать ответы, не требующие пояснений от спрашивающего. - Из обзора

loki 20.07.2017 11:38

Это определенно дает ответ на вопрос @loki. Просто потому, что для этого нет дополнительных объяснений, это не значит, что он неправильный или не пытался ответить на него.

geisterfurz007 30.01.2018 17:03

Самый простой и полезный ответ! Спасибо!

iedmrc 03.07.2019 15:39

Хотел бы я дать вам 10 упов.

Adam 21.02.2021 18:58

Все остальные ответы очень сильно устарели !!

Все, что вам нужно сделать, это:

input.labels

HTML5 уже много лет поддерживается всеми основными браузерами. Нет абсолютно никаких причин, по которым вам придется делать это с нуля самостоятельно или заполнять его полифиллами! Буквально просто используйте input.labels, и он решит все ваши проблемы.

Согласно эта страница, input.labels не поддерживается IE или Edge, а Firefox только что добавил поддержку.

Antti29 06.02.2018 12:42

@ Antti29 Вы можете добавить функциональность с помощью прокладки: github.com/termi/ES5-DOM-SHIM Вы можете увидеть добавляемую функцию здесь: github.com/termi/ES5-DOM-SHIM/blob/…

ADJenks 23.04.2020 23:05

По-настоящему краткое решение, использующее такие функции ES6, как деструктуризация и неявный возврат, чтобы превратить его в удобный один лайнер, было бы:

const getLabels = ({ labels, id }) => labels || document.querySelectorAll(`label[for=${id}]`)

Или просто получить одну метку, а не NodeList:

const getFirstLabel = ({ labels, id }) => labels && labels[0] || document.querySelector(`label[for=${id}]`)

Лучший ответ работает отлично, но в большинстве случаев перебор всех элементов label является излишним и неэффективным.

Вот эффективная функция для получения 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;

В большинстве случаев label будет очень близко или рядом со входом, что означает, что цикл в приведенной выше функции должен повторяться очень небольшое количество раз.

Другие вопросы по теме