ค้นหาป้ายกำกับ html ที่เกี่ยวข้องกับอินพุตที่ระบุ


110

สมมติว่าฉันมีแบบฟอร์ม html อินพุต / เลือก / textarea แต่ละรายการจะมีความสอดคล้อง<label>กับforแอตทริบิวต์ที่ตั้งค่าเป็น id ของสหาย ในกรณีนี้ฉันรู้ว่าอินพุตแต่ละรายการจะมีป้ายกำกับเดียวเท่านั้น

ระบุองค์ประกอบอินพุตในจาวาสคริปต์ - ผ่านเหตุการณ์ onkeyup ตัวอย่างเช่นวิธีใดที่ดีที่สุดในการค้นหาป้ายกำกับที่เกี่ยวข้อง


5
โปรดทราบว่าองค์ประกอบอาจมีป้ายกำกับมากกว่าหนึ่งป้ายฉันเคยเห็นบางแอปพลิเคชัน (SAP สำหรับหนึ่งรายการ) ที่มีหลายป้ายกำกับต่อองค์ประกอบ
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

หรือเพียงแค่ node.parentNode.querySelector ("label [for = '" + node.id + "']") innerHTML; lol
Solomon P Byer

คำตอบ:


87

ขั้นแรกให้สแกนหน้าเพื่อหาป้ายกำกับและกำหนดการอ้างอิงไปยังฉลากจากองค์ประกอบฟอร์มจริง:

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

จากนั้นคุณสามารถไป:

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

ไม่จำเป็นต้องค้นหาอาร์เรย์ :)


คุณอธิบายได้ไหมว่าการใช้คุณสมบัติ expando ของคุณแตกต่างจากของฉันอย่างไร ฉันไม่ได้ใช้ "อาร์เรย์การค้นหา" ใด ๆ ฉันใช้วัตถุที่มีคุณสมบัติ มีเพียงความแตกต่างทางไวยากรณ์ระหว่าง "element.label", "element ['label']" หรือ "lookup ['elementId']" เบื้องหลังพวกเขาเป็นสิ่งเดียวกัน
Tomalak

4
นี่ดีกว่าเพราะฉันไม่ต้องเก็บวัตถุแยกไว้รอบ ๆ - ความสัมพันธ์จะถูกเก็บไว้กับองค์ประกอบอินพุตโดยตรง
Joel Coehoorn

3
สิ่งนี้ควรได้รับการจัดการโดยเบราว์เซอร์
เมื่อ

103

หากคุณใช้ jQuery คุณสามารถทำสิ่งนี้ได้

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

ถ้าคุณไม่ได้ใช้ jQuery คุณจะต้องค้นหาป้ายกำกับ นี่คือฟังก์ชันที่ใช้องค์ประกอบเป็นอาร์กิวเมนต์และส่งคืนป้ายกำกับที่เกี่ยวข้อง

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

มีlabelsคุณสมบัติในมาตรฐาน HTML5ซึ่งชี้ไปที่ป้ายกำกับที่เกี่ยวข้องกับองค์ประกอบอินพุต

ดังนั้นคุณสามารถใช้สิ่งนี้ได้ (รองรับlabelsคุณสมบัติเนทีฟ แต่มีทางเลือกในการดึงป้ายกำกับในกรณีที่เบราว์เซอร์ไม่รองรับ) ...

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

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
ไม่เพียง แต่ใน Chrome มันอยู่ในมาตรฐาน HTML5
Bergi

1
นี่ควรจะรอ ขอบคุณ!
maxhm10

23

ฉันแปลกใจเล็กน้อยที่ดูเหมือนจะไม่มีใครรู้ว่าคุณได้รับอนุญาตให้ทำ:

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

ซึ่งจะไม่ถูกเลือกโดยคำตอบที่แนะนำ แต่จะติดป้ายกำกับข้อมูลที่ป้อนให้ถูกต้อง

นี่คือรหัสบางส่วนที่ใช้ในกรณีนี้:

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

การใช้งาน:

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

