Submit Hint Search The Forums LinksStatsPollsHeadlinesRSS
14,000 hints and counting!


Click here to return to the 'Saving and restoring tabs in Safari, re: Save Dialog' hint
The following comments are owned by whoever posted them. This site is not responsible for what they say.
Saving and restoring tabs in Safari, re: Save Dialog
Authored by: Bubby Johnson on Apr 30, '04 11:35:13AM
Great hint! Being able to save the file to a desired location is perfect. Very useful if you want to open the info up somewhere else or just to have a bunch of safari link files sitting around. But I did notice that the last person to paste the script didn't use the NEW script. After I realized that the script didn't save tabs beyond one screen's worth of windows I discovered the error. So to add to the scripting madness already on this page, here is my version of the script, using the NEW script and the save file implementation. By the way the restore script still worked, but I edited it slightly with a tell block to bring the "Choose File Name" dialogue to the front. I also added this same tell block to the save script, so here they are again. Save Script:

-- localizations 
property windowMenu : "Window"
property nextTabMenuItem : "Select Next Tab"
-- end localizations 

property url_list : {}
property docCount : 0


tell application "Safari"
	activate
	set docCount to count of documents
end tell

tell application "System Events"
	tell process "Safari"
		
		set menuItemCount to count of menu items of menu windowMenu of ¬
			menu bar 1
		set menuItemOffset to menuItemCount - docCount
		
		set url_list to {}
		
		-- count the windows
		set winCount to count of windows
		
		-- loop through the windows
		repeat with k from 1 to winCount
			
			set winNum to k
			
			set winTitle to title of window winNum
			
			-- a bit nasty, but the front window is always number 1
			set winNum to 1
			
			if (count of characters of winTitle) > 20 then
				set winTitle to text 1 thru 20 of winTitle
			end if
			
			repeat with j from menuItemOffset + 1 to menuItemCount
				if ((title of menu item j of menu windowMenu of menu bar 1) ¬
					starts with winTitle) then
					set itemNum to j
					exit repeat
				end if
			end repeat
			
			-- activate a window
			click menu item itemNum of menu windowMenu of menu bar 1
			
			set firstUrl to ""
			
			-- check for browser window         
			if (count of radio buttons of window winNum) > 0 then
				
				-- activate the first tab 
				click radio button 1 of window winNum
				
				-- url of first tab
				set firstUrl to value of text field 1 of group 1 ¬
					of splitter group 1 of window winNum
				
				-- save the url
				set url_list to url_list & firstUrl
				
				my nextTab()
				
				-- url of the next tab
				set nextUrl to value of text field 1 of group 1 ¬
					of splitter group 1 of window winNum
				
				repeat until firstUrl is equal to nextUrl
					
					-- save the last url
					set url_list to url_list & nextUrl
					
					my nextTab()
					
					-- url of next tab
					set nextUrl to value of text field 1 of group 1 ¬
						of splitter group 1 of window winNum
					
				end repeat
				
				-- empty line to seprate windows
				set url_list to url_list & ""
				
			end if
			
		end repeat
	end tell
end tell

-- convert url list  to text
set old_delim to AppleScript's text item delimiters
set AppleScript's text item delimiters to return
set url_list_text to url_list as text
set AppleScript's text item delimiters to old_delim

-- get path to prefs file where URLs will be stored
tell application "System Events" --this tell block bring the save dialog up front as the active window
	activate
end tell

choose file name

set prefs_file to result as string

try
	set open_file to ¬
		open for access file prefs_file with write permission
	-- erase current contents of file:
	set eof of open_file to 0
	write url_list_text to open_file starting at eof
	close access open_file
on error
	try
		close access file prefs_file
	end try
end try


on nextTab()
	tell application "Safari" to activate
	tell application "System Events"
		tell process "Safari"
			click menu item nextTabMenuItem of ¬
				menu windowMenu of menu bar 1
		end tell
	end tell
end nextTab

And now the Restore Script:

tell application "Safari" to activate

