Pergunta

Digamos que eu tenha um formulário HTML. Cada entrada/select/textarea terá um correspondente <label> com o for atributo definido para o ID de seu companheiro. Nesse caso, eu sei que cada entrada terá apenas um único rótulo.

Dado um elemento de entrada no JavaScript - através de um evento OnkeyUp, por exemplo - qual é a melhor maneira de encontrar o rótulo associado?

Foi útil?

Solução

Primeiro, digitalize a página em busca de etiquetas e atribua uma referência ao rótulo do elemento de formulário real:

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

Então, você pode simplesmente ir:

document.getElementById('MyFormElem').label.innerHTML = 'Look ma this works!';

Não há necessidade de uma matriz de pesquisa :)

Outras dicas

Se você está usando o jQuery, você pode fazer algo assim

$('label[for="foo"]').hide ();

Se você não estiver usando o jQuery, precisará procurar o rótulo. Aqui está uma função que toma o elemento como argumento e retorna o rótulo associado

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

Existe um labels propriedade no Padrão html5 que aponta para rótulos associados a um elemento de entrada.

Então você poderia usar algo assim (suporte para nativos labels Propriedade, mas com um fallback para recuperar rótulos, caso o navegador não o apoie) ...

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

Ainda mais fácil se você estiver usando 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;
};

Estou um pouco surpreso que ninguém parece saber que você está perfeitamente permitido façam:

<label>Put your stuff here: <input value="Stuff"></label>

Que não será escolhido por nenhuma das respostas sugeridas, mas vai Rotule a entrada corretamente.

Aqui está algum código que leva em consideração este caso:

$.fn.getLabels = function() {
    return this.map(function() {
        var labels = $(this).parents('label');
        if (this.id) {
            labels.add('label[for="' + this.id + '"]');
        }
        return labels.get();
    });
};

Uso:

$('#myfancyinput').getLabels();

Algumas notas:

  • O código foi escrito para clareza, não para desempenho. Mais alternativas de desempenho podem estar disponíveis.
  • Este código suporta obter os rótulos de vários itens de uma só vez. Se não é isso que você deseja, adapte -se conforme necessário.
  • Isso ainda não cuida de coisas como aria-labelledby Se você usasse isso (deixado como exercício para o leitor).
  • O uso de vários rótulos é um negócio complicado quando se trata de suporte em diferentes agentes de usuários e tecnologias assistivas; portanto, teste bem e use por seu próprio risco, etc. etc.
  • Sim, você também pode implementar isso sem usar o jQuery. :-)

Mais cedo...

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

Mais tarde...

var myLabel = lookup[myInput.id];

Comentário Snarky: Sim, você também pode fazê -lo com o jQuery. :-)

com jQuery você poderia fazer algo como

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

