Belirli bir girişle ilişkili html etiketini bulun


110

Bir html formum olduğunu varsayalım. Her girdi / seçme / metin alanı <label>, forözniteliği tamamlayıcı kimliğine ayarlanmış bir karşılık gelir . Bu durumda, her girişin yalnızca tek bir etikete sahip olacağını biliyorum.

Javascript'te bir giriş öğesi verildiğinde - örneğin, bir onkeyup olayı aracılığıyla - ilişkili etiketi bulmanın en iyi yolu nedir?


5
Bir elemanın birden fazla etiketi olabileceğini unutmayın, eleman başına birden fazla etiketi olan bazı uygulamalar (biri için SAP) gördüm.
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

veya sadece node.parentNode.querySelector ("label [for = '" + node.id + "']"). innerHTML; lol
Solomon P Byer

Yanıtlar:


87

Önce, sayfada etiket taraması yapın ve gerçek form öğesinden etikete bir referans atayın:

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

Ardından, basitçe gidebilirsiniz:

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

Arama dizisine gerek yok :)


Bir expando mülkü kullanımınızın benimkinden nerede farklı olduğunu açıklayabilir misiniz? Herhangi bir "arama dizisi" kullanmıyorum, özelliklere sahip bir nesne kullanıyorum. "Element.label", "element ['label']" veya "lookup ['elementId']" arasında yalnızca sözdizimsel fark vardır. Perde arkasında aynı şey var .
Tomalak

4
Bu daha hoş çünkü etrafımda ayrı bir nesne bulundurmak zorunda değilim - ilişki doğrudan giriş öğesiyle saklanıyor.
Joel Coehoorn

3
Bu, tarayıcı tarafından ele alınmalıdır
andho

103

JQuery kullanıyorsanız bunun gibi bir şey yapabilirsiniz

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

JQuery kullanmıyorsanız, etiketi aramanız gerekir. Burada, öğeyi bağımsız değişken olarak alan ve ilişkili etiketi döndüren bir işlev

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

HTML5 standardında , bir giriş öğesiyle ilişkilendirilmiş etiketlere işaret eden bir labelsözellik vardır .

Dolayısıyla, bunun gibi bir şey kullanabilirsiniz (yerel labelsmülk için destek ancak tarayıcının desteklememesi durumunda etiketleri almak için bir geri dönüş ile) ...

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

JQuery kullanıyorsanız daha da kolay ...

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
Yalnızca Chrome'da değil , HTML5 standardında .
Bergi

1
Bu waaaay olmalı. Teşekkürler!
maxhm10

23

Kimsenin senin mükemmel bir şekilde yapmana izin verildiğini bilmemesine biraz şaşırdım :

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

Bu, önerilen cevapların hiçbiri tarafından alınmayacak , ancak girdiyi doğru şekilde etiketleyecektir.

İşte bu durumu dikkate alan bazı kodlar:

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

Kullanım:

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

Bazı notlar:

  • Kod, performans için değil, açıklık için yazılmıştır. Daha performanslı alternatifler mevcut olabilir.
  • Bu kod, tek seferde birden çok öğenin etiketini almayı destekler. İstediğiniz bu değilse, gerektiği gibi uyarlayın.
  • Bu aria-labelledby, onu kullanacaksın gibi şeylerle hala ilgilenmiyor ( okuyucuya egzersiz olarak bırakıldı).
  • Farklı kullanıcı aracılarını ve yardımcı teknolojileri desteklemek söz konusu olduğunda, birden fazla etiket kullanmak zor bir iştir, bu nedenle iyi test edin ve riski size ait olacak şekilde kullanın vb.
  • Evet, bunu jQuery kullanmadan da uygulayabilirsiniz. :-)

6
Bir varsayım her zaman olacaktır yapma aksine birileri örtülü etiket ilişkilendirmesi yetiştirme görmek güzel forüzerindeki özellik labelelemanı.
Josh Habdas

14

Daha erken...

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

Sonra...

var myLabel = lookup[myInput.id];

Snarky yorum: Evet, bunu JQuery ile de yapabilirsiniz. :-)


1
Güzel. Yöntemi ilk çağırdığımda aramayı oluşturması için bunu biraz yeniden düzenleyeceğim, ancak hile yapması gerekir.
Joel Coehoorn

Aramayı yalnızca bir kez oluşturacağınızı ima ettim.
Tomalak

