What is Best Method to Activate Google Chrome Tab for Existing URL?

FWIW, I threw this little ditty to set the stage for testing. I’m curious if your results are the same after running this.

It closes all Google Chrome windows, then opens ten new ones, each with ten tabs, then sets the last tab of the last window to the target tab, so any testing has to go through every tab.

tell application "Google Chrome" to close windows

set targetURL to "http://macscripter.net/"


set newURLList to {"http://macscripter.net/index.php", ¬
	"http://macscripter.net/register-pp.php", ¬
	"http://macscripter.net/guidelines.php", ¬
	"http://macscripter.net/page.php?id=1", ¬
	"http://macscripter.net/login.php", ¬
	"http://macscripter.net/viewforum.php?id=2", ¬
	"http://macscripter.net/viewforum.php?id=31", ¬
	"http://macscripter.net/viewforum.php?id=63", ¬
	"http://macscripter.net/viewtopic.php?pid=190102#p190102"}
tell application "Google Chrome"
	repeat 10 times
		make new window
		set URL of tab 1 of window 1 to some item of newURLList
		repeat 9 times
			make new tab at beginning of window 1
			set URL of tab 1 of window 1 to some item of newURLList
		end repeat
	end repeat
	set the URL of the last tab of the last window to targetURL
end tell

I already have a similar test set, saved/restored using the Chrome extension Session Buddy.

Also, I make sure the target URL is NOT opened in any tab. This will force the script to loop through all tabs in all windows.

I’ve actually tested this on two different Macs now, with the results being within 0.01 of each other.

1 Like

Hey Ed,

You did a great job optimizing the list-based version.  :smiley:

I tried pretty hard to beat it and couldn’t, although I didn’t resort to script-objects.

(I think Nigel Garvey has a way to make a script-object iterate through lists faster than a plain script, but I’m not going to go there.)

While I was experimenting I had one more go at using whose clauses.

-Chris

------------------------------------------------------------------------------
# Auth: Christopher Stone
# dCre: 2017/05/15 15:45
# dMod: 2017/05/15 17:14
# Appl: Google Chrome
# Task: Get Tabs whose URL starts with a given string - whose clause version.
# Libs: None
# Osax: None
# Tags: @Applescript, @Script, @Google_Chrome, @Get, @Tabs, @Whose, @URL, @Starts_With, @String
------------------------------------------------------------------------------

set targetURL to "https://www.macupdate.com/"

tell application "Google Chrome"
   tell windows
      set tabList to tabs where its URL starts with targetURL
   end tell
end tell

try
   tabList / 0
on error e
   set AppleScript's text item delimiters to {"Can’t make {", "} into type real.", "{", "}", ", ", "«class asDB» id (application \"Google Chrome\") of "}
   set tabList to text items of e
   repeat with theTab in tabList
      if contents of theTab = "" then set contents of theTab to 0
   end repeat
   
   set tabList to text of tabList
   
   if length of tabList > 0 then
      set theTab to item 1 of tabList
      set AppleScript's text item delimiters to {"id ", " of"}
      set {tabID, winID} to {text item 2, text item 4} of theTab
      set tabID to tabID as integer
      
      tell application "Google Chrome" to set tabIDList to id of tabs of window id winID
      
      repeat with i from 1 to length of tabIDList
         if (item i of tabIDList) = tabID then
            set tabIndex to i
            exit repeat
         end if
      end repeat
      
      tell application "Google Chrome"
         tell window id winID
            set index to 1
            set active tab index to tabIndex
         end tell
      end tell
      
      raiseWindowOne() of me
      
   else
      
      tell application "Google Chrome" to make new tab at window 1 with properties {URL:targetURL}
      
   end if
   
end try

------------------------------------------------------------------------------
--» HANDLERS
------------------------------------------------------------------------------
on raiseWindowOne()
   tell application "System Events"
      tell application process "Google Chrome"
         tell window 1
            perform action "AXRaise"
         end tell
      end tell
   end tell
