0

I'm writing a Safari App Extension to automate logging into a Citrix web portal. My injected JavaScript needs to do two things. First, there is an HTML form to submit (with name/password). That works just fine and takes me to another page with an HTML anchor that needs to be clicked. The problem is that I am unable to programmatically click on the HTML anchor link.

// This is the `script.js` injected by my Safari App Extension

document.addEventListener("DOMContentLoaded", function(event) {


    if (document.URL.includes("IdentityFederationPortal")) {
        document.getElementById("UserId").value = "..." // my login
        document.getElementById("Password").value = "..." // my password
        document.getElementById("submit").click() // <- works correctly
    }

    // The `.click()` method above works just fine, I assume because it is used on a form button.


    if (document.URL.includes("TPDCWeb")) {

        var loginLink = document.querySelector("#plugin-assistance-download > div > div > div > div.footer > a.pluginassistant-skiplink.web-screen-link._ctxstxt_SkipToLogon._ctxsattr_title_SkipToLogonTip");

        console.log(loginLink) // console shows loginLink is assigned the correct HTML anchor

        loginLink.click() // does not work!
    }
});

Notes:

  1. The actual HTML for the anchor link I need to programmatically click on is: <a class="pluginassistant-skiplink web-screen-link _ctxstxt_SkipToLogon _ctxsattr_title_SkipToLogonTip" href="#" title="Click here to skip to log on">Log on</a> I am not familiar enough with web programming to understand what is happening when a regular user clicks on that link, which by simple inspection doesn't seem to lead anywhere (and has a NULL onClick property).

  2. I've seen scattered references suggesting that jQuery might be useful here, but I also can't figure out how to inject jQuery into a Safari App Extension script. My attempts so far lead to the Can't find variable $ error when I try to use jQuery.

  • I'll start by saying jQuery is pretty much obsolete in 2020, if it can't be done in vanilla JS, jQuery probably won't help. Secondly, have you tried just running sandboxed JS on the site to see if executing `click` on that button works? Sure actually clicking it as a user works, but a website could have a few different mechanisms for handling clicks (take for example map tags and areas, though I doubt this is the case), so it may be worth it just to check and see if using JS to click the button within the Dev Tools console even works. – gabriel.hayes Jan 24 '20 at 17:38
  • Sorry, I absolutely should have mentioned that. Using the JavaScript console in Safari, I can get the HTML anchor link object using the same ‘document.querySelector’ syntax as in my code above—and then (again, typed at the JS console) ‘loginLink.click()’ works perfectly and does exactly what I want the script to do. I will add this into my question. – Christopher Monsour Jan 24 '20 at 17:44
  • 1
    Based on the markup you posted in your question, that anchor tag doesn't have a link, which means some JS is probably providing it an onclick handler (or some eventListener; and yes this may be possible even if onclick is null or undefined; this is always the case with Vue apps with clickable elements). Maybe you just need to wait for the page to be hydrated before clicking it? I imagine when the DOM Content is loaded the JS on the site probably hasn't finished initializing. – gabriel.hayes Jan 24 '20 at 17:46
  • Ah, such a simple solution. Thanks. I put my link-clicking code in a setTimeout block and now it works great. I'll need to read up on a better way to verify the JS has all been initialized before executing my code. – Christopher Monsour Jan 24 '20 at 17:52
  • No problem! Yeah, with the rise of SPAs nowadays, awaiting page hydration is very important when interacting with an external website. – gabriel.hayes Jan 24 '20 at 17:55

1 Answers1

0

With the help of user1538301 I now have this working, just by delaying the .click() method invocation by 4 seconds. As was pointed out, presumably I was trying to 'click' the link before the page's own JavaScript had finished its business and assigned an onclick handler or some such. I'm sure there's a more elegant way to deal with this, but the simple time delay gets the job done for me for now.

if (document.URL.includes("TPDCWeb")) {

    function getAndClickLink() {
        var loginLink = document.querySelector("#plugin-assistance-download > div > div > div > div.footer > a.pluginassistant-skiplink.web-screen-link._ctxstxt_SkipToLogon._ctxsattr_title_SkipToLogonTip");

        loginLink.click()
    }

    setTimeout(getAndClickLink, 4000);


}