Wait for a page to finish loading in Safari

This has probably been discussed numerous times here before, but I thought I’d throw up my handler for it that I believe is flawless, (though it may have excess code?).

on finishLoad()
	tell application "System Events"
		tell process "Safari"
			set x to 1
			repeat
				delay 1
				repeat until value of static text 1 of group 1 of window 1 is "" --Done Loading
					delay 1
					set x to (x + 1)
					if x > 19 then --20sec Idle
						click menu item "Reload Page" of menu 1 of menu bar item "View" of menu bar 1 --Refresh
						set x to 1
						exit repeat
					end if
				end repeat
				if value of static text 1 of group 1 of window 1 is "" then exit repeat
			end repeat
		end tell
	end tell
end finishLoad

The gist of it is the 1 second delay to give Safari a chance to start loading said page so the static text actually says something. Then it just repeat until said static text is “” a.k.a the page is done loading. Then on that rare occasion when for whatever reason, the page hangs while loading, rather than timeout, I have it count to 20 and then refresh the page if the page has not finished loading yet because 20 seconds should be plenty of time for any page.

In the script I use this on, it happens often enough that I deemed it necessary to do something to prevent the timeouts. If interested in said script, I can start another topic. My girlfriend basically wanted me to make a script for her to automate logging into accounts on Gaia Online and collecting the Daily Rewards on each of the main pages. Other than being a tad slow at a certain point in the script due to Safari whoring my cpu… I believe the script is flawless GUI scripting. :slight_smile: It hasn’t broken once yet. Anyways, glad I could share something of use.

Model: 1.67 GHz PowerPC G4 Powerbook
AppleScript: Version 2.2.1
Browser: Camino Version 2.0b3
Operating System: Mac OS X (10.5)

Hi.

Safari’s AppleScript implementation allows JavaScript code to be applied to Safari documents, which would be preferable to GUI Scripting. Your handler could then look something like this, though I haven’t actually soak-tested it:

on finishLoad()
	tell application "Safari"
		delay 1
		set x to 0
		repeat until ((do JavaScript "document.readyState" in front document) is "complete")
			set x to x + 1
			if (x mod 20 is 0) then do JavaScript "window.location.reload()" in front document
			delay 1
		end repeat
	end tell
end finishLoad

Real JavaScript experts could probably render the whole of the repeat as one piece of JavaScript code. :rolleyes:

I guess you didn’t notice, but both my script and Nigel’s reload the page after 20 seconds. That’s what the counting to 20 with x is. All you gotta do is say if x = 20 then reload and set y to y + 1 if y = 2 then reset modem. Pretty simple.

I deleted the above post because I should not have posted a simple query in Code Exchange forum. ( i had landed on this thread through google and so I did not check the name of the forum).
Thanks, Sk8.4.Life for the reply. I have moved the post and edited the handler here: http://macscripter.net/viewtopic.php?pid=117165#p117165

In Safari 4 the javascript method Nigel posted doesn’t work for me. I get many false positives. I like the method Sk8.4.Life posted. I would make one change to it though. If you feed a bad url to safari you get a page titled “Failed to open page”. Sk8.4.Life method tells you that the page loaded properly when this happens. I modified the method to let you know that there was an error when this happened or when the page times out or when there are any other errors.

I also modified the way the handler checks for the timeout.

-- Note: "access for assistive devices" in the "Universal Access" system preference must be enabled for this to work

set loadStatus to safariWebPageLoaded(10)
if loadStatus is not true then display alert "There was an error:" message loadStatus as warning

on safariWebPageLoaded(waitTime) -- waitTime is the time in seconds the script will wait to let a web page load
	set myDelay to 0.5 -- the time in seconds you wait between checks for the web page loaded status
	set loadStatus to "There was an error when checking the load status!"
	
	try
		-- calculate the endTime... the time when you will stop waiting for the page to finish loading
		set endTime to (current date) + waitTime
		
		-- repeat until either the web page is loaded or the endTime is reached
		tell application "System Events" to tell process "Safari"
			repeat
				delay myDelay
				if (name of window 1) is "Failed to open page" then
					set loadStatus to "The url for the current web page is bad!"
					exit repeat
				else if (value of static text 1 of group 1 of window 1) is "" then
					set loadStatus to true
					exit repeat
				end if
				
				if (current date) is greater than endTime then
					set loadStatus to "The web page could not load in the allotted time!"
					exit repeat
				end if
			end repeat
		end tell
	on error theError
		set loadStatus to theError
	end try
	return loadStatus
end safariWebPageLoaded