Click Button on Web Page

I have a slightly newer version of the above script.

I made a few changes, but the biggest is adding a repeat loop.
Sometimes when making a new tab in safari, the page isn’t finished fully loaded when the script tries to find the Email & Password fields, so it doesn’t find one or both.
The repeat loop catches this and tries again. EDIT fixed repeat loop so its not infinite

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
-- https://www.dividend.com/login/?redirect_url=/login

property myURL : "https://www.dividend.com/login/?redirect_url=/login"
property eNames : {"Robert", "Mark", "Steven", "Joseph", "Anthony", "Edward", "James", "Ethan", "Henry", "Carlos", "Noah", "Arthur", "Louis", "Zachary", "Thomas", "Alexander", "Jacob", "Vincent", "Dylan", "William", "Jack", "Samuel", "Andrew", "Gabriel", "Benjamin", "Lawrence", "Christopher", "Matthew", "George", "Nicholas", "Daniel", "Nathan", "Peter", "Paul", "Harold", "Adam", "Charles", "Aaron", "Kenneth", "Walter", "Patrick", "Philip", "Austin", "Jesse", "Ryan", "Bruce", "Albert", "Michael", "Eugene", "David", "Eric", "Jonathan", "Frank", "Paul", "Jason", "Brian", "Richard", "Jordan", "Keith", "Kevin", "Russell", "Roger", "Jeremy", "Justin", "Timothy", "Greg", "Alan", "Brandon", "Tyler", "Scott", "Wayne", "Jeffrey", "Dennis", "Douglas", "Roy", "Sean", "Carl", "Ronald", "Donald", "Gerald", "Gary", "Randolph", "Terry"}

on run
	local myApp, myTab, myURLs, UIElements, subElements, loginPane, anElement, anItem, i, stack, uname, flag, emailFlag, pwdFlag, tmp
	tell application "Safari"
		if it is not running then activate it
		set tmp to windows
		if (count tmp) = 0 then -- Safari is running but has no windows
			make new document
			set myTab to current tab of window 1
			set URL of myTab to myURL
			--delay 0.5
		else
			set myURLs to URL of tabs of window 1
			if myURL is in myURLs then -- check to see if one of it's tabs already has the URL
				repeat with i from 1 to count myURLs
					if (item i of myURLs) = myURL then
						exit repeat
					end if
				end repeat
				if current tab of window 1 ≠ tab i of window 1 then set current tab of window 1 to tab i of window 1
			else -- no tab or window with URL was found
				if (source of current tab of window 1) = "" then -- empty page found, so load URL
					set myTab to current tab of window 1
				else -- no empty window found, so create a new tab
					set myTab to (make new tab at window 1)
					set current tab of window 1 to myTab
				end if
				set URL of myTab to myURL
			end if
		end if
		set flag to true
		repeat 50 times
			if (name of window 1) = "Login - Dividend.com - Dividend.com" then
				set flag to false
				exit repeat
			end if
			delay 0.2
		end repeat
	end tell
	if flag then return false
	tell application "System Events"
		set myApp to application process "Safari"
		repeat 3 times
			set emailFlag to false
			set pwdFlag to false
			set subElements to groups of toolbar 1 of window 1 of myApp -- test if page done loading
			repeat with i in subElements -- find group in toolbar that has 'Reload' button
				set tmp to contents of i
				if exists (button "Add page to Reading List" of tmp) then exit repeat
			end repeat
			tell tmp
				repeat until exists button "Reload this page" --accessibility description
					delay 0.2
				end repeat
			end tell
			
			set flag to false
			repeat until flag
				try
					window 1 of myApp
					set anElement to UI element 1 of scroll area 1 of group 1 of group 1 of tab group 1 of splitter group 1 of window 1 of myApp
					--get anElement
					set flag to true
				on error --errMsg number errNum
					set anElement to missing value
					delay 0.2
				end try
				if anElement = missing value then set flag to false
			end repeat
			set flag to false
			repeat until flag
				try
					set subElements to groups of anElement whose subrole is "AXLandmarkMain"
					--get subElements
					set flag to true
				on error --errMsg number errNum
					beep 1
				end try
				if (subElements = missing value) or ((count subElements) = 0) then set flag to false
				if flag then
					set loginPane to item 1 of subElements
					try
						set subElements to groups of loginPane whose subrole is not "AXEmptyGroup"
					on error
						set flag to false
					end try
					if (count subElements) = 0 then set flag to false
					if not flag then tell me to delay 0.2
				end if
			end repeat
			try
				repeat with i in subElements -- finds the Email group
					set i to contents of i
					if (static text 1 of i) exists then
						if (value of static text 1 of i) = "Email" then
							set anItem to text field 1 of i
							set focused of anItem to true
							tell me to delay 0.2
							set tmp to value of anItem
							set uname to tmp
							repeat while uname = tmp
								set uname to some item of eNames
							end repeat
							set value of anItem to uname --"Robert"
							set emailFlag to true
							set focused of anItem to true --text field 1 of i to true -- screen refreshes to remove 'This field is required' notice (if there is one)
							tell me to delay 0.2
							exit repeat
						end if
					end if
				end repeat
			end try
			if emailFlag then -- do Password only if Email is done
				try
					set subElements to groups of loginPane whose subrole is not "AXEmptyGroup"
					repeat with i in subElements -- finds the Password group
						set i to contents of i
						if (static text 1 of i) exists then
							if (value of static text 1 of i) = "Password" then
								set anItem to text field 1 of i
								set focused of anItem to true
								tell me to delay 0.2
								set value of anItem to my getPWD() --"mypwd"
								set pwdFlag to true
								exit repeat
							end if
						end if
					end repeat
				end try
			end if
			if pwdFlag then exit repeat -- both fields found, so continue on
		end repeat
		
		if pwdFlag then
			repeat with i in subElements -- finds the Login button
				set i to contents of i
				if (button "Log in" of i) exists then
					tell button "Log in" of i to perform action "AXPress"
					exit repeat
				end if
			end repeat
		end if
	end tell
