cmcculloh web design
cmcculloh.com - Personal - Tutorials - Firefox Extension Tutorials - Creating the Calculator Extension

Status Bar Calculator

Christopher McCulloh
2.23.06

Valid XHTML 1.0 Strict

Download the Extension

The Status Bar Calculator is a tiny extension that fits in your browser status bar. The current version (0.9.4) collapses to just a small picture when clicked, and expands for use when needed. You can use the numberpad to do all of your calculations too!

Start by placing your cursor in the left text box, typing in your number, and either using the pop-up menu to select your function, or pressing a function key on your number pad. Then to get the result, you can either press the "=" key, or any of the function keys and keep going (just like a normal calculator).

See it on the Firefox Extensions page

V 0.9.0

My Goal is to create a calculator that resides in the bottom of your browser.

I started with the simple "hello, world" extension, and simply changed the code in "sample.xul" to:

This produced the following:

Great! Now lets add a text box...


Ok, cool. This is going well.

Now I need to think about my user interface. What I want is to have a small textbox, then a pop-up menu that allows the user to select whether they want to add, subtract, multiply, divide. Then I want another small textbox. Then I want a button that has an "=" sign that will perform the selected operation on both of the numbers and display the output in the first text-box...

So I need:
[textbox][pop-up choices:+,=,/,*][textbox][button: =]

So let's add another text-box and a button placeholder for my pop-up. Also, it turns out besides the "button" element, there is a "toolbarbutton" element I can use since it's in a toolbar...


Ok, so now let's tackle that pop-up since I know I can make a textbox and a button. Then I will worry about styling it all, then I'll tackle making it work.


Now, besides adjusting the order the operators appear in, I need to make it so that the label of the menu is dynamically changed based upon what you select.

Ok, so what probably needs to happen is that whenever you select something it calls a javaScript function that changes the label of the menu. This means the menu will also need to have an id. So let's get our xul code ready...

and now we need to make our javaScript. For now, let's just make the javascript alert which one you chose to make sure we got the linking right...

Sorry about the poor quality screenshot... On a computer that only has MSPaint...

Hamsterdance! Got it working. Ok, so now we need to make it actually change the + sign to whatever we decide it should be.

Upon further investigation I find that you can't actually change the label of the menu directly. So now we need to add an actual "label" attribute inside of the menu code and work with it's value through the javascript to change the operator.

Now we need to use the DOM to select the element we want to work with (the new operatorLabel) and change it's value to whatever value we selected. I know technically we probably should have used some other word besides "value" for our code since value is an attribute, but this works and for some reason it wouldn't let me use "this"...

Great! So now we have the ability to choose what we want to calculate with. Ok, now lets actually make it do the calculation. For this we are going to want to add some script to the equals button, and take the value from the first textbox and perform an operation on it with the second text box. Lets take the baby step of just seeing if we can get it to alert the value in the first text box...

So we added an "onCommand" to our calculate button, and called a javascript function:

This resulted in:

Sweet. Now let's try to make two numbers calculate based on what's in the middle

So, in order to do that, we will want to take what is in the first box and perform whatever the selected operator is on it by the number in the second box, and then for now we will just alert it to the user. We only need to change the JavaScript for this, so...


Nice. Ok, so that's working, now we just need to make it display back into the first textbox. Then we need to make the second textbox clear, and receive the focus so that the user can just start typing in the next number. Simple as pie. Just add three lines to the javascript

Now, I put 500 in the first text box and 55 in the next, and hit "=" and came up with:

Great! We now have a working calculator that anyone can use. It has a few issues though:

  1. Text boxes are too long
  2. User cannot enter commas
  3. Does not warn you when you forget to put a number in the second textbox

Ok, so lets just take them in order.

The first one is just a simple formatting issue, so let's get them to just allow for the display of, say, 7 numbers each to start off with (we will make it dynamically expand later). This will be a style property. So we will make it 50px wide...


Now we will make it dynamically change width depending on how big the number is. So first let's just get it to detect how big the number is successfully, and then we can worry about making it change it's appearance.


Cool, now let's make it change it's size using the DOM based upon who big the number is...