end raiseWindowOne
------------------------------------------------------------------------------

And, we have a new record: 0.14 seconds

TEST: Search 10 windows with a total of 20 tabs, and open new tab
@ccstone: 0.14 (ver 2) @estocky: 0.17 @ccstone: 0.38 @JMichaelTX: 0.39

Great job Chris! :+1:

Given that all of these are << 0.5 sec, it seems to me that this is mostly an academic test, unless you are one of those that like 10’s of windows with hundreds of tabs (not me).

Chris, I know you love to shave hundredths of a second off a script/process, but I am not nearly that driven. :wink: I routinely use a delay of 0.20 sec in my KM Macros, and they all seem fast to me (but maybe not to others).

As one of our colleagues likes to point out, sometimes programmer’s time is more valuable than execution time.

Still, it is good to know what techniques are the fastest. Now that I know that, there is no reason not to use that technique unless I have a compelling reason to do otherwise.

Chris, how do you explain this?

I thought I saw an opportunity to yet further optimize your script by checking for an empty “tabList”, meaning the the URL is not found in any of the tabs.
Seems like it should be faster, but it also runs in 0.14 seconds.

Tested with Script Debugger 6.0.4 (6A198) on macOS 10.11.6.

###My Mod to Chris’ Script
This just shows the changes.

tell application "Google Chrome"
  tell windows
    set tabList to tabs where its URL starts with targetURL
  end tell
end tell

### MOD by JMichaelTX ###
set actionStr to "TBD"
if tabList as text = "" then
  set actionStr to "** JUST OPEN URL IN NEW TAB"
  tell application "Google Chrome" to make new tab at window 1 with properties {URL:targetURL}
  return
end if
### End of MOD ###

try
  tabList / 0
on error e

BTW, is there a better method for testing for an empty list of lists than:
if tabList as text = "" then

where tabList = {{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}}

Hey JM,

There’s not much overhead in my code, so we’re probably talking a few milliseconds.

Not with vanilla AppleScript.

Of course that code will throw an error if there’s any content in the nested lists, but catching it with a try-block is very fast.

-Chris

1 Like

Yep, you’re right, as usual!

This simple handler seems to work fast enough:


tell application "Google Chrome"
  tell windows
    set tabList to tabs
  end tell
end tell

set testTabs to my isEmpty(tabList)

set testListEmpty to my isEmpty({{}, {}, {}})
set testListNotEmpty to my isEmpty({{}, {"not empty"}, {}})
set testTextNotEmpty to my isEmpty("not empty")
set testTextEmpty to my isEmpty("")

on isEmpty(pObject)
  
  try
    if (pObject as text = "") then
      return true
    else
      return false
    end if
  on error
    return false
  end try
  
end isEmpty

Many thanks to all in this thread for creating and posting scripts for this task. This is a life saver for me and something I would be unlikely to have created with my beginner Applescript skills. I’ve estimated this applescript – triggered using Keyboard Maestro – will save me between 3 to 6 hours per year of tedious tab hunting in my management role.

Thank you all!

1 Like

Hi, I aspire to achieve

  1. Copy text in "Active"chrome tab
  2. Paste in another chrome tab "DropBox Paper
  3. The Back to "Active"chrome tab

I have tried setting a variable A to id / tab object to restore the active tab after using the above script (post 16) to activate the tab

set A to the front tab of the front window
or
set A to the id of the active tab of the front window

Run Script from post 16

tell application “System Events” to keystroke (the clipboard as text)
delay 3
set active tab index of front window to A
Errors
If set A to the id of the active tab of the front window
=Google Chrome got an error: Invalid tab index entered." number 9
If set A to the front tab of the front window, then
=error “Google Chrome got an error: Can’t make tab id 714 of window id 98 into type integer.” number -1700 from tab id 714 of window id 98 to integer

This fails… Any suggestions
Cheers

Hi, I have managed to get a working solution for I wanted to do
Its a dirty workaround from brilliant work from Masters of applescript art

