Address Bar Scripts

Copyright © 2005 by Pteromys Fortissimus.
Permission is granted to mirror this article as-is.

Introduction

A few of my friends have watched me do silly things by typing funky stuff into the address bar, and several have asked me how I do it. The idea is simple: in a modern browser (Internet Explorer or Firefox will do), you can execute arbitrary javascript code wherever you can enter an Internet address (URL). The concept comes from bookmarklets.com, and they have a number of scripts you can use in this manner from your bookmarks/favorites menu.
I'm going to assume that you have some familiarity with javascript in your favorite browser, whichever it may be. Those who would like to learn javascript can find a fairly decent tutorial at http://htmlgoodies.com/primers/jsp/. Nearly everybody will want to keep a window or a tab open to some sort of javascript reference. I suggest this one at www.devguru.com.
Now, if you're ready, let's get cracking!

The Basics

The javascript: Prefix

A normal Internet address begins with the string http://. This indicates that the browser should use the HTTP protocol to fetch a file or something like that. To tell the browser to execute javascript code, all you need is to begin it with the string javascript:.
So, let's construct a script. I like to start with simple things, so we'll use the javascript alert method. We take our command and we add the required prefix to it:
javascript:alert('Hello world!');
You can type that into your address bar, or you can just click on it. Go ahead, try it. It does exactly what you'd expect.
Now you might notice that I've used single quotes. Why? Well, if I were to type this into the address bar, it would work with either single or double quotes. However, since I had made it into a link and used double quotes around the link, I had to use single quotes inside the javascript. Fortunately, there's a way around that. If you take advantage of HTML character codes, you'll be able to use both single and double quotes. Use ' for single quotes and " for double quotes. In this way, the above code snippet could be rewritten to use double quotes in a link:
<a href="javascript:alert(&quot;Hello world!&quot;);">Link text</a>
This produces: Link text
Try making use of what you learned. Use the javascript: prefix and try to execute some code. Here are some examples for you to try (copy and paste into your address bar, or just click on them).
javascript:alert(document.title);
javascript:alert(document.links[0].href);
javascript:alert(document.body.innerHTML);
javascript:alert(document.getElementsByTagName("div")[0].innerHTML);

Putting Your Code in a void();

If you tried to execute something other than an alert, chances are you didn't get what you expected. For those of you who didn't try, use the code below. It appears that it should set the background color of the page to red, right?
javascript:document.body.style.background = "#ff0000";
Well, that almost worked. On my computer, the background flashes red, and then the browser goes to a page with only the text "#ff0000".
So what went wrong? Well, I don't actually know for sure. My guess is that when code gives a return value, the browser interprets that as document text and loads it into the window. Certainly, if we keep the code from returning a value, it seems to behave the way we want it to. (Since the alert method does not return a value, we were able to use it without any trouble.)
An expression placed in a void(); will execute without returning a value. We make use of this in our script:
javascript:void(document.body.style.background = "#ff0000");
Well, it worked, but that color is awful! Refreshing the page effectively undoes any modifications you make to a page, so let's hit "refresh" to return the background to its original color.
If you want to execute more than one line of code, you can use a single void(); and separate your statements by commas rather than semicolons, or you can just use void(); multiple times. The following scripts perform the same function: they change the background to black and then change the text color to white.
javascript:void(document.body.style.background = "#000000"); void(document.body.style.color = "#ffffff");
javascript:void(document.body.style.background = "#000000", document.body.style.color = "#ffffff");

Uses and Applications

Integrating with a prompt();

The nice people at Bookmarklets have a few scripts that take user input. They're not terribly difficult to write; you can do it yourself!
The prompt method takes one required argument (the message) and one optional argument (the default input). It returns a string containing whatever the user types in.
Our example will be a script that sets the page background to an arbitrary color obtained from user input. We need our script to (1) set the page background to the value received when we (2) pop up the prompt. It sounds simple enough.
javascript:void(document.body.style.background = prompt("Enter a background color", "#ffcc99"));
Not bad, eh? If you went with the default, it made the background a pretty orange color.

