Bookmarklets
Someone at Clearleft asked me a question recently about making bookmarklets. I have a bit of experience in that department. As well as making a bookmarklet for adding links to my own site, there’s the Huffduffer bookmarklet that’s been chugging away since 2008.
I told them that there are basically two approaches:
- Have the bookmarklet pop open a new browser window at your service, passing in the URL of the current page. Then do all the heavy lifting on your server.
- Have the bookmarklet inject JavaScript to analyse and edit the DOM of the document in the current browser window. All the heavy lifting is done directly in client-side JavaScript.
I favour the first approach. Partly that’s because it makes it easier to update the functionality. As you improve your server-side script, the bookmarklet functionality gets better automatically. But also, if your server-side script doesn’t do its magic, you can always fall back to letting the end user fill in the details.
Here’s an example…
When you click the Huffduffer bookmarklet, it pops open this URL:
https://huffduffer.com/add?page=…
…with that page
parameter filled in with whatever page you currently have open. Let’s say I’ve got this page currently open in my browser:
https://adactio.com/journal/6786
If I press the Huffduffer bookmarklet, that will spawn a new window with this URL:
https://huffduffer.com/add?page=https://adactio.com/journal/6786
And that’s all it does. Now it’s up to that page on Huffduffer to figure out what to do with the URL it has been given. In this case, it makes a CURL request to figure out what to use as a title, what to use as a description, what audio file to use, etc. If it can’t figure that out, I can always fill in those fields myself by hand.
I could’ve chosen to get at that information by injecting JavaScript directly into the page open in the browser. But that’s somewhat invasive.
Brian Donohue wrote on Ev’s blog a while back about one of the problems with that approach. Sites that—quite correctly—have a strict Content Security Policy will object to having arbitrary JavaScript injected into their documents.
Content Security Policies (https://en.wikipedia.org/wiki/Content_Security_Policy) are great except that they prevent bookmarklets like @instapaper from loading. 😐
— Jason Garber (@jgarber) March 16, 2016
But remember this only applies to some bookmarklets. If a bookmarklet just spawns a new window—like Huffduffer’s—then there’s no problem. That approach to bookmarklets was dismissed with this justification:
The crux of the issue for bookmarklets is that web authors can control the origin of the JavaScript, network calls, and CSS, all of which are necessary for any non-trivial bookmarklet.
Citation needed. I submit that Huffduffer and Instapaper provide very similar services: “listen later” and “read later”. Both use cases could be described as “non-trivial”. But only one of the bookmarklets works on sites with strict CSPs.
Time and time again, I see over-engineered technical solutions that are built with the justification that “this problem is very complex therefore the solution needs to be complex” (yes, I am talking about web thangs that rely on complex JavaScript). In my experience, it’s exactly the opposite way around. The more complex the problem, the more important it is to solve it in the simplest way possible. It’s the only way of making sure the solution is resilient to unexpected scenarios.
The situation with bookmarklets is a perfect example. It’s not just an issue with strict Content Security Policies either. I’ve seen JavaScript-injecting bookmarklets fail because someone has set their browser cookie preferences to only accept cookies from the originating server.
Bookmarklets are not dead. They may, however, be pining for the fjords. Nobody has a figured out a way to get bookmarklets to work on mobile. Now that might well be a death sentence.