Znajdź etykietę html powiązaną z danym wejściem


110

Powiedzmy, że mam formularz HTML. Każde wejście / select / textarea będzie miało odpowiednik <label>z foratrybutem ustawionym na id jego towarzysza. W tym przypadku wiem, że każde wejście będzie miało tylko jedną etykietę.

Biorąc pod uwagę element wejściowy w javascript - na przykład poprzez zdarzenie onkeyup - jaki jest najlepszy sposób na znalezienie powiązanej etykiety?


5
Zauważ, że element może mieć więcej niż jedną etykietę, widziałem niektóre aplikacje (SAP dla jednej), które mają wiele etykiet na element.
— 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

lub po prostu node.parentNode.querySelector ("label [for = '" + node.id + "']"). innerHTML; lol
— Solomon P Byer

Odpowiedzi:


87

Najpierw zeskanuj stronę w poszukiwaniu etykiet i przypisz odwołanie do etykiety z rzeczywistego elementu formularza:

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

Następnie możesz po prostu przejść:

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

Nie ma potrzeby wyszukiwania tablicy :)


Czy możesz wyjaśnić, czym różni się korzystanie z właściwości expando od mojego? Nie używam żadnej "tablicy przeglądowej", używam obiektu z właściwościami. Istnieje tylko różnica składniowa między „element.label”, „element ['label']” lub „lookup ['elementId']”. Za kulisami są tym samym .
— Tomalak

4
Jest to przyjemniejsze, ponieważ nie muszę trzymać osobnego obiektu wokół - relacja jest przechowywana bezpośrednio z elementem wejściowym.
— Joel Coehoorn

3
Powinna się tym
— zająć

103

Jeśli używasz jQuery, możesz zrobić coś takiego

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

Jeśli nie używasz jQuery, będziesz musiał wyszukać etykietę. Oto funkcja, która przyjmuje element jako argument i zwraca skojarzoną etykietę

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

W standardzie HTML5 istnieje labelswłaściwość wskazująca na etykiety skojarzone z elementem wejściowym.

Możesz więc użyć czegoś takiego (obsługa labelswłaściwości natywnej, ale z funkcją awaryjną do pobierania etykiet na wypadek, gdyby przeglądarka jej nie obsługiwała) ...

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

Nawet łatwiej, jeśli używasz 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
Nie tylko w Chrome, jest w standardzie HTML5 .
— Bergi

1
To powinno być gotowe. Dzięki!
— maxhm10

23

Jestem trochę zaskoczony, że nikt nie wie, że wolno ci:

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

Które nie zostaną odebrane przez któregokolwiek z sugerowanych odpowiedzi, ale będzie poprawnie oznaczyć wejście.

Oto kod, który bierze pod uwagę ten przypadek:

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

Stosowanie:

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

Kilka uwag:

  • Kod został napisany dla przejrzystości, a nie wydajności. Mogą być dostępne bardziej wydajne alternatywy.
  • Ten kod obsługuje pobieranie etykiet wielu elementów za jednym razem. Jeśli nie tego chcesz, dostosuj się w razie potrzeby.
  • To nadal nie dotyczy rzeczy, takich jak aria-labelledbyużycie tego (pozostawione jako ćwiczenie czytelnikowi).
  • Używanie wielu etykiet to trudna sprawa, jeśli chodzi o wsparcie w różnych programach użytkownika i technologiach pomocniczych, więc dobrze przetestuj i używaj na własne ryzyko itp.
  • Tak, można to również zaimplementować bez użycia jQuery. :-)

6
Miło widzieć, jak ktoś przywołuje niejawne skojarzenie z etykietą, zamiast zakładać, że element zawsze będzie zawierał foratrybut label.
— Josh Habdas

14

Wcześniej...

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

Później...

var myLabel = lookup[myInput.id];

Snarky komentarz: Tak, możesz to również zrobić za pomocą JQuery. :-)


1
Miły. Zmienię to trochę, tak aby przy pierwszym wywołaniu metody było budowane wyszukiwanie, ale powinno to załatwić sprawę.
— Joel Coehoorn

Zasugerowałem, że możesz zbudować wyszukiwanie tylko raz.
— Tomalak