Küçük bir hata olduğunu unutmayın: "for" değil, "htmlFor" özelliğini kullanın, çünkü ikincisi JS'de ayrılmış bir kelimedir. Etiket nesnelerini kullanırken bunu unutmaya meyilliyim ... :-)
Tomalak

Yukarıdaki arama dizisi olmadan bunu yapmanın bir yolunu buldum.
FlySwat

Başlangıç ​​kodunu yöntemin içine taşımayı kastetmiştim, bunu bir kez yapma :(
Joel Coehoorn

13

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

Bu, soruyu en basit ve en yalın şekilde yanıtlar. Bu, vanilya javascript kullanır ve tüm ana akış uygun tarayıcılarda çalışır.


Bu soruya bir cevap vermiyor. Yeterli itibara sahip olduğunuzda , herhangi bir gönderi hakkında yorum yapabileceksiniz ; bunun yerine soruyu soranın açıklamasını gerektirmeyen yanıtlar verin . - Yorumdan
loki

1
Bu, @loki sorusuna kesinlikle bir cevap sağlar Sırf bunun daha fazla açıklaması olmadığı için, bu yanlış olduğu veya cevap vermeye çalışmadığı anlamına gelmez.
geisterfurz007

En basit ve faydalı cevap! Teşekkürler!
iedmrc

8

jquery ile şöyle bir şey yapabilirsiniz

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

Atalar olsa da potansiyel olarak etiketleri kaçırır.
alex

4

QuerySelector'ı kullanmak istiyorsan (ve hatta IE9'a ve bazen IE8'e kadar yapabilirsen!), Başka bir yöntem uygulanabilir hale gelir.

Form alanınızın bir kimliği varsa ve etiketin forözniteliğini kullanıyorsanız, bu modern JavaScript'te oldukça basit hale gelir:

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

Bazıları çoklu etiketlere dikkat çekti; hepsi foröznitelik için aynı değeri kullanıyorsa, ihtiyacınız olan her şeyi elde etmek için querySelectorAllbunun yerine querySelectorve döngüyü kullanın .


3

Diğer tüm cevaplar son derece güncel değil !!

Tüm yapman gereken:

input.labels

HTML5, tüm büyük tarayıcılar tarafından yıllardır desteklenmektedir. Bunu kendi başınıza yapmanız ya da çoklu doldurmanız için kesinlikle hiçbir neden yok! Kelimenin tam anlamıyla sadece kullanın input.labelsve tüm sorunlarınızı çözer.


1
Bu sayfaya göre , input.labelsIE veya Edge tarafından desteklenmiyor ve Firefox yalnızca desteği ekledi.
Antti29

@ Antti29 Bir şim kullanarak işlevselliği ekleyebilirsiniz: github.com/termi/ES5-DOM-SHIM Eklenen özelliği burada görebilirsiniz: github.com/termi/ES5-DOM-SHIM/blob/…
ADJenks

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

Bu, kimliğini kullanarak bir giriş öğesinin etiketini almamda bana yardımcı oldu.


2

Gijs'in cevabı benim için çok değerliydi, ancak maalesef uzantı çalışmıyor.

İşte işe yarayan yeniden yazılmış bir uzantı, birine yardımcı olabilir:

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

Yıkım ve örtük geri dönüşler gibi ES6 özelliklerini kullanarak onu kullanışlı bir astara dönüştürmek için gerçekten özlü bir çözüm şöyle olacaktır:

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

Ya da bir DüğümListesi değil, yalnızca bir etiket almak için:

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

1

Etikete bir kimlik eklemek aslında formun kendisinde çok daha kolaydır, örneğin:

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

Ardından, bunun gibi bir şey kullanabilirsiniz:

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’in çalışması için vücut yükleme işlevinde olması gerekir.

Sadece bir düşünce, benim için çok güzel çalışıyor.


1

Daha önce de belirtildiği gibi, (şu anda) en yüksek puan alan yanıt, bir girişin bir etiketin içine yerleştirilmesi olasılığını hesaba katmaz.

Hiç kimse JQuery içermeyen bir yanıt göndermediğine göre, işte benimki:

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

Bu örnekte, basitlik açısından, arama tablosu doğrudan girdi HTML öğeleri tarafından indekslenmiştir. Bu pek verimli değil ve istediğiniz gibi uyarlayabilirsiniz.

Bir formu temel öğe olarak veya birden çok form için aynı anda etiket almak istiyorsanız tüm belgeyi kullanabilirsiniz.

Yanlış HTML için kontrol yapılmaz (etiketlerin içinde birden fazla veya eksik giriş, karşılık gelen htmlFor id ile eksik giriş vb.), Ancak bunları eklemekten çekinmeyin.

Giriş etikete gömülü olduğunda genellikle takip eden boşluklar bulunduğundan etiket metinlerini kırpmak isteyebilirsiniz.


1

En iyi cevap mükemmel bir şekilde işe yarar, ancak çoğu durumda, tüm labelunsurlar arasında döngü yapmak aşırı ve verimsizdir .

İşte öğeyle labeluyumlu olanı elde etmek için etkili bir işlev 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;
}