Now let's take care of the user not being able to enter commas. We will need to use regular expressions to check for commas, and then tell the user not to use them if they did. We could remove the commas, but since the answer will be displayed without commas, and since the user will have to go out of their way when entering a number to also enter a comma, it will be simpler for everyone if we just make it so that they can't use commas. So, again, we simply add a few lines to the javaScript:

Yes, we could also check for letters and such, but since it will just display an error if they enter a letter, we don't need to worry about that. However if they enter a comma, it will simply truncate anything following the comma without telling the user. Then the user could end up entering lots of things with commas without realising that it is not calculating the full number. This keeps that from happening.

Now we need to make it warn you when you forget to put a number in the second text box instead of trying to perform the calculation and saying "NaN". So we will need to make sure that the textbox is not empty, and if it is, not do the calculation, and tell them it was empty.


Since it only required about 12 more letters in our code, I went ahead and made sure that the first textbox had something in it... You never know, and it's better safe than sorry.

Great! We took care of all of the bugs that we could. Now there are a few usability things we might want to do. Since some people have large amounts of crap packed into their status-bar, we might want to make it so that the calculator start off hidden. When you click a little picture of a calculator it will pop out. When you click the picture again, it will go away. That way it only takes up a little 15x15 pixel square in your status-bar, instead of 150px...

So first we will create the image.

Then we add some code to the .xul doc, and then some javascript to hide and show the calc interface. For some reason inline and block are displaying the same way, but if you just change the display property to "" it displays how inline should. So:


Then, when you click:

Now, the status bar gets a little taller when you reveal the calculator, and it just looks bad. So let's add some style elements to it to keep it the same. We need to take the padding off of the textbox, because otherwise it hides the bottom of the numbers, and that looks even worse than the problem we are trying to solve. The whole point of this calculator is that it fits seamlessly into the browser, without hogging any space. We want it to be as small as possible...


We probably didn't need to add ALL of the styles we added, but at least we covered all of our bases.

Ok, for all practical purposes, the extension is ready to go live. Not necissarily to the firefox extensions page yet, but definately as a beta test on our website. So let's explore making it an xpi, and linking to it from our web page so people can download it...

Ok, I changed alot of the folder and file names and heirarchies. I won't go through all the steps, but the mian problem I had I will note here. In the "chrome.manifest" file, this line:

There are a few things that are important to know. The first word just tells firefox where the "content" of your extension go. The next word (calculloh) needs to be a unique word that then defines the... root path... of your extesion (sort of). It's sort of like mapping a drive letter to your extension. So from now on, you will refer to your extension using the root path "chrome://calculloh/content/" Then you need to tell what the "root path" of your extension is refering to (in relation to the chrome.manifest" file. So since it is refering to our xul doc and our javascript which are both at chrome/chromeFiles/content/ (relative to our chrome.manifest file), we put that next. Don't let the fact that you have a folder called content throw you off. The word "content" at the beginning of the line has nothing to do with the folder "content" at the end of the line. Think of it like telling the browser that you will be creating the root of your extension for content, and calling it calculloh, and then when you call the calculloh directory, you are then looking for the content directory, with is a shortcut for just saying chrome/chromeFiles/content/. I've probably just confused you more than helped you, but you will figure it out. I'm not positive, but I think that you could just do the following and have it work just as well:

and then call it with chrome://X/C/

