Learn How to Easily Make Bookmarklets
Recently I wrote about how you can create your own Chrome extensions to improve the throughput of your workflow and I was wondering whether there are more lightweight alternatives to them.
What if we only want to copy/highlight texts, do things that should require no more than 10 lines of code? Can you think of writing out the same thing over and over again on a daily basis? I definitely can.
Things that are repetitive can always be automated. And if there is an opportunity to automate, then we should invest in it. Time is the most valuable resource we have. It is finite and unlike other assets, it can’t be earned.
So next time if you catch yourself doing the same things day to day, think if those steps can be replaced by a bookmarklet or other automated tool.
What Are Bookmarklets?
A bookmarlet is a bookmark that contains JavaScript code that can enhance your browsing experience
The good thing about bookmarklets is that you can turn any JavaScript code into one. Code pieces that you keep placing into the console can be replaced by them.
So how do you create one? Say we want to highlight outgoing links on a website.
How to Turn JavaScript Code Into a Bookmarklet?
First, you write your JavaScript code inside the console just as usual. Going with the above example, it can be done using the following:
Array.from(
document.querySelectorAll(`a:not([href*="${document.location.hostname}"])`)
).forEach(selector => {
selector.style.background = 'red'
});
I purposefully wrote it in multiple lines. A bookmarklet needs to be compressed into one single line in order for it to work. To minify JavaScript, there are various online tools, so you don’t have to download anything additionally. I’m using Javascript-minifier.com.
A bookmark always points to a website through a link. To make the bookmarklet valid and use JavaScript instead of a link, we need to prefix it with javascript:
. There are two ways to turn a script into a functioning bookmarklet. Using an immediately invoked function or the void
operator.
// Using an IIFE
javascript:(() => {
// Your script goes here
})();
// Using the void operator
javascript:{
// Your script goes here
};void(0);
And to finally add it as a bookmark, open a new tab and click on the star icon inside the address bar.
Name your bookmark and place it into the bookmarks bar. Once that’s done, right-click on the newly created bookmark and click on edit, then replace the URL with the script we created. And that’s it! You’ve just created your first bookmarklet.
A Practical Example
I’ve recently started using Quora and I noticed that the numbers under the stats menu are not equivalent to the number of views added together on my profile’s home page.
That’s reasonable, it would require a ton of resources to keep each user’s stats updating in real-time, so they are updated for a given interval. But what if I want to see them on my profile’s page? Each question’s view count added together. We have them in the DOM so we could easily query them. The problem is they only appear once an answer is uncollapsed. To uncollapse them all we can trigger a click event on each “more” link:
Array.from(document.querySelectorAll('.ui_qtext_more_link')).forEach(item => item.click());
Once we have the views inside the DOM, it’s just a matter of collecting their values and creating a new element for it:
const views = Array.from(document.querySelectorAll('.ContentFooter > span:first-child'))
.map(views => parseInt(views.innerText))
.reduce((a, b) => a + b, 0);
const clone = document.querySelector('.icon_action_bar a').cloneNode(true);
clone.innerText = `${views} views`;
document.querySelector('.icon_action_bar span').appendChild(clone);
This will create a new element, right next to the number of followers on the profile page.
But now, we have another problem. If we try to run this code right after the “more” links are clicked, we will get 0 for the views as the requests haven’t been made by the time the code runs. Luckily, we have jQuery available on Quora which means we can use ajaxStop
. ajaxStop
runs when there are no pending requests left — this is what we are looking for.
Array.from(document.querySelectorAll('.ui_qtext_more_link')).forEach(item => item.click());
jQuery(document).ajaxStop(function () {
const views = Array.from(document.querySelectorAll('.ContentFooter > span:first-child'))
.map(views => parseInt(views.innerText))
.reduce((a, b) => a + b, 0);
const clone = document.querySelector('.icon_action_bar a').cloneNode(true);
clone.innerText = `${views} views`;
document.querySelector('.icon_action_bar span').appendChild(clone);
jQuery(this).unbind('ajaxStop');
});
After we trigger the clicks on the links, we wait for ajaxStop
to be called. It will run once all answers have been loaded successfully. Then we count up the views and display it.
Last but not least, we can unbind the subscription to ajaxStop
to avoid adding the same element multiple times if other requests are being made after using the bookmarklet.
The whole script took less than 15 lines. After minification and adding the javascript:
prefix, we can start using our brand new bookmarklet.
Summary
The possibilities are endless, the complexity can go to infinity. How about writing a bookmarklet that only does one thing? — Inject an external script into the site. The external resource can then pull in a whole application that doubles the user experience by adding various stats about the site and new user functionality.
Some other examples where you can use bookmarklets in a daily basis to boost your productivity can include things like:
- Auto generating branch names based on tickets
- Auto generating pull request descriptions
- Displaying information for items that are only available in the DOM
- Deleting emails older than x days
- You name it
Thank you for taking the time to read this article, happy coding!
Rocket Launch Your Career
Speed up your learning progress with our mentorship program. Join as a mentee to unlock the full potential of Webtips and get a personalized learning experience by experts to master the following frontend technologies: