Trova l'etichetta html associata a un dato input


110

Diciamo che ho un modulo html. Ogni input / select / textarea avrà una corrispondenza <label>con l' forattributo impostato sull'id del suo compagno. In questo caso, so che ogni ingresso avrà solo una singola etichetta.

Dato un elemento di input in javascript, ad esempio tramite un evento onkeyup, qual è il modo migliore per trovare l'etichetta associata?


5
Nota che un elemento può avere più di un'etichetta, ho visto alcune applicazioni (SAP per una) che hanno più etichette per elemento.
Motti

2
function getInputLabel(thisElement) { var theAssociatedLabel,elementID; elementID = thisElement.id; theAssociatedLabel = thisElement.parentNode.querySelector("label[for='" + elementID + "']"); console.log('theAssociatedLabel.htmlFor: ' + theAssociatedLabel.htmlFor); theAssociatedLabel.style.backgroundColor = "green";//Set the label background color to green };
Alan Wells

o solo node.parentNode.querySelector ("label [for = '" + node.id + "']"). innerHTML; lol
Solomon P Byer

Risposte:


87

Innanzitutto, scansiona la pagina per le etichette e assegna un riferimento all'etichetta dall'elemento del modulo effettivo:

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

Quindi, puoi semplicemente andare:

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

Non c'è bisogno di un array di ricerca :)


Puoi spiegare dove il tuo uso di una proprietà expando differisce dal mio? Non utilizzo alcun "lookup array", utilizzo un oggetto con proprietà. C'è solo una differenza sintattica tra "element.label", "element ['label']" o "lookup ['elementId']". Dietro le quinte sono la stessa cosa .
Tomalak

4
Questo è più bello perché non devo mantenere un oggetto separato in giro: la relazione viene memorizzata direttamente con l'elemento di input.
Joel Coehoorn

3
Questo dovrebbe essere gestito dal browser
e il

103

Se stai usando jQuery puoi fare qualcosa di simile

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

Se non stai usando jQuery dovrai cercare l'etichetta. Ecco una funzione che prende l'elemento come argomento e restituisce l'etichetta associata

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

33

C'è una labelsproprietà nello standard HTML5 che punta alle etichette associate a un elemento di input.

Quindi potresti usare qualcosa di simile (supporto per la labelsproprietà nativa ma con un fallback per il recupero delle etichette nel caso in cui il browser non lo supporti) ...

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

Ancora più semplice se stai 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;
};

4
Non solo in Chrome, è nello standard HTML5 .
Bergi

1
Questo dovrebbe essere mooolto. Grazie!
maxhm10

23

Sono un po 'sorpreso che nessuno sembri sapere che sei perfettamente autorizzato a fare:

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

Il che non andranno prelevati da una delle risposte suggerite, ma sarà etichettare l'ingresso in modo corretto.

Ecco un codice che tiene conto di questo 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();

Alcune note:

  • Il codice è stato scritto per chiarezza, non per le prestazioni. Potrebbero essere disponibili alternative più performanti.
  • Questo codice supporta l'acquisizione delle etichette di più elementi in una volta. Se non è quello che vuoi, adattalo se necessario.
  • Questo ancora non si prende cura di cose come aria-labelledbyse dovessi usarlo (lasciato come esercizio al lettore).
  • L'utilizzo di più etichette è un'attività complicata quando si tratta di supportare in diversi programmi utente e tecnologie assistive, quindi testare bene e utilizzare a proprio rischio, ecc.
  • Sì, puoi anche implementarlo senza usare jQuery. :-)

6
È bello vedere qualcuno che solleva un'associazione di etichette implicite invece di supporre che ci sarà sempre un forattributo labelsull'elemento.
Josh Habdas

14

In precedenza ...

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

Dopo...

var myLabel = lookup[myInput.id];

Commento irritante: Sì, puoi farlo anche con JQuery. :-)