wud be grateful to suggest changes to look like a proper work

use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"
--https://apple.stackexchange.com/questions/271161/how-to-get-the-selected-text-into-an-applescript-without-copying-the-text-to-th
--https://mjtsai.com/blog/2017/01/30/processing-the-selected-text-via-script/#comment-2669464
-- Back up clipboard contents:
set savedClipboard to my fetchStorableClipboard()
-- Copy selected text to clipboard:
set thePasteboard to current application's NSPasteboard's generalPasteboard()
set theCount to thePasteboard's changeCount()
-- Copy selected text to clipboard:
tell application "System Events" to keystroke "c" using {command down}
-- Check for changed clipboard:
repeat 20 times
	if thePasteboard's changeCount() is not theCount then exit repeat
	delay 0.1
end repeat
-- Set the selected to ClipBoard, Ready to paste
set theSelectedText to the clipboard
-- Block for doing Copy & paste
on fetchStorableClipboard()
	set aMutableArray to current application's NSMutableArray's array() -- used to store contents
	-- get the pasteboard and then its pasteboard items
	set thePasteboard to current application's NSPasteboard's generalPasteboard()
	-- loop through pasteboard items
	repeat with anItem in thePasteboard's pasteboardItems()
		-- make a new pasteboard item to store existing item's stuff
		set newPBItem to current application's NSPasteboardItem's alloc()'s init()
		-- get the types of data stored on the pasteboard item
		set theTypes to anItem's types()
		-- for each type, get the corresponding data and store it all in the new pasteboard item
		repeat with aType in theTypes
			set theData to (anItem's dataForType:aType)'s mutableCopy()
			if theData is not missing value then
				(newPBItem's setData:theData forType:aType)
			end if
		end repeat
		-- add new pasteboard item to array
		(aMutableArray's addObject:newPBItem)
	end repeat
	return aMutableArray
end fetchStorableClipboard
on putOnClipboard:theArray
	-- get pasteboard
	set thePasteboard to current application's NSPasteboard's generalPasteboard()
	-- clear it, then write new contents
	thePasteboard's clearContents()
	thePasteboard's writeObjects:theArray
end putOnClipboard:
-- Google Chrome
tell application "Google Chrome"
		set restoreURL to URL of active tab of front window as text
	--https://forum.latenightsw.com/t/what-is-best-method-to-activate-google-chrome-tab-for-existing-url/600/16
	-- Find paper DropBox URL, and set it active to paste
	set windowTabList to URL of tabs of every window
	set targetURL to "paper.dropbox.com"
	set found to false
	set windowIndex to 1
	repeat with thisWindowsTabs in windowTabList
		set TabIndex to 1
		repeat with TabURL in thisWindowsTabs
			if (TabURL as text) contains targetURL then
				
				tell application "Google Chrome"
					set index of window windowIndex to 1
					set active tab index of window 1 to TabIndex
				end tell
				
				set found to true
				exit repeat
			end if
			set TabIndex to TabIndex + 1
		end repeat
		if found then exit repeat
		set windowIndex to windowIndex + 1
	end repeat
	delay 1
	-- Block to paste the clipBoard & restore to Saved one
	tell application "System Events" to keystroke "v" using {command down}
	tell application "System Events" to keystroke {return}
	delay 0.1 -- Without this delay, may restore clipboard before pasting.
	-- Restore clipboard:
	(my putOnClipboard:savedClipboard)
	delay 1
	-- Block to restore the URL
	set found to false
	set windowIndex to 1
	repeat with thisWindowsTabs in windowTabList
		set TabIndex to 1
		repeat with TabURL in thisWindowsTabs
			if (TabURL as text) = restoreURL then
				
				tell application "Google Chrome"
					set index of window windowIndex to 1
					set active tab index of window 1 to TabIndex
				end tell
				
				set found to true
				exit repeat
			end if
			set TabIndex to TabIndex + 1
		end repeat
		if found then exit repeat
		set windowIndex to windowIndex + 1
	end repeat
end tell