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

Saving and restoring tabs in Safari Web Browsers

So, one day I needed to quit Safari for some reason. The problem was that I had a window with something like 10 tabs open and I needed those pages still. I really find it a pain that I have to bookmark each tab separately, otherwise I would just bookmark all the tabs at once and load them back up when I restarted Safari, but Safari doesn't do this.

I did a little searching and found some scripts on John Gruber's site that saved and restored windows in Safari. This looked good, but it didn't save/restore tabs in those windows. So starting with John's scripts, I added support for tabs to the save script. After learning about GUI Scripting I came up with the following -- read the rest of the hint for the scripts.

The script to save the open windows...


set url_list to {}

tell application "System Events"
  tell process "Safari"
        
    -- count the windows
    set winCount to count of windows
        
    -- loop through the windows
    repeat with i from 1 to winCount
            
      -- count the tabs
      set tabCount to count of radio buttons of window i
            
      -- loop through the tabs
      repeat with j from 1 to tabCount
        -- activate the tab 
        click radio button j of window i
                
        -- url of window
        set theUrl to value of text field 1 of group 1 ¬
        of splitter group 1 of window i
                
        -- save the url
        set url_list to url_list & theUrl
      end repeat
            
      -- empty line to seprate windows
      set url_list to url_list & ""
    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 to url_list as text
set AppleScript's text item delimiters to old_delim

-- get path to prefs file where URLs will be stored
set prefs_folder to path to preferences folder as string
set prefs_file to prefs_folder & "Safari Saved URLs"

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 to open_file starting at eof
  close access open_file
  on error
  try
    close access file prefs_file
  end try
end try

-- let the user know we are done.
tell application "Safari"
  activate
  display dialog "All Done" buttons {"OK"} default button 1
end tell

Now that i have the tabs saved to a text file in my Preferences folder, I need to restore them. To do this, I needed to be able to open new tabs. MacOSXHints to the rescue. I found a hint that showed how to do just that. So, again starting with John's restore script and the hint on opening tabs, I came up with the following.


tell application "Safari" to activate

-- get path to prefs file where URLs are stored
set prefs_folder to path to preferences folder as string
set prefs_file to prefs_folder & "Safari Saved URLs"

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.
tell application "Safari"
  activate
  display dialog "All Done" buttons {"OK"} default button 1
end tell

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

For this all to work you need to have GUI Scripting, from Apple, installed. Also, the "Enable access for assistive devices" check box must be checked in the Universal Access preference pane.

Save these scripts to your script folder so you can access them from your Script Menu, and you're all set.

    •    
  • Currently 2.80 / 5
  You rated: 1 / 5 (5 votes cast)
 
[78,431 views]  

Saving and restoring tabs in Safari | 52 comments | Create New Account
Click here to return to the 'Saving and restoring tabs in Safari' 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
Authored by: swanksalot on Sep 16, '03 10:23:41AM

I don't know why you can't just save all tabs as a folder, then command click to reopen them all. I, for instance, have a bookmark folder called News, and when I command click it, it opens 10 or so news/blogs I frequent. Perhaps I misunderstand your problem.



