Modifier(s) + Click to Copy URL from Hyperlink?

Ok here's what SHOULD work but I'm a little perplexed because suddenly my AppleScript is NOT fetching the LAST url in Safari, even though it was earlier. My knowledge of AppleScript is very poor.

There are two differences here. The first is that the CMD modifier is BLUE in the first action, the second is that I inserted the word LAST in the AppleScript.

This should work, but I appeal to JM, who is an AppleScript expert, to tell me why it's not fetching the LAST tab URL but the CURRENT one.

If that is the case, it sounds much like a macro I use many times a day to select a link from a Google Search:

I just enter the number of the search results I want:

image

Is that what you're looking for?

Wow, GG, I had no idea that mechanism even existed. That indeed makes you an expert.

Your approach seems better than mine already. Not that mine is bad, but yours is smarter.

Any idea why my AppleScript isn't fetching the URL from the last tab?

1 Like

This would be great except that I'm being selective with what results I'm pulling.

In a given list I'll only want half or so and that's a decision I'm making every time I look at a link.

I'm empathetic with your requirement. GG provided a new idea that I hadn't realized was even possible. I had no idea you could type letters when a pop-up menu appeared. This is amazing. It opens up new possibilities. My solution is not as elegant but might still be shorter and easier to understand.

Nice! Didn't realize you could type in copy link to select it which makes this feasible, also thanks providing the url opening macro.

1 Like

Hey GG, your code shows a need for a feature in KM that we don't have. We need a condition that allows us to test for a change in an expression. That would reduce the number of variables and statements in all of my programs.

There would be various ways to implement this, but I would prefer a pull down so that I could replace "returns true (non-zero)" in your Pause Until action with "changes". Do you see my idea?

In Safari's AppleScript dictionary, there's only one document, the one of the currently open tab, so "last document" is no different from the first or current document. What you want is

tell application "Safari"
	tell front window
		return URL of last tab
	end tell
end tell

While I'm at it, I'm afraid even this wouldn't get the URL of a tab opened in the background with a command-click, since tabs opened like that open directly to the right of the current tab, which may or may not be the last/right-most tab in the window, so to get the URL of a background-opened tab, we would need something like

tell application "Safari"
	tell front window
		set CurrTab to current tab
		return URL of tab behind CurrTab
	end tell
end tell

No problem. Typing to select an open menu item, either from the menu bar or a right-click menu, is something we've long been able to do on macOS; KM just makes it easy to automate :slightly_smiling_face:

Why not just use "Pause Until none of the following are true"?
09%20PM
That's something you can do right now, and seems like it would accomplish the same goal, since you could re-use the same expression from an earlier calculation with this pause.

Thanks for the correction on the current tab. I must have misread that.

The "Pause Until none of the following are true" options doesn't help me at all. I'm looking for a feature that tells me when an expression has changed. I need this all the time, and your code also needed it. but that feature doesn't exist.

No problem. I wouldn't know that about the Safari document model either if I didn't have Script Debugger.

I'll take your word that you could use an "expression changed" condition in your own macros, but at least in this use case, I don't see how mine needed it here. To verify that the clipboard has changed the macro needs to check the CLIPBOARDSEED() state once before the attempted copy operation, then again after the copy should have been completed. It's not enough to just check that CLIPBOARDSEED() has changed, it needs to be explicitly checked against a pre-copy state, which as far as I can tell this requires two actions at a minimum, and I'm not currently seeing any advantage to having that second action be "Pause until this expression changes" instead of "Pause until this calculation is no longer true." How would a "Pause until this expression changes" condition reduce the number of actions required or otherwise improve the code in a situation like this?

Sorry, perhaps I misread your code. I thought you were just looking for a change in the expression.

So I've made the attached macro which almost does what you want. The trigger is a hotkey (set it to whatever you want) that does not utilise a mouse click so you need to hover the mouse over the link and then use your other hand to activate the hotkey. This could be done with a mouse button as another option but then you'd need to handle ignoring the actual mouse click. I suspect my way works fine.

It uses javascript to grab the url of the link element that you're hovering over and append it to a variable. It then inserts a linefeed into the variable so that all of your URLs are on separate lines for easy looping when you want to open them all as tabs.

Handy gif showing it working right at the bottom of this post.

Warranties definitely not given, this has zero error handling.

grab link and append to variable Macro (v9.0.1)

[forum] grab link and append to variable.kmmacros (2.3 KB)

https://gfycat.com/dismallivebanteng

4 Likes

This is excellent, Vincent. I was hoping there was a better way to acquire URLs from hyperlinks than automating the right-click menu, and this is much better. I think I'd have the macro perform slightly different actions after executing the JavaScript to, IMO, make it a bit clearer what it's doing with the results, but that's just a matter of preference:

Copy Hyperlink, Append to List of URLs 1.1.kmmacros (2.2 KB)
image

Thanks again for a great contribution.

1 Like

Thanks Vincent, this is exactly what I'm looking for, looking forward to trying it out

Yup, that would be the Javascript code that I mentioned earlier might solve this problem. I just had no idea how to figure that out.

I understand why a "pause until expression changes" statement wouldn't help in your case, because in this case the clipboard may have changed before the first iteration of the "pause until expression changes" test in which case it will never detect the change. Although even if that was the case you could probably address the majority of the problems with a timeout, say 1 second. But we don't want 99% successful code, we want 100%. So I agree in your case it's not a good idea.

When I consider my requirements I see that some of my situations may face the same problem that you are facing. That is, in some cases I need to start monitoring the changes after some statement. For example I may want to click on a button on a web page and then wait for the button to change colour. Normally this won't be a problem because web pages take roughly one second to get to me from the internet, so I don't have to worry about that.

So to make this idea work 100% reliably my idea would require an action which allows an internal statement. For example to apply my idea to your situation it would have to look like this:

If it isn't apparent, the condition at the bottom of this hypothetical new action is first evaluated BEFORE the block of code, then retested over and over once the block of code is finished.

I think this action would meet your requirement and eliminate your need for the LocalCBSeedBefore variable and the action to set it. Of course Peter doesn't introduce new actions unless there is a compelling need, and I'm doubtful everyone would use this construct. So I don't expect Peter to comment on it here.

This is terrific Vincent. Just when I think I have KBM figured out, a whole new realm of possibility. Thank you!