Adjusting Element Properties

Sometimes you'll come upon a page with a fixed-width table that's too wide for your screen or your tastes. Sometimes you want to quickly see the extent of an element on the page. Sometimes you just want to tweak things.

Adjusting Styles

One of the most often adjusted things is the style listing of an object. To edit the style, you would set (object).style.(property) to some value. The object should be some element on the page. The property can be any valid CSS property, such as background, margin, width, or something like that.
A Note About Hyphens
If you've ever tried to access a CSS property such as font-family, you've realized that it doesn't work. The hyphen becomes the subtraction operator in javascript, so how are you supposed to change CSS properties with hyphens in them? The answer is to delete the hyphen and capitalize the next letter. So, font-family becomes fontFamily. See below for an example.

Accessing Images by document.images[]

There are various ways to access elements on the page. If you're accessing an image, you can use document.images[(index)]. As an example, we will change the width of the first image on this page.
document.images[0]
javascript:void(document.images[0].style.width = "24px");
javascript:void(document.images[0].style.width = "48px");
Swapping Images
While we're at it, we can change the src attribute of the image too. This lets us swap one image for another, sometimes leading to funny results.
javascript:void(document.images[0].src = "/bigseed.png");
javascript:void(document.images[0].src = "/slice.png");

Accessing Identified Elements by document.getElementById();

If our element has its id attribute set, we can access it using document.getElementById();. For example, this paragraph has the id some_div. We'll change this paragraph's background to pink:
javascript:void(document.getElementById("some_div").style.background = "#ffccff");

Accessing Unidentified Elements by document.getElementsByTagName();

Suppose the element isn't named. Then we have to resort to the ugly but powerful document.getElementsByTagName();. In this example, we'll change the font of the 4th <h4> tag on this page:
javascript:void(document.getElementsByTagName("h4")[3].style.fontFamily = "monospace");
Interesting, huh? Note that I used fontFamily instead of font-family. An explanation is given above.

Editing and/or Deleting HTML

This one is lots of fun to play with, and also sometimes useful.

Replacing an Element's innerHTML

This is the simplest editing operation. Accessing (element).innerHTML will give you the HTML code between that element's start and end tags. In this example, I have a <span> tag with the id quick_brown_fox. We will replace its contents with something different.
HTML code: <span id="quick_brown_fox">The quick brown fox jumps over the lazy dog.</span>
The quick brown fox jumps over the lazy dog.
javascript:void(document.getElementById("quick_brown_fox").innerHTML = "Jackdaws love my big sphinx of quartz.");

Running a Search-and-Replace

