web-dev-qa-db-fra.com

Trouver une étiquette HTML associée à une entrée donnée

Disons que j'ai un formulaire HTML. Chaque entrée/sélection/zone de texte aura un <label> correspondant avec l'attribut for défini sur l'id de son compagnon. Dans ce cas, je sais que chaque entrée n’aura qu’une seule étiquette.

Étant donné un élément d'entrée en javascript - via un événement onkeyup, par exemple - quel est le meilleur moyen de trouver son étiquette associée?

91
Joel Coehoorn

Commencez par rechercher des étiquettes dans la page et attribuez une référence à l'étiquette à partir de l'élément de formulaire actuel:

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

Ensuite, vous pouvez simplement aller:

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

Pas besoin d'un tableau de recherche :)

71
FlySwat

Si vous utilisez jQuery, vous pouvez faire quelque chose comme ceci

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

Si vous n'utilisez pas jQuery, vous devrez rechercher l'étiquette. Voici une fonction qui prend l'élément en argument et retourne l'étiquette associée

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

Il existe une propriété labels dans norme HTML5 qui pointe vers des étiquettes associées à un élément d'entrée.

Vous pouvez donc utiliser quelque chose comme ceci (support de la propriété native labels mais avec un repli pour récupérer les étiquettes si le navigateur ne la prend pas en charge) ...

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

Encore plus facile si vous utilisez 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;
};
20
alex

Je suis un peu surpris que personne ne semble savoir que vous êtes parfaitement autorisé à faire:

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

Ce qui ne sera retenu par aucune des réponses suggérées, mais will identifiera correctement l’entrée.

Voici un code qui prend ce cas en compte:

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

Usage:

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

Quelques notes:

  • Le code a été écrit pour la clarté, pas pour la performance. Des alternatives plus performantes peuvent être disponibles.
  • Ce code prend en charge l’obtention des étiquettes de plusieurs éléments en une fois. Si ce n'est pas ce que vous voulez, adaptez-vous au besoin.
  • Cela ne prend toujours pas en charge des choses comme aria-labelledby si vous deviez utiliser cela (laissé comme exercice au lecteur).
  • L'utilisation de plusieurs étiquettes est une tâche délicate lorsqu'il s'agit de prendre en charge différents agents utilisateurs et technologies d'assistance, testez-le bien et utilisez-le à vos risques et périls, etc.
  • Oui, vous pouvez également implémenter cela sans utiliser jQuery. :-)
19
Gijs

Plus tôt...

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

Plus tard...

var myLabel = lookup[myInput.id];

Commentaire Snarky: Oui, vous pouvez aussi le faire avec JQuery. :-)

13
Tomalak

avec jQuery vous pourriez faire quelque chose comme 

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

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

Cela répond à la question de la manière la plus simple et la plus simple ... Cela utilise le javascript Vanilla et fonctionne sur tous les navigateurs appropriés du flux principal.

3
Luigi D'Amico

