【问题标题】:How to get Label without htmlFor with Javasript?如何使用 Javascript 获取没有 htmlFor 的标签?
【发布时间】:2020-10-21 17:56:27
【问题描述】:

我有一个网站正在 iFrame 中加载帮助台表单。 10 个输入有 10 个标签。其中 8 个有一个 htmlFor 和一个“控制标签”类。其中一个有一个没有类名的 htmlFor。一个类名为“control-label”,没有 htmlFor。

我需要使用 JavaScript 来获取最后一个标签并添加一个 htmlFor。但是,我不能抓住它。

var labels = document.getElementsByTagName('label') 

这将返回一个包含 9 个标签的 HTML 集合,这些标签都具有 htmlFor。它不包括没有 htmlFor 的第 10 个标签。但是,如果我运行:

console.log('Labels: ', labels); 

这将显示 10 个标签的列表,但是当我尝试定位第 10 个标签时,它将返回未定义。

var controlLabels = document.getElementsByClassName('control-label') 

这将返回一个包含 8 个标签的 HTML 集合,这些标签都具有 htmlFor。它不包括没有 htmlFor 的第 9 个标签。

var labels = [];
for (var i = 0; i < document.getElementsByTagName.length; i++) {
    labels.push(document.getElementsByTagName[i]);
}

这得到了一个包含 9 个对象的数组,但同样,不是没有 htmlFor 的标签。

var controlLabels = [];
for (var i = 0; i < document.getElementsByClassName('control-label').length; i++) {
    controlLabels.push(document.getElementsByClassName('control-label')[i]);
}

这让我得到了一个包含 8 个标签的数组,同样没有缺少 htmlFor 的标签。

我需要获取最后一个标签,但是当我运行 document.getElementsByX 时,它会得到一个 HTML 集合而不是数组。如何返回所有标签的数组,而不是 HTML 集合,以便我可以定位此标签?

这是 HTML 中的确切代码行:

<label class="control-label">Zip Code * </label>

【问题讨论】:

  • 能否包含表单的完整 HTML?另外,您是否尝试在 iframe 中执行此操作?另外,在setTimeout(() =&gt; {}, 1000) 中执行查询选择器代码的结果是什么?我想知道是否可能在其他字段之后加载没有 for 的字段。
  • 是的,小部件在 iFrame 中加载,尽管代码是在 iFrame 底部注入的。添加 setTimeout 现在正在修复它,因为您是正确的,最终标签正在其他字段之后加载。
  • 哦,太好了。我会发布一个答案。
  • 我发布了一些解决方案的答案。

标签: javascript html


【解决方案1】:

问题可能是您所定位的表单元素/标签是在其他元素之后加载的。为了确定是否是这种情况,您可以尝试以下操作:

const labels = document.getElementsByTagName('label')
console.log("before", labels)

setTimeout(() => {
  const labels = document.getElementsByTagName('label')
  console.log("after", labels)
}, 1000)

如果额外的标签出现在setTimeout 中,那么您将知道该标签是在其他标签之后加载的。

只是将您的代码放入setTimeout 并不是一个好的长期解决方案。问题是您不知道何时添加元素。所以你要么等待太久才能运行你的代码,要么等待的时间不够长。

另一种方法是使用MutationObserver 之类的东西。您可以使用它在表单的 DOM 更改时触发事件,然后查找您的标签。此代码未经测试,但可能会起作用:

const targetNode = document.getElementById('your-form-id');

// Options for the observer (which mutations to observe)
const config = { attributes: true, childList: true, subtree: true };

// Callback function to execute when mutations are observed
const callback = function(mutationsList, observer) {
    const labels = targetNode.querySelectorAll('label')

    // look for your label with a missing for attribute
};

// Create an observer instance linked to the callback function
const observer = new MutationObserver(callback);

// Start observing the target node for configured mutations
observer.observe(targetNode, config);

如果问题是在您运行代码时您的页面尚未完全加载,您可以等到页面的 DOM 加载完毕后再运行您的代码:

window.addEventListener('DOMContentLoaded', () => {
  const labels = document.getElementsByTagName('label')
  console.log(labels)
});

如果元素仍未显示,请尝试侦听 load 事件而不是 DOMContentLoaded

在任何一种情况下,您都应确保您的标签在加载文档时始终可用。如果在加载文档后第三方代码正在创建元素,则等待loadDOMContentLoaded 将无法可靠地工作。你可能想使用 MutationObserver。

【讨论】:

    【解决方案2】:

    没有 htmlFor 属性。您应该在输入的标签元素上放置一个“for”属性。然后浏览器和辅助技术将标签与输入相关联。

    例如,您可以点击单选按钮的标签来切换检查状态。

    但听起来你需要一个 CSS 选择器。所以使用属性选择器语法:

    document.querySelector("[for='your-input-id']")
    

    【讨论】:

    • htmlFor 是您在 JS 中访问 for 属性的方式,因为 for 是 JS 中的保留字。例如。 el.htmlFor(你不能使用el.for访问它)
    • 另外,OP 想要获取元素 without a for 属性。
    • 但是您正在使用 CSS 选择器语法选择元素,而不是访问属性值。同样,不是属性。当您将元素作为 JS 中的变量时,该属性将映射到 htmlFor。但在您的 HTML 中,它是“for”,这就是您在 CSS 中选择它的方式。
    • 是的,没有 ID,也没有 'for=""',所以我很难抓住它。它会在我执行 document.getElementsByTagName('label') 时显示,它包含在列表中,但不包含在 HTML 集合中,因此我无法通过 HTML 集合定位它。
    • 对,您没有指定属性。您需要指定一个 for 属性,并且该值应映射到相应输入的 id。否则,您只是添加一个自定义属性,选择器语法将起作用,但它不会添加任何语义值。
    【解决方案3】:

    您可以改用querySelectorAll

    _labels = document.querySelectorAll("label");
    _labels.forEach(function(e) {
      console.log(e)
    });
    <input type="text" id="tet">
    <label For="tet">test</label>
    <label>testa</label>
    <label class="control-label">Zip Code * </label>

    【讨论】:

    • 这会返回一个包含 9 个对象的 NodeList,除了没有 htmlFor 的那个之外,它们都是标签。
    • @JasonBoyce 作为一个测试,你能从 HTML 中去掉标签,然后在 sn-p 或小提琴中运行吗?
    • 我创建了一个只有 2 个标签的 jsfiddle,一个带有 htmlFor,一个没有,getElementsByTagName 抓住了这两个标签并允许我抓住一个没有 htmlFor 的标签,所以我不知道发生了什么我正在处理的页面。我怀疑这可能与它在页面加载时从 JavaScript 生成 HTML 的事实有关。
    【解决方案4】:

    感谢@Cully 提供此提示。

    function myFunction() {
        var labels = document.getElementsByTagName('label');
        var label = labels[labels.length -1];
        label.htmlFor = "id_zipcode";
    }
    
    $(document).ready(function() {
        setTimeout(myFunction, 1000);
    });
    

    添加超时允许第三方 JavaScript 完成生成 HTML 并为我提供一个可以使用 getElementsByTagName 定位的标签

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-10
      • 1970-01-01
      • 2015-08-29
      • 1970-01-01
      相关资源
      最近更新 更多