查找与给定输入关联的html标签


110

假设我有一个html表单。每个输入/选择/文本区域将具有一个对应<label>for属性,该属性设置为其同伴的ID。在这种情况下,我知道每个输入将只有一个标签。

给定javascript中的input元素(例如,通过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 };
艾伦·威尔斯

或只是node.parentNode.querySelector(“ label [for ='” + node.id +“']”)。innerHTML; 大声笑
所罗门·P·拜尔

Answers:


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
这应该由浏览器处理
-andho

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

HTML5标准中有一个labels属性,该属性指向与输入元素关联的标签。

因此,您可以使用类似的方法(支持本机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 2013年

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
乔什·哈布达斯

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
真好 我将对其进行一点重构,以便在我第一次调用该方法时构建查找,但是它应该可以解决问题。
Joel Coehoorn

我暗示您只会建立一次查询。
Tomalak

请注意,其中存在一个小错误:请使用“ htmlFor”属性,而不要使用“ for”属性,因为后者是JS中的保留字。我倾向于忘记使用标签对象时... :-)
Tomalak

我没有上面的查找数组就可以做到这一点。
FlySwat

我的意思是将初始化代码移动到方法内部,而不是只执行一次:(
Joel Coehoorn

13

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

这以最简单,最精简的方式回答了这个问题。这使用香草javascript,并且可以在所有主流主流浏览器上使用。


这不能为问题提供答案。一旦您拥有足够的声誉,您就可以在任何帖子中发表评论;相反,请提供不需要问询者澄清的答案。- 评论
loki

1
这绝对可以为@loki问题提供答案。仅仅因为没有进一步的解释,并不意味着它是错误的或没有尝试回答它。
geisterfurz007 '18

最简单有用的答案!谢谢!
iedmrc '19

8

用jQuery,你可以做类似的事情

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

尽管是祖先,但可能会丢失标签。
Alex

4

如果您愿意使用querySelector(并且甚至可以使用IE9,有时甚至是IE8!),那么另一种方法将变得可行。

如果您的表单字段具有ID,并且您使用了标签的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.labelsIE或Edge不支持它,而Firefox仅添加了支持。
Antti29年

@ Antti29您可以使用垫片添加功能:github.com/termi/ES5-DOM-SHIM你可以看到这里的功能被添加:github.com/termi/ES5-DOM-SHIM/blob/...
ADJenks

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

这有助于我使用其ID获得输入元素的标签。


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

javascript确实必须在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,或者是您不知道要查找哪个情况的情况


我知道输入元素的ID,但不知道标签的ID。
Joel Coehoorn

您是否不能为标签设置相应的ID,例如输入id ='test'和label id ='lbl_test”
Josh Mein


0

对于将来的搜索者...以下是FlySwat接受的答案的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]));   
        }
    }
}

使用:

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

+1,但从我的角度来看,没有理由在第一个块中使用jQuery版本:它不短也不可读,并且普通的javascript可能会表现更好。不过,最好有一个有关如何使用它的jQuery示例。
Joel Coehoorn

显然,对于我们许多人来说,这种方法并没有太多的技术原因,而是至少在我看来是人力资源的原因。想象一下,您有一个包括设计人员,集成人员甚至是Jr开发人员的团队,而您已经放慢了使用jQuery的速度。将事物保留在jQuery范式中可以帮助提高生产率并减少挫败感。
ObjectType

这不是jQuery风格的。为什么for循环过来each()?为什么要htmlFor代替attr("for")
alex 2013年

我猜取决于视角。消耗是基于jQuery的,而不是内部的。
ObjectType 2013年

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

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关系方法?

在样式表中,您可以从元素选择器中引用标签:

<style>

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

</style>

如果复选框的ID为“ XXX”,则可以通过jQuery通过以下方式找到标签:

$('#XXX + label');

您还可以应用.find('+ label')从jQuery复选框元素返回标签,即在循环时非常有用:

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

糟糕,我要注意,这依赖于紧随元素之后的标签。
Gordon Rouse
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.