【问题标题】:Is there any way to getElementBy the text content?有什么办法可以通过文本内容获取元素?
【发布时间】:2014-02-14 22:52:53
【问题描述】:

我有一个问题困扰了我一段时间,抱歉给论坛发了一点垃圾邮件。

有什么方法可以通过文本内容获取元素?这是一个例子:

<span id="result_5_name" class="market_listing_item_name" style="color: #FFD700;">Item | Anodized Navy</span>

我正在尝试通过文本内容获取元素,即 'Item |阳极氧化海军'。 是否可以做类似的事情:

function getelem {
    var item = document.getElementsByTextContent('Item | Anodized Navy');

    item[0].click();
}

我知道这不存在,但这只是为了让你明白这一点。另外,我不能通过Id或类名使用,也不能更改元素的HTML代码,所以必须用文本内容来完成,我没有看到其他方式。

非常感谢任何反馈,

谢谢!

【问题讨论】:

  • 您需要获取文本节点的内容并将它们与您所需的字符串进行比较。然后你可以选择你想要的父节点。

标签: javascript click getelementbyid tampermonkey


【解决方案1】:

尽管 jQuery 公开了 :contains 伪选择器,但明智的做法是在可能的情况下首先使用类来限制结果:

$('.market_listing_item_name:contains("Item | Anodized Navy")')

缩小要搜索的初始标签集可以提高性能,否则将考虑所有标签;此外,重叠的标签也会匹配。

在更现代的浏览器上,您可以考虑这一点,基于this answer

function contains(selector, text) {
    var elements = document.querySelectorAll(selector);
    return [].filter.call(elements, function(element) {
        var contents = element.textContent || element.innerText || '';
        return contents.indexOf(text) != -1;
    });
}

var items = contains('.market_listing_item_name', 'Item | Anodized Navy')

items[0] && items[0].click();

