Tìm nhãn html được liên kết với một đầu vào nhất định


110

Giả sử tôi có một dạng html. Mỗi đầu vào / select / textarea sẽ có một tương ứng <label>với forthuộc tính được đặt thành id của đồng hành của nó. Trong trường hợp này, tôi biết rằng mỗi đầu vào sẽ chỉ có một nhãn duy nhất.

Cho một phần tử đầu vào trong javascript - ví dụ: thông qua sự kiện onkeyup - cách tốt nhất để tìm nhãn được liên kết của nó là gì?


5
Lưu ý rằng một phần tử có thể có nhiều nhãn, tôi đã thấy một số ứng dụng (SAP cho một phần tử) có nhiều nhãn cho mỗi phần tử.
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

hoặc chỉ node.parentNode.querySelector ("label [for = '" + node.id + "']"). innerHTML; lol
Solomon P Byer

Câu trả lời:


87

Đầu tiên, hãy quét trang để tìm nhãn và chỉ định một tham chiếu cho nhãn từ phần tử biểu mẫu thực tế:

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

Sau đó, bạn có thể chỉ cần đi:

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

Không cần mảng tra cứu :)


Bạn có thể giải thích cách sử dụng thuộc tính expando của bạn khác với của tôi không? Tôi không sử dụng bất kỳ "mảng tra cứu" nào, tôi sử dụng một đối tượng có thuộc tính. Chỉ có sự khác biệt về cú pháp giữa "element.label", "element ['label']" hoặc "lookup ['elementId']". Đằng sau hậu trường, chúng giống nhau .
Tomalak

4
Điều này đẹp hơn vì tôi không phải giữ một đối tượng riêng biệt - mối quan hệ được lưu trữ trực tiếp với phần tử đầu vào.
Joel Coehoorn

3
Điều này sẽ được xử lý bởi trình duyệt
vào

103

Nếu bạn đang sử dụng jQuery, bạn có thể làm như thế này

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

Nếu bạn không sử dụng jQuery, bạn sẽ phải tìm kiếm nhãn. Đây là một hàm nhận phần tử làm đối số và trả về nhãn được liên kết

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

Có một labelsthuộc tính trong tiêu chuẩn HTML5 trỏ đến các nhãn được liên kết với một phần tử đầu vào.

Vì vậy, bạn có thể sử dụng một cái gì đó như thế này (hỗ trợ cho thuộc labelstính gốc nhưng có dự phòng để truy xuất nhãn trong trường hợp trình duyệt không hỗ trợ nó) ...

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

Thậm chí dễ dàng hơn nếu bạn đang sử dụng 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
Không chỉ trong Chrome, nó còn ở chuẩn HTML5 .
Bergi

1
Điều này sẽ được chờ đợi. Cảm ơn!
maxhm10

23

Tôi hơi ngạc nhiên rằng dường như không ai biết rằng bạn hoàn toàn được phép làm:

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

Câu trả lời nào sẽ không được chọn bởi bất kỳ câu trả lời gợi ý nào, nhưng sẽ gắn nhãn đầu vào chính xác.

Dưới đây là một số mã có tính đến trường hợp này:

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

Sử dụng:

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

Một số lưu ý:

  • Mã được viết để rõ ràng, không phải để thực hiện. Có thể có nhiều lựa chọn thay thế hiệu quả hơn.
  • Mã này hỗ trợ lấy nhãn của nhiều mục trong một lần. Nếu đó không phải là điều bạn muốn, hãy thích nghi khi cần thiết.
  • Điều này vẫn không quan tâm đến những thứ như aria-labelledbynếu bạn sử dụng nó (để lại như một bài tập cho người đọc).
  • Sử dụng nhiều nhãn là một công việc khó khăn khi cần hỗ trợ các tác nhân người dùng và công nghệ hỗ trợ khác nhau, vì vậy hãy kiểm tra tốt và tự chịu rủi ro khi sử dụng, v.v.
  • Có, bạn cũng có thể thực hiện điều này mà không cần sử dụng jQuery. :-)

6
Rất vui khi thấy ai đó đưa ra liên kết nhãn ngầm thay vì đưa ra giả định rằng sẽ luôn có một forthuộc tính trên labelphần tử.
Josh Habdas

14

Sớm hơn...

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

Một lát sau...

var myLabel = lookup[myInput.id];

Nhận xét của Snarky: Có, bạn cũng có thể làm điều đó với JQuery. :-)


1
Đẹp. Tôi sẽ cấu trúc lại một chút để nó xây dựng bản tra cứu trong lần đầu tiên tôi gọi phương thức, nhưng nó sẽ thực hiện được một mẹo nhỏ.
Joel Coehoorn