หมายเหตุบางประการ:

  • รหัสถูกเขียนขึ้นเพื่อความชัดเจนไม่ใช่เพื่อประสิทธิภาพ อาจมีทางเลือกอื่นที่มีประสิทธิภาพมากขึ้น
  • รหัสนี้รองรับการรับป้ายกำกับของหลายรายการในครั้งเดียว หากนั่นไม่ใช่สิ่งที่คุณต้องการให้ปรับเปลี่ยนตามความจำเป็น
  • สิ่งนี้ยังไม่ได้ดูแลสิ่งต่างๆเช่นaria-labelledbyหากคุณใช้สิ่งนั้น (ปล่อยให้เป็นแบบฝึกหัดสำหรับผู้อ่าน)
  • การใช้ป้ายกำกับหลายป้ายเป็นธุรกิจที่ยุ่งยากเมื่อต้องรองรับตัวแทนผู้ใช้และเทคโนโลยีอำนวยความสะดวกที่แตกต่างกันดังนั้นควรทดสอบให้ดีและใช้ด้วยความเสี่ยงของคุณเองเป็นต้น
  • ใช่คุณสามารถใช้สิ่งนี้ได้โดยไม่ต้องใช้ jQuery :-)

6
ยินดีที่ได้เห็นใครบางคนนำการเชื่อมโยงป้ายกำกับโดยนัยซึ่งตรงข้ามกับการตั้งสมมติฐานจะมีforแอตทริบิวต์อยู่ในlabelองค์ประกอบเสมอ
Josh Habdas

14

ก่อนหน้านี้ ...

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

ต่อมา ...

var myLabel = lookup[myInput.id];

ความคิดเห็นที่น่ากลัว: ใช่คุณสามารถทำได้ด้วย JQuery :-)


1
ดี. ฉันจะ refactor เพียงเล็กน้อยเพื่อที่จะสร้างการค้นหาในครั้งแรกที่ฉันเรียกเมธอด แต่มันควรจะเป็นเคล็ดลับ
Joel Coehoorn

ฉันบอกเป็นนัยว่าคุณจะสร้างการค้นหาเพียงครั้งเดียว
Tomalak

โปรดทราบว่ามีข้อผิดพลาดเล็กน้อย: ใช้คุณสมบัติ "htmlFor" ไม่ใช่ "for" เนื่องจากคำหลังเป็นคำสงวนใน JS ฉันมักจะลืมว่าเมื่อใช้วัตถุฉลาก ... :-)
Tomalak

ฉันมีวิธีทำโดยไม่ต้องค้นหาอาร์เรย์ด้านบน
FlySwat

ฉันหมายถึงย้ายรหัส init ภายในวิธีการไม่ใช่ทำเพียงครั้งเดียว :(
Joel Coehoorn

13

document.querySelector ("ป้ายกำกับ [for =" + vHtmlInputElement.id + "]");

สิ่งนี้ตอบคำถามด้วยวิธีที่เรียบง่ายและน้อยที่สุด สิ่งนี้ใช้วานิลลาจาวาสคริปต์และทำงานบนเบราว์เซอร์ที่เหมาะสมสำหรับสตรีมหลักทั้งหมด


สิ่งนี้ไม่ได้ให้คำตอบสำหรับคำถาม เมื่อคุณมีเพียงพอชื่อเสียงคุณจะสามารถที่จะแสดงความคิดเห็นในโพสต์ใด ๆ ; แทนที่จะให้คำตอบที่ไม่จำเป็นต้องชี้แจงจากผู้ถาม - จากรีวิว
loki

1
นี่เป็นคำตอบที่แน่นอนที่สุดสำหรับคำถาม @loki เพียงเพราะไม่มีคำอธิบายเพิ่มเติมนั่นไม่ได้หมายความว่ามันผิดหรือไม่ได้พยายามตอบ
geisterfurz007

คำตอบที่ง่ายและมีประโยชน์ที่สุด! ขอบคุณ!
iedmrc

8

ด้วย jquery คุณสามารถทำสิ่งที่ชอบ

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

อาจพลาดป้ายกำกับแม้ว่าจะเป็นบรรพบุรุษก็ตาม
alex

4

หากคุณยินดีที่จะใช้querySelector (และคุณสามารถทำได้แม้กระทั่งถึง IE9 และบางครั้งก็คือ IE8!) วิธีอื่นก็ใช้ได้

หากช่องแบบฟอร์มของคุณมีรหัสและคุณใช้forแอตทริบิวต์ของป้ายกำกับสิ่งนี้จะกลายเป็นเรื่องง่ายใน 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);
});

บางคนตั้งข้อสังเกตเกี่ยวกับป้ายกำกับต่างๆ หากทุกคนใช้ค่าเดียวกันสำหรับforแอตทริบิวต์เพียงแค่ใช้querySelectorAllแทนquerySelectorและวนซ้ำเพื่อรับทุกสิ่งที่คุณต้องการ