1
Bello. Lo rifatterò solo un po 'in modo che costruisca la ricerca la prima volta che chiamo il metodo, ma dovrebbe fare il trucco.
Joel Coehoorn

Ho sottinteso che avresti costruito la ricerca solo una volta.
Tomalak

Tieni presente che c'era un piccolo errore: usa la proprietà "htmlFor", non "for", poiché quest'ultima è una parola riservata in JS. Tendo a dimenticarlo quando si usano oggetti etichetta ... :-)
Tomalak

Ho un modo per farlo senza un array di ricerca sopra.
FlySwat

Intendevo spostare il codice di inizializzazione all'interno del metodo, non farlo solo una volta :(
Joel Coehoorn

13

document.querySelector ("label [for =" + vHtmlInputElement.id + "]");

Questo risponde alla domanda nel modo più semplice e snello. Questo utilizza javascript vanilla e funziona su tutti i browser appropriati per il flusso principale.


Questo non fornisce una risposta alla domanda. Una volta che avrai una reputazione sufficiente, potrai commentare qualsiasi post ; fornire invece risposte che non richiedono chiarimenti da parte del richiedente . - Dalla recensione
loki

1
Questo fornisce sicuramente una risposta alla domanda @loki Solo perché non ci sono ulteriori spiegazioni, ciò non significa che sia sbagliato o non abbia tentato di rispondere.
geisterfurz007

La risposta più semplice e utile! Grazie!
iedmrc

8

con jquery potresti fare qualcosa di simile

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

Potenzialmente manca le etichette anche se sono antenati.
alex

4

Se sei disposto a utilizzare querySelector (e puoi, anche fino a IE9 e talvolta IE8!), Un altro metodo diventa praticabile.

Se il campo del modulo ha un ID e utilizzi l' forattributo dell'etichetta , questo diventa piuttosto semplice nel moderno 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);
});

Alcuni hanno notato più etichette; se usano tutti lo stesso valore per l' forattributo, basta usare querySelectorAllinvece di querySelectore scorrere per ottenere tutto ciò di cui hai bisogno.


3

Tutte le altre risposte sono estremamente obsolete !!

Tutto quello che devi fare è:

input.labels

HTML5 è supportato da tutti i principali browser già da molti anni. Non c'è assolutamente alcun motivo per cui dovresti farlo da zero da solo o riempirlo con il polyfill! Letteralmente basta usare input.labelse risolve tutti i tuoi problemi.


1
Secondo questa pagina , input.labelsnon è supportato da IE o Edge e Firefox ha appena aggiunto il supporto.
Antti29

@ Antti29 Puoi aggiungere la funzionalità utilizzando uno shim: github.com/termi/ES5-DOM-SHIM Puoi vedere la funzione aggiunta qui: github.com/termi/ES5-DOM-SHIM/blob/…
ADJenks

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

Questo mi ha aiutato a ottenere l'etichetta di un elemento di input utilizzando il suo ID.


2

La risposta di Gijs è stata molto preziosa per me, ma purtroppo l'estensione non funziona.

Ecco un'estensione riscritta che funziona, potrebbe aiutare qualcuno:

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

2

Una soluzione davvero concisa che utilizza le funzionalità di ES6 come la destrutturazione e i ritorni impliciti per trasformarlo in un pratico rivestimento sarebbe:

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

O semplicemente per ottenere un'etichetta, non una NodeList:

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

1

In realtà è molto più semplice aggiungere un ID all'etichetta nel modulo stesso, ad esempio:

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

Quindi, puoi semplicemente usare qualcosa del genere:

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

Il javascript deve essere in una funzione onload del corpo per funzionare.

Solo un pensiero, funziona magnificamente per me.


1

Come è stato già accennato, la risposta (attualmente) più votata non tiene conto della possibilità di incorporare un input all'interno di un'etichetta.

Poiché nessuno ha pubblicato una risposta priva di JQuery, ecco la mia:

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