Tôi ngụ ý rằng bạn sẽ xây dựng bản tra cứu chỉ một lần.
Tomalak

Xin lưu ý rằng có một lỗi nhỏ trong đó: Sử dụng thuộc tính "htmlFor", không phải "for", vì thuộc tính sau là một từ dành riêng trong JS. Tôi có xu hướng quên điều đó khi sử dụng các đối tượng nhãn ... :-)
Tomalak.

Tôi có một cách để làm điều này mà không cần một mảng tra cứu ở trên.
FlySwat

Tôi có nghĩa là di chuyển mã init bên trong phương pháp, không làm điều đó chỉ một lần :(
Joel Coehoorn

13

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

Điều này trả lời câu hỏi theo cách đơn giản và gọn gàng nhất. Điều này sử dụng vani javascript và hoạt động trên tất cả các trình duyệt phù hợp với luồng chính.


Điều này không cung cấp câu trả lời cho câu hỏi. Khi bạn có đủ danh tiếng, bạn sẽ có thể nhận xét về bất kỳ bài đăng nào ; thay vào đó, cung cấp câu trả lời không yêu cầu người hỏi làm rõ . - Từ đánh giá
loki

1
Điều này chắc chắn cung cấp câu trả lời cho câu hỏi @loki Chỉ vì không có lời giải thích nào thêm cho nó, điều đó không có nghĩa là nó sai hoặc không cố gắng trả lời nó.
geisterfurz007 30/01

Câu trả lời đơn giản và hữu ích! Cảm ơn!
iedmrc

8

với jquery bạn có thể làm điều gì đó như

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

Có khả năng bỏ sót nhãn mặc dù đó là tổ tiên.
alex

4

Nếu bạn sẵn sàng sử dụng querySelector (và thậm chí bạn có thể xuống IE9 và đôi khi là IE8!), Một phương pháp khác sẽ khả thi.

Nếu trường biểu mẫu của bạn có ID và bạn sử dụng forthuộc tính của nhãn , điều này trở nên khá đơn giản trong JavaScript hiện đại:

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

Một số đã lưu ý về nhiều nhãn; nếu tất cả chúng đều sử dụng cùng một giá trị cho forthuộc tính, chỉ cần sử dụng querySelectorAllthay vì querySelectorvà lặp lại để nhận mọi thứ bạn cần.


3

Tất cả các câu trả lời khác đều vô cùng lỗi thời !!

Tât cả nhưng điêu bạn phải lam la:

input.labels

HTML5 đã được hỗ trợ bởi tất cả các trình duyệt chính trong nhiều năm. Hoàn toàn không có lý do gì mà bạn phải tự mình làm từ đầu hoặc làm đầy nó! Theo nghĩa đen, chỉ cần sử dụng input.labelsvà nó giải quyết tất cả các vấn đề của bạn.


1
Theo trang này , input.labelsIE hoặc Edge không hỗ trợ và Firefox chỉ bổ sung hỗ trợ.
Antti29

@ Antti29 Bạn có thể thêm chức năng bằng cách sử dụng miếng đệm: github.com/termi/ES5-DOM-SHIM Bạn có thể thấy tính năng đang được thêm tại đây: github.com/termi/ES5-DOM-SHIM/blob/…
ADJenks

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

Điều này đã giúp tôi lấy nhãn của một phần tử đầu vào bằng cách sử dụng ID của nó.


2

Câu trả lời từ Gijs có giá trị nhất đối với tôi, nhưng tiếc là tiện ích mở rộng không hoạt động.

Đây là một tiện ích mở rộng được viết lại hoạt động, nó có thể giúp ai đó:

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

Một giải pháp thực sự ngắn gọn sử dụng các tính năng của ES6 như hủy cấu trúc và trả về ngầm định để biến nó thành một lớp lót tiện dụng sẽ là:

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

Hoặc đơn giản là lấy một nhãn, không phải NodeList:

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

1

Thực sự dễ dàng hơn nhiều để thêm id vào nhãn trong chính biểu mẫu, ví dụ:

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

Sau đó, bạn có thể chỉ cần sử dụng một cái gì đó như sau:

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 phải có trong hàm body onload mới hoạt động được.

Chỉ là một suy nghĩ, làm việc tuyệt vời cho tôi.


1

Như nó đã được đề cập, câu trả lời (hiện tại) được xếp hạng cao nhất không tính đến khả năng nhúng đầu vào bên trong nhãn.

Vì không ai đăng câu trả lời không có JQuery, đây là của tôi:

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

Trong ví dụ này, để đơn giản, bảng tra cứu được lập chỉ mục trực tiếp bởi các phần tử HTML đầu vào. Điều này hầu như không hiệu quả và bạn có thể điều chỉnh nó theo cách bạn muốn.

Bạn có thể sử dụng biểu mẫu làm phần tử cơ sở hoặc toàn bộ tài liệu nếu bạn muốn lấy nhãn cho nhiều biểu mẫu cùng một lúc.

Không có kiểm tra nào được thực hiện đối với HTML không chính xác (nhiều hoặc thiếu đầu vào bên trong nhãn, thiếu đầu vào với id htmlFor tương ứng, v.v.), nhưng hãy thêm chúng vào.

Bạn có thể muốn cắt bớt văn bản nhãn, vì dấu cách ở cuối thường xuất hiện khi đầu vào được nhúng vào nhãn.


1

Câu trả lời tốt nhất hoạt động hoàn toàn tốt nhưng trong hầu hết các trường hợp, việc lặp qua tất cả các labelphần tử là quá mức cần thiết và không hiệu quả .

Đây là một hàm hiệu quả để lấy phần tử labelđi kèm 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;
}

