Temukan label html yang terkait dengan masukan yang diberikan

110

Katakanlah saya memiliki bentuk html. Setiap input / select / textarea akan memiliki atribut yang sesuai <label>dengan forid pengiringnya. Dalam hal ini, saya tahu bahwa setiap masukan hanya akan memiliki satu label.

Diberikan elemen input dalam javascript - melalui acara onkeyup, misalnya - apa cara terbaik untuk menemukan label terkaitnya?

Joel Coehoorn
sumber
5
Perhatikan bahwa sebuah elemen mungkin memiliki lebih dari satu label, saya telah melihat beberapa aplikasi (SAP untuk satu) yang memiliki beberapa label per elemen.
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
atau hanya node.parentNode.querySelector ("label [for = '" + node.id + "']"). innerHTML; lol
Solomon P Byer

Jawaban:

87

Pertama, pindai halaman untuk label, dan tetapkan referensi ke label dari elemen formulir sebenarnya:

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

Kemudian, Anda cukup pergi:

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

Tidak perlu array pencarian :)

FlySwat
sumber
Dapatkah Anda menjelaskan di mana perbedaan penggunaan properti expando dengan saya? Saya tidak menggunakan "array pencarian", saya menggunakan objek dengan properti. Hanya ada perbedaan sintaksis antara "element.label", "element ['label']" atau "lookup ['elementId']". Di balik layar mereka adalah hal yang sama .
Tomalak
4
Ini lebih bagus karena saya tidak perlu menyimpan objek terpisah di sekitar- hubungan disimpan dengan elemen input secara langsung.
Joel Coehoorn
3
Ini harus ditangani oleh browser
andho
103

Jika Anda menggunakan jQuery, Anda dapat melakukan sesuatu seperti ini

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

Jika Anda tidak menggunakan jQuery, Anda harus mencari labelnya. Berikut adalah fungsi yang mengambil elemen sebagai argumen dan mengembalikan label terkait

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

Ada labelsproperti dalam standar HTML5 yang menunjuk ke label yang terkait dengan elemen masukan.

Jadi, Anda dapat menggunakan sesuatu seperti ini (dukungan untuk labelsproperti asli tetapi dengan cadangan untuk mengambil label jika browser tidak mendukungnya) ...

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

Lebih mudah jika Anda menggunakan 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;
};
alex
sumber
4
Tidak hanya di Chrome, ini dalam standar HTML5 .
Bergi
1
Ini harus waaaay up. Terima kasih!
maxhm10
23

Saya sedikit terkejut bahwa sepertinya tidak ada yang tahu bahwa Anda diperbolehkan melakukan:

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

Yang tidak akan diambil oleh jawaban yang disarankan, tetapi akan memberi label input dengan benar.

Berikut beberapa kode yang memperhitungkan kasus ini:

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

Pemakaian:

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

Beberapa catatan:

  • Kode itu ditulis untuk kejelasan, bukan untuk kinerja. Alternatif yang lebih berkinerja mungkin tersedia.
  • Kode ini mendukung mendapatkan label beberapa item sekaligus. Jika bukan itu yang Anda inginkan, sesuaikan seperlunya.
  • Ini masih tidak menangani hal-hal seperti aria-labelledbyjika Anda menggunakannya (diserahkan sebagai latihan kepada pembaca).
  • Menggunakan banyak label adalah bisnis yang rumit dalam hal dukungan di berbagai agen pengguna dan teknologi pendukung, jadi uji dengan baik dan gunakan dengan risiko Anda sendiri, dll.
  • Ya, Anda juga bisa mengimplementasikan ini tanpa menggunakan jQuery. :-)
Gijs
sumber
6
Senang melihat seseorang mengemukakan asosiasi label implisit sebagai lawan membuat asumsi akan selalu ada foratribut pada labelelemen.
Josh Habdas
14

Sebelumnya ...

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

Kemudian...

var myLabel = lookup[myInput.id];

Komentar snarky: Ya, Anda juga bisa melakukannya dengan JQuery. :-)