Document.QuerySelector ("Label [for =" + vhtmlinputElement.id + "]);

Isso responde à pergunta da maneira mais simples e magra. Isso usa JavaScript de baunilha e funciona em todos os navegadores adequados do fluxo principal.

Se você estiver disposto a usar QuerySelector (E você pode, mesmo até o IE9 e às vezes IE8!), Outro método se torna viável.

Se o seu campo de formulário tiver um ID e você usar o rótulo for atributo, isso se torna bastante simples no javascript moderno:

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

Alguns notaram sobre vários rótulos; Se todos eles usam o mesmo valor para o for atributo, basta usar querySelectorAll ao invés de querySelector e passear para obter tudo o que você precisa.

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

Isso me ajudou a obter o rótulo de um elemento de entrada usando seu ID.

A resposta do GIJS foi mais valiosa para mim, mas infelizmente a extensão não funciona.

Aqui está uma extensão reescrita que funciona, pode ajudar alguém:

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

Na verdade, é muito mais fácil adicionar um ID ao rótulo no próprio formulário, por exemplo:

<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
/>

Então, você pode simplesmente usar algo assim:

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

O JavaScript precisa estar em uma função de Onload do corpo para funcionar.

Apenas um pensamento, funciona lindamente para mim.

Como já foi mencionado, a resposta (atualmente) com melhor classificação não leva em consideração a possibilidade de incorporar uma entrada dentro de um rótulo.

Como ninguém postou uma resposta sem jQuery, aqui está minha:

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

Neste exemplo, por uma questão de simplicidade, a tabela de pesquisa é indexada diretamente pelos elementos HTML de entrada. Isso é dificilmente eficiente e você pode adaptá -lo como quiser.

Você pode usar um formulário como elemento base, ou o documento inteiro se deseja obter rótulos para vários formulários de uma só vez.

Nenhuma verificação é feita para HTML incorreto (entradas múltiplas ou ausentes dentro dos rótulos, faltando a entrada com o HTMLFor ID correspondente, etc.), mas fique à vontade para adicioná -las.

Você pode querer aparar os textos da etiqueta, uma vez que os espaços à direita geralmente estão presentes quando a entrada é incorporada no rótulo.

Você já tentou usar o document.getElementById ('id') onde ID é o ID do rótulo ou é a situação que você não sabe qual deles está procurando

Use um seletor de jQuery:

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

Para futuros pesquisadores ... a seguir é uma versão do JQuery-Iff da resposta aceita pelo 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]));   
        }
    }
}

Usando:

$("#myFormElemId").data("label").css("border","3px solid red");

Sei que isso é velho, mas tive problemas com algumas soluções e reuni isso. Eu testei isso no Windows (Chrome, Firefox e MSIE) e OS X (Chrome e Safari) e acredito que essa é a solução mais simples. Funciona com esses três estilos de anexar uma etiqueta.

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

Usando jQuery:

$(".c123").click(function() {
    $cb = $(this);
    $lb = $(this).parent();
    alert( $cb.attr('id') + ' = ' + $lb.text() );
});

Meu jsfiddle: http://jsfiddle.net/pnosko/6pqcw/

Eu fiz para minha própria necessidade, pode ser útil para alguém: 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");
            }
        }
    }
});

Estou um pouco surpreso que ninguém está sugerindo usar o método de relacionamento CSS?

Em uma folha de estilo, você pode fazer referência a uma etiqueta do seletor de elementos:

<style>

//for input element with class 'YYY'
input.YYY + label {}

</style>

Se a caixa de seleção tiver um ID de 'xxx', o rótulo será encontrado através do jQuery por:

$('#XXX + label');

Você também pode aplicar .Find ('+ Label') para devolver o rótulo de um elemento de caixa de seleção JQuery, ou seja, útil ao fazer loop:

$('input[type=checkbox]').each( function(){
   $(this).find('+ label');
});

Todas as outras respostas são extremamente Desatualizado !!

Tudo que você tem a fazer é:

input.labels

O HTML5 foi apoiado por todos os principais navegadores por muitos anos já. Não há absolutamente nenhuma razão para que você precise fazer isso do zero por conta própria ou poli -o! Literalmente apenas use input.labels E resolve todos os seus problemas.

A melhor resposta funciona perfeitamente bem, mas na maioria dos casos é exagerada e ineficiente para percorrer todos os label elementos.

Aqui está uma função eficaz para obter o label isso vai com o input elemento:

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

Para mim, esta linha de código foi suficiente:

el = document.getElementById(id).previousElementSibling;

Na maioria dos casos, o label estará muito próximo ou próximo à entrada, o que significa que o loop na função acima precisa apenas para iterar um número muito pequeno de vezes.

Uma solução realmente concisa usando recursos ES6, como destruição e retornos implícitos, para transformá -la em um forro prático:

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

Ou simplesmente obter um rótulo, não uma lista de nodelas:

const getFirstLabel = ({ labels, id }) => labels && labels[0] || document.querySelector(`label[for=${id}]`)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top