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

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

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


person Joel Coehoorn    schedule 12.11.2008    source источник
comment
Обратите внимание, что у элемента может быть более одной метки, я видел некоторые приложения (например, SAP), у которых есть несколько меток для каждого элемента.   -  person Motti    schedule 08.07.2009
comment
или просто node.parentNode.querySelector (label [for = '+ node.id +']). innerHTML; ржу не могу   -  person Solomon P Byer    schedule 25.11.2019


Ответы (21)


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

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

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

person FlySwat    schedule 12.11.2008
comment
Можете ли вы объяснить, чем ваше использование свойства expando отличается от моего? Я не использую поисковый массив, я использую объект со свойствами. Существует только синтаксическая разница между element.label, element ['label'] или lookup ['elementId']. За кадром они одно и то же. - person Tomalak; 13.11.2008
comment
Это лучше, потому что мне не нужно держать вокруг отдельный объект - связь сохраняется непосредственно с элементом ввода. - person Joel Coehoorn; 13.11.2008
comment
Это должно выполняться браузером. - person andho; 25.01.2013

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

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

Таким образом, вы можете использовать что-то вроде этого (поддержка собственного свойства 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;
};
person alex    schedule 25.02.2013
comment
Не только в Chrome, это в стандарте HTML5. - person Bergi; 11.08.2013
comment
Это должно быть скоро. Спасибо! - person maxhm10; 13.09.2017

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

<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. :-)
person Gijs    schedule 18.01.2012
comment
Приятно видеть, что кто-то поднимает неявную ассоциацию меток, а не делает предположение, что в элементе label всегда будет атрибут for. - person Josh Habdas; 25.03.2014

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

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

person Luigi D'Amico    schedule 20.07.2017
comment
Это не дает ответа на вопрос. Когда у вас будет достаточная репутация, вы сможете комментировать любой пост; вместо этого предоставит ответы которые не требуют пояснений от автора вопроса. - Из отзыва - person loki; 20.07.2017
comment
Это определенно дает ответ на вопрос @loki. Просто потому, что для этого нет дополнительных объяснений, это не значит, что он неправильный или не пытался ответить на него. - person geisterfurz007; 30.01.2018
comment
Самый простой и полезный ответ! Спасибо! - person iedmrc; 03.07.2019
comment
Хотел бы я дать вам 10 упов. - person Adam; 21.02.2021

Ранее...

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

