Chris Weirup

Random ramblings

Capture Selection in Safari App Extension

Posted at — Jun 3, 2020

My Joplin Web Clipper for Safari includes support for clipping any selection the user made in the current web page. The Chrome/Firefox version does a nice job of this by grabbing whatever the user selects from the browser window, parsing the selected DOM, and sending it to Joplin.

The issue is that when you load the Popover, Safari drops your selection in the main browser window. Why it does this, I have no idea. What’s stranger, if you have any of the Developer Tools open (say the Console or Source Code), then the selection is actually preserved when you launch the Popover.

To get around this, I started by “borrowing” (stealing) from Bookmarker for Pinboard. Basically, I kept track of any selection changes a user makes in my content script and store that in a global variable. If the user selects the “Clip Selection” option, my content script sent the text of that selection back to the App Extension. The issue was it only sent back the text, not any of the other content or styling. To do that, I needed to capture the Range.

So instead, I now store additional values related to the Range of the selection (still continuing to track selection changes). I did the “stole code from StackOverflow” thing and used this approach.

I need to store:

I can use all of this to build a Range object to recreate the selection when Clip Selection is selected. It seems like overkill, but it works.

There is one problem I’ve found. If a user is running the StopTheMadness extension and has Text selection option turned on, this won’t work any longer, as I can no longer track selection changes. Nothing I can do about that, other than disable that option in StopTheMadness.

At some point, I hope to find a better solution to this, For now, this is acceptable.