-- get path to prefs file where URLs are stored
tell application "System Events" --This tell block brings the Choose File dialog up front as the active window
	activate
end tell

choose file

set prefs_file to result as string

try
	-- read the saved urls
	set open_file to ¬
		open for access file prefs_file without write permission
	set url_list to read open_file using delimiter return
	close access open_file
	
	set tmpList to {}
	set newUrl_list to {}
	
	-- make urls from file into a list of lists
	-- each window is a seperate list in the big list
	repeat with aUrl in url_list
		if aUrl & "x" is "x" then
			set newUrl_list to newUrl_list & {tmpList}
			set tmpList to {}
		else
			set tmpList to tmpList & aUrl
		end if
	end repeat
	
	-- don't forget the last list, or maybe the only
	set newUrl_list to newUrl_list & {tmpList}
	
	tell application "Safari"
		
		-- loop through the list of windows
		repeat with urls in newUrl_list
			
			my new_window()
			set emptyWindow to true
			
			-- loop through the list of tabs
			repeat with aUrl in urls
				if emptyWindow then
					set emptyWindow to false
				else
					my new_tab()
				end if
				
				-- open the url
				set URL of document 1 to aUrl
				
			end repeat
			
		end repeat
	end tell
on error
	try
		close access file prefs_file
	end try
end try

-- let the user know we are done.
on new_tab()
	tell application "Safari" to activate
	tell application "System Events"
		tell process "Safari"
			click menu item "New Tab" of menu "File" of menu bar 1
		end tell
	end tell
end new_tab

on new_window()
	tell application "Safari" to activate
	tell application "System Events"
		tell process "Safari"
			click menu item "New Window" of menu "File" of menu bar 1
		end tell
	end tell
end new_window