end run

on getPWD()
	local pwd, c
	set pwd to ""
	set c to random number from 6 to 12
	repeat with i from 1 to c
		set pwd to pwd & some character of "abcdeefghijklmnopqrstuvwxyz!#$%^*-+?~"
	end repeat
end getPWD

I would try something like this (but, since I don’t have access to the actual page, I can’t verify it will work).

set theClass to "t-text-sm"
set elementNumber to 0

set theScript to JSForGetInputByClass(theClass, elementNumber)
set scriptResult to JavaScriptInSafari(theScript)

to JSForGetInputByClass(theClass, num)
	return " document.getElementsByClassName('" & theClass & "')[" & num & "].innerHTML;"
end JSForGetInputByClass

on JavaScriptInSafari(theScript)
	my WaitUntillSafariPageIsLoaded()
	tell application "Safari"
		activate
		set safariJSScriptResults to do JavaScript " " & theScript in current tab of window 1
	end tell
end JavaScriptInSafari

on WaitUntillSafariPageIsLoaded()
	try
		tell application "Safari"
			tell current tab of window 1
				repeat until the length of (get the source as text) is not 0
					delay 0.1
				end repeat
				return "Complete"
			end tell
		end tell
	end try
end WaitUntillSafariPageIsLoaded

Ed thank u again but this did not work but that could be because I described the problem badly.

My log in details for Dividend.com are user mitchbvi@mac.com PW Div10182022#. from the log in this page should open https://www.dividend.com/premium/ at the bottom select “Best Dividend Capture stocks” which is under the heading tools. From there the 1st script below opens the page with “Ex-div Date” on it.

The 2nd script shows the loop which is set to a max of 4 but that could change and the way I know I am in the correct place is to get the name in the last line of the quote below “Ex-div Date”. I hope this makes sense

--Based on Ed Stockly advise this opens the 2nd page which containes Ex-div date , Dec Date etc
set theClassName to "mp-page-filter-all-filter-button mp-page-filter-all-filter-button__on_page 12"
set the elementNumber to 0
set theScript to JSForClickByClassName(theClassName, elementNumber)

tell application "Safari"
	activate
	set safariJSScriptResults to do JavaScript " " & theScript in current tab of window 1
end tell

to JSForClickByClassName(theClassName, elementNumber)
	log elementNumber
	return " document.getElementsByClassName('" & theClassName & "')[" & elementNumber & "].click();"