3

คำตอบอื่น ๆ ทั้งหมดล้าสมัยมาก !!

สิ่งที่คุณต้องทำคือ:

input.labels

HTML5 ได้รับการสนับสนุนโดยเบราว์เซอร์หลัก ๆ ทั้งหมดเป็นเวลาหลายปีแล้ว ไม่มีเหตุผลอย่างแน่นอนที่คุณควรต้องทำสิ่งนี้ตั้งแต่เริ่มต้นด้วยตัวคุณเองหรือเติมโพลี! แท้จริงเพียงแค่ใช้input.labelsและแก้ปัญหาทั้งหมดของคุณ


1
ตามหน้านี้ , input.labelsไม่ได้รับการสนับสนุนจาก IE หรือขอบและ Firefox เท่านั้นเพียงแค่เพิ่มการสนับสนุน
Antti29

@ Antti29 คุณสามารถเพิ่มฟังก์ชันโดยใช้ shim: github.com/termi/ES5-DOM-SHIMคุณสามารถดูคุณสมบัติที่เพิ่มได้ที่นี่: github.com/termi/ES5-DOM-SHIM/blob/…
ADJenks


2

คำตอบจาก Gijs มีค่ามากที่สุดสำหรับฉัน แต่น่าเสียดายที่ส่วนขยายไม่ทำงาน

นี่คือส่วนขยายที่เขียนใหม่ซึ่งใช้งานได้ซึ่งอาจช่วยใครบางคนได้:

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

วิธีแก้ปัญหาที่รัดกุมอย่างแท้จริงโดยใช้คุณสมบัติ ES6 เช่นการทำลายโครงสร้างและผลตอบแทนโดยปริยายเพื่อเปลี่ยนเป็นซับเดียวที่มีประโยชน์คือ:

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

หรือเพียงแค่รับป้ายกำกับเดียวไม่ใช่ NodeList:

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

1

การเพิ่ม id ลงในป้ายกำกับในแบบฟอร์มนั้นง่ายกว่ามากตัวอย่างเช่น:

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

จากนั้นคุณสามารถใช้สิ่งนี้:

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

จาวาสคริปต์ต้องอยู่ในฟังก์ชัน body onload จึงจะทำงานได้

แค่คิดก็ใช้ได้ดีสำหรับฉัน


1

ดังที่ได้กล่าวไปแล้วคำตอบยอดนิยม (ในปัจจุบัน) ไม่ได้คำนึงถึงความเป็นไปได้ที่จะฝังอินพุตไว้ในป้ายกำกับ

เนื่องจากไม่มีใครโพสต์คำตอบที่ไม่ใช้ JQuery นี่จึงเป็นของฉัน:

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

ในตัวอย่างนี้เพื่อความเรียบง่ายตารางการค้นหาจะถูกจัดทำดัชนีโดยตรงโดยองค์ประกอบ HTML ที่ป้อนเข้า สิ่งนี้แทบจะไม่มีประสิทธิภาพและคุณสามารถปรับเปลี่ยนได้ตามต้องการ

คุณสามารถใช้แบบฟอร์มเป็นองค์ประกอบพื้นฐานหรือทั้งเอกสารหากคุณต้องการรับป้ายชื่อสำหรับหลายรูปแบบพร้อมกัน

ไม่มีการตรวจสอบ HTML ที่ไม่ถูกต้อง (อินพุตหลายหรือขาดหายไปภายในป้ายกำกับไม่มีอินพุตที่มี htmlFor id ที่เกี่ยวข้อง ฯลฯ ) แต่คุณสามารถเพิ่มได้

คุณอาจต้องการตัดแต่งข้อความป้ายกำกับเนื่องจากมักจะมีช่องว่างต่อท้ายเมื่ออินพุตฝังอยู่ในป้ายกำกับ


1

คำตอบที่ดีที่สุดใช้งานได้ดีอย่างสมบูรณ์ แต่ในกรณีส่วนใหญ่การวนซ้ำlabelองค์ประกอบทั้งหมดใช้งานมากเกินไปและไม่มีประสิทธิภาพ

นี่คือฟังก์ชั่นที่มีประสิทธิภาพในการรับสิ่งlabelที่ไปกับ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;
}

สำหรับฉันโค้ดหนึ่งบรรทัดนี้เพียงพอแล้ว:

