I've got a problem I've been stuck with for a while, sorry for spamming the forum a little.

Is there any way I can get an element by it's text content? Here's an example:

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

I'm trying to get the element by the text content which is 'Item | Anodized Navy'. Is it possible to do something like:

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

    item[0].click();
}

I know this doesn't exist, but it's just so you get the idea. Also, I cannot use by Id or classname, and I can't change the HTML code of the element, so it has to be done with the text content, I don't see another way.

I'd greatly appreciate any feedback,

Thanks!

有帮助吗?

解决方案 2

Well, since you tagged the question with , you could use the :contains selector:

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

Note, however, that this will return every element which contains that text, including the span and all the parent elements of the span. If you'd like to get just the inner-most element (assuming there is only one) just get the last item, like this:

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

To do the equivalent without using jQuery, you'd have to implement a function like this:

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

Or possibly like this, depending on exactly what you need:

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, []);
}

And then call this function like this:

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

Note also in your code, getelem needs to have () after the function name, like this:

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

其他提示

Even though jQuery exposes the :contains pseudo selector, it would be wise to restrict the results first by using the class where possible:

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

Narrowing down the initial set of tags to search through improves the performance, otherwise all tags would be considered; also, overlapping tags would match as well.

On more modern browsers you could consider this, based on 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();

Maybe I'm late in answering this, but I didn't see the question tagged with JQuery, so here's a pure JavaScript solution:

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

You want something like this

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

Output

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

On jsFiddle

Additional 1, as we talked about 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'));

On jsFiddle

Additional 2, as we talked about 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'));

On jsFiddle

Note that these solutions are the same but they are different to all the contains solutions given here. Because these solutions actually give you the nodes that have a matching text node as a child. The simple markup that I have used does not demonstrate this, but you will soon notice the difference when your markup is highly nested.

And finally here is a jsPerf of these 3 solutions.

You can simply use Jquery's :contains()

If you want to select all spans containing the text "mytext", use

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

Please mark as answer if I helped you.

Thank you :)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top