Należy pamiętać, że jest w nim mały błąd: użyj właściwości „htmlFor”, a nie „for”, ponieważ to ostatnie jest słowem zastrzeżonym w JS. Zwykle zapominam o tym, używając obiektów etykiet ... :-)
— Tomalak

Mam sposób, aby to zrobić bez tablicy wyszukiwania powyżej.
— FlySwat

Miałem na myśli przeniesienie kodu init do metody, a nie robienie tego tylko raz :(
— Joel Coehoorn,

13

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

To odpowiada na pytanie w najprostszy i najprostszy sposób. Wykorzystuje javascript typu vanilla i działa na wszystkich przeglądarkach głównego strumienia.


To nie daje odpowiedzi na pytanie. Gdy zdobędziesz wystarczającą reputację , będziesz mógł komentować każdy post ; zamiast tego udziel odpowiedzi, które nie wymagają wyjaśnień od pytającego . - Z recenzji
— loki

1
To z całą pewnością daje odpowiedź na pytanie @loki Tylko dlatego, że nie ma na to dalszych wyjaśnień, nie oznacza to, że jest błędne lub nie próbowano na nie odpowiedzieć.
— geisterfurz007

Najprostsza i użyteczna odpowiedź! Dzięki!
— iedmrc,

8

z jquery możesz zrobić coś takiego

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

Potencjalnie pomija etykiety, które są przodkami.
— Alex

4

Jeśli chcesz użyć querySelector (a możesz nawet do IE9, a czasem IE8!), Inna metoda staje się użyteczna.

Jeśli twoje pole formularza ma identyfikator i używasz foratrybutu etykiety , staje się to całkiem proste w nowoczesnym 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);
});

Niektórzy zauważyli o wielu etykietach; jeśli wszystkie używają tej samej wartości foratrybutu, po prostu użyj querySelectorAllzamiast querySelectori pętla, aby uzyskać wszystko, czego potrzebujesz.


3

Wszystkie inne odpowiedzi są bardzo nieaktualne!

Wszystko co musisz zrobić to:

input.labels

HTML5 jest obsługiwany przez wszystkie główne przeglądarki już od wielu lat. Nie ma absolutnie żadnego powodu, dla którego powinieneś zrobić to od podstaw samodzielnie lub wypełnić go w całości! Dosłownie po prostu użyj input.labelsi rozwiązuje wszystkie twoje problemy.


1
Według tej strony , input.labelsnie jest obsługiwane przez IE lub Firefox Edge, i dopiero dodaje wsparcie.
— Antti29,

@ Antti29 Możesz dodać funkcjonalność za pomocą podkładki: github.com/termi/ES5-DOM-SHIM Możesz zobaczyć dodawaną funkcję tutaj: github.com/termi/ES5-DOM-SHIM/blob/…
— ADJenks

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

Pomogło mi to uzyskać etykietę elementu wejściowego za pomocą jego identyfikatora.


2

Odpowiedź od Gijsa była dla mnie najcenniejsza, ale niestety rozszerzenie nie działa.

Oto przepisane rozszerzenie, które działa, może komuś pomóc:

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

Naprawdę zwięzłym rozwiązaniem wykorzystującym funkcje ES6, takie jak destrukturyzacja i niejawne zwroty, w celu przekształcenia go w poręczny jeden liniowiec, byłoby:

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

Lub po prostu uzyskać jedną etykietę, a nie NodeList:

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

1

W rzeczywistości znacznie łatwiej jest dodać identyfikator do etykiety w samym formularzu, na przykład:

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

Następnie możesz po prostu użyć czegoś takiego:

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

Aby kod JavaScript działał, musi znajdować się w funkcji ładowania ciała.

Tylko myśl, działa na mnie pięknie.


1

Jak już wspomniano, (obecnie) najwyżej oceniana odpowiedź nie uwzględnia możliwości osadzenia wejścia wewnątrz etykiety.

Ponieważ nikt nie opublikował odpowiedzi wolnej od JQuery, oto moja:

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

W tym przykładzie, dla uproszczenia, tabela przeglądowa jest bezpośrednio indeksowana przez wejściowe elementy HTML. Jest to mało wydajne i możesz je dostosować w dowolny sposób.