Ok, so at this point we are ready to zip it up. Just go into the root folder of your extension (the one with your chrome.manifest files and such). and select everything in that root folder. Right click and say "send to" then "compressed (zipped) folder". Then (when it's done) rename the extension ".xpi". That's it! You're good to go! You can test install it by just taking that .xpi file and dragging and dropping it into the firefox browser, and it should install for you! Also, you could get an account and submit it to the extensions page at mozilla.com. It takes about a day or two to get approved and posted.

V 0.9.1

Two days ago I put up my extension, and got some awesome feedback (thanks Mike, thanks Fernando!). There were two problems with the calculator, which doesn't suprise me as it is beta. They are as follows:

  1. It does not handle decimals properly
  2. It does not do "^" calculations (not really a problem, just a suggested feature)

Since the first one is a real problem, we need to get on that right away.

Upon reviewing our code we see that we are using this to parse our strings into integers:

However, this just drops everything after the decimal. NOT GOOD. So after looking at some different solutions, I have come up with this as a possible fix:

Let's see if it works...

Then hit equals...

Great! That works. Ok, now on to the next one...

This is just a simple calculation for powers. So "number1" to the power of "number2". Thanks to Fernando for the following code snippet:

So, we add that to our JS, and add a bit of code to our xul and we get the following:

You might have noticed I also added a simple "else" statement at the very end of our operator function that detects for the unlikely event that somehow an un-recognized operator is passed to our function. (this is very unlikely since we control the operators that get passed with a pop-up menu).

Ok, now we should probably make our own little image for our extension, since technically the one we used is copyrighted, and I don't want to get sued. So, thank you very much Microsoft for unknowingly letting me borrow your image to test my extesion, I will now make my own. This is beyond this tutorial to describe this process, just wanted to make note that I did make my own image here...

So there it is. It isn't beautifull by any means, but I own it. Now I can give it away with a clear conscience.

Ok, so time to package it up (and change the version number to 0.9.1) for uploading so no one else will download the old version...

V 0.9.2

There is still a bit of a problem with the decimals. If you keep adding .1 + .1 you will see that sometimes it is off by .01~. One possible solution is to do the following:

So I'll change my Javascript to this:

And now it works fine!

V 0.9.3

Now, as far as usability goes, this thing sucks. You have to keep grabbing your mouse to make selections. If you are only adding two numbers together, I guess that will do just fine. But if you are doing anything you couldn't just do in your head anyways, it's just no good.

So we need to make it actually respond to you hitting the function keys. Looking over the documentation, it appears there should be some way to make it detect when you hit what key, but I just couldn't get that to work. So instead, I made it detect EVERY key stroke, and if you happen to hit a non-numeric key, it will decide what to do at that point (if anything). I was having alot of trouble with this, so I wasn't in the mood to really go through HOW I came up with the solution. I will outline the process below, but no screenshots this time (or I'd have to do it all over again...)

  1. Set up an alert that gets called from the textbox each time you enter text (use the oninput="" method)
  2. Make a regex that checks to see if the input is a number or not. Alert "do nothing" if it is a number or "do something" if it is not
  3. Now, instead of alerting "do something" make it detect which non-number charactor you entered, and alert that
  4. Now make it replace the non-number charactor you are checking for with nothing so that it gets rid of that charactor and you are just left with the number
  5. Now make it detect if you have entered a number along with that charactor. If you have entered a number, make it perform the calculation based on the charactor you entered. If you have NOT entered a number, simply make it change the value of the function pop-up to whatever non-number you entered

Here is the code I came up with:

It's not the best solution I guess. It would definately be better if there were a listener that detected when a certain key were pressed. Also, it can get a little bit confusing when you are looking at the calculator bar. It will say something like: 3 * 3, and if you hit "=" it will perform the operation (which is fine). But if you are doing math quickly, you would enter a 3 in the first textbox, hit * to change the modifier and move to the second textbox, and then hit 3 again. But then what if you want to add 3 to the answer? Well, your instinct (or mine was) would be to hit +, but if you did that at this point, that would actually add 3 and 3 together instead of multiplying them and then preparing to add something to them. So it looks like we need to change the order in which we perform our functions. Instead of making it first change the operator, and then calculate the number, let's make it calculate the number, and THEN change the operator...

MUCH better...

Now, There is a big problem with the methodology we used to find the length of the number. What if the number is 1.999999999999999999999? Then it is way too long for our textbox, but the textbox doesn't "grow". Let's see if there is a better way...

There is a method in javaScript that allows for you to detect the length of a string (var.length), however I didn't originally use this method because I couldn't get it to work. I realized that I first have to convert the number to a string, and THEN detect the length of it. So now we will use this new methodology for our length detection since it will work much better than detecting the actual value of our number.

V 0.9.4

Now there are a few other things we should do. Like we should add a way to customize where the calculator goes. Should it go over on the right where it is now, should it go on the left, or should it go in the top right of the browser? We need to give the user those options. We could either put the preferences in the "general" category of the options menu. We could put it in it's own tab under "advanced". Or we could put it in it's own pop-up that is activated from the "tools" menu itself. Let's do two things. One, put it in it's own pop-up incase someone has some sort of special customization of the options menu that negates our customization, and also we will put a link to our pop-up from the options menu incase someone misses the link in the tools menu.