In Safari, I want to search all windows for a tab with a specific URL and activate that tab/bring it to the foreground. I loop through all tabs in all windows until I found a tab with the URL I am looking for:
repeat with aWindow in windows
repeat with aTab in tabs of aWindow
if (URL of aTab) is equal to targetURL then
set targetTab to aTab
end if
end repeat
Now I expect aWindow to be a reference to the window that contains the found tab but if the aWindow is in the background and I move it to the front like this
set index of aWindow to 1
and then change the tab
set current tab of aWindow to targetTab
it changes the tab of the window that took over aWindow’s position in the background!?!?
An example: I have two windows, fg (foreground) and bg (background), and in both windows, tab 1 is displayed. I then loop through both windows and find the tab I am looking for, tab 3 in bg. If I then raise the bg window to the foreground and change the tab, tab 3 in fg is activated while bg still is at tab 1!?!?
However, if I first change the tab and then bring the parental window to the front it works.
Hmm, I tried using windows IDs instead of indexes (which I guess is the default):
repeat with aWindow in windows
repeat with aTab in tabs of aWindow
if (URL of aTab) is equal to targetURL then
set targetTab to aTab
set targetWinID to id of aWindow
end if
end repeat
set current tab of (window id targetWinID) to targetTab
set index of (window id targetWinID) to 1
Result:
set current tab of window id 16642 to item 8 of every tab of item 2 of every window|
set index of window id 16642 to 1|
But it is the same problem here: if I bring the window to the front first
set current tab of (window id targetWinID) to targetTab|
set index of (window id targetWinID) to 1|
switching tab fails:
set index of window id 16642 to 1
set current tab of window id 16642 to item 8 of every tab of item 2 of every window
--> error number -10000
I suspect the culprit is this part of the log of item 2 of every window but where does it come from??
All this code is just surrounded by a tell application "safari".
I think it has to do with ‘repeat with aWindow in windows’.
When you use this command, ‘aWindow’ does not contain a window, but a reference to a window. The reference then fails if the order of windows gets changed while its executing.
Try putting this line directly after.
repeat with aWindow in windows
set aWindows to contents of aWindow
• • •
end repeat
or you can dot the loop by using
repeat with i from 1 to count windows
set aWindow to window i
• • •
end repeat
In both instances ‘aWindow’ should now contain a window object, not a reference to a window.
I just realized you might also run into another similar issue.
If the window order changes the window command will also return a list in z order,
and it also gets re-calculated each time called.
you might want to call it once and save the results in a variable like so…
set allWindows to windows
repeat with aWindow in allWindows
set aWindows to contents of aWindow
• • •
end repeat
but this might cause another issue such as what if a window gets closed in the middle of execution. One of the windows in the saved variable will now be a non-existent window. You would have to put code in to check if window still exists.
I had some trouble following the discussion and decided to write a full script, which worked as expected on my Sonoma computer. However, there can be an issue when the URL of a tab is not precisely what is expected, causing the test for equality to fail. An alternative is to test if the URL of the tab begins with the target URL; another might be to test for tab names.
set targetURL to "https://www.google.com/"
tell application "Safari"
set theWindows to every window
repeat with aWindow in theWindows
set theTabs to every tab of aWindow
repeat with aTab in theTabs
if (URL of aTab) is equal to targetURL then -- consider "begins with" instead of "is equal to"
set index of aWindow to 1
set current tab of aWindow to aTab
error number -128
end if
end repeat
end repeat
end tell
display alert "A tab with the target URL was not found" message targetURL
What you did was to move the activation of the window/tab with the URL you are looking for into the loop rather than, as I did, have it outside the loop? Or was it something more that you changed?
Hmm, moving the window activation into the inner loop worked. I am bit surprised, but when I write this I realise that I had more than two windows open and that the looping continued after the tab was found. OTOH, I used window IDs which should be constant. Confusing.
Exiting two repeat loops in AppleScript is not always a simple matter, and that’s why I wrote my script as I did. Bash has a break [n] command that will exit multiple repeat loops, but I don’t know of anything similar in AppleScript. FWIW, the following is functionally equivalent to my earlier script.
set targetURL to "https://www.macscripter.net"
tell application "Safari"
set matchFound to false
set theWindows to every window
repeat with aWindow in theWindows
set theTabs to every tab of aWindow
repeat with aTab in theTabs
if (URL of aTab) begins with targetURL then -- use "is" instead of "begins with" if desired
set matchFound to true
exit repeat -- exit inner repeat loop
end if
end repeat
if matchFound is true then exit repeat -- exit outer repeat loop
end repeat
if matchFound is true then
set index of aWindow to 1
set current tab of aWindow to aTab
else
display dialog "A tab with the target URL was not found" buttons {"OK"} default button 1
end if
end tell
lagr. I rewrote my script to implement your suggestion, and, while it worked, it was pretty ugly. Please post your script that puts the repeat loop in a handler. Thanks!