Don’t pollute the global namespace: You don’t want to mess up the environment of the web site “in which” your bookmarklet is executed. For example, by using an Immediately Invoked Function Expression (IIFE) the variable t won’t become global, below.
(function() { var t=document.title; console.log("Title: "+t); }())Develop in strict mode: If you switch on strict mode, JavaScript warns you about more potential problems. Later on, you can switch it off so that the bookmarklet URL is more compact, but for development, it is very helpful. For example, the code below inadvertently creates a global variable, because a var has been forgotten. The output is abc.
(function() { t = "abc"; }()); console.log(t);Strict mode, however warns you that there is a problem:
(function() { "use strict"; t = "abc"; }());Result: ReferenceError: assignment to undeclared variable t
Finish with undefined: If you don’t return (or finish with!) undefined, the result replaces the current web page. [Note: Webkit browsers such as Chrome and Safari never replace a page, only non-Webkit browsers such as Firefox do.]
javascript:window.open("http://www.whitehouse.gov/") javascript:void window.open("http://www.whitehouse.gov/")
var d = document; var s = d.createElement('script'); s.src='https://ajax.googleapis.com/.../jquery.min.js'; s.onload = function() {...}; d.getElementsByTagName('head')[0].appendChild(s);Caveat: A bookmarklet is subject to the same restrictions as the page on which it is executed. Thus, invoking a bookmarklet on an online page cannot load files from your local hard drive. This is unfortunate, because it would allow you to put most of the code of a bookmarklet into an (offline-accessible) separate file.
Parse HTML manually: Standard DOM provides several methods that let you retrieve HTML elements from the current page.
[].forEach.call( document.getElementsByTagName("a"), function(x) { console.log(x); });forEach() is an array method (available in ECMAScript 5). By using call(), you can apply it to the non-array returned by the DOM. The DOM frequently returns array-like objects that look like arrays, but are not.
Using jQuery: jQuery is very helpful for extracting information from a web page. But you want to avoid the jQuery instance that you load from clashing with a jQuery instance that the page uses. The following code shows you how to do that.
jQuery.noConflict(true)(function($) { // code using jQuery });This reverts everything to the way it was before loading jQuery. The true argument means that in addition to the global variable $, jQuery will also be reverted to is prior value (if any). The jQuery web site has more information on jQuery.noConflict().
Transform HTML with JQuery: The following code snippet prepends the text "BLA: " to each <h3> tag in the current web page. You can run it in Firefox on a web page that has many of those tags (for example: spiegel.de).
var d = document; var s = d.createElement('script'); s.src='https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js'; s.onload = function() { jQuery.noConflict(true)(function($){ $("h3").each(function(i,e) { e.innerHTML = "BLA: "+$(e).text(); }); }); }; d.getElementsByTagName('head')[0].appendChild(s);
Show output in the current tab:
document.body.innerHTML="<h1>Hi!</h1> Test!";
Show output in a new tab:
var d=window.open().document; d.write("<html><body><h1>Hi!</h1> Test!</body></html>"); d.close();
$ java -jar yuicompressor-2.4.6.jar copy_url.jsThe following code has been minified by YUI Compressor.
The original looks as follows.javascript:(function(){var e=window.open().document;var c=(window.getSelection?""+window.getSelection():"").replace("<","<");var b={h:document.location.href,t:document.title,st:(c?"\n\n"+c:c),sh:(c?"<br>"+c:c)};e.write(("<html><head><title>Copy link: {t}</title></head><body><a href='{h}'>{t}</a>{sh}<br><br><textarea id='text' cols='80' rows='10'>{t} {h}\n\n<a href='{h}'>{t}</a>{st}</textarea></body></html>").replace(/{([a-z]+)}/g,function(d,a){return b[a]}));e.close()}())
(function() { var d=window.open().document; var s=(window.getSelection?""+window.getSelection():"") .replace("<","<"); var a={ h: document.location.href, t: document.title, st: (s ? "\n\n"+s : s), // selection as text sh: (s ? "<br>"+s : s) // selection as HTML }; d.write( ("<html><head><title>Copy link: {t}</title></head><body>" +"<a href='{h}'>{t}</a>{sh}<br><br>" +"<textarea id='text' cols='80' rows='10'>" +"{t} {h}" +"\n\n<a href='{h}'>{t}</a>" +"{st}" +"</textarea>" +"</body></html>" ).replace(/{([a-z]+)}/g, function(g0,g1){return a[g1]}) ); d.close(); }())This code is the “copy link” bookmarklet, which uses two notable techniques:
> "javascript:"+encodeURIComponent('alert("hello: world/universe")') 'javascript:alert(%22hello%3A%20world%2Funiverse%22)'Try out the link inside the single quotes in a browser, it correctly brings up an alert.
<a href="alert("hello: world/universe")">link</a>The following table shows you what to escape:
Escape as < < > > " " ' '
location.href='http://example.com/postLink?url=' + encodeURIComponent(location.href);
js 7*45And “go” to the following URL:
javascript:alert(7*45)The blog post “Tip: use JavaScript as a calculator in Firefox and Chrome” has more details.