Benim için bu bir satır kod yeterliydi:

el = document.getElementById(id).previousElementSibling;

Çoğu durumda, labelgirişe çok yakın veya yanında olacaktır, bu da yukarıdaki işlevdeki döngünün yalnızca çok az sayıda yineleme yapması gerektiği anlamına gelir.


0

document.getElementbyID ('id') kullanmayı denediniz mi, burada id etiketin kimliğidir veya hangisini aradığınızı bilmediğiniz bir durumdur


Giriş öğesinin kimliğini biliyorum, ancak etiketin kimliğini bilmiyorum.
Joel Coehoorn

etiket için input id = 'test' ve label id = 'lbl_test "gibi karşılık gelen bir kimlik ayarlayamazsınız
Josh Mein

0

Bir JQuery seçici kullanın:

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

0

Gelecekteki arama yapanlar için ... Aşağıda FlySwat'ın kabul edilen cevabının jQuery uyumlu bir versiyonu bulunmaktadır:

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

Kullanarak:

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

+1, ancak gördüğüm kadarıyla ilk blok için jQuery sürümünü kullanmak için bir neden yok: daha kısa veya daha okunaklı değil ve düz javascript muhtemelen daha iyi performans gösterecek. Yine de, oluşturulduktan sonra nasıl kullanılacağına dair bir jQuery örneğinin olması güzel.
Joel Coehoorn

Açıkçası çoğumuz için bu yaklaşımın teknik bir sebebi yok, bunun yerine en azından benim durumumda bir İK nedeni var. Tasarımcılar, entegratörler ve hatta yavaşlamakta olduğunuz Jr geliştiricilerin jQuery kullanmaya alıştığı bir ekibiniz olduğunu hayal edin. İşleri jQuery paradigmasında tutmak, üretkenliği yüksek tutmaya ve hayal kırıklığını azaltmaya yardımcı olabilir.
ObjectType

Bu çok jQuery uyumlu değil . forDöngü neden bitti each()? Neden htmlForyerine attr("for")?
alex

Perspektife bağlı, sanırım. Tüketim dahili değil, jQuery-ified idi.
ObjectType

0

Bunun eski olduğunu biliyorum, ancak bazı çözümlerde sorun yaşadım ve bunu bir araya getirdim. Bunu Windows (Chrome, Firefox ve MSIE) ve OS X (Chrome ve Safari) üzerinde test ettim ve bunun en basit çözüm olduğuna inanıyorum. Bu üç etiket yapıştırma stiliyle çalışır.

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

JQuery kullanarak:

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

JSFiddle'ım: http://jsfiddle.net/pnosko/6PQCw/


Bu aslında işe yaramıyor - sadece ana öğenin metnini döndürüyor, ki bu bazen istediğiniz metin oluyor.
John Hascall 01

0

Kendi ihtiyacım için yaptım, birisi için faydalı olabilir: 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

Kimsenin CSS ilişki yöntemini kullanmayı önermemesine biraz şaşırdım mı?

bir stil sayfasında, öğe seçiciden bir etikete başvurabilirsiniz:

<style>

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

</style>

onay kutusu 'XXX' kimliğine sahipse, etiket jQuery aracılığıyla şu şekilde bulunur:

$('#XXX + label');

Etiketi bir jQuery onay kutusu öğesinden döndürmek için .find ('+ etiket') de uygulayabilirsiniz, yani döngü sırasında kullanışlıdır:

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

Hata! Bunun, öğeden hemen sonra gelen etikete bağlı olduğuna dikkat etmeliyim.
Gordon Rouse
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.