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.