person Tomalak    schedule 12.11.2008
comment
Отлично. Я немного реорганизую его, чтобы он создавал поиск при первом вызове метода, но он должен помочь. - person Joel Coehoorn; 13.11.2008
comment
Я имел в виду, что вы создадите поиск только один раз. - person Tomalak; 13.11.2008
comment
Имейте в виду, что в нем была небольшая ошибка: используйте свойство htmlFor, а не for, поскольку последнее является зарезервированным словом в JS. Я забываю, что при использовании объектов меток ... :-) - person Tomalak; 13.11.2008
comment
У меня есть способ сделать это без массива поиска выше. - person FlySwat; 13.11.2008
comment
Я имел в виду переместить код инициализации внутри метода, а не делать это только один раз :( - person Joel Coehoorn; 13.11.2008
comment
Вы не упомянули ни одного метода, и в настоящее время я даже не уверен, знаю ли я, что вы называете кодом инициализации. Все, что я сказал, это то, что для одной страницы поисковый объект нужно построить только один раз. Где и когда вы это сделаете, это полностью зависит от вас. - person Tomalak; 13.11.2008
comment
Я думал, что мое использование слов ранее и позже дало бы понять, что первое произойдет при загрузке документа, а второе произойдет в любое время, когда вам это понадобится. - person Tomalak; 13.11.2008
comment
Я думаю, что в строке 3 допущена опечатка:; - person bogatyrjov; 19.08.2013
comment
И метки [i] вместо метки в строке 5 - person bogatyrjov; 19.08.2013
comment
@Jevgeni Ой, какое-то время это оставалось незамеченным. Спасибо, что предложили исправить. Я обновил весь код, чтобы он соответствовал последнему стилю JS, и добавил также проверку, если существует цель метки. - person Tomalak; 19.08.2013

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

var nameOfLabel = someInput.attr('id');
var label = $("label[for='" + nameOfLabel + "']");
person AndreasKnudsen    schedule 12.11.2008
comment
Потенциально пропускает ярлыки, которые являются предками. - person alex; 21.02.2017

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

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

input.labels

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

person dj nag    schedule 14.11.2017
comment
Согласно этой странице input.labels isn ' t поддерживается IE или Edge, а Firefox только что добавил поддержку. - person Antti29; 06.02.2018
comment
@ Antti29 Вы можете добавить функциональность с помощью прокладки: github.com/termi/ES5-DOM-SHIM Вы можете увидеть добавляемую функцию здесь: github.com/termi/ES5-DOM-SHIM/blob/ - person ADJenks; 23.04.2020

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

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

person Brendan    schedule 11.08.2015

$("label[for='inputId']").text()

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

person haifacarina    schedule 05.09.2011

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

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

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

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

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

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

<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 должен быть включен в функцию загрузки тела.

Просто мысль, прекрасно работает для меня.

person Martie Henry    schedule 26.11.2013

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

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

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

person kuroi neko    schedule 17.12.2013

Лучший ответ работает отлично, но в большинстве случаев перебирать все элементы 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 будет очень близко или рядом с входом, что означает, что цикл в приведенной выше функции должен повторяться очень небольшое количество раз.

person Dan Bray    schedule 14.07.2018

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

person Josh Mein    schedule 12.11.2008
comment
Я знаю идентификатор входного элемента, но не идентификатор метки. - person Joel Coehoorn; 13.11.2008
comment
Вы не можете установить соответствующий идентификатор для метки, например input id = 'test' и label id = 'lbl_test - person Josh Mein; 13.11.2008

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

$("label[for="+inputElement.id+"]")
person Mike McKay    schedule 12.04.2011

Для будущих искателей ... Ниже приведена версия принятого ответа 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");
person ObjectType    schedule 19.08.2011
comment
+1, но из того, что я вижу, нет причин использовать версию jQuery для первого блока: она не короче и не читабельнее, а простой javascript, вероятно, будет работать лучше. Тем не менее, неплохо иметь пример jQuery того, как его использовать после создания. - person Joel Coehoorn; 19.08.2011
comment
Очевидно, что для многих из нас нет особой технической причины для такого подхода, скорее причина, по крайней мере, в моем случае, связана с HR. Представьте, что у вас есть команда, в которую входят дизайнеры, интеграторы и даже младшие разработчики, которые, по вашему мнению, привыкли к использованию jQuery. Использование парадигмы jQuery может помочь повысить продуктивность и уменьшить разочарование. - person ObjectType; 19.08.2011
comment
Это не очень jQuery-ified. Почему for зацикливается на each()? Почему htmlFor вместо attr("for")? - person alex; 05.09.2013
comment
Полагаю, это зависит от перспективы. Потребление было jQuery-ified, а не внутренним. - person ObjectType; 06.09.2013

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

person Peter Nosko    schedule 21.05.2014
comment
На самом деле это не работает - он просто возвращает текст родительского элемента, который иногда бывает тем текстом, который вам нужен. - person John Hascall; 01.07.2016

Я сделал для себя, может быть кому-то полезен: 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");
            }
        }
    }
});
person itsazzad    schedule 26.11.2014

Я немного удивлен, что никто не предлагает использовать метод отношений 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');
});
person Gordon Rouse    schedule 20.01.2017
comment
К сожалению, я должен отметить, что это зависит от метки, идущей непосредственно после элемента. - person Gordon Rouse; 28.09.2017