Đối với tôi, một dòng mã này là đủ:

el = document.getElementById(id).previousElementSibling;

Trong hầu hết các trường hợp, labelwill rất gần hoặc bên cạnh đầu vào, có nghĩa là vòng lặp trong hàm trên chỉ cần lặp lại một số lần rất nhỏ.


0

bạn đã thử sử dụng document.getElementbyID ('id') trong đó id là id của nhãn hay là trường hợp bạn không biết mình đang tìm cái nào


Tôi biết id của phần tử đầu vào, nhưng không biết id của nhãn.
Joel Coehoorn

bạn không thể thiết lập một id tương ứng cho các nhãn như input id = 'test' và id label = 'lbl_test"
Josh Mein


0

Đối với những người tìm kiếm trong tương lai ... Sau đây là phiên bản jQuery-ified của câu trả lời được chấp nhận của 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]));   
        }
    }
}

Sử dụng:

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

+1, nhưng theo những gì tôi thấy thì không có lý do gì để sử dụng phiên bản jQuery cho khối đầu tiên: nó không ngắn hơn hoặc dễ đọc hơn và javascript thuần túy có thể sẽ hoạt động tốt hơn. Tuy nhiên, thật tuyệt khi có một ví dụ jQuery về cách sử dụng nó sau khi được tạo.
Joel Coehoorn

Rõ ràng là đối với nhiều người trong chúng ta, không có nhiều lý do kỹ thuật cho cách tiếp cận này, mà lý do, ít nhất là trong trường hợp của tôi, là một lý do nhân sự. Hãy tưởng tượng bạn có một nhóm bao gồm các nhà thiết kế, tích hợp và thậm chí cả các nhà phát triển Jr, những người mà bạn đã quen với việc sử dụng jQuery. Giữ mọi thứ trong mô hình jQuery có thể giúp tăng năng suất và giảm sự thất vọng.
ObjectType,

Đây không phải là jQuery-ified . Tại sao forvòng lặp qua each()? Tại sao htmlForthay vì attr("for")?
alex

Tôi đoán là phụ thuộc vào quan điểm. Việc tiêu thụ là jQuery-ified, không phải nội bộ.
ObjectType

0

Tôi biết điều này đã cũ, nhưng tôi đã gặp khó khăn với một số giải pháp và kết hợp điều này lại với nhau. Tôi đã thử nghiệm điều này trên Windows (Chrome, Firefox và MSIE) và OS X (Chrome và Safari) và tin rằng đây là giải pháp đơn giản nhất. Nó hoạt động với ba kiểu gắn nhãn này.

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

Sử dụng jQuery:

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

JSFiddle của tôi: http://jsfiddle.net/pnosko/6PQCw/


Điều này thực sự không hoạt động - nó chỉ trả về văn bản của phần tử mẹ, đôi khi là văn bản bạn muốn.
John Hascall

0

Tôi đã làm cho nhu cầu của riêng mình, có thể hữu ích cho ai đó: 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

Tôi hơi ngạc nhiên khi không có ai đề xuất sử dụng phương pháp quan hệ CSS?

trong biểu định kiểu, bạn có thể tham chiếu nhãn từ bộ chọn phần tử:

<style>

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

</style>

nếu hộp kiểm có id là 'XXX' thì nhãn sẽ được tìm thấy thông qua jQuery bằng cách:

$('#XXX + label');

Bạn cũng có thể áp dụng .find ('+ label') để trả về nhãn từ phần tử hộp kiểm jQuery, tức là hữu ích khi lặp:

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

Rất tiếc, tôi cần lưu ý rằng điều này phụ thuộc vào nhãn nằm ngay sau phần tử.
Gordon Rouse
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.