Tomalak
sumber
1
Bagus. Saya akan memfaktorkan ulang itu sedikit sehingga membangun pencarian saat pertama kali saya memanggil metode, tetapi itu harus melakukan trik.
Joel Coehoorn
Saya menyiratkan bahwa Anda akan membuat pencarian hanya sekali.
Tomalak
Ketahuilah bahwa ada kesalahan kecil di dalamnya: Gunakan properti "htmlFor", bukan "for", karena yang terakhir adalah kata khusus di JS. Saya cenderung lupa bahwa saat menggunakan objek label ... :-)
Tomalak
Saya punya cara untuk melakukan ini tanpa array pencarian di atas.
FlySwat
Maksud saya, pindahkan kode init di dalam metode, jangan lakukan hanya sekali :(
Joel Coehoorn
13

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

Ini menjawab pertanyaan dengan cara yang paling sederhana dan paling ramping. Ini menggunakan vanilla javascript dan bekerja pada semua browser yang sesuai arus utama.

Luigi D'Amico
sumber
Ini tidak memberikan jawaban atas pertanyaan tersebut. Setelah memiliki reputasi yang memadai, Anda dapat mengomentari kiriman apa pun ; sebagai gantinya, berikan jawaban yang tidak memerlukan klarifikasi dari penanya . - Dari Ulasan
loki
1
Ini paling pasti memberikan jawaban atas pertanyaan @loki Hanya karena tidak ada penjelasan lebih lanjut, bukan berarti salah atau tidak berusaha menjawabnya.
geisterfurz007
Jawaban paling sederhana dan berguna! Terima kasih!
iedmrc
8

dengan jquery Anda bisa melakukan sesuatu seperti

var nameOfLabel = someInput.attr('id');
var label = $("label[for='" + nameOfLabel + "']");
AndreasKnudsen
sumber
Berpotensi melewatkan label meskipun itu adalah leluhur.
alex
4

Jika Anda ingin menggunakan querySelector (dan Anda bisa, bahkan hingga IE9 dan terkadang IE8!), Metode lain menjadi layak.

Jika kolom formulir Anda memiliki ID, dan Anda menggunakan foratribut label , ini menjadi sangat sederhana di JavaScript modern:

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

Beberapa telah mencatat tentang banyak label; jika mereka semua menggunakan nilai yang sama untuk foratributnya, cukup gunakan querySelectorAllsebagai ganti querySelectordan lakukan perulangan untuk mendapatkan semua yang Anda butuhkan.

Brendan
sumber
3

Semua jawaban lainnya sangat ketinggalan jaman !!

Yang harus Anda lakukan adalah:

input.labels

HTML5 telah didukung oleh semua browser utama selama bertahun-tahun. Sama sekali tidak ada alasan bahwa Anda harus membuat ini dari awal sendiri atau mengisinya sendiri! Secara harfiah, gunakan saja input.labelsdan itu menyelesaikan semua masalah Anda.

dj cerewet
sumber
1
Menurut halaman ini , input.labelstidak didukung oleh IE atau Edge, dan Firefox hanya menambahkan dukungan.
Antti29
@ Antti29 Anda dapat menambahkan fungsionalitas menggunakan shim: github.com/termi/ES5-DOM-SHIM Anda dapat melihat fitur yang ditambahkan di sini: github.com/termi/ES5-DOM-SHIM/blob/…
ADJenks
2
$("label[for='inputId']").text()

Ini membantu saya mendapatkan label elemen input menggunakan ID-nya.

haifacarina.dll
sumber
2

Jawaban dari Gijs sangat berharga bagi saya, tetapi sayangnya ekstensi tersebut tidak berfungsi.

Berikut ekstensi yang ditulis ulang yang berfungsi, ini dapat membantu seseorang:

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);
    });
};
OzrenTkalcecKrznaric
sumber
2

Solusi yang sangat ringkas menggunakan fitur ES6 seperti destrukturisasi dan pengembalian implisit untuk mengubahnya menjadi liner yang praktis adalah:

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

Atau untuk mendapatkan satu label, bukan NodeList:

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

Sebenarnya jauh lebih mudah untuk menambahkan id ke label di formulir itu sendiri, misalnya:

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

Kemudian, Anda dapat menggunakan sesuatu seperti ini:

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

Javascript memang harus dalam fungsi body onload agar berfungsi.

Hanya sebuah pikiran, bekerja dengan indah untuk saya.

Martie Henry
sumber
1

Seperti yang telah disebutkan, jawaban teratas (saat ini) tidak memperhitungkan kemungkinan untuk menyematkan input di dalam label.

Karena tidak ada yang memposting jawaban bebas JQuery, ini jawaban saya:

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

Dalam contoh ini, demi kesederhanaan, tabel pemeta diindeks secara langsung oleh elemen HTML input. Ini hampir tidak efisien dan Anda dapat menyesuaikannya sesuka Anda.

