Pregunta

Digamos que tengo un formulario html.Cada entrada/seleccionar/textarea tendrá un correspondiente <label> con el for conjunto de atributos para la identificación de su acompañante.En este caso, sé que cada entrada sólo tendrá una única etiqueta.

Dado un elemento de entrada en javascript — a través de un evento onkeyup, por ejemplo — ¿cuál es la mejor manera de encontrar la etiqueta asociada?

¿Fue útil?

Solución

Primero, escanee la página en busca de etiquetas y asigne una referencia a la etiqueta desde el elemento de formulario 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];         
    }
}

Entonces, simplemente puedes ir:

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

No necesita una matriz de búsqueda :)

Otros consejos

Si está utilizando jQuery, puede hacer algo como esto

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

Si no está utilizando jQuery, tendrá que buscar la etiqueta. Aquí hay una función que toma el elemento como argumento y devuelve la etiqueta asociada

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

Hay una propiedad labels en estándar HTML5 que apunta a etiquetas asociadas a un elemento de entrada.

Entonces, podría usar algo como esto (soporte para la propiedad nativa <=> pero con un respaldo para recuperar etiquetas en caso de que el navegador no lo soporte) ...

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

Aún más fácil si estás 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;
};

Estoy un poco sorprendido de que nadie parezca saber que eres perfectamente permitido hacer:

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

Que no será recogido por ninguna de las respuestas sugeridas, pero etiquetará la entrada correctamente.

Aquí hay un código que tiene en cuenta 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();

Algunas notas:

  • El código fue escrito para mayor claridad, no para el rendimiento. Es posible que haya más alternativas disponibles.
  • Este código admite obtener las etiquetas de varios elementos de una vez. Si eso no es lo que quieres, adáptate según sea necesario.
  • Esto todavía no se ocupa de cosas como aria-labelledby si usaras eso (dejado como ejercicio para el lector).
  • El uso de múltiples etiquetas es un negocio complicado cuando se trata de soporte en diferentes agentes de usuario y tecnologías de asistencia, así que pruebe bien y use bajo su propio riesgo, etc., etc.
  • Sí, también podría implementar esto sin usar jQuery. :-)

Anteriormente ...

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

Más tarde ...

var myLabel = lookup[myInput.id];

Comentario sarcástico: Sí, también puedes hacerlo con JQuery. :-)

con jquery podrías hacer algo como

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

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

Esto responde a la pregunta de la manera más simple y ágil. Utiliza JavaScript de vainilla y funciona en todos los navegadores adecuados de la corriente principal.

Si usted está dispuesto a utilizar querySelector (y puede, incluso a IE9 y a veces IE8!), otro método es viable.

Si el campo de formulario tiene un ID, y el uso de la etiqueta de la for atributo, esto se vuelve bastante simple en 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);
});

Algunos han señalado acerca de varias etiquetas;si todos utilizan el mismo valor para la for atributo, sólo tiene que utilizar querySelectorAll en lugar de querySelector y el bucle a través de para obtener todo lo que usted necesita.

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

Esto me ayudó a obtener la etiqueta de un elemento de entrada usando su ID.

La respuesta de Gijs fue muy valiosa para mí, pero desafortunadamente la extensión no funciona.

Aquí hay una extensión reescrita que funciona, puede ayudar a alguien:

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

En realidad, es mucho más fácil agregar una identificación a la etiqueta en el formulario, por ejemplo:

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

Entonces, simplemente puede usar algo como esto:

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

El javascript tiene que estar en una función de carga corporal para funcionar.

Solo un pensamiento, funciona muy bien para mí.

Como ya se ha mencionado, la respuesta (actualmente) mejor valorada no tiene en cuenta la posibilidad de insertar una entrada dentro de una etiqueta.

Como nadie ha publicado una respuesta sin JQuery, aquí está la mía:

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

En este ejemplo, en aras de la simplicidad, los elementos HTML de entrada indexan directamente la tabla de búsqueda. Esto no es eficiente y puedes adaptarlo como quieras.

Puede usar un formulario como elemento base o todo el documento si desea obtener etiquetas para varios formularios a la vez.

No se realizan verificaciones para HTML incorrecto (entradas múltiples o faltantes dentro de las etiquetas, entradas faltantes con htmlFor id correspondiente, etc.), pero siéntase libre de agregarlas.

Es posible que desee recortar los textos de la etiqueta, ya que los espacios finales a menudo están presentes cuando la entrada está incrustada en la etiqueta.

ha intentado usar document.getElementbyID ('id') donde id es el id de la etiqueta o es la situación en la que no sabe cuál está buscando

Use un selector JQuery:

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

Para futuros buscadores ... La siguiente es una versión jQuery-ified de la respuesta aceptada de 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]));   
        }
    }
}

Uso:

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

Sé que esto es viejo, pero tuve problemas con algunas soluciones y lo reconstruí. He probado esto en Windows (Chrome, Firefox y MSIE) y OS X (Chrome y Safari) y creo que esta es la solución más simple. Funciona con estos tres estilos de adjuntar una 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() );
});

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

He creado para mi propia necesidad, puede ser útil para alguien: 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");
            }
        }
    }
});

¿Estoy un poco sorprendido de que nadie sugiera usar el método de relación CSS?

en una hoja de estilo puede hacer referencia a una etiqueta desde el selector de elementos:

<style>

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

</style>

si la casilla de verificación tiene una identificación de 'XXX' entonces la etiqueta se encontraría a través de jQuery:

$('#XXX + label');

También puede aplicar .find ('+ etiqueta') para devolver la etiqueta de un elemento de casilla de verificación jQuery, es decir, útil cuando se repite:

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

Todas las otras respuestas son muy anticuado!!

Todo lo que tienes que hacer es:

input.labels

HTML5 ha sido apoyado por todos los principales navegadores ya muchos años.No hay absolutamente ninguna razón por la que usted debe tener para hacer esto desde el principio en su propia o relleno de ella!Literalmente, acaba de uso input.labels y resuelve todos sus problemas.

La mejor respuesta funciona perfectamente bien, pero en la mayoría de los casos, es excesivo e ineficiente recorrer todos los label elementos.

Aquí hay una función eficiente para obtener el input que acompaña al 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 mí, esta línea de código fue suficiente:

el = document.getElementById(id).previousElementSibling;

En la mayoría de los casos, el <=> estará muy cerca o al lado de la entrada, lo que significa que el bucle en la función anterior solo necesita iterar un número muy pequeño de veces.

Una solución realmente concisa que utiliza características de ES6 como la desestructuración y los retornos implícitos para convertirlo en un práctico revestimiento sería:

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

O simplemente para obtener una etiqueta, no una NodeList:

const getFirstLabel = ({ labels, id }) => labels && labels[0] || document.querySelector(`label[for=${id}]`)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top