Si vous êtes prêt à utiliser querySelector (et vous pouvez, même jusqu'à IE9 et parfois IE8!), Une autre méthode devient viable.

Si votre champ de formulaire a un ID et que vous utilisez l'attribut for du libellé, cela devient assez simple dans JavaScript moderne:

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

Certains ont noté plusieurs étiquettes. s'ils utilisent tous la même valeur pour l'attribut for, utilisez simplement querySelectorAll au lieu de querySelector et effectuez une boucle pour obtenir tout ce dont vous avez besoin.

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

Cela m'a aidé à obtenir l'étiquette d'un élément d'entrée en utilisant son ID. 

2
haifacarina

La réponse de Gijs a été très précieuse pour moi, mais malheureusement l'extension ne fonctionne pas.

Voici une extension réécrite qui fonctionne, elle peut aider quelqu'un:

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

Il est en fait beaucoup plus facile d'ajouter un identifiant à l'étiquette dans le formulaire lui-même, par exemple

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

Ensuite, vous pouvez simplement utiliser quelque chose comme ceci:

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

Le javascript doit être dans une fonction body onload pour fonctionner.

Juste une pensée, fonctionne à merveille pour moi.

1
Martie Henry

Comme il a déjà été mentionné, la réponse (actuellement) la mieux notée ne tient pas compte de la possibilité d’incorporer une entrée dans une étiquette.

Puisque personne n'a posté de réponse sans JQuery, voici le mien:

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

Dans cet exemple, dans un souci de simplicité, la table de recherche est directement indexée par les éléments HTML en entrée. Ceci n’est guère efficace et vous pouvez l’adapter à votre guise.

Vous pouvez utiliser un formulaire comme élément de base ou le document entier si vous souhaitez obtenir des étiquettes pour plusieurs formulaires à la fois.

Aucune vérification n'est effectuée pour le code HTML incorrect (entrées multiples ou manquantes dans les étiquettes, entrée manquante avec l'identifiant htmlFor correspondant, etc.), mais vous pouvez les ajouter.

Vous voudrez peut-être rogner les textes des étiquettes, car les espaces de fin sont souvent présents lorsque l'entrée est incorporée dans l'étiquette.

1
kuroi neko

Utilisez un sélecteur JQuery:

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

avez-vous essayé d'utiliser document.getElementbyID ('id') où id est l'identifiant du libellé ou la situation dans laquelle vous ne savez pas lequel vous recherchez

0
Josh Mein

Je sais que c'est vieux, mais j'ai eu du mal à trouver des solutions et je l'ai reconstitué. J'ai testé cela sur Windows (Chrome, Firefox et MSIE) et OS X (Chrome et Safari) et je pense que c'est la solution la plus simple. Cela fonctionne avec ces trois styles de fixation d'une étiquette.

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

Utilisation de jQuery:

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

Mon JSFiddle: http://jsfiddle.net/pnosko/6PQCw/

0
Peter Nosko

La meilleure solution fonctionne parfaitement, mais dans la plupart des cas, il est excessif et inefficace de parcourir tous les éléments label.

Voici une fonction efficace pour obtenir la variable label associée à l'élément 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;
}

Pour moi, cette ligne de code était suffisante:

el = document.getElementById(id).previousElementSibling;

Dans la plupart des cas, la variable label sera très proche ou proche de l'entrée, ce qui signifie que la boucle dans la fonction ci-dessus n'a à itérer qu'un très petit nombre de fois.

0
Dan Bray

Toutes les autres réponses sont extrêmement obsolètes !!

Tout ce que tu dois faire est:

input.labels

HTML5 est supporté par tous les principaux navigateurs depuis de nombreuses années déjà. Il n'y a absolument aucune raison pour que vous deviez le fabriquer vous-même ou le polyfiller! Littéralement, utilisez simplement input.labels et cela résoudra tous vos problèmes.

0
dj nag

J'ai fait pour mon propre besoin, peut être utile pour quelqu'un: 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
itsazzad

Je suis un peu surpris que personne ne suggère d'utiliser la méthode de relation CSS?

dans une feuille de style, vous pouvez référencer une étiquette à partir du sélecteur d'élément:

<style>

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

</style>

si la case à cocher a un identifiant de 'XXX' alors l'étiquette sera trouvée par jQuery par:

$('#XXX + label');

Vous pouvez également appliquer .find ('+ label') pour renvoyer l’étiquette à partir d’un élément de case à cocher jQuery, c’est-à-dire utile lors de la mise en boucle:

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

Une solution très concise utilisant des fonctionnalités ES6 telles que la déstructuration et les retours implicites pour en faire un support pratique serait: 

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

Ou simplement obtenir un label, pas un NodeList: 

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

Pour les futurs chercheurs ... Voici une version jQuery de la réponse acceptée par 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]));   
        }
    }
}

En utilisant:

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