end JSForClickByClassName

--Source Ed Stockly
set theClassName to "t-py-3 t-mr-2 t-mb-2 t-w-max t-px-3 t-text-black hover:t-bg-mitre-gray-200 t-text-sm t-flex t-items-center t-relative t-min-w-150 t-justify-between"

set the elementNumber to 0
repeat 4 times
	set theScript to JSForClickByClassName(theClassName, elementNumber)
	tell application "Safari"
		activate
		set safariJSScriptResults to do JavaScript " " & theScript in current tab of window 1
	end tell
	set elementNumber to elementNumber + 1
end repeat

to JSForClickByClassName(theClassName, elementNumber)
	return " document.getElementsByClassName('" & theClassName & "')[" & elementNumber & "].click();"
end JSForClickByClassName

This is kind of a complex page. Explain what you want to do via the user interface. (Which buttons or links to click, what to click and hold, what values to enter or get) and I’ll see if I can help.

Hi Ed

On that page I first need to set the start and end dates .

Clicking on the “Ex-div Date” box produces another menu with start and end dates. Unfortunately it does not allow the operator to type in the date but they must be select it from the calendars that drop down when clicked. My present GUI code select the current date as the start and then 7 days later for the end date.

Then I click the apply filters box which is at the bottom of that page. That obviously goes back to the page it was opened from and next to the filter icon is a download icon which has to be clicked and that downloads the data as a CSV file which I have further GUI code to process the results.

So far I have not addressed either “Recovery” or “Frequency” in my GUI approach but I would like to set the days to recovery and select the frequency of payments .

Thanks once again for all your help.

Peter

PS The following subroutine shows how I set the dates using GUI

on NewStocks()
	log "In NewStocks"
	set {TodaysDate, Date1, cnt, Cnt2, CheckSYM, GrpNo} to {day of (current date), "", 0, 0, "", 20}
	tell application "System Events" to tell process "Safari"
		--Open "All Filters" box so dates can be set
		set RefEnd to UI element 1 of scroll area 1 of group 1 of group 1 of tab group 1 of splitter group 1 of window 1
		repeat until CheckSYM is "Stocks"
			set GrpNo to GrpNo + 1
			try --Using "Stocks" as the button has a name and the filter button does not
				set CheckSYM to get name of button 1 of group GrpNo of RefEnd
			end try
			delay 0.25
		end repeat
		delay 2
		click button 2 of group GrpNo of RefEnd --"All Filters" icon. 
		delay 2 --Need find way to check the box "All Filters" is open
		set CheckName to ""
		repeat with cnt from 10 to 50
			set CheckName to name of button cnt of group GrpNo of RefEnd --Ex Div Date
			if CheckName is "Ex-div Date" then exit repeat
		end repeat
		click button cnt of group GrpNo of RefEnd --Ex Div Date
		repeat with cnt from 175 to 250 --Open the From Calendar
			try
				click text field 1 of group cnt of group GrpNo of RefEnd --opens From calendar
				exit repeat
			end try
		end repeat
		--the "From" Date	
		repeat with Cnt3 from 20 to 45 --get major group no
			try
				set Date1 to value of static text 1 of group 1 of group 1 of group 9 of group Cnt3 of RefEnd --The Date
				exit repeat
			end try
		end repeat
		delay 2 --Added as next leg could stall
		repeat until Date1 as number = TodaysDate as number --Data Starting to day
			set Cnt2 to Cnt2 + 1
			set Date1 to value of static text 1 of group Cnt2 of group 1 of group 9 of group Cnt3 of RefEnd --The Date
		end repeat
		click static text 1 of group Cnt2 of group 1 of group 9 of group Cnt3 of RefEnd --The Date
		--The "To" date
		click text field 2 of group cnt of group GrpNo of RefEnd --opens the "To" calendar
		click static text 1 of group (Cnt2 + 7) of group 1 of group 9 of group Cnt3 of RefEnd -- "To" Date + 7 days 
		click button 2 of group GrpNo of RefEnd --Closes the Date box
		delay 2
		click button 50 of group GrpNo of RefEnd --Close the "ALL FILTERS" box
		click UI element 25 of group GrpNo of RefEnd --Download Button
		delay 5 --Give it time to download
	end tell
end NewStocks