Archive for the ‘Software’ Category

“Built in” text field calculator

Wednesday, September 26th, 2007

I have a little web application that I wrote to balance my check book. I often enter a calculated value into a form text field. I usually use the Google Calculator in the Firefox Search Bar to perform the calculations. I often perform simple calculations like “25 * .03”. (Why? I impose a personal finance fee on each credit card purchase that I make. I use a 3% fee. I put all of my personal finance fees into an online high-interest savings account. So, if I charge $25.00 on a card, I transfer “25 * .03” or $0.75 to my online savings account. It isn’t much, but it adds up.) So, yesterday, I thought, “I wonder if I can integrate Google Calculator functionality into my web application?”

Here is what I came up with.

Calculator example.

You can take a look at the source of the “calculator.html“. It includes “JPetersonCalculator100.js“, which is where the JavaScript that actually implements the calculator is sourced. The calculator function is attached to the text input field using an onKeyPress event handler in the HTML:

onkeypress="processCalculatorKeyPress(event, 2);"

Here is the processCalculatorKeyPress function.

001: /**
002:  * Handle a key press from a text field that can automatically calculate a
003:  * derived value. Basically, enter normal mathematical formula like
004:  * "5 * .03 =". When you press the equal ("=") key, the value in the text field
005:  * will be replaced with the calculated value. If the value can't be
006:  * calculated, it is left unchanged.
007:  *
008:  * @param e the event
009:  * @param precision the decimal precision to round to.
010:  */
011:  function processCalculatorKeyPress(e, precision) {
012:   var targ;
013:   if (!e) var e = window.event;
014:   if (e.target) targ = e.target;
015:   else if (e.srcElement) targ = e.srcElement;
016:   if (targ.nodeType == 3) // defeat Safari bug
017: 	targ = targ.parentNode;
018:
019:   if (e.keyCode) code = e.keyCode;
020:   else if (e.which) code = e.which;
021:
022:   if (code == 61) { // '='
023:     var expression;
024:     var result;
025:     expression = targ.value;
026:
027:     try {
028:       // calculate, evaluating arithmetic expression
029:       result = eval(expression);
030:
031:       if (typeof result == "number") {
032:         // round, if necessary
033:         if (typeof precision == "number") {
034:           if (precision > 0) {
035:             if (result.toFixed) {
036:               result = result.toFixed(precision);
037:             } else {
038:               var factor = Math.pow(10,precision);
039:               result = Math.round(result * factor) / factor;
040:             }
041:           }
042:         }
043:
044:         targ.value = result;
045:
046:         // don't display key that triggered the calculation
047:         if (e.preventDefault) {
048:           e.preventDefault();
049:         } else {
050:           e.returnValue = false; // IE
051:         }
052:       }
053:     } catch (e) {
054:       // expression wasn't an arithmetic expression, let normal text be displayed
055:     }
056:   }
057:
058:   // var character = String.fromCharCode(code);
059:   // alert('Code was: ' + code + ' Character was: [' + character + '] targ: [' + targ.value + ']');
060:
061:   return false;
062: }

Lines 12 -10 process the event, makeing a “normalized” version that handles differences in browser implementations. Since the function processCalculatorKeyPress is called for EVERY key press, line 22 filters out all key presses except for the one that we care about: the equals (“=”) key. Line 25 saves the value currently entered into the text field. Line 29 uses the JavaScript eval function to evaluate the arithmetic expression. (This is the actual calculator. The rest of the function make the results look pretty.) The “try”, on line 27, and associated “catch”, on line 53, are there to handle any error thrown by the “eval” function. An error would be thrown if the value entered into the test field was not an arithmetic expression. (Or more generally, not a valid JavaScript expression, since “eval” found evaluate any valid JavaScript expression. But that’s not really useful for the calculator.) Line 31 makes sure that the result of the “eval” is a number. Note that execution will only reach line 31 if “eval” didn’t throw an exception. Lines 33 through 41 perform any required rounding of the result. If available, line 36 uses the “toFixed” function to convert the number to the requested number of decimal places, rounding and padding with zero as necessary. If this function is not available, lines 38 and 39 perform rounding without any padding. Line 44 assigns the result of the arithmetic expression to the text input form element. Lines 47-51 indicate that the calculation succeeded so that the equals sign isn’t added to value of the text input field. Line 58 and 59 are commented out. But they illustrate how you can use an alert box to see what characters are pressed. I used this technique when developing the function.