[ Reply to This | # ]
Saving and restoring tabs in Safari
Authored by: Dieringer on Sep 16, '03 11:26:20AM

I think the author is saying that he wants to be able to save random sites for later retrieval, not a set of frequently visited sites.

This works for me. I often have a browser full of tabs I want to save in case Safari crashes, or save because I want to revisit this "working set" later. I don't want to bookmark them because I won't visit them frequently - I only want them saved until I finish the task at hand.



[ Reply to This | # ]
Saving and restoring tabs in Safari
Authored by: gopes on Sep 16, '03 11:31:50AM

The point of the script is so that one doesn't have to a) make a new bookmark folder and b) manually bookmark each tab.

I'm going to find this incredibly useful for when I install (for example) the Java update, or anything needing a logout/restart. Thanks!



[ Reply to This | # ]
Saving and restoring tabs in Safari
Authored by: luhmann on Sep 16, '03 11:28:57AM

This would all be a lot easier if Apple simply implemented a "save all tabs" option. Why they don't have one is beyond me. Camino has this. If you use this script, please write to Apple on the OS X feedback page and tell them you'd like to see this feature!!! Really, how hard can it be?



[ Reply to This | # ]
Worked like a charm!
Authored by: sinjin on Sep 16, '03 01:55:48PM

Thanks mazatty,

I've needed this hint more times than I can remember! Very nice script solution to the problem; wish I had your skill. And "GUI scripting" too! I didn't even know it exisited. That opens up all sorts of new ideas for scripts.



[ Reply to This | # ]
Saving and restoring tabs in Safari
Authored by: samkass on Sep 16, '03 04:14:13PM

IMHO, a near-perfect implementation of tabs is present in the Windows version of Opera. By default, when you quit Opera, all the tabs are saved, and loading it back up again brings you back to the pages you were at when you quit. My left few tabs have been "Java 2 Platform SE" and "Java 2 Platform EE" APIs, and the "ord.apache.struts.taglib" pages. I can count on them always being there when coding at work. When I go home to my Mac, I really miss this feature in Safari.

I do like Safari's combination of multi-window and multi-tab, though. It's especially nice for multi-monitor support. I just wish the tabs were more persistent.



[ Reply to This | # ]
Saving and restoring tabs in Safari
Authored by: splattertrousers on Sep 16, '03 05:56:01PM

In addition to saving the current tab set when you quit and restoring them when you re-launch, it would be great if Safari would save the current tab set often so if Safari crashes, everything is back as it was when you re-launch.



[ Reply to This | # ]
Galeon does this
Authored by: brainsik on Dec 02, '03 04:21:15AM
Galeon autosaves your windows/tabs as you are using the browser. If it crashes, just restart and you are back to the exact same position you left off. This can actually be problematic if particular page is crashing the browser. Then you have to quickly nuke the tab while everything is reloading. :)

Galeon is still the best browser I've ever used.

[ Reply to This | # ]

Galeon does this
Authored by: tamaracks on Feb 01, '04 02:47:40AM

So does Opera for Windows. And Firebird, with an extension. Too bad Opera for Mac does not have the same features.



[ Reply to This | # ]
trouble in script-land
Authored by: duien on Sep 16, '03 04:48:03PM

for some reason this script won't work for me. no errors when it runs, it gives me the "all done" dialogue, but nothing is written to the "Safari Saved URLs" file. its created, but blank.

i tried adding an error dialogue for if the file couldn't be opened writeable, but it didn't get triggered...

i installed UI scripting

anybody have any idea what the problem might be or hints on figuring it out?

thanks



[ Reply to This | # ]
trouble in script-land
Authored by: muttley8 on Sep 16, '03 07:35:16PM
I had the same problem, but then reread the hint and saw I missed this crucial step:
"Enable access for assistive devices" check box must be checked in the Universal Access preference pane.
This is probably your problem.

[ Reply to This | # ]
trouble in script-land
Authored by: dindin on Sep 21, '03 04:20:14PM

I'm having the exact same problem. I have the "enable access for assistive devices" selected too. Does anyone have the finished scripts to download. Perhaps I did it wrong. This is my first attempt at an AppleScript.



[ Reply to This | # ]
Useful But Loads in Same Tab
Authored by: Enkerli on Sep 17, '03 12:40:55AM

This'll be quite useful as I tend to do a lot of offline browsing and Safari still has a way of crashing with several tabs open.
Strangely enough, the restore script loads all pages in the same tab for me. Didn't investigate much but it doesn't seem to have to do with preferences.
OTOH, what I'd really like is a "Web Archive" format which could just be opened and have the full set of tabs with full content for each. In fact, any kind of web archive feature would greatly enhance Safari...



[ Reply to This | # ]
SiteSucker?
Authored by: sinjin on Sep 17, '03 11:36:26AM
If I understand you correctly I think you are looking for an application like "SiteSucker". Supposedly used to download sites to your disk for offline browsing. There are probably others. Sorry, I don't have any experience using them - just know of their existence.

[ Reply to This | # ]
WWWOFFLE
Authored by: brainsik on Dec 02, '03 04:17:02AM
Check out the World Wide Web Offline Explorer, WWWOFFLE. It acts as proxy and saves pages as you read them. I believe it can also be used to grab pages you want to read for later (that you haven't browsed to yet).

It's also available in Fink.

[ Reply to This | # ]

Saving and restoring tabs in Safari
Authored by: bfr00 on Sep 17, '03 01:25:22AM

Your new tab and new window script can be simplified. Remember that Safari understands javascript. This opens a new window:

tell app "Safari" to do javascript "window.open()" in document 1

To open a new tab just type command-T:
tell app "Safari" to activate
tell app "System Events" to keystroke "t" with command down



[ Reply to This | # ]
Saving and restoring tabs in Safari
Authored by: Chuck on Sep 17, '03 05:07:08AM

Thanks for publishing this. I had written a similar set of scripts, but your implementation is better.

I have made this feature request to Apple. Anyone who uses these (as I do every time I have to install something from Software Update that requires a restart) should request the feature from Apple's feedback page.

Chuck



[ Reply to This | # ]
Saving and restoring tabs in Safari
Authored by: gctuser on Sep 17, '03 07:59:45AM
to make this work on non-englisch system languages modify the "System Events"-calls:

on new_tab()
  tell application "Safari" to activate
  tell application "System Events"
    tell process "Safari"
      click menu item 2 of menu 3 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 1 of menu 3 of menu bar 1
    end tell
  end tell
end new_window


[ Reply to This | # ]
won't work
Authored by: vman on Sep 18, '03 09:23:03PM

when I run the save-script all I get is:

"System Events got an error: NSCannotCreateScriptCommandError"

checked the syntax...did install UIelements, checked the universal access button mentioned before..
??
anyone?



[ Reply to This | # ]
Saving and restoring tabs in Safari
Authored by: mottram on Sep 20, '03 10:16:42AM

Thanks for this - my number one missing Safari feature fixed (and my first attempt at using AppleScript trauma-free!)



[ Reply to This | # ]
Saving and restoring tabs in Safari
Authored by: snoozy on Sep 21, '03 05:57:52PM

Works great! Thanks for the scripting, this hit the nail right on the head for me. I often have 10-15 open tabs at any given time and this script-zygote made your scripts work no problem. One other aspect to add would be to make the saved Tabs save their respective histories as well (and maintain them upon Restore).



[ Reply to This | # ]
Updated Save script
Authored by: mazatty on Oct 20, '03 11:24:07PM

it appears that the 10.2.8 update has broken the save script. i have updated this script to handle tabs that you don't see, the one you get to from the ">>" button. this update also seems to fix the problem with 10.2.8. here it is

-- 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
        
        -- count the windows
        set winCount to count of windows
        
        -- loop through the windows
        repeat with i from 1 to winCount
            
            set winTitle to title of window i
            
            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
            
            -- check for browser window         
            if (count of radio buttons of window i) > 0 then
                
                -- activate the first tab 
                click radio button 1 of window i
                
                -- url of first tab
                set firstUrl to value of text field 1 of group 1 ¬
                    of splitter group 1 of window i
                
                -- 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 i
                
                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 i
                    
                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 to url_list as text
set AppleScript's text item delimiters to old_delim

-- get path to prefs file where URLs will be stored
set prefs_folder to path to preferences folder as string
set prefs_file to prefs_folder & "Safari Saved URLs"

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 to open_file starting at eof
    close access open_file
on error
    try
        close access file prefs_file
    end try
end try

-- let the user know we are done.
tell application "Safari"
    activate
    display dialog "All Done" buttons {"OK"} default button 1
end tell


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
hope this helps. good luck.

[ Reply to This | # ]
Updated Save script
Authored by: Pierre Igot on Nov 12, '03 03:02:10PM

I thoroughly enjoyed using your Saving and restoring tabs in Safari script for Jaguar

Unfortunately, it appears that this script no longer works properly in Panther with Safari 1.1.

Any plans on an update?

TIA

Pierre

---
Pierre Igot
LATEXT - Literature & Visuals @ www.latext.com
BETALOGUE - Weblog at www.latext.com/blog/
"Apple Peel" Columnist @ Applelust.com



[ Reply to This | # ]
Updated Save script -- for Panther
Authored by: jeffschuler on Dec 07, '03 12:49:51AM
I'm trying to make this work in Panther with Safari 1.1. Using the "Updated Save script" from mazatty posted here in the comments, the first thing to change is that the two occurrences of
menu windowMenu of menu bar 1
should be changed to
menu windowMenu of menu bar item windowMenu of menu bar 1
Doing this, the script works mostly... However, something screwy is going on when saving your tabs after the first time running the script. Instead of writing over the previous file, the new URLs are tacked onto the end of the file, and returns aren't used as delimiters. Even if the file is deleted & a new one written, the old results come back from the dead... Strange. Could this have something to do with Panther's journalling?

[ Reply to This | # ]
Updated Save script -- for Panther
Authored by: sfreimark on Dec 21, '03 09:53:20AM
That doesn't work for me either. With your changes for Panther I'm getting this error: NSReceiverEvaluationScriptError: 4 Script Editor marks these two lines near the beginning of the script:

set menuItemCount to count of menu items of ¬
menu windowMenu of menu bar item windowMenu of menu bar 1
Any ideas?

[ Reply to This | # ]
Updated Save script -- for Panther
Authored by: sfreimark on Dec 21, '03 10:02:17AM

Me again. Sorry, I didn't changed the localizations at the beginning of the scripts. Now it's working - except of the same errors you are experiencing (dead URLs, no return delimiters).
Would be glad if someone could solve that problem...



[ Reply to This | # ]
Updated Save script
Authored by: snoozy on Nov 13, '03 11:54:03PM

Actually the original script works fine for me in 10.2.8, and as a lark I tried this updated script and it would not function properly. So I went back to the original script and it is back functioning just grand!

I also saved the scripts as a application to another location and placed them in the dock for quick access.

Thanks again for a fine bit of scripting.



[ Reply to This | # ]
Updated Save script
Authored by: kwaits on Jan 20, '04 02:16:23PM

I'm operatings under 10.2.8. This script DID NOT work. The script breaks down at the "my nextTab()" point following the
-- save the url
set url_list to url_list & firstUrl

command



I get the following error message: Can't make «class pcap» "Safari" of application "System Events" into the expected type.

I let others do my scripting for me, so I have no idea what this means.

But I DO need this refined script, because I want to capture LOTS of Safari tabs, including those in the >> part, and the previous script works, but only captures the tabs in active windows.

Thanks for your help. Even the old script is better than nothing.

---
kwaits



[ Reply to This | # ]
10.3.2 Update
Authored by: mazatty on Jan 17, '04 07:32:21PM
Here is the updated save script for 10.3.2 (Panther). enjoy.


-- 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
set prefs_folder to path to preferences folder as string
set prefs_file to prefs_folder & "Safari Saved URLs"

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

-- let the user know we are done.
tell application "Safari"
    activate
    display dialog "All Done" buttons {"OK"} default button 1
end tell


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



[ Reply to This | # ]
10.3.2 Update works perfectly
Authored by: Safar on Jan 21, '04 10:25:52AM

your update works fine. thank you.



[ Reply to This | # ]
10.3.2 Update Seing Double
Authored by: harywilke on Jan 28, '04 12:34:39PM

when i run the save script it cycles though my tabs twice.
not suprisingly when i run the restore it opens two windows full of restored tabs.

any idea? why i'd be getting doubles? and is GUI scripting now part of the default install for 10.3? i couldn'd find where to download it and the option to enable it under SystemPreferences>UniversalAccess was avalable so i just clikced that



[ Reply to This | # ]
Works nice but...
Authored by: kmue on Feb 02, '04 08:22:12AM
The Update works nice but unfortunatley the tabs of the last window are recorded twice. So if you have just one window with tabs they are all recorded twice.

[ Reply to This | # ]
Works nice but...
Authored by: penum6ra on Feb 23, '04 01:57:12AM

Any fix to this yet?
This is still happening for me too... but the feature is great despite!



[ Reply to This | # ]
This script also works on multiple open windows!
Authored by: bakalite on Mar 25, '04 01:42:48AM

This script is GREAT! It not only restores the tabs, it restores them in multiple windows. Basically, it saves the whole Safari session. This is one of the best hints I've read on this site. Also, this is a feature that I would gladly pay $10 for. I don't know how many times I've done huge searches and wished I could save all the windows with all the tabs so I can come back to it later. Great work!

BTW, the last version works for me under Safari 1.2.1 and OS 10.3.3

Thank You!



[ Reply to This | # ]
Saving and restoring tabs in Safari
Authored by: Bardamard on Apr 28, '04 07:01:09PM
Great hint but wouldn't it be nice to save the information to a file so that you can have a collection of save tab files?? Here is a new script from the one listed that will give you a save dialog box to give it a name and to decide a location.

set url_list to {}

tell application "System Events"
	tell process "Safari"
		
		-- count the windows
		set winCount to count of windows
		
		-- loop through the windows
		repeat with i from 1 to winCount
			
			-- count the tabs
			set tabCount to count of radio buttons of window i
			
			-- loop through the tabs
			repeat with j from 1 to tabCount
				-- activate the tab 
				click radio button j of window i
				
				-- url of window
				set theUrl to value of text field 1 of group 1 ¬
					of splitter group 1 of window i
				
				-- save the url
				set url_list to url_list & theUrl
			end repeat
			
			-- empty line to seprate windows
			set url_list to url_list & ""
		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 to url_list as text
set AppleScript's text item delimiters to old_delim

-- get path to prefs file where URLs will be stored
set prefs_folder to ("iBook1:Users:Shared:MySafariTabs:") as string
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 to open_file starting at eof
	close access open_file
on error
	try
		close access file prefs_file
	end try
end try
I didn't bother to extricate the unneeded code from the script, but it works great. But I did get rid of the unwanted "Done" dialog box. Seems a bit redundant. Here is the Restore All Tabs script with a "choose File" dialog as well. Again I didn't remove the unneeded code.

tell application "Safari" to activate

-- get path to prefs file where URLs are stored
set prefs_folder to path to preferences folder as string
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
Authored by: glowurm on Apr 28, '04 11:22:47PM

That's freeking awesome. Thanks to all contributers.

BTW - The error above about "NSReceiverEvaluationScriptError: 4" was solved for me by making sure I had the "Enable access for assistive devices" option checked in the Universal Access Preference Pane, and running the script as an application from the Script Menu. I also checked the Full Keyboard Access option just to be sure.

Thanks again, all.

PS: Working on OS X 10.3.3, full implementation within 10 minutes, including time to write message here. :D



[ Reply to This | # ]
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 | # ]
Safari Extender
Authored by: mikerose on Aug 16, '04 02:36:56PM
Safari Extender is supposed to do this ($10 shareware) smoothly.

http://batista.org/extender.html

[ Reply to This | # ]

Saving and restoring tabs in Safari
Authored by: gboudrea on Nov 02, '04 10:28:55PM

Saft does this automatically when you close Safari, and restore all tabs and windows when your restart it.

http://haoli.dnsalias.com/Saft/
10$ shareware

does more than just that, but I personally don't use anything else in it.



[ Reply to This | # ]
Saving and restoring tabs in Safari
Authored by: LightYear on Dec 05, '04 03:27:27AM

Righto, dragging this one back to the top. I finally got around to implementing this great feature (which I do miss, using Opera at work) but still found a couple of bugs with the revisions in the comments. Dusting off my Applescript skills (muchly lacking), here's what I found:

You must have "Always show tab bar" enabled in Preferences, Tabs for single page windows to be picked up! This is because the Applescript uses the count of the tabs to determine if we are looking at a browser window (as opposed to the Downloads window or a source window or something). There could well be better ways of determining this, but I'll deal with the tab bar always being there for now.

There were some inefficiences and old code mucking a couple of things up, so here's my version (which does not include the Save dialog feature!) of the Save URLs Applescript.


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

property url_list : {}
property docCount : 0
property frontMostWindow : 1

tell application "System Events"
	tell process "Safari"
		activate
		
		-- count the windows
		set winCount to count of windows
		
		set menuItemCount to count of menu items of menu windowMenu of menu bar 1
		set menuItemOffset to menuItemCount - winCount
		
		set url_list to {}
		
		-- loop through the windows
		repeat with winNum from 1 to winCount
			-- find this window in the Window menu using the window title
			set winTitle to title of window winNum
			
			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
			
			-- Check for browser window
			set tabCount to count of radio buttons of window frontMostWindow
			if tabCount > 0 then
				-- activate the first tab
				click radio button 1 of window frontMostWindow
				
				repeat with tab from 1 to tabCount
					set tabURL to value of text field 1 of group 1 of ¬
					splitter group 1 of window frontMostWindow
					
					-- save the url
					set url_list to url_list & tabURL
					my nextTab()
				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
set prefs_folder to path to preferences folder as string
set prefs_file to prefs_folder & "Safari Saved URLs"

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

-- let the user know we are done.
tell application "Safari"
	activate
	display dialog "All Done" buttons {"OK"} default button 1
end tell


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

---
* Nothing is foolproof to a sufficiently talented fool *

[ Reply to This | # ]

Bugs in this version.
Authored by: papley on Mar 30, '05 07:21:01PM
There are a few things about this that won't work.

One thing that worked in the previous version but doesn't work in this version is handling more tabs than are able to be displayed in the window. When safari can no longer fit all the tabs in the window a drop-down list is provided to access the remaining tabs.

Because you iterate on the count of radio buttons instead of by the number of tabs (which you don't have direct access to) you'll miss any additional tabs.


set tabCount to count of radio buttons of window frontMostWindow 
repeat with tab from 1 to tabCount
       set tabURL to value of text field 1 of group 1 of ¬
       splitter group 1 of window frontMostWindow
       -- save the url
       set url_list to url_list & tabURL
       my nextTab()


[ Reply to This | # ]
Improved version of saving tabs in Safari
Authored by: papley on Mar 30, '05 04:20:28PM
Take a look at this improved version.

http://www.macosxhints.com/comment.php?mode=display&sid=20030913153245341&title=Other+problems+with+this+script+and+another+revision.&type=article&order=&pid=40762


[ Reply to This | # ]
Improved version of saving tabs in Safari
Authored by: sjk on Mar 31, '05 01:43:23PM

Thanks for the improved version! Any chance of making it available via download? It's fairly long so more prone to errors if copied/pasted.



[ Reply to This | # ]
Saving and Restoring Tabs in Safari - Documented and Improved
Authored by: papley on Mar 30, '05 08:12:46PM

-- Save all tabs in Safari, choosing a file to write URL collection. 

(* This script was found in http://www.macosxhints.com/article.php?story=20030913153245341
I found a few problems with the versions in the thread and fixed all of the issues below.

 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. Instead I now check to see if the first tab 
is selected.

 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'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.
		--Therefore, it's better to iterate through the menu items
		--directly, and just skip any items, such as "Downloads" which
		--have no URLs. So we collect the indices here.
		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
		
		--Iterate through the list of browser window indexes.
		repeat with x in browserButtons
			-- Activate each valid browser window in turn.
			-- Here we will lose the order of the windows on 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
--this tell block will bring the save dialog up front as the active window
tell application "System Events"
	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

tell application "Safari"
	activate
	display dialog "All Done" buttons {"OK"} default button 1
end tell

-- This used to assume urls don't repeat within a set of tabs. Not any more. 
-- Now we get the URL from every tab.
property firstTabButton : null
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
				--If there are no tabs at all then then we won't get the contents of this window.
				set firstTabButton to radio button 1 of window (my discoverWinNum(winNum))
				-- Activate the first tab 
				click firstTabButton
				
				-- Get url of first tab
				set firstUrl to my urlOfTab(winNum)
				
				-- save the url
				set url_list to url_list & firstUrl
				
				-- Select the next tab, whether or not there's a radio button for it.				
				my nextTab()
				
				-- Get url of the tab
				set nextUrl to my urlOfTab(winNum)
				
				-- The value of the radio button is magically 1 if it's the current tab,
				-- so we iterate around the 'tab ring' till we get back to the 
				-- beginning.
				repeat until value of (radio button 1 of window (my discoverWinNum(winNum))) is 1
					-- save the url
					set url_list to url_list & nextUrl
					-- Select the next tab and get it's url.
					my nextTab()
					
					-- url of next tab
					set nextUrl to my urlOfTab(winNum)
				end repeat
				-- Append an empty line to separate this window from the next.
				set url_list to url_list & ""
				return
			end if
		end tell
	end tell
end collectURLsFromTabs

on urlOfTab(winNum)
	-- Get the URL from the tab. If necessary wait for the window to finish
	-- initializing before returning the value.
	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

-- Restore Tabs in Safari


--Restore

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.
tell application "Safari"
	activate
	display dialog "All Done" buttons {"OK"} default button 1
end tell

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

Do let me know if you find this useful or you have any additional improvements.



[ Reply to This | # ]

Saving and Restoring Tabs in Safari - Documented and Improved
Authored by: papley on Apr 26, '05 01:58:47PM

I just spent a couple of hours trying to figure out why these scripts I wrote no longer works in version 1.3 (current version as of this date) of Safari. I found several things that have changed. The one detail I can't seem to get is to figure out whether a particular tab is selected. The tab object used to have a value of true if it was the current tab. This is no longer the case, and I can't figure out how to get around this. If anyone knows how to detect whether the first tab in the window is selected please let me know. Comparing the url doesn't work because the url may not be unique.



[ Reply to This | # ]
Saving and Restoring Tabs in Safari - Documented and Improved
Authored by: ehouwink on Jun 28, '05 05:24:15AM
I added some checks on the url field and tab field indexes (that may change with Safari's different view options). Also: modified the prefs file dialog to be more configurable. For the time being, the script works (until Apple, in their wildest fantasies, change Safari's dicitonary again) for Safari 1.3+ int.

-- Save all tabs in Safari, choosing a file to write URL collection. 

(* This script was found in http://www.macosxhints.com/article.php?story=20030913153245341
I found a few problems with the versions in the thread and fixed all of the issues below.

 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. Instead I now check to see if the first tab 
is selected.

 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'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 browserWds : {}
-- This used to assume urls don't repeat within a set of tabs. Not any more. 
-- Now we get the URL from every tab.
property firstTabButton : null

global winTitle, tabgroupNo

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.
		--Therefore, it's better to iterate through the menu items
		--directly, and just skip any items, such as "Downloads" which
		--have no URLs. So we collect the indices here.
		repeat with j from menuItemOffset to menuItemCount -- was menuitemOffset + 1
			set mbut to menu item j of menu windowMenu of menu bar 1
			
			if ((title of mbut) ¬
				does not start with "Downloads") then
				set browserWds to browserWds & {j}
			end if
			
			--	display dialog ("title " & title of mbut & return & return & "browserWds " & browserWds) as string
		end repeat
		--Iterate through the list of browser window indexes.
		repeat with x in browserWds
			-- Activate each valid browser window in turn.
			-- Here we will lose the order of the windows on 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 to url_list as text
set AppleScript's text item delimiters to old_delim
-- Ask user to name a  file where URLs will be stored
set prefs_folder to (path to preferences folder as string) & "Safari:"
set prefs_fold to prefs_folder & "Saved Tabs"
tell application "Finder"
	if not (exists folder prefs_fold) then
		make new folder at prefs_folder with properties {name:"Saved Tabs"}
	end if
	set tNumb to (number of items in folder prefs_fold) + 1
end tell

tell application "Safari"
	activate
	beep
	set fName to text returned of (display dialog "Enter a name…" buttons {"Cancel", "OK"} default button 2 default answer "Safari tabs " & tNumb) --& ".rtf"
end tell

tell application "Finder"
	set prefs_file to make new file with properties {name:fName} at prefs_fold
	set prefs_name to prefs_file as string
	
	set open_file to open for access alias prefs_name with write permission
	-- erase current contents of file:
	set eof of open_file to 0
	write url_list to alias prefs_name starting at eof
	close access open_file
	
	try
		close access file prefs_file
	end try
end tell


tell application "Safari"
	activate
	beep
	set tB to button returned of (display dialog "Your Bookmarks were saved !!" buttons {"Show in Finder", "OK"} default button 2)
	if "Show" is in tB then
		tell application "Finder"
			activate
			open alias prefs_fold
		end tell
	end if
end tell


on collectURLsFromTabs(winNum)
	tell application "Safari" to activate
	tell application "System Events"
		tell process "Safari"
			repeat with tabgroupNo from 1 to 15
				set bNames to name of buttons of group tabgroupNo of window (my discoverWinNum(winNum))
				if "missing value" is not in bNames as string and {} is not bNames then exit repeat
			end repeat
			(*	repeat with urlgroupNo from 1 to 15
				if exists splitter 1 of splitter group 1 of group urlgroupNo of window (my discoverWinNum(winNum)) then exit repeat
			end repeat *)
			set urlgroupNo to 2
			---->>> vooralsnog altijd group2!!! 
			
			
			set firstUrl to ""
			
			-- check for browser window 
			set buttonCount to (count of buttons of group tabgroupNo of window (my discoverWinNum(winNum)))
			if buttonCount > 1 then
				-- lukt niet meer bij Tiger if buttonCount > 0 then
				
				--try
				
				set firstTabButton to button 1 of group tabgroupNo of window (my discoverWinNum(winNum))
				-- Activate the first tab 
				click firstTabButton
				
				-- Get url of first tab
				set firstUrl to my urlOfTab(winNum, urlgroupNo)
				--display dialog firstUrl
				-- save the url
				set url_list to url_list & firstUrl
				
				-- Select the next tab, whether or not there's a radio button for it.                           
				my nextTab()
				
				-- Get url of the tab
				set nextUrl to my urlOfTab(winNum, urlgroupNo)
				
				-- The value of the radio button is magically 1 if it's the current tab,
				-- so we iterate around the 'tab ring' till we get back to the 
				-- beginning.
				set i to 0
				repeat until nextUrl is firstUrl or i > 30 -- werkt niet meer until value of (button 1 of group tabgroupNo of window (my discoverWinNum(winNum))) is 1
					-- save the url
					set i to i + 1
					set url_list to url_list & nextUrl
					-- Select the next tab and get it's url.
					my nextTab()
					-- url of next tab
					set nextUrl to my urlOfTab(winNum, urlgroupNo)
					if nextUrl is firstUrl then
						--say "Go next window"
						exit repeat
					end if
				end repeat
				-- Append an empty line to separate this window from the next.
				set url_list to url_list & ""
				(*on error
					return
				end try*)
			end if
		end tell
	end tell
end collectURLsFromTabs

on urlOfTab(winNum, urlgroupNo)
	-- Get the URL from the tab. If necessary wait for the window to finish
	-- initializing before returning the value.
	
	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 group urlgroupNo of window (my discoverWinNum(winNum))
				-- was: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, urlgroupNo)
				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.
			try
				if (subroleStr is "AXStandardWindow") then
					return winNum
				else
					return winNum + 1
				end if
			on error
				say winTitle as string
			end try
		end tell
	end tell
end discoverWinNum
Eelco Houwink

[ Reply to This | # ]
Saving and Restoring Tabs in Safari - Documented and Improved
Authored by: ehouwink on Jun 28, '05 05:31:32AM
The "restore" script that adheres to this prefs-file location is:


tell application "Safari" to activate

-- Ask user for  file where Tabs were stored
set prefs_folder to (path to preferences folder as string) & "Safari:"
set prefs_fold to prefs_folder & "Saved Tabs:"
set choices to {}
tell application "Finder"
	set lizt to list folder prefs_fold
	if lizt is not "" then
		repeat with i from 1 to number of items in lizt
			if ".DS" is not in item i of lizt then ¬
				set choices to choices & item i of lizt
		end repeat
	end if
end tell
tell application "Safari" to set tFile to (choose from list choices default items (item 1 of choices) ¬
	OK button name "Get these" cancel button name ¬
	"Cancel" without multiple selections allowed)
set tFile to prefs_fold & text items of tFile as string


--try
-- read the saved urls
set open_file to ¬
	open for access alias tFile without write permission
set url_list to read alias tFile 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.
tell application "Safari"
	activate
	display dialog "All Done !" buttons {"OK"} default button 1
end tell

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 - Documented and Improved
Authored by: lrivers on Aug 24, '05 03:37:23PM

This script stalls out and does not progress past the first tab. It seems to loop without incrementing the tab.

There's no split group that I can tell, for one. I can't figure out how to make it work, though.



[ Reply to This | # ]
Saving and restoring tabs in Safari
Authored by: ccstone on Dec 02, '10 08:19:19PM

{Mac OS 10.6.5, Safari 5.0.3}

Not sure if there's any point in adding to this thread at this late date, but I found it while researching something else.

In Safari 5 of course you can save all tabs in the front window at once, however since I often have 5 to 10 windows open with as many as 200 total tabs open I'd rather script it directly if I just want a temporary backup. (UI scripting is cumbersome.)

tell application "Safari"
try
set urlList to URL of tab of every window where its document is not missing value
on error errMsg number errNum
beep
tell me to display dialog "Error: " & errMsg & return & "Error Number: " & errNum
end try
end tell

This script produces a list with sublists of tabs for every document window.

It's easy to write that list to a file as data, so there's no need to convert it to text. You can then read the list as data and simply iterate through it to restore windows and tabs.

If anyone cares I'll post complete scripts.

-ccs



[ Reply to This | # ]