[ Reply to This | # ]
Saving and restoring tabs in Safari, re: Save Dialog
Authored by: sjk on May 01, '04 04:55:23PM

Two issues:

* Doesn't save URLs for open windows that don't contain tabs. Using New Tab (command-T) on those windows before running the save script is a workaround.

* Saves a duplicate set of URLs for tabs from the top window, as has already been mentioned in this hint. No obvious workaround.

Otherwise it's working fine.



[ Reply to This | # ]
Other problems with this script and another revision.
Authored by: papley on Mar 30, '05 04:11:27PM
I found a few problems with this, and presumably with all of the versions in the thread so far. I didn't actually read the last submission to see if it addressed any of the same issues.

1. If you have 2 tabs in the same window, one of which is the first tab and both have the same url in them, you'll stop collecting url's when you hit the second copy of the first tab. You could lose a whole lot of stuff without noticing it. I haven't yet figured a full fix for this. The right way to do it is to better identify the tab.

2. There's a big problem with PDF files and presumably other file types which may be loaded into Safari. When Safari loads these files it significantly changes the way it structures its list of windows, placing a new window in the list of active windows. The way this code is written it gets an unhandled exception when it tries to extract the url from such a page.

3. Another thing which would confuse this code is if you have a Download window opened. It will try to get a URL from that and get an unhandled exception.

4. Since the code finds windows by using the name of each browser window from it's description in the window menu, it can confuse two windows with one-another if they have the same name. If there are two windows which have the current tab set to a file whose title starts the same, this will happen and the same window will be processed twice, and the other window skipped.

I'm going to submit this new version now and if I have a chance I'll work on the problem in 1 and follow up.

I'd love to hear if anyone actually uses this or has further comments.



-- localizations 
property windowMenu : "Window"
property nextTabMenuItem : "Select Next Tab"
-- end localizations 

property url_list : {}
property docCount : 0
property browserButtons : {}

tell application "Safari"
	activate
	-- docCount is actually the count of standard browser windows.
	set docCount to count of documents
end tell

tell application "System Events"
	tell process "Safari"
		-- menuItemCount is the number of menu items in the window menu,
		-- including a bunch of junk, then browser windows + download window
		-- and possibly others, but not the activity window.
		set menuItemCount to count of menu items of menu windowMenu of ¬
			menu bar 1
		
		-- menuItemOffset is the menu index where the user-visible window list
		-- begins. Again, the download window and possibly others may be 
		-- here as well.
		set menuItemOffset to menuItemCount - docCount
		
		set url_list to {}
		
		-- count the windows
		-- winCount includes browser windows, and if present:
		-- download window, activity window, and special windows 
		-- e.g. pdf plugin window. This number can change
		--when changing tabs adds or removes a pdf plugin window.
		
		set winCount to count of windows
		-- loop through the browser windows, driving from the menu.
		-- Make a list of menu items.
		
		--Note the names will not be unique if the first 20 characters of 
		--the url or document title is not unique across browser windows.
		--This would not be the case if the current tab of two browser windows
		--each had the same document or one whose name was similar.
		repeat with j from menuItemOffset + 1 to menuItemCount
			set mbut to menu item j of menu windowMenu of menu bar 1
			if ((title of mbut) ¬
				does not start with "Downloads") then
				set browserButtons to browserButtons & {j}
			end if
		end repeat
		
		repeat with x in browserButtons
			-- Activate each valid browser window in turn.
			-- Here we will lose the order of the windows in the current desktop.
			click menu item x of menu windowMenu of menu bar 1
			set winTitle to title of window (my discoverWinNum(1))
			my collectURLsFromTabs(1)
			
		end repeat
	end tell
end tell

-- convert url list  to text
set old_delim to AppleScript's text item delimiters
set AppleScript's text item delimiters to return
set url_list_text to url_list as text
set AppleScript's text item delimiters to old_delim

-- get path to prefs file where URLs will be stored
tell application "System Events" --this tell block bring the save dialog up front as the active window
	activate
end tell

choose file name

set prefs_file to result as string

try
	set open_file to ¬
		open for access file prefs_file with write permission
	-- erase current contents of file:
	set eof of open_file to 0
	write url_list_text to open_file starting at eof
	close access open_file
on error
	try
		close access file prefs_file
	end try
end try

(* 			-- Find the menu item that will select the desired window.
			--But this will not work if the first 20 characters of 
			--the url or document title is not unique across browser windows.
			--This would not be the case if the current tab of two browser windows
			--each had the same document or one whose name was similar.
			repeat with j from menuItemOffset + 1 to menuItemCount
				if ((title of menu item j of menu windowMenu of menu bar 1) ¬
					starts with winTitle) then
					set itemNum to j
					exit repeat
				end if
			end repeat
 *)

-- Except this assumes urls don't repeat within a set of tabs. Not a good assumption.
on collectURLsFromTabs(winNum)
	tell application "Safari" to activate
	tell application "System Events"
		tell process "Safari"
			set firstUrl to ""
			
			-- check for browser window 
			set buttonCount to (count of radio buttons of window (my discoverWinNum(winNum)))
			if buttonCount > 0 then
				
				-- activate the first tab 
				click radio button 1 of window (my discoverWinNum(winNum))
				-- url of first tab
				set firstUrl to my urlOfTab(winNum)
				
				-- save the url
				set url_list to url_list & firstUrl
				
				my nextTab()
				
				-- url of the next tab
				set nextUrl to my urlOfTab(winNum)
				
				repeat until firstUrl is equal to nextUrl
					
					-- save the last url
					set url_list to url_list & nextUrl
					
					my nextTab()
					
					-- url of next tab
					set nextUrl to my urlOfTab(winNum)
					
				end repeat
				
				-- empty line to seprate windows
				set url_list to url_list & ""
				return
			end if
		end tell
	end tell
end collectURLsFromTabs

on urlOfTab(winNum)
	tell application "System Events"
		tell process "Safari"
			try
				set t1 to title of window (my discoverWinNum(winNum))
				set v1 to value of text field 1 of group 1 ¬
					of splitter group 1 of window (my discoverWinNum(winNum))
				-- return "<" & v1 & ">" & t1 -- Experimenting with output formats.
				return v1
			on error
				try
					-- Sometimes the URL isn't there immediately so there's a delay.
					-- This could infinite loop if there's something more seriously wrong.
					-- Should figure out a way to terminate this recursion gracefully.
					delay 2
					return my urlOfTab(winNum)
				end try
			end try
		end tell
	end tell
end urlOfTab

on nextTab()
	tell application "Safari" to activate
	tell application "System Events"
		tell process "Safari"
			click menu item nextTabMenuItem of ¬
				menu windowMenu of menu bar 1
		end tell
	end tell
end nextTab

on discoverWinNum(winNum)
	tell application "System Events"
		tell process "Safari"
			set subroleStr to ""
			if subrole of window winNum exists then
				set subroleStr to subrole of window winNum
			end if
			-- a bit nasty, but the front window is always number 1 except when it's window 2 
			-- which happens when displaying a pdf and possibly other special formats in the browser.
			if (subroleStr is "AXStandardWindow") then
				return winNum
			else
				return winNum + 1
			end if
		end tell
	end tell
end discoverWinNum




[ Reply to This | # ]
Other problems with this script and another revision.
Authored by: papley on Mar 30, '05 04:24:57PM
I found a few problems with this, and presumably with all of the versions in the thread so far. I didn't actually read the last submission to see if it addressed any of the same issues.

The first issue below is still open, but as far as I know I've fixed the other issues.

1. If you have 2 tabs in the same window, one of which is the first tab and both have the same url in them, you'll stop collecting url's when you hit the second copy of the first tab. You could lose a whole lot of stuff without noticing it. I haven't yet figured a full fix for this. The right way to do it is to better identify the tab.

2. There's a big problem with PDF files and presumably other file types which may be loaded into Safari. When Safari loads these files it significantly changes the way it structures its list of windows, placing a new window in the list of active windows. The way this code is written it gets an unhandled exception when it tries to extract the url from such a page.

3. Another thing which would confuse this code is if you have a Download window opened. It will try to get a URL from that and get an unhandled exception.

4. Since the code finds windows by using the name of each browser window from it's description in the window menu, it can confuse two windows with one-another if they have the same name. If there are two windows which have the current tab set to a file whose title starts the same, this will happen and the same window will be processed twice, and the other window skipped.

I'm going to submit this new version now and if I have a chance I'll work on the problem in 1 and follow up.

I'd love to hear if anyone actually uses this or has further comments.



-- localizations 
property windowMenu : "Window"
property nextTabMenuItem : "Select Next Tab"
-- end localizations 

property url_list : {}
property docCount : 0
property browserButtons : {}

tell application "Safari"
	activate
	-- docCount is actually the count of standard browser windows.
	set docCount to count of documents
end tell

tell application "System Events"
	tell process "Safari"
		-- menuItemCount is the number of menu items in the window menu,
		-- including a bunch of junk, then browser windows + download window
		-- and possibly others, but not the activity window.
		set menuItemCount to count of menu items of menu windowMenu of ¬
			menu bar 1
		
		-- menuItemOffset is the menu index where the user-visible window list
		-- begins. Again, the download window and possibly others may be 
		-- here as well.
		set menuItemOffset to menuItemCount - docCount
		
		set url_list to {}
		
		-- count the windows
		-- winCount includes browser windows, and if present:
		-- download window, activity window, and special windows 
		-- e.g. pdf plugin window. This number can change
		--when changing tabs adds or removes a pdf plugin window.
		
		set winCount to count of windows
		-- loop through the browser windows, driving from the menu.
		-- Make a list of menu items.
		
		--Note the names will not be unique if the first 20 characters of 
		--the url or document title is not unique across browser windows.
		--This would not be the case if the current tab of two browser windows
		--each had the same document or one whose name was similar.
		repeat with j from menuItemOffset + 1 to menuItemCount
			set mbut to menu item j of menu windowMenu of menu bar 1
			if ((title of mbut) ¬
				does not start with "Downloads") then
				set browserButtons to browserButtons & {j}
			end if
		end repeat
		
		repeat with x in browserButtons
			-- Activate each valid browser window in turn.
			-- Here we will lose the order of the windows in the current desktop.
			click menu item x of menu windowMenu of menu bar 1
			set winTitle to title of window (my discoverWinNum(1))
			my collectURLsFromTabs(1)
			
		end repeat
	end tell
end tell

-- convert url list  to text
set old_delim to AppleScript's text item delimiters
set AppleScript's text item delimiters to return
set url_list_text to url_list as text
set AppleScript's text item delimiters to old_delim

-- get path to prefs file where URLs will be stored
tell application "System Events" --this tell block bring the save dialog up front as the active window
	activate
end tell

choose file name

set prefs_file to result as string

try
	set open_file to ¬
		open for access file prefs_file with write permission
	-- erase current contents of file:
	set eof of open_file to 0
	write url_list_text to open_file starting at eof
	close access open_file
on error
	try
		close access file prefs_file
	end try
end try

(* 			-- Find the menu item that will select the desired window.
			--But this will not work if the first 20 characters of 
			--the url or document title is not unique across browser windows.
			--This would not be the case if the current tab of two browser windows
			--each had the same document or one whose name was similar.
			repeat with j from menuItemOffset + 1 to menuItemCount
				if ((title of menu item j of menu windowMenu of menu bar 1) ¬
					starts with winTitle) then
					set itemNum to j
					exit repeat
				end if
			end repeat
 *)

-- Except this assumes urls don't repeat within a set of tabs. Not a good assumption.
on collectURLsFromTabs(winNum)
	tell application "Safari" to activate
	tell application "System Events"
		tell process "Safari"
			set firstUrl to ""
			
			-- check for browser window 
			set buttonCount to (count of radio buttons of window (my discoverWinNum(winNum)))
			if buttonCount > 0 then
				
				-- activate the first tab 
				click radio button 1 of window (my discoverWinNum(winNum))
				-- url of first tab
				set firstUrl to my urlOfTab(winNum)
				
				-- save the url
				set url_list to url_list & firstUrl
				
				my nextTab()
				
				-- url of the next tab
				set nextUrl to my urlOfTab(winNum)
				
				repeat until firstUrl is equal to nextUrl
					
					-- save the last url
					set url_list to url_list & nextUrl
					
					my nextTab()
					
					-- url of next tab
					set nextUrl to my urlOfTab(winNum)
					
				end repeat
				
				-- empty line to seprate windows
				set url_list to url_list & ""
				return
			end if
		end tell
	end tell
end collectURLsFromTabs

on urlOfTab(winNum)
	tell application "System Events"
		tell process "Safari"
			try
				set t1 to title of window (my discoverWinNum(winNum))
				set v1 to value of text field 1 of group 1 ¬
					of splitter group 1 of window (my discoverWinNum(winNum))
				-- return "<" & v1 & ">" & t1 -- Experimenting with output formats.
				return v1
			on error
				try
					-- Sometimes the URL isn't there immediately so there's a delay.
					-- This could infinite loop if there's something more seriously wrong.
					-- Should figure out a way to terminate this recursion gracefully.
					delay 2
					return my urlOfTab(winNum)
				end try
			end try
		end tell
	end tell
end urlOfTab

on nextTab()
	tell application "Safari" to activate
	tell application "System Events"
		tell process "Safari"
			click menu item nextTabMenuItem of ¬
				menu windowMenu of menu bar 1
		end tell
	end tell
end nextTab

on discoverWinNum(winNum)
	tell application "System Events"
		tell process "Safari"
			set subroleStr to ""
			if subrole of window winNum exists then
				set subroleStr to subrole of window winNum
			end if
			-- a bit nasty, but the front window is always number 1 except when it's window 2 
			-- which happens when displaying a pdf and possibly other special formats in the browser.
			if (subroleStr is "AXStandardWindow") then
				return winNum
			else
				return winNum + 1
			end if
		end tell
	end tell
end discoverWinNum




[ Reply to This | # ]