Możesz użyć formularza jako elementu podstawowego lub całego dokumentu, jeśli chcesz uzyskać etykiety dla wielu formularzy jednocześnie.

Nie sprawdza się nieprawidłowego kodu HTML (wiele lub brak danych wejściowych w etykietach, brak danych wejściowych z odpowiednim identyfikatorem htmlFor itp.), Ale możesz je dodać.

Możesz chcieć przyciąć teksty etykiety, ponieważ końcowe spacje są często obecne, gdy dane wejściowe są osadzone w etykiecie.


1

Najlepsza odpowiedź działa doskonale, ale w większości przypadków pętla przez wszystkie labelelementy jest przesadna i nieefektywna .

Oto skuteczna funkcja, która pozwala uzyskać to, labelco pasuje do inputelementu:

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

Dla mnie wystarczyła ta jedna linijka kodu:

el = document.getElementById(id).previousElementSibling;

W większości przypadków labelbędzie znajdować się bardzo blisko wejścia lub obok niego, co oznacza, że ​​pętla w powyższej funkcji musi wykonać iterację bardzo małą liczbę razy.


0

czy próbowałeś użyć document.getElementbyID ('id'), gdzie id jest identyfikatorem etykiety lub jest to sytuacja, w której nie wiesz, której szukasz


Znam identyfikator elementu wejściowego, ale nie znam identyfikatora etykiety.
— Joel Coehoorn

czy nie możesz ustawić odpowiedniego identyfikatora dla etykiety, np. input id = 'test' i label id = 'lbl_test "
— Josh Mein


0

Dla przyszłych poszukiwaczy ... Poniżej znajduje się wersja zaakceptowanej odpowiedzi FlySwat wykorzystująca 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]));   
        }
    }
}

Za pomocą:

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

+1, ale z tego, co widzę, nie ma powodu, aby używać wersji jQuery w pierwszym bloku: nie jest ona ani krótsza ani bardziej czytelna, a zwykły javascript prawdopodobnie będzie działał lepiej. Jednak fajnie jest mieć przykład jQuery na temat tego, jak go używać po utworzeniu.
— Joel Coehoorn

Oczywiście dla wielu z nas nie ma technicznego powodu takiego podejścia, raczej powód, przynajmniej w moim przypadku, to powód HR. Wyobraź sobie, że masz zespół składający się z projektantów, integratorów, a nawet programistów Jr, których zwalniasz, przyzwyczaiłeś się do używania jQuery. Utrzymanie paradygmatu jQuery może pomóc w utrzymaniu produktywności i zmniejszeniu frustracji.
— ObjectType

To nie jest bardzo oparte na jQuery . Dlaczego forpętla się skończyła each()? Dlaczego htmlForzamiast attr("for")?
— Alex,

Chyba zależy od perspektywy. Konsumpcja była oparta na jQuery, a nie na elementach wewnętrznych.
— ObjectType

0

Wiem, że to jest stare, ale miałem problem z niektórymi rozwiązaniami i złożyłem to razem. Przetestowałem to na Windows (Chrome, Firefox i MSIE) i OS X (Chrome i Safari) i uważam, że jest to najprostsze rozwiązanie. Działa z tymi trzema stylami mocowania etykiety.

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

Korzystanie z jQuery:

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

Mój JSFiddle: http://jsfiddle.net/pnosko/6PQCw/


To tak naprawdę nie działa - po prostu zwraca tekst elementu nadrzędnego, który czasami jest tekstem, który chcesz.
— John Hascall

0

Zrobiłem na własne potrzeby, może być przydatny dla kogoś: 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

Jestem trochę zaskoczony, że nikt nie sugeruje użycia metody relacji CSS?

w arkuszu stylów możesz odwołać się do etykiety z selektora elementów:

<style>

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

</style>

jeśli pole wyboru ma identyfikator „XXX”, etykietę można znaleźć w jQuery przez:

$('#XXX + label');

Możesz również zastosować .find ('+ label'), aby zwrócić etykietę z elementu jQuery checkbox, np. Przydatne podczas zapętlania:

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

Ups, powinienem zauważyć, że zależy to od etykiety znajdującej się bezpośrednio po elemencie.
— Gordon Rouse
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.