In questo esempio, per semplicità, la tabella di ricerca è indicizzata direttamente dagli elementi HTML di input. Questo è difficilmente efficiente e puoi adattarlo come preferisci.

Puoi utilizzare un modulo come elemento di base o l'intero documento se desideri ottenere etichette per più moduli contemporaneamente.

Non vengono effettuati controlli per HTML errato (input multipli o mancanti all'interno delle etichette, input mancante con il corrispondente htmlFor id, ecc.), Ma sentiti libero di aggiungerli.

Potresti voler tagliare il testo dell'etichetta, poiché gli spazi finali sono spesso presenti quando l'input è incorporato nell'etichetta.


1

La risposta migliore funziona perfettamente, ma nella maggior parte dei casi è eccessivo e inefficiente scorrere tutti gli labelelementi.

Ecco una funzione efficace per ottenere labelciò che accompagna l' inputelemento:

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

Per me, questa riga di codice era sufficiente:

el = document.getElementById(id).previousElementSibling;

Nella maggior parte dei casi, labelsarà molto vicino o vicino all'input, il che significa che il ciclo nella funzione sopra deve solo iterare un numero molto piccolo di volte.


0

hai provato a usare document.getElementbyID ('id') dove id è l'id dell'etichetta o è la situazione in cui non sai quale stai cercando


Conosco l'id dell'elemento di input, ma non l'id dell'etichetta.
Joel Coehoorn

non puoi impostare un id corrispondente per l'etichetta come input id = 'test' e label id = 'lbl_test "
Josh Mein

0

Usa un selettore JQuery:

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

0

Per i futuri ricercatori ... Quella che segue è una versione jQuery-ified della risposta accettata da 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");

+1, ma da quello che vedo non c'è motivo di usare la versione jQuery per il primo blocco: non è più breve o più leggibile e il semplice javascript probabilmente funzionerà meglio. Tuttavia, è bello avere un esempio jQuery su come usarlo una volta creato.
Joel Coehoorn

Ovviamente per molti di noi non c'è molta ragione tecnica per questo approccio, piuttosto una ragione, almeno nel mio caso, è una ragione per le risorse umane. Immagina di avere un team che include designer, integratori e persino sviluppatori Jr a cui stai rallentando si sono abituati a usare jQuery. Mantenere le cose nel paradigma jQuery può aiutare a mantenere alta la produttività e ridurre la frustrazione.
ObjectType

Questo non è molto jQuery-ified . Perché il forgiro è finito each()? Perché htmlForinvece di attr("for")?
alex

Dipende dalla prospettiva, immagino. Il consumo era jQuery-ified, non gli interni.
ObjectType

0

So che questo è vecchio, ma ho avuto problemi con alcune soluzioni e l'ho messo insieme. L'ho testato su Windows (Chrome, Firefox e MSIE) e OS X (Chrome e Safari) e credo che questa sia la soluzione più semplice. Funziona con questi tre stili di attaccare un'etichetta.

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

Utilizzando jQuery:

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

Il mio JSFiddle: http://jsfiddle.net/pnosko/6PQCw/


Questo in realtà non funziona: restituisce solo il testo dell'elemento genitore, che a volte sembra essere il testo che desideri.
John Hascall

0

L'ho fatto per le mie esigenze, può essere utile per qualcuno: 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");
            }
        }
    }
});

0

Sono un po 'sorpreso che nessuno stia suggerendo di utilizzare il metodo di relazione CSS?

in un foglio di stile puoi fare riferimento a un'etichetta dal selettore di elementi:

<style>

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

</style>

se la casella di controllo ha un id di "XXX", l'etichetta verrà trovata tramite jQuery da:

$('#XXX + label');

Puoi anche applicare .find ('+ label') per restituire l'etichetta da un elemento casella di controllo jQuery, cioè utile durante il loop:

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

Ops, dovrei notare che questo si basa sull'etichetta che viene direttamente dopo l'elemento.
Gordon Rouse,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.