Suppose you want to replace some text in a page. This is a more complicated task. We need to (1) change the body's HTML code to (2) a string of the old HTML code in which (3) one instance (or all instances) of a certain phrase are replaced with a different phrase. For (1), we'll need to access document.body.innerHTML. For (2), we need to use the String constructor. For (3), we'll take advantage of the String object's regular expression search-and-replace capability.
I won't go into much detail on regular expressions here, but you'll be able to find some valuable information on them at http://www.regular-expressions.info/tutorial.html
Now we construct our example. In this example, we will replace all occurrences of HTML header tags with textareas.
javascript:void(document.body.innerHTML = String(document.body.innerHTML).replace(/<(\/?)h[1-6][^>]*>/g, "<$1textarea>"));
That seems to have caused a moderate amount of chaos. Let's refresh the page and continue.
Most of that code should be comprehensible to you, except perhaps the expressions inside replace. I'll explain...
The operation replaces all matches of /<(\/?)h[1-6][^>]*>/g with "<$1textarea>". I wrote the regular expression in the format /(stuff)/g, putting the regular expression itself in (stuff) and using the g to indicate that it should return all matches, not just the first one.
In <(\/?)h[1-6][^>]*>, I started with the < character, which simply matches itself in text. This makes it start at the first character of an HTML tag.
I continued with the expression \/? in parentheses. I wanted to match a forward slash, but since I used the forward slash to delimit my expression, I had to precede this particular one with a backslash to indicate that it was not supposed to have any special meaning. The question mark indicates that it should match either once or not at all. In this way, I manage to match (1) the start of an HTML tag, and (2) the forward slash that denotes a closing tag, if it is there. The parentheses cause the expression to be remembered as $1, which I have used in the replacement string "<$1textarea>". If it matched an opening tag, the replacement text will be an opening tag. If it matched a closing tag, the replacement text will be a closing tag.
Next come the letter h and the character class [1-6]. This matches a letter "h" and then any digit between 1 and 6, so all the header tags (h1, h2, h3, etc.) are covered.
I then included [^>]*. The caret at the beginning of a character class indicates that the expression should match any character that is not listed there. The asterisk indicates that it can match any number of times or even not at all. Thus, this part of the expression will match a string of characters that does not contain a right angle bracket. This is to accommodate for any attributes that may be in a header tag.
I ended with >, to match the end of an HTML tag.
Now you know how to conduct a search-and-replace. This opens lots of possibilities for you. Have fun!

Viewing Source Code

This one sounds easy enough. All you have to do is retrieve the code between the <html> and </html> tags and show it in a pop-up message, right? Let's try that.
javascript:void(alert(document.getElementsByTagName("html")[0].innerHTML));
Well, yuck. That goes right off the screen, and we can't have that happening. Let's see if we can stick our code in a real window. We'll need to (1) open a window, (2) insert the (3) HTML code, and (4) close the document. We have to make up a variable to store the window handle in. We have no other scripts currently running, so we won't run into any conflicts, and any variable name will do. I've broken the code into lines for readability, but when you actually execute the code, you have to type it in as one line. Execute the code, then close the new window/tab when you're done.
javascript:void(
hwin = window.open("about:blank","sourcelist"),
hwin.document.write(document.getElementsByTagName("html")[0].innerHTML),
hwin.document.close()
);
That's not what we expected; it just duplicated the page!
We're writing HTML code to a window, so if we just leave it untouched, the browser will render it as a page. The solution is to use escape sequences. We'll need to (1) escape ampersands and (2) escape angle brackets.
javascript:void(
hwin = window.open("about:blank","sourcelist"),
str = String(document.getElementsByTagName("html")[0].innerHTML),
str = str.replace(/&/g, "&amp;"),
str = str.replace(/</g, "&lt;"),
str = str.replace(/>/g, "&gt;"),
hwin.document.write(str),
hwin.document.close()
);
Wow, that's still ugly. It spits out the whole thing in one blob. To fix it, we'll edit the page style and set the white-space property to pre. While we're at it, we'll add in the <html> and </html> tags, since we notice we're missing them.
javascript:void(
hwin = window.open("about:blank","sourcelist"),
str = String(document.getElementsByTagName("html")[0].innerHTML),
str = str.replace(/&/g, "&amp;"),
str = str.replace(/</g, "&lt;"),
str = str.replace(/>/g, "&gt;"),
hwin.document.write("&lt;html&gt;\n" + str + "\n&lt;/html&gt;"),
hwin.document.close(),
hwin.document.body.style.whiteSpace = "pre"
);
We could continue to expand on this, changing the font, adding syntax highlighting, editing indentation, etc. I'll leave that as an exercise for the reader.

Peeking into Google