el = document.getElementById(id).previousElementSibling;

ในกรณีส่วนใหญ่labelจะอยู่ใกล้มากหรือถัดจากอินพุตซึ่งหมายความว่าการวนซ้ำในฟังก์ชันด้านบนจะต้องวนซ้ำเพียงไม่กี่ครั้งเท่านั้น


0

คุณได้ลองใช้ document.getElementbyID ('id') โดยที่ id คือ id ของป้ายกำกับหรือเป็นสถานการณ์ที่คุณไม่รู้ว่ากำลังมองหาอันไหน


ฉันรู้รหัสขององค์ประกอบอินพุต แต่ไม่ใช่รหัสของป้ายกำกับ
Joel Coehoorn

คุณไม่สามารถตั้งรหัสที่สอดคล้องกันสำหรับป้ายกำกับเช่น input id = 'test' และ label id = 'lbl_test "
Josh Mein


0

สำหรับผู้ค้นหาในอนาคต ... ต่อไปนี้เป็นคำตอบที่ยอมรับของ FlySwat เวอร์ชัน jQuery-ified:

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

ใช้:

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

+1 แต่จากสิ่งที่ฉันเห็นไม่มีเหตุผลที่จะใช้เวอร์ชัน jQuery สำหรับบล็อกแรก: มันไม่สั้นหรืออ่านได้มากกว่าและจาวาสคริปต์ธรรมดาจะทำงานได้ดีกว่า เป็นเรื่องดีที่จะมีตัวอย่าง jQuery เกี่ยวกับวิธีใช้เมื่อสร้างขึ้นแล้ว
Joel Coehoorn

เห็นได้ชัดว่าสำหรับพวกเราหลายคนไม่มีเหตุผลทางเทคนิคมากนักสำหรับแนวทางนี้ แต่อย่างน้อยในกรณีของฉันก็คือ HR ลองนึกภาพคุณมีทีมที่รวมนักออกแบบผู้ผสานรวมและแม้แต่นักพัฒนา Jr ที่คุณเคยชินกับการใช้ jQuery การรักษาสิ่งต่างๆไว้ในกระบวนทัศน์ jQuery สามารถช่วยรักษาประสิทธิผลและลดความยุ่งยาก
ObjectType

นี่ไม่ใช่jQuery-ifiedมากนัก ทำไมต้องforวนซ้ำeach()? ทำไมhtmlForแทนที่จะเป็นattr("for")?
อเล็กซ์

ขึ้นอยู่กับมุมมองฉันเดา การบริโภคเป็น jQuery-ified ไม่ใช่ภายใน
ObjectType

0

ฉันรู้ว่ามันเก่า แต่ฉันมีปัญหากับวิธีแก้ปัญหาบางอย่างและรวมเข้าด้วยกัน ฉันได้ทดสอบสิ่งนี้บน Windows (Chrome, Firefox และ MSIE) และ OS X (Chrome และ Safari) และเชื่อว่านี่เป็นวิธีที่ง่ายที่สุด ใช้งานได้กับรูปแบบการติดป้ายทั้งสามแบบนี้

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

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

JSFiddle ของฉัน: http://jsfiddle.net/pnosko/6PQCw/


สิ่งนี้ใช้ไม่ได้จริง - เป็นเพียงการส่งคืนข้อความขององค์ประกอบหลักซึ่งบางครั้งอาจเป็นข้อความที่คุณต้องการ
John Hascall

0

ฉันทำเพื่อความต้องการของตัวเองมีประโยชน์สำหรับใครบางคน: 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

ฉันแปลกใจเล็กน้อยที่ไม่มีใครแนะนำให้ใช้วิธี CSS relationship?

ในสไตล์ชีตคุณสามารถอ้างอิงป้ายกำกับจากตัวเลือกองค์ประกอบ:

<style>

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

</style>

หากช่องทำเครื่องหมายมีรหัสเป็น "XXX" จะพบป้ายกำกับผ่าน jQuery โดย:

$('#XXX + label');

คุณยังสามารถใช้. find ('+ label') เพื่อส่งคืนป้ายกำกับจากองค์ประกอบช่องทำเครื่องหมาย jQuery ซึ่งมีประโยชน์เมื่อทำการวนซ้ำ:

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

อ๊ะฉันควรทราบว่าสิ่งนี้ขึ้นอยู่กับป้ายกำกับที่อยู่หลังองค์ประกอบโดยตรง
Gordon Rouse
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.