Anda dapat menggunakan formulir sebagai elemen dasar, atau seluruh dokumen jika Anda ingin mendapatkan label untuk beberapa formulir sekaligus.

Tidak ada pemeriksaan yang dilakukan untuk HTML yang salah (beberapa atau masukan hilang di dalam label, masukan yang hilang dengan id htmlFor yang sesuai, dll), tetapi silakan menambahkannya.

Anda mungkin ingin memangkas teks label, karena spasi di belakang sering muncul saat input disematkan di label.

kuroi neko
sumber
1

Jawaban terbaik berfungsi dengan baik tetapi dalam banyak kasus, itu berlebihan dan tidak efisien untuk mengulang melalui semua labelelemen.

Berikut adalah fungsi yang efektif untuk mendapatkan labelyang sesuai dengan inputelemen:

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

Bagi saya, satu baris kode ini sudah cukup:

el = document.getElementById(id).previousElementSibling;

Dalam kebanyakan kasus, labelakan sangat dekat atau di sebelah input, yang berarti loop dalam fungsi di atas hanya perlu mengulang beberapa kali.

Dan Bray
sumber
0

sudahkah Anda mencoba menggunakan document.getElementbyID ('id') di mana id adalah id label atau situasi di mana Anda tidak tahu mana yang Anda cari

Josh Mein
sumber
Saya tahu id dari elemen input, tetapi bukan id label.
Joel Coehoorn
tidak dapatkah Anda menyetel id yang sesuai untuk label seperti input id = 'test' dan label id = 'lbl_test "
Josh Mein
0

Gunakan pemilih JQuery:

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

Untuk pencari masa depan ... Berikut ini adalah versi jQuery-ified dari jawaban yang diterima 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]));   
        }
    }
}

Menggunakan:

$("#myFormElemId").data("label").css("border","3px solid red");
ObjectType
sumber
+1, tetapi dari apa yang saya lihat tidak ada alasan untuk menggunakan versi jQuery untuk blok pertama: itu tidak lebih pendek atau lebih mudah dibaca, dan javascript biasa kemungkinan akan berkinerja lebih baik. Sangat menyenangkan memiliki contoh jQuery tentang bagaimana menggunakannya setelah dibuat.
Joel Coehoorn
Jelas bagi banyak dari kita tidak banyak alasan teknis untuk pendekatan ini, melainkan alasan, setidaknya dalam kasus saya, adalah alasan SDM. Bayangkan Anda memiliki tim yang mencakup desainer, integrator, dan bahkan pengembang Jr yang Anda perlambat terbiasa menggunakan jQuery. Menjaga hal-hal dalam paradigma jQuery dapat membantu menjaga produktivitas dan mengurangi frustrasi.
ObjectType
Ini tidak terlalu jQuery-ified . Mengapa forloop berakhir each()? Mengapa htmlForbukan attr("for")?
alex
Bergantung pada perspektif, kurasa. Konsumsi adalah jQuery-ified, bukan internal.
ObjectType
0

Saya tahu ini sudah tua, tetapi saya mengalami masalah dengan beberapa solusi dan menyatukannya. Saya telah menguji ini di Windows (Chrome, Firefox dan MSIE) dan OS X (Chrome dan Safari) dan percaya ini adalah solusi paling sederhana. Ia bekerja dengan tiga gaya melampirkan label ini.

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

Menggunakan jQuery:

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

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

Peter Nosko
sumber
Ini sebenarnya tidak berfungsi - ini hanya mengembalikan teks dari elemen induk, yang terkadang merupakan teks yang Anda inginkan.
John Hascall
0

Saya telah membuat untuk kebutuhan saya sendiri, dapat berguna untuk seseorang: 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");
            }
        }
    }
});
itsazzad
sumber
0

Saya agak terkejut tidak ada yang menyarankan untuk menggunakan metode hubungan CSS?

di lembar gaya, Anda dapat mereferensikan label dari pemilih elemen:

<style>

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

</style>

jika kotak centang memiliki id 'XXX' maka label akan ditemukan melalui jQuery oleh:

$('#XXX + label');

Anda juga dapat menerapkan .find ('+ label') untuk mengembalikan label dari elemen kotak centang jQuery, yaitu berguna saat melakukan perulangan:

$('input[type=checkbox]').each( function(){
   $(this).find('+ label');
});
Gordon Rouse
sumber
Ups, saya harus mencatat bahwa ini bergantung pada label yang muncul tepat setelah elemen.
Gordon Rouse