有没有办法通过文本内容获取元素?

问题描述 投票:0回答:6
javascript click getelementbyid tampermonkey
6个回答
3
投票

尽管 jQuery 公开了

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

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

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

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

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

但请注意,这将返回包含该文本的 every 元素,包括

span
和跨度的所有父元素。如果您只想获取最里面的元素(假设只有一个),只需获取最后一项,如下所示:

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

要使用 jQuery 实现等效的 without,你必须实现这样的函数:

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

2
投票

也许我回答这个问题晚了,但我没有看到用 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;
}

2
投票

你想要这样的东西

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


0
投票

您可以简单地使用Jquery的

:contains()

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

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

如果对您有帮助,请标记为答案。

谢谢你:)


0
投票

对于我的用例,我编写了一些简单的版本。

:not(has(*))
对于防止父母的出现很有用。

function getElementsByText(root, text, selector = 'div:not(:has(*))') {
  const els = [...root.querySelectorAll(selector)];
  return els.filter(el => el.innerText == text);
}
© www.soinside.com 2019 - 2024. All rights reserved.