Using Bookmarklets for Simple Browser Tasks

Bookmarklets provide a way to add small customized tools to your browser. They look like regular bookmarks, but instead of having a “http:” address to a page on the web, they contain Javascript code that runs whenever the bookmarklet is clicked.

Here’s the obligatory “Hello World” demonstration of a bookmarklet: create a new bookmark in your browser, then edit its properties and make this the content of the “location” field (where the “http:” address would usually go):

1
javascript:alert('Hello, World!');

The leading “javascript:” text indicates that this is Javascript code that should be run when the bookmark is clicked (technically, this is simply a different “URL scheme” from the usual “http:”). Now click the bookmarklet and an alert dialog should show.

Here are some of the details for creating good bookmarklets:

  • all javascript code must be on a single line – separate multiple statements with semicolons
  • wrap the code in an anonymous function to control scope of variables: “javascript:(function(){ … })();”
  • define any variables used in the bookmarklet with ‘var’ – make them local to the wrapping function
  • always use single quotes in the javascript code, never double quotes
  • the code must not return any value: a return value other than undefined would replace the current page content
  • encode some special characters
    • double quote (“): %22
    • less than (<): %3C
    • greater than (>): %3E

Why is it a good idea to surround the code of a bookmarklet with an anonymous function? Try putting this in a bookmark and click it:

1
javascript:alert('Hello, World!'); "<h2>Goodbye!</h2>"

If the javascript code in the bookmarklet has a last statement that evaluates to a defined value, the browser will replace its current content with that value. So clicking this bookmarklet will first display the alert dialog over whatever page the browser is on; when the alert dialog is replaced, the browser will erase the current page and then show a simple blank page with “Goodbye!” on it.

Now wrap an anonymous function around the content of the javascript code in the bookmarklet:

1
javascript:(function(){alert('Hello, World!'); "<h2>Goodbye!</h2>"})();

Clicking this will display the alert, and the browser will stay on the page when the alert dialog is dismissed. The incidental value at the end of the javascript code is never returned from the function. In real world cases you’d be trying to protect against functions that may be used in the bookmarklet and that may return a value.

If the code inside the bookmarklet sets any variables, they may get set on the window object, and may interfere with the parent page working correctly. Always define variables in a bookmarklet with ‘var’ so that they’re made local to the anonymous function.

Here is a more substantial example of a bookmarklet implementation: a “night mode” bookmarklet that will set the background of all divs, spans, and other block elements to be black with white foreground (for text). Useful for cutting down the glare when reading web pages at nighttime!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
javascript:(function () {
    var eltypes={'BODY':1,'DIV':1,'SPAN':1,'TH':1,'TD':1,'LI':1,
            'A':1,'H1':1,'H2':1,'H3':1,'H4':1,'H5':1,'PRE':1,
            'HEADER':1,'FOOTER':1,'ARTICLE':1,'NAV':1,'ASIDE':1},
        fgcolor='#DDD',
        bgcolor='#222';
    var all_els=document.getElementsByTagName('*');
    for(var i=0;i< all_els.length;i++) {
        var el= all_els[i];
        if (eltypes[el.tagName]) {
            el.style.color=fgcolor;
            el.style.backgroundColor=bgcolor;
        }
    }
})();

When developing a bookmarklet, it’s handy to have the code on multiple lines in order to develop it. But the final product has to all be on one line. Uglify-js can be used to render the code for a bookmarklet to one line, compressing it in the process to minimize its size.

$ npm init
...the usual params...
 
$ npm install --save-dev uglify-js
 
$ grep -A 2 scripts package.json  ## added an "uglify" script to package.json
  "scripts": {
    "uglify": "uglifyjs -m -c"
  },
 
$ npm run-script uglify < nite.js
 
> bookmarklets@0.0.1 uglify /Users/joedev/example-code/bookmarklets
> uglifyjs -m -c
 
!function(){for(var e={BODY:1,DIV:1,SPAN:1,TH:1,TD:1,LI:1,...more content...}}();

Copy the output to the “location” field of a bookmark, prefixing “javascript:” to it.

A Security Note

Some web sites offer a bookmarklet to enhance the use of their site. Because the javascript code in a bookmarklet has full access to the DOM in any web page that’s displayed in the browser, you should only install bookmarklets from well know and trusted sources.

Final thoughts

The bookmarklet feature, supported by all browsers for a long time, provides a way to implement small tools that can interact with the content of whatever web page is current in the browser. The javascript has full access to the DOM in the browser window and can read it, write to it, and modify it.

Versions

$ npm –version
3.10.10

$ node_modules/.bin/uglifyjs -V
uglify-js 3.3.12

Add a Comment