There are quite a few people who use Google's Gmail service. Since much of it runs on javascript, you might be curious to see how it works. Since I don't understand the source code myself, I'm not going to explain it to you, but I'll show you how to get to it.
The scripts I give you in this section are not intended to be executed on this particular page. Therefore, I have not made them clickable. If you wish to execute the scripts, you will have to copy and paste them into the address bar yourself.
I login at Gmail, and the first thing I do is use view the source of the entire page (not just the main frame) from my browser's menu. All I end up with is an embedded script, a noscript block, and no content.
Not to be discouraged, I scroll up and find the address bar script that lets me view the source code. I copy and paste that (as one line) into the address bar and hit enter. Again I end up with the noscript block, but now the embedded script is replaced by a frameset tag! Now I'm getting somewhere!
So now I'd like to know where the frames are. I use window.frames[(index)] to access browser information about the frames. I enter each script below into my address bar.
javascript:void(alert(window.frames[0].location));
javascript:void(alert(window.frames[1].location));
That's not much use... but I can certainly can alter my source-viewing script to view the source from the frames.
I choose to examine frame 0 first. I again use window.frames[(index)] to access the code. I execute the address bar script and it spits out something without line breaks! So, I make another edit and cause it to add a line break before every tag. This should make it much more readable:
javascript:void(
hwin = window.open("about:blank","sourcelist"),
str = String(window.frames[0].document.getElementsByTagName("html")[0].innerHTML),
str = str.replace(/&/g, "&amp;"),
str = str.replace(/</g, "\n&lt;"),
str = str.replace(/>/g, "&gt;"),
hwin.document.write("&lt;html&gt;\n" + str + "\n&lt;/html&gt;"),
hwin.document.close(),
hwin.document.body.style.whiteSpace = "pre",
hwin.document.body.style.fontFamily = "monospace",
hwin.document.body.style.background = "#ffffcc"
);
Well, it's still not perfect, but I notice at once that there are lots of iframe tags. Iframes can be accessed just as regular frames, so I do that:
javascript:void(
hwin = window.open("about:blank","sourcelist"),
str = String(window.frames[0].frames[prompt("Frame #? (0 to " + (window.frames[0].frames.length-1) + ")",
"0")].document.getElementsByTagName("html")[0].innerHTML),
str = str.replace(/&/g, "&amp;"),
str = str.replace(/</g, "&lt;"),
str = str.replace(/>/g, "&gt;"),
hwin.document.write("&lt;html&gt;\n" + str + "\n&lt;/html&gt;"),
hwin.document.close(),
hwin.document.body.style.whiteSpace = "pre",
hwin.document.body.style.fontFamily = "monospace",
hwin.document.body.style.background = "#ffffcc"
);
I copy and paste the obtained source listings into my favorite text editor. I can analyze them later.
I go to frame 1, using this code again:
javascript:void(
hwin = window.open("about:blank","sourcelist"),
str = String(window.frames[1].document.getElementsByTagName("html")[0].innerHTML),
str = str.replace(/&/g, "&amp;"),
str = str.replace(/</g, "&lt;"),
str = str.replace(/>/g, "&gt;"),
hwin.document.write("&lt;html&gt;\n" + str + "\n&lt;/html&gt;"),
hwin.document.close(),
hwin.document.body.style.whiteSpace = "pre",
hwin.document.body.style.fontFamily = "monospace",
hwin.document.body.style.background = "#ffffcc"
);
Suddenly I see more code than I thought could exist in the world. It's almost certainly machine-generated; it looks like the people at Google have somehow post-processed their code. I save the source listings on my hard disk so that I may come back to them when I'm bored someday.
I log out of Gmail and notice their space counter. A quick peek at the source code reveals it's also driven by javascript. Somewhere in the code, there's a line that says var CP = ... and is followed by a couple of ordered pairs. Each ordered pair contains (1) a huge number and (2) a number just over 2000. It looks like the first number is a date and the second number is a storage quota. It appears that they're interpolating linearly between the dates given. Of course, that huge number is meaningless as it is, so we can use an address bar script to analyze it...
javascript:alert((new Date(eval(prompt("Enter the huge number", "1117609200000")))).toString());
Hopefully you've learned something new about Gmail today. I certainly did.

Useful Resources