I have used JavaScript to create an array of a couple of URL links on a page.
I want to open each one in a new background tab in Safari.
How can I do that?
I understand I probably need to use AppleScript but I’m not sure how to use the array in AppleScript?
I don’t think that will work.
Open URL opens a new URL in a tab or a window depending on your application setting but it will not be in the background.
PS. Edited my first post to reflect that I was talking about an Array of strings.
I have a script I run to open all my ‘news’ websites. Perhaps this is what you are looking for too. Here is the bash script :
#!/bin/zsh
# URLs to open
read -r -d '' URLS <<'EOS'
https://github.com/trending
http://hckrnews.com/
https://www.reddit.com/
https://www.reddit.com/r/all/
https://www.reddit.com/me/m/apple
https://www.reddit.com/me/m/music
https://www.reddit.com/me/m/linux
https://www.reddit.com/me/m/code
https://www.reddit.com/me/m/web
https://www.reddit.com/me/m/health
https://slashdot.org/
https://www.producthunt.com
EOS
# Split string into array
URLS=("${(@f)URLS}")
for u in $URLS; do
open "$u"
done
Thanks Dan. That link was the one I was looking at.
The problem was that I did not know that I had to split a string into an array.
Thanks to nikivi's script I understood that it was what was needed.
@nikivi could you describe what the script is doing? I'm not good at bash at all
I managed to solve it with AppleScript at last.
I made a version of that script to open Google search results in background tabs:
Well done. The querySelectorAll() Method is spiffy!
Keyboard Maestro uses AppleScript to perform its Execute a JavaScript in Safari action.
If you do the JavaScript in AppleScript the array returns as an AppleScript list, so you can skip a processing step and bypass the Clipboard.
I've added a link limiter property for flexibility, so if your Google search returns 100 items but you only want to see the first X you're covered. Set it to 0 (zero) for no limit.
--------------------------------------------------------------------------------
# Auth: Christopher Stone (Adapted from a script by Eric Bradley)
# dCre: 2016/08/18 00:23
# dMod: 2016/08/18 00:35
# Appl: Safari
# Task: Open Google Search Links in New Tabs – Number limited by ‘linkLimit’.
# Libs: None
# Osax: None
# Tags: @Applescript, @Script, @Safari, @Open, @Google, @URLs, @Tabs
--------------------------------------------------------------------------------
property linkLimit : 10 -- Set to 0 (zero) for no limit.
--------------------------------------------------------------------------------
set jsStr to text 2 thru -1 of "
var x = document.querySelectorAll('.g .rc .r a');
var myArray = [];
for (i = 0; i < x.length; i++) {
myArray.push(x[i].href)
}
myArray;
"
set googleLinks to doJavaScriptInSafari(jsStr)
if length of googleLinks > 0 then
if (linkLimit ≠ 0) and (length of googleLinks > linkLimit) then
set googleLinks to items 1 thru linkLimit of googleLinks
end if
makeSafariTabsFromUrlList(googleLinks)
end if
--------------------------------------------------------------------------------
--» HANDLERS
--------------------------------------------------------------------------------
on makeSafariTabsFromUrlList(urlList)
repeat with i from 1 to number of items in urlList
set x to item i of urlList
tell application "Safari"
tell front window
make new tab at end of tabs with properties {URL:x}
end tell
end tell
end repeat
end makeSafariTabsFromUrlList
--------------------------------------------------------------------------------
on doJavaScriptInSafari(javascriptStr)
try
tell application "Safari" to do JavaScript javascriptStr in front document
on error e
error "Error in handler doJavaScriptInSafari() of library NLb!" & return & return & e
end try
end doJavaScriptInSafari
--------------------------------------------------------------------------------
I don't like having the first line of a text script (JavaScript in this case) misaligned from the rest of it.
set js to "var txt = 'Goofy'
txt;
"
doJavaScriptInSafari(js)
To me this is just pure yuck, so I typically add a blank line to the top of the script.
set js to "
var txt = 'Goofy'
txt;
"
doJavaScriptInSafari(js)
Some command parsers (not JavaScript) choke if the first line you pass them is whitespace, so my convention is to remove that first blank line. I do this with text 2 thru -1 which reads from the second to the last character of the text.
Doing this also allows the script to visualize better in Script Debugger's variable inspector:
When I look at the js variable in the inspector I don't want to see that leading \n – I want to see the beginning of the script.
By chomping that first newline character I get this instead:
The makeSafariTabsFromUrlList handler can be made trifle more efficient:
on makeSafariTabsFromUrlList(urlList)
tell application "Safari"
tell front window
repeat with theURL in urlList
make new tab at end of tabs with properties {URL:theURL}
end repeat
end tell
end tell
end makeSafariTabsFromUrlList
Chris, thanks for sharing your technique about formatting JavaScript in AppleScript.
I totally get your point, and agree with it. You inspired me, and this popped out, perhaps slightly simpler: Just make the first line a comment.
set jsStr to "//
var x = document.querySelectorAll('.g .rc .r a');
var myArray = [];
for (i = 0; i < x.length; i++) {
myArray.push(x[i].href)
}
myArray;
"
If you run the first script below you'll find the output to be a bit confusing.
This is because theItem is a reference (and behind the scenes this list-iteration method is faster).
In the second script to get the output I want i have to de-reference theItem.
--------------------------------------------
set theList to {"one", "two", "three"}
set newList to {}
repeat with theItem in theList
set end of newList to theItem
end repeat
newList
--------------------------------------------
set theList to {"one", "two", "three"}
set newList to {}
repeat with theItem in theList
set end of newList to contents of theItem
end repeat
newList
--------------------------------------------
The confusing part is that in some applications you don't have to manually de-reference theItem – it gets done automagically.
But there's not a specific rule for when this automagic happens, so the only way to be sure it works without manual de-referencing is to test.