AppleScript Help: Wait for Safari Page to load

applescriptsafari

I am trying to create a script to open the URL csbsju.instructure.com in Safari, wait for the page to load all the way, click the login button, and then double check if the URL is correct (there's a bug that adds dashboard-sidebar, so I'm just checking the URL and if it's incorrect, redirecting the page.
The typing of credentials is handled by Safari's iCloud Password thing, so I don't need to worry about that.
The big issue I'm having is the waiting till page is loaded part. I've been looking around, and currently am attempting to use this code, although it does not work:

tell application "Safari"
    activate
    delay 1
    repeat
        if (do JavaScript "document.readyState" in document 1) is "complete" then exit repeat
        delay 1
    end repeat
    delay 1
end tell

I'm currently using this script to click the login button and check if the URL is correct:

tell application "Safari"
    set theURL to URL of front document



    tell front document
        do JavaScript "document.getElementById('btnLogin').click()"
    end tell

    set theURL to URL of front document
    if (theURL = "https://csbsju.instructure.com/dashboard-sidebar") then
        tell application "Safari" to set the URL of the front document to "https://csbsju.instructure.com"
    end if
end tell

Any suggestions on how to make this work better? Namely the checking if page is loaded part?

Best Answer

There are a few methods you could use to check whether the page has finished loading. Here are a selection that I've had good results with during testing:

Document name

Monitor for the existence of the Safari document that has the same name as the title of the webpage, which (I believe) only gets assigned after the page has finished loading, up until which point it retains the name it had previously, or "Untitled" if it's a newly created document:

tell application "Safari"
    make new document with properties {URL:"https://csbsju.instructure.com"}

    repeat until the document named ("Central Authentication Service " & ¬
        "| College of Saint Benedict & Saint John's University") exists
    end repeat

    log "Finished loading"
end tell

The Login button

Monitor for the existence of the "Login" button, given that you can't do what you need to do until that particular HTML element has been created:

tell application "Safari"
    make new document with properties {URL:"https://csbsju.instructure.com"}

    tell front document to repeat until (do JavaScript ¬
        "document.getElementById('btnLogin').id") as text is not ""
    end repeat

    log "Finished loading"
end tell

Safari's Reload button

Monitor particular properties of Safari's Reload button, which changes according to whether a page is loading or has loaded:

Note: This was written and tested under macOS High Sierra; however, for macOS Mojave one minor edit is required. Change UI element 1 to ¬ to UI element 2 to ¬ in the code directly below.

tell application "Safari" to ¬
    make new document with properties {URL:"https://csbsju.instructure.com"}

tell ¬
    application "System Events" to tell ¬
    process "Safari" to tell ¬
    window 1 to tell ¬
    toolbar 1 to tell ¬
    groups to tell ¬
    UI element 1 to ¬
    set reload_button to a reference to ¬
        (first button whose name is "Reload this page")

using terms from application "System Events"
    repeat until the accessibility description ¬
        of the reload_button ¬
        contains "Reload this page"
    end repeat
end using terms from

log "Finished loading"

Page content

Monitor for specific text to appear within the page content. In this case, I've chosen to monitor for all of it, but you can choose smaller elements instead. Items that appear towards the end of the page are most suitable:

tell application "Safari"
    make new document with properties {URL:"https://csbsju.instructure.com"}

    ignoring white space
        tell front document to repeat until its text contains ¬
            "Central Authentication Service Network Username: " & ¬
            "Password: Warn me before logging me into other sites. " & ¬
            "Copyright © 2017 - All Rights Reserved College of Saint " & ¬
            "Benedict and Saint John's University"
        end repeat
    end ignoring

    log "Finished loading"
end tell

Username & Password fields

Since these fields are getting filled out automatically by Safari's password manager—which only happens when the page has fully loaded—you can monitor the text content of the Username and Password fields:

tell application "Safari"
    make new document with properties {URL:"https://csbsju.instructure.com"}

    tell front document to repeat
        set a to (do JavaScript "document.getElementById('username').value") as text
        set b to (do JavaScript "document.getElementById('password').value") as text

        if length of (a & b) ≠ 0 then exit repeat
    end repeat

    log "Finished loading"
end tell