How to find and click link based on the letters/words it contains

448 Views Asked by At

I have this code that was working up until recently, not sure why, but I think it's because there are 2 links with the same class name.

This is how the code originally looked --

if (tweet[0].match(theName) == theName) {
      document.getElementsByClassName("twitter-timeline-link")[0].click();
        tFunction = "get outa here";
        theName = " 4444  4 456 7 8 456 7 345 7 345  345 3 1 1 133s "; //buffer to jump out of interval loop

    } 

This is how my code looks now, its part of a function that scans and refresh until variables are matched so that I can then click the link --

if (tweet[0].match(theName) == theName) {
        document.getElementsByClassName("twitter-timeline-link").find("a:contains('swoo.sh')").bind('click', function() {
            window.location.href = this.href;
            return false;
        }).trigger('click');
        tFunction = "get outa here";
        theName = " 4444  4 456 7 8 456 7 345 7 345  345 3 1 1 133s "; //buffer to jump out of interval loop

    } 

The problem is theres usually 2 links, and the wrong link ends up getting clicked, so Im looking for a way to match some of the text from the link (ie. swoo ) that I want it to click.

I was trying to use another code, but it required I inject jquery library (because of $) which I cant do/dont want to do cause its a chrome extension.

Any idea on how to fix it? Thanks

1

There are 1 best solutions below

17
On BEST ANSWER

Your second code-block uses jQuery anyway (in case you didn't notice).

Regarding your first code-block (and putting aside the fact that I have no idea what those tFunction and theName are for), you can modify it like this:

if (tweet[0].match(theName) == theName) {
    [].slice.call(document.querySelectorAll('a.twitter-timeline-link'))
      .some(function(elem) {
        if (elem.textContent.indexOf('swoo.sh') > -1) {
            elem.click();
            return true;
        }
        return false;
    });
    tFunction = ...;
    theName = ...;
} 

UPDATE:

Using the sample extension below, I was able to get my link clicked :) It reloads the page every second, until it finds the specified shoe-entry, then it looks for the correct link (containing 'swoo.sh') and clicks it.

UPDATE 2:

It turned out some dynamic DOM manipulation was causing inconsistent behaviour when there was a lag in the network-connection. I made some modifications in the code to take into account the element's attributes (which are unaffected by dynamic DOM element creation and offer increased consistency). In fact, I was not able to reproduce any sort of inconsistency after trying a dozen of times (which was not the case with the previous approach).

content.js:

var shoeName = ...;
var tweets = new Array();

function twitterScan() {

    tweets = [].slice.call(document.getElementsByClassName("js-tweet-text"));

    var targetLink = null;
    var foundTweet = tweets.some(function(tweet) {
        if (tweet.innerHTML.indexOf(shoeName) !== -1) {
            var foundLink = [].slice
                    .call(tweet.querySelectorAll('a.twitter-timeline-link'))
                    .some(function(el) {
                if (el.dataset.expandedUrl.indexOf('swoo.sh') !== -1) {
                    targetLink = el;
                    return true;
                }
                return false;
            });
            if (!foundLink) {
                alert('Found ' + shoeName + ', but couldn\'t find the link :(');
            }
            return true;
        }
        return false;
    });

    if (targetLink) {
        window.open(targetLink.href);
    } else if (!foundTweet) {
        location.reload(true);
    }
}

setTimeout(twitterScan, 1000);

manifest.json:

{
    "manifest_version": 2,

    "name":    "Test Extension",
    "version": "0.0",
    "offline_enabled": false,

    "content_scripts": [{
        "matches":    ["*://some.domain.com/*"],
        "js":         ["content.js"],
        "run_at":     "document_end",
        "all_frames": false
    }]
}