【讨论】:

    【解决方案2】:

    好吧,既然你用 标记了这个问题,你可以使用:contains 选择器:

    var item = $(':contains(Item | Anodized Navy)');
    

    但是请注意,这将返回包含该文本的 每个 元素,包括 span 和 span 的所有父元素。如果您只想获取最里面的元素(假设只有一个),只需获取最后一项,如下所示:

    var item = $(':contains(Item | Anodized Navy)').last();
    

    要使用 jQuery 实现等价的 ,您必须实现如下函数:

    function getElementsByText(text) {
        var spans = document.getElementsByTagName('span'),
            results = [];
        for(var i = 0; i < spans.length; i++) {
            var content = spans[i].textContent || spans[i].innerText || '';
            if (content.indexOf(text) != -1)
                results.push(spans[i]);
        }
        return results;
    }
    

    或者可能像这样,具体取决于您的需要:

    function getElementsByText(text) {
        function rec(ele, arr)
        {
            if (ele.childNodes.length > 0) 
                for (var i = 0; i < ele.childNodes.length; i++) 
                    rec(ele.childNodes[i], arr);
            else if (ele.nodeType == Node.TEXT_NODE && 
                     ele.nodeValue.indexOf(text) != -1) 
                arr.push(ele.parentNode);
            return arr;
        }
        return rec(document.body, []);
    }
    

    然后像这样调用这个函数:

    var item = getElementsByText('Item | Anodized Navy');
    

    还要注意在您的代码中,getelem 需要在函数名称后加上 (),如下所示:

    function getelem() {
        var item = getElementsByText('Item | Anodized Navy');
        ...
    }
    

    【讨论】:

    • 非常感谢,这是迄今为止最好的评论!你知道没有 jQuery 的任何方法吗?因为我认为 tampermonkey 支持 jQuery,但它看起来不支持所以我只使用 javascript 现在它看起来像它,除非我可以导入 jQuery 库或其他东西?
    • 非常感谢您的努力,非常感谢!在给你最好的答案之前,我有一个最后的问题^^:我用项目替换(文本)吗?阳极氧化海军?我的意思是我是一个完全的菜鸟,所以我不清楚在哪里引用代码中的项目:) 另外,我指的是什么来点击它?我使用 spans[0].click 吗?再次感谢
    • @user3302404:不起作用 === 最完整? ...无论如何,如果您在 Firefox 中进行测试,它将无法正常工作,因为 FF 不支持.innerText。根据您支持的浏览器,使用spans[i].textContent.indexOf(...(spans[i].textContent || spans[i].innerText).indexOf(...
    • @cookiemonster 啊谢谢。我已经忘记了。更新为更兼容跨浏览器。
    • 现在,如果 span 的 .textContent 是一个空字符串,它将使用 .innerText 可能是 undefined :) 如果发生这种情况,您需要 .textContent || .innerText || ''
    【解决方案3】:

    也许我回答得晚了,但我没有看到用 JQuery 标记的问题,所以这里有一个纯 JavaScript 解决方案:

    var myID = getElementsByTextContent('Item | Anodized Navy');
    
    function getElementsByTextContent (elText){
        var spanID;
        var allSpans = document.getElementsByTagName("span"); 
        for (var i = 0; i < allSpans.length; i++) { 
            var spanText = allSpans[i].innerHTML;
            if(spanText == elText ){
                spanID = allSpans[i].id;
            }
        }
        return spanID;
    }
    

    【讨论】:

    • OP 稍后编辑了问题以删除 jquery 标记:)
    【解决方案4】:

    你想要这样的东西

    HTML

    <span id="result_5_name" class="market_listing_item_name" style="color: #FFD700;">Item | Anodized Blue</span>
    <span id="result_6_name" class="market_listing_item_name" style="color: #FFD700;">Item | Anodized Navy</span>
    <span id="result_7_name" class="market_listing_item_name" style="color: #FFD700;">Item | Anodized Red</span>
    <span id="result_8_name" class="market_listing_item_name" style="color: #FFD700;">Item | Anodized Green</span>
    <span id="result_9_name" class="market_listing_item_name" style="color: #FFD700;">Item | Anodized Navy</span>
    

    Javascript

    function walkTheDOM(node, func) {
        func(node);
        node = node.firstChild;
        while (node) {
            walkTheDOM(node, func);
            node = node.nextSibling;
        }
    }
    
    function getElementsByText(node, text) {
        var results = [];
    
        walkTheDOM(node, function (currentNode) {
            if (currentNode.nodeType === 3 && currentNode.nodeValue === text) {
                results.push(currentNode.parentNode);
            }
        });
    
        return results;
    }
    
    console.log(getElementsByText(document, 'Item | Anodized Navy'));
    

    输出

    [span#result_6_name.market_listing_item_name, span#result_9_name.market_listing_item_name]
    

    开启jsFiddle

    附加 1,正如我们谈到的 treeWalker

    function getElementsByText(node, text) {
        var results = [],
            treeWalker = document.createTreeWalker(
            node,
            NodeFilter.SHOW_TEXT, {
                acceptNode: function (node) {
                    return NodeFilter.FILTER_ACCEPT;
                }
            }, false);
    
        while (treeWalker.nextNode()) {
            if (treeWalker.currentNode.nodeValue === text) {
                results.push(treeWalker.currentNode.parentNode);
            }
        }
    
        return results;
    }
    
    console.log(getElementsByText(document, 'Item | Anodized Navy'));
    

    开启jsFiddle

    附加 2,正如我们谈到的 getElementsByTagName('*')

    function getElementsByText(node, text) {
        var results = [],
            tags = node.getElementsByTagName('*'),
            tagsLength = tags.length,
            tagsIndex,
            currentTag,
            childNodes,
            childNodesLength,
            ChildNodesIndex,
            currentChildNode;
    
        for (tagsIndex = 0; tagsIndex < tagsLength; tagsIndex += 1) {
            currentTag = tags[tagsIndex];
            childNodes = currentTag.childNodes;
            childNodesLength = childNodes.length;
            for (ChildNodesIndex = 0; ChildNodesIndex < childNodesLength; ChildNodesIndex += 1) {
                currentChildNode = childNodes[ChildNodesIndex];
                if (currentChildNode.nodeType === 3 && currentChildNode.nodeValue === text) {
                    results.push(currentTag);
                }
            }
        }
    
        return results;
    }
    
    console.log(getElementsByText(document, 'Item | Anodized Navy'));
    

    开启jsFiddle

    请注意,这些解决方案是相同的,但与此处给出的所有contains 解决方案不同。因为这些解决方案实际上为您提供了具有匹配文本节点的节点作为子节点。我使用的简单标记没有说明这一点,但是当您的标记高度嵌套时,您很快就会注意到差异。

    最后是这 3 个解决方案中的 jsPerf

    【讨论】:

    • 为此,document.getElementsByTagName('*') 将使代码更简单。
    • 是的,我在这个演示中使用了非常简单(非嵌套)的标记。我会很乐意让你演示一下吗?我本可以使用treeWalker,但这段代码是跨浏览器的。
    • 使用getElementsByTagName('*')也是跨浏览器:)
    • 我并不是说它不是。 :)
    • 我没说你做过 :) 我的意思是很少需要滚动你自己的遍历代码。
    【解决方案5】:

    你可以简单地使用Jquery的:contains()

    如果要选择包含文本“mytext”的所有跨度,请使用

    var elements=$('span:contains("mytext"));
    

    如果我帮助了你,请标记为答案。

    谢谢你:)

    【讨论】:

      猜你喜欢
      • 2011-02-14
      • 2021-01-13
      • 2019-02-14
      • 2011-03-20
      • 1970-01-01
      • 2016-05-18
      • 1970-01-01
      • 2019-09-28
      • 1970-01-01
      相关资源
      最近更新 更多