That’s it. It should be relatively easy for you to include this build in text field calculator into your own web application. The basic steps are:

  1. Include the JavaScript function “processCalculatorKeyPress”.
  2. Add the “onkeypress” to the text fields that you would to support the build in calculator functionality. You can configure the precision value, from no rounding (use a negative value, like “-1”) to whatever decimal place is important. For currency input, I use a precision of “2”.

littles3 works with S3Fox Organizer

Friday, August 31st, 2007

S3Fox Organizer and “littles3″I have successfully used S3Fox Organizer with the current “littles3” source code. S3Fox Organizer is a Firefox extension which provides a simple interface for managing files with Amazon S3. To get it to work, I needed to control the resolving of “http://s3.amazonaws.com”, which is the URL that S3Fox Organizer is coded to use. I edited my machines “hosts” file, C:\WINDOWS\system32\drivers\etc\hosts on Windows, to have s3.amazonaws.com resolve to 127.0.0.1, localhost. I have “littles3” running within Tomcat. I have it running as the “ROOT” application so that there is no application context. I also have Apache running with mod_jk connecting to Tomcat.

This definitely takes advanced skills to get running and “littles3” isn’t complete yet, but this is a good integration test. The current “littles3” source code has ACL support now. It still needs to implement metadata and the ability to “provision” user accounts. But it is at a personally usable state now.

Project “littles3” launched

Saturday, July 21st, 2007

I have launched a project, “littles3“, on Google Code. This project is a Java web application which provides a storage service based on the Amazon Simple Storage Service (Amazon S3) API.

So far, I have implemented a StorageEngine which stores content to the local file system. It currently does the basic storage function outlined in the S3 api. What isn’t implemented yet?

  1. ACL
  2. Custom metadata

Why am I doing this? I think that Amazon S3 is a pretty neat thing. It provides hosted storage at a very reasonable rate. But there may be times when you want to store your data locally but still use the Amazon S3 API. This server will do that.

X10 API source code

Tuesday, May 29th, 2007

Many years ago, I created an API for interacting with the home automation technology called X10. The API interfaced with power line modules via a serial interface. I haven’t done anything with the X10 home automation API that I created a couple years ago. I have gotten a bit sidetracked by fatherhood. 🙂

You can find the source code here. If you do try to compile this, you may get an error about a missing class. This isn’t important; you can whack away the reference and compile again. (Not very helpful, I know, but if I get more time, I may update this with some more information.)

History: My first Google Gadget – Goal Chart

Thursday, April 5th, 2007

I have created my first Google Gadget, Goal Chart, back in November 17, 2006.

Goal Chart

It is still hosted on my Google Pages site: http://cubeinhabitant.googlepages.com/. Here is a little blurb about the Goal Chart…

It is a simple gadget that shows one horizontal bar chart. In the preferences, you can edit the goal name, goal value, and current value. It is intended to be a “Savings Goal” chart, where you can specify a monetary value and track your current progress toward the goal. The goal value and current value should be decimal numbers. Once the user preferences are saved, the goal progress is displayed in the bar chart as a percentage.

I have had the Goal Chart installed since November 17, 2006 on my Google Personalized Homepage. I use it to track my progress towards paying off my second mortgage. It provides “visual motivation” by showing a bar chart of my progress towards paying off the loan.

Once the gadget is installed in Google Personal Homepage, you need to edit the preferences. The field “Name” is used in the title of the gadget. The field “Goal” is a decimal number that represents what you want to reach. The field “Current” is a decimal number that represents where you are currently at.

Goal Chart Preferences

This shows my load amount of $22,869.00. I have currently paid back $12,168.43 of the principal. This means that I have paid back 53.21% of the loan. Each month when I send in my loan payment check, I update the Goal Chart preferences, changing the “Current” field. This updates the percentage calculation and bar chart.

(How do I know how much principal I have paid back? That’s a good question. It’s also another topic for another blog post. 🙂 )

[Updated April 5, 2007: I almost forgot. The Goal Chart stores the values that you enter using the Google Gadget API for your Personalized Homepage only. The data isn’t shared with me or anyone else. (Besides Google, who is storing your Personalized Homepage.)]