How to use the DOM Inspector to hack your Firefox UI

Before Firefox 3 was released I wrote about exclusive Firefox userChrome.css hacks got a TON of responses and requests. So in the spirit of "teaching a man to fish", I’m providing a tutorial on how to use Firefox’s DOM Inspector add-on to tweak whatever you want.

Suppose we want to remove that bookmark star on the right side of the URL bar. I’ll show you a simple way to do this and then generalize the technique for use with anything.

Setup

If you didn’t get the DOM Inspector when you downloaded Firefox, you’ll obviously want to do that first. Open it up by hitting Tools > DOM Inspector or key in Ctrl+Shift+I (default). You’ll want to start out by going to File > Inspect a Chrome Document and choosing the first option which is your Firefox window.

Find your target

The easiest way to check it out is to inspect it by clicking the Inspect button and clicking on the star. The DOM Inspector is helpful here because it will highlight the block containing the star with a big red border and show you the markup in the browser document with the XML element highlighted.

We also could have clicked the Search button and searched for "bookmark" to see if we could find it that way, but that would not really be the easiest way in this case.

DOM Inspector Tree

From there you can easily right click and "Insert" a new node. Type "style" in the Node Name field and then the CSS you want to apply in the Node Value. In this case you’ll type "display: none;" which removes the star immediately once you click OK. We won’t worry about the Namespace URI in this tutorial.

Now take note of the node name, class, or id so you can use CSS rules in your userChrome.css file. We can see that the ID of the element is "star-button". Great, in this case that’s all we need. You’ll need to know a bit of CSS to do any good tweaks so if you want you should check out sitepoint’s CSS reference.

Since you know the element ID, class, etc. you should add a snippet to you userChrome.css (instructions) file like this:

#star-button { display: none; }

So easy! Once you get the hang of it you’ll think of all kinds of things you’d like to change about Firefox’s interface. Now to save you time on some bits I’ll close up with a…

Big ol’ list of userChrome.css tweaks

/* Autohide Back/Forward Buttons and Dropdown Marker when there is nothing to go Back/Forward to */
#back-button[disabled="true"] { display: none; }
#forward-button[disabled="true"] { display: none; }
#back-forward-dropmarker[disabled="true"] { display: none; }

/* Hide the Sidebar bookmarks Search box */
#bookmarksPanel > hbox { display:none; }

/* remove Sidebar maximum width restriction */
#sidebar { min-width: none !important; min-width: 0px !important; }

/* hide live feed icon in Address url toolbar */
#feed-button { display: none !important; }

/* Add a keyword when adding a bookmark */
#editBMPanel_keywordRow { visibility: visible; }

/* Combine Stop and Reload Buttons, Hide Both as Necessary */
#reload-button[disabled="true"] { display: none; }
#stop-button[disabled="true"] { display: none; }
#stop-button:not([disabled]) + #reload-button { display: none;}

/* Remove search magnifying glass */
.search-go-button { display: none !important; }

/* Hide the green "Go" arrow */
#go-button { display: none !important; }

/* Move "List All Tabs" Button to the left side of the tab bar */
.tabs-alltabs-stack {-moz-box-ordinal-group: 1 !important}
.tabbrowser-arrowscrollbox {-moz-box-ordinal-group: 2 !important}
.tabs-closebutton-box {-moz-box-ordinal-group: 3 !important}

/* Style the new auto-complete list */
.autocomplete-richlistitem { background: #222222 !important; color: #FFFFFF !important; padding: 0px !important; margin: 0px !important; }
.autocomplete-richlistitem:hover, .autocomplete-richlistitem[selected="true"] {  background: #444444 !important; }  

/* Remove unimportant Location Bar Icon Text */
#identity-icon-label { display: none !important; } 

/* Remove separator under Bookmarks Toolbar */
#bookmarksToolbarFolderMenu + menuseparator { display: none; }

/* Remove Favicon placeholder in Tab Bar */
.tab-icon {display: none !important; }

/* Search bar color */
#search-container .searchbar-textbox { -moz-appearance: none !important; border: 1px !important; font-weight: bold !important; color: darkslateblue important }

/* Hide the Sidebar bookmarks Search box */
#bookmarksPanel > hbox { display:none; }

/* Hide the dropmarker in the Address url toolbar */
.autocomplete-history-dropmarker { display: none !important; }

/* Hide live feed icon in Address url toolbar */
#feed-button { display: none !important; }

/* Chage tab background */
tab { -moz-appearance: none !important; }
.tabbrowser-tabs > tab[selected="true"] .tab-text { background-color: #FF9 !important; color: #0F0 !important; font-style: bold !important;}

/* Change color of inactive tabs */
.tabbrowser-tabs > tab:not([selected="true"]) .tab-text { background-color: #8D6 !important; color: #000 !important;}

/* Hide "List All Tabs" button */
.tabbrowser-arrowscrollbox + stack { display:none !important; }

/* Dim the RSS icon until hover */
#feed-button {-moz-opacity: 0.2 !important;}
#feed-button:hover {-moz-opacity: 1.5 !important;}

/* Dim the URL Bar star icon until hover */
.ac-result-type-bookmark{-moz-opacity: 0.2 !important;}
.ac-result-type-bookmark:hover {-moz-opacity: 1.5 !important;}

/* Dim the Bookmark star icon until hover */
#star-button {-moz-opacity: 0.2 !important;}
#star-button:hover {-moz-opacity: 1.5 !important;}

/* Display only Location Bar textbox */
#menubar-items, #unified-back-forward-button, #stop-button, #reload-button, #search-container, #identity-box, #urlbar-container dropmarker { display: none; }

/* Change Location Bar font */
#urlbar { font-family: “Courier New”, monospace; }

/* Turn Location Bar Yellow for HTTPS */
#urlbar[level] .autocomplete-textbox-container { background-color: #FFFFB7 !important; }

/* Remove Search Engine dropdown button */
.searchbar-engine-button { display: none; }

/* Change border of unselected tabs */
#content tab:not([selected="true"]) { border-style: dotted !important; }

/* Remove History Sidebar Search */
#bmHi-toolbar { display: none; }

There you have it! I welcome any questions or additional tweaks.

New bling and licensing

From the "in case you care" department, a couple quick updates about the blog and some questions for you readers.

Un-copyright

Since I had a reader ask about licensing for some code posted here, I thought I should make it perfectly clear: I hereby release all content and code on Eric Wendelin’s Blog to the public domain. Everything is provided AS IS with no warranty. The point of this blog is to be helpful and its usefulness is restricted if I attach a license that can prevent anyone for using it under any circumstances.

So there you have it! Copy it, modify it, tell everyone you wrote it, whatever. Enjoy!

New Design Afloat

I have wanted to create a unique design for this blog for a few months now, so you may have noticed a change if you dropped by eriwen.com since my last post. It needs a few more tweaks but the major bits are there.

I want to thank friends David Walsh and CSS-Tricks author Chris Coyier for their help nailing stuff down. Their sites have helped me along the way as well so you might give them a look if you haven’t.

I hope you like it! Please give me your feedback especially if something could be easier for you. Feel free to email me at emwendelin [at) gmail (dot] com about the direction this blog is and should be going if you like.

A Javascript stacktrace in any browser

Chances are that if you’ve done any significant Javascript work, you’ve run into a situation where part of the debugging process could be much improved if you just had the function call stack.

I’m going to give you some ways of doing this with and without the popular Firebug extension and have some examples of their uses.

Without Firebug and friends? Using IE?

Sometimes s**t only happens in other browsers. Here’s how to create/log your own stack trace. Put this code in an accessible place in your Javascript file(s) and call the printStackTrace() function inside any function.

function printStackTrace() {
    var callstack = [];
    var isCallstackPopulated = false;
    try {
        i.dont.exist+=0; //does not exist - that's the point
    } catch(e) {
        if (e.stack) { //Firefox
            var lines = e.stack.split("\n");
            for (var i = 0, len = lines.length; i < len; i++) {
                if (lines[i].match(/^\s*[A-Za-z0-9\-_\$]+\(/)) {
                    callstack.push(lines[i]);
                }
            }
            //Remove call to printStackTrace()
            callstack.shift();
            isCallstackPopulated = true;
        }
        else if (window.opera && e.message) { //Opera
            var lines = e.message.split("\n");
            for (var i = 0, len = lines.length; i < len; i++) {
                if (lines[i].match(/^\s*[A-Za-z0-9\-_\$]+\(/)) {
                    var entry = lines[i];
                    //Append next line also since it has the file info
                    if (lines[i+1]) {
                        entry += " at " + lines[i+1];
                        i++;
                    }
                    callstack.push(entry);
                }
            }
            //Remove call to printStackTrace()
            callstack.shift();
            isCallstackPopulated = true;
        }
    }
    if (!isCallstackPopulated) { //IE and Safari
        var currentFunction = arguments.callee.caller;
        while (currentFunction) {
            var fn = currentFunction.toString();
            //If we can't get the function name set to "anonymous"
            var fname = fn.substring(fn.indexOf("function") + 8, fn.indexOf("(")) || "anonymous";
            callstack.push(fname);
            currentFunction = currentFunction.caller;
        }
    }
    output(callstack);
}

function output(arr) {
    //Optput however you want
    alert(arr.join("\n\n"));
}

UPDATE: Luke Smith has taken and upgraded the script with a bunch of new features. I encourage you to check out his code here. Thanks, Luke!

It’s ugly, but this works for the latest versions of IE, Firefox, Opera, and Safari. Firefox and Opera give you file names and line numbers when they can, but I couldn’t find a mechanism to get the same from IE and Opera. Hopefully the inline comments describe enough of what is going on. If not, ask :).

Try it out


Give it a shot by clicking here. It will run the snippet below.

function foo() {
    var blah;
    bar("blah");
}

function bar(blah) {
    var stuff;
    thing();
}

function thing() {
    if (true) { //your error condition here
        printStackTrace();
    }
}

foo();

Obvious easy way: Firebug (eventually Drosera and Dragonfly)

You can easily get a stack trace at any time by calling console.trace() in your Javascript or in the Firebug console.

Not only will it tell you which functions are on the stack, but it will include the value of each argument that was passed to each function.

This is obviously the best way to go if you are using Firefox.

Furthermore, these tools allow you to dig deeper. Of course, we can’t count on them for ALL situations.

Conclusion

I hope you find this useful. If you have any suggestions/improvements I’d like to hear them! Also all kidding aside, I worked pretty hard on this function, so I’d really appreciate if you’d help me share this with more people. Thanks!