CCAS Inc., which produces accounting software for Government Contractors, uses JavaScript to demonstrate one of the formulas included in their CCAS for Government Contractors financial and job cost accounting package.
The Indirect Cost Rate sheet is available at
http://www.ccas.com/ccasrate.html
It provides a good example of building a complex worksheet using JavaScript.
The application uses one large form spanning four separate tables to guide the user through entering the required information for the form. The worksheet is designed to calculate the Fringe Benefit Rate, Overhead Rate, and G&A Rate based on information in the form. At the bottom of the page, the formulas being used are described. The source code for the CCAS Worksheet appears in Listing W6.1.
Input
<HTML> <HEAD> <TITLE>CCAS Indirect Cost Rate Worksheet (JavaScript)</TITLE> <SCRIPT LANGUAGE="LiveScript"> <!-- hide this script tag's contents from old browsers function checkNumber(input, min, max, msg) { msg = msg + " field has invalid data: " + input.value; var str = input.value; for (var i = 0; i < str.length; i++) { var ch = str.substring(i, i + 1) if ((ch < "0" || "9" < ch) && ch != '.') { alert(msg); return false; } } var num = 0 + str if (num < min || max < num) { alert(msg + " not in range [" + min + ".." + max + "]"); return false; } input.value = str; return true; } function computeField(input) { if (input.value != null && input.value.length != 0) input.value = "" + eval(input.value); computeForm(input.form); } function computeForm(form) { if ((form.DL.value == null || form.DL.value.length == 0) || (form.ODC.value == null || form.ODC.value.length == 0) || (form.TFB.value == null || form.TFB.value.length == 0) || (form.TOH.value == null || form.TOH.value.length == 0) || (form.TGA.value == null || form.TGA.value.length == 0) || (form.TBP.value == null || form.TBP.value.length == 0) || (form.FBR.value == null || form.TBP.value.length == 0) || (form.OHL.value == null || form.OHL.value.length == 0) || (form.GAL.value == null || form.GAL.value.length == 0) || (form.BPL.value == null || form.BPL.value.length == 0)) { form.FBR.value = "Incomplete data"; form.OHR.value = "Incomplete data"; form.GAR.value = "Incomplete data"; return; } if (!checkNumber(form.DL, 1,99999999, "Direct Labor") || !checkNumber(form.ODC,0,99999999, "Other Direct Costs") || !checkNumber(form.TFB,1,99999999, "Total Fringe Benefits") || !checkNumber(form.TOH,1,99999999, "Total Overhead") || !checkNumber(form.TGA,0,99999999, "Total G&A") || !checkNumber(form.TBP,0,99999999, "Total B&P") || !checkNumber(form.TBP,0,99999999, "Total B&P") || !checkNumber(form.DLL,0,99999999, "Total B&P") || !checkNumber(form.OHL,1,99999999, "Total Overhead Labor") || !checkNumber(form.GAL,0,99999999, "Total G&A Labor") || !checkNumber(form.BPL,0,99999999, "Total B&P Labor")) { form.FBR.value = "Invalid"; form.OHR.value = "Invalid"; form.GAR.value = "Invalid"; return; } var i=form.DL.value *1 var j=form.ODC.value*1 form.TOTDIR.value=i + j form.DLL.value=i var k=form.TFB.value *1 var l=form.TOH.value *1 var m=form.TGA.value *1 var n=form.TBP.value *1 form.TOTIND.value=k + l + m + n var z=i + j + k + l + m + n form.TC.value=z var o=form.OHL.value *1 var p=form.GAL.value *1 var q=form.BPL.value *1 var r=i + o + p + q form.TOTLAB.value= r var s=(k / r) form.FBR.value=s * 100 var t=(((i + o + q) * s) + l) / (i + q) form.OHR.value= t * 100 var u=(m + n+ (p * s) + (t * q)) var z=z - u var z= u / z form.GAR.value=z * 100 form.DLB.value=i var v=i * t form.OHRB.value=v form.OHRR.value=t * 100 form.ODCB.value=j form.GARR.value=z * 100 var w=(i + v + j) * z form.GARB.value=w form.TCB.value=w + i + v + j } function clearForm(form) { form.DL.value = ""; form.ODC.value = ""; form.TFB.value = ""; } <!-- done hiding from old browsers --> </SCRIPT> <BODY BGCOLOR="#ffffff" TEXT="#020225"></HEAD> <CENTER> <FORM method=POST> <TABLE BORDER=5 CELLSPACING=2 CELLPADDING=5 ALIGN=MIDDLE> <TR><TD><IMG SRC= "ccaslogoTR.gif" WIDTH="343" HEIGHT="36" NATURALSIZEFLAG="3" ALIGN=bottom [ic:ccc]alt="CCAS accounting solutions for Government Contractors"></TABLE><BR> <H1>Indirect Cost Rate Worksheet</H1> <IMG SRC="javatr.gif" alt="JavaScript(tm)"><BR><BR> </Center> <FONT SIZE=3> In this JavaScript(tm) application, you can determine your indirect cost rates [ic:ccc]based upon a commonly used (and DCAA accepted) rate structure. [ic:ccc]This rate structure is one of several options that are included in [ic:ccc]<A HREF="ccassw.html">CCAS for Government Contractors</A><B>, "Internet Edition"</B>. Simply complete Steps 1 and 2, and [ic:ccc]then in Step 3 calculate your indirect cost rates. Be sure to review [ic:ccc]the proof of the calculation and details of the calculation formulas [ic:ccc]employed.<BR><BR> Note that if this page (which requires Netscape 2.0b5 or later) is saved using [ic:ccc]the "Save As...Format...Source" command from your browser's "File" menu, [ic:ccc]it can be run locally when loaded into your browser using "Open File"--<B> [ic:ccc]even without an active Internet connection.</B> <P> <CENTER> <H2>Step 1-Enter Your Total Costs</H2> <TABLE BORDER=6 CELLSPACING=2 CELLPADDING=3 ALIGN=MIDDLE> <TR> <TD><DIV ALIGN=CENTER><B>COST CATEGORY<BR>DESCRIPTION</B></DIV></TD> <TD><DIV ALIGN=CENTER><B><br>AMOUNT</B></DIV></TD> <TD><DIV ALIGN=CENTER><B>SUBTOTAL<br>(Computed)</B></DIV></TD> </TR> <TD><DIV ALIGN=CENTER><B>Total Costs From General Ledger</B></DIV> </TD> </TR> <TD><B>Direct Costs:</B></DIV> </TD> </TR> <TR> <TD>A. <B>Total</B> Direct Labor</TD> <TD><DIV ALIGN=CENTER><INPUT TYPE=TEXT NAME=DL SIZE=15 [ic:ccc]onChange=computeField(this)></DIV></TD> <TD><DIV ALIGN=CENTER> </TD></TR> <TD>B. <B>Total</B> Other Direct Costs</TD> <TD><DIV ALIGN=CENTER><INPUT TYPE=TEXT NAME=ODC SIZE=15 [ic:ccc]onChange=computeField(this)></DIV> </TD> <TD><DIV ALIGN=CENTER></DIV> </TD></TR> <TD><DIV ALIGN=RIGHT>Total Direct Costs</DIV></TD> <TD><DIV ALIGN=CENTER> </DIV></TD> <TD><DIV ALIGN=CENTER><INPUT TYPE=TEXT NAME=TOTDIR SIZE=15></DIV> </TD></TR> <TR> <TD><B>Indirect Costs:</B> </TD> </TR> <TR> <TD>C. <B>Total</B> Fringe Benefits</TD> <TD><DIV ALIGN=CENTER><INPUT TYPE=TEXT NAME=TFB SIZE=15 [ic:ccc]onChange=computeField(this)> </DIV></TD> <TD><DIV ALIGN=CENTER></DIV> </TD></TR> <TD>D. <B>Total</B> Overhead</TD> <TD><DIV ALIGN=CENTER><INPUT TYPE=TEXT NAME=TOH SIZE=15></DIV> </TD> <TD><DIV ALIGN=CENTER> </DIV></TD></TR> <TD>E. <B>Total</B> G&A</TD> <TD><DIV ALIGN=CENTER><INPUT TYPE=TEXT NAME=TGA SIZE=15></DIV> </TD> <TD><DIV ALIGN=CENTER></DIV> </TD></TR> <TD>F. <B>Total</B> B&P and IR&D</TD> <TD><DIV ALIGN=CENTER><INPUT TYPE=TEXT NAME=TBP SIZE=15> </DIV></TD> <TD><DIV ALIGN=CENTER></DIV> </TD></TR> <TD><DIV ALIGN=RIGHT>Total Indirect Costs</DIV></TD> <TD><DIV ALIGN=CENTER> </DIV></TD> <TD><DIV ALIGN=CENTER><INPUT TYPE=TEXT NAME=TOTIND SIZE=15></DIV> </TD></TR> <TD><DIV ALIGN=RIGHT>G. Total Costs</DIV></TD> <TD><DIV ALIGN=CENTER> </DIV></TD> <TD><DIV ALIGN=CENTER><INPUT TYPE=TEXT NAME=TC SIZE=15></DIV> </TD></TR> </Table><br><br> <H2>Step 2-Enter Your Total Labor Costs<BR> (subset of Total Costs)</H2> <TABLE BORDER=6 CELLSPACING=2 CELLPADDING=3 ALIGN=MIDDLE> <TR> <TD><DIV ALIGN=CENTER><B>COST ELEMENT<BR>DESCRIPTION</B></DIV></TD> <TD><DIV ALIGN=CENTER><B><br>AMOUNT</B></DIV></TD> <TD><DIV ALIGN=CENTER><B>SUBTOTAL<br>(Computed)</B></DIV></TD></TR> <TR> <TD><DIV ALIGN=CENTER><B>Labor Costs from General Ledger</B></DIV> </TD> </TR> <TR><TD>A. <B>Total</B> Direct Labor (from Step 1)</TD> <TD><DIV ALIGN=CENTER><INPUT TYPE=TEXT NAME=DLL SIZE=15> </DIV></TD> <TD><DIV ALIGN=CENTER> </TD></TR> <TD>H. <B>Total</B> Overhead Labor</TD> <TD><DIV ALIGN=CENTER><INPUT TYPE=TEXT NAME=OHL SIZE=15> </DIV></TD> <TD><DIV ALIGN=CENTER> </DIV></TD></TR> <TD>I. <B>Total</B> G&A Labor</TD> <TD><DIV ALIGN=CENTER><INPUT TYPE=TEXT NAME=GAL SIZE=15> </DIV></TD> <TD><DIV ALIGN=CENTER> </DIV></TD></TR> <TD>J. <B>Total</B> B&P and IR&D Labor</TD> <TD><DIV ALIGN=CENTER><INPUT TYPE=TEXT NAME=BPL SIZE=15> </DIV></TD> <TD><DIV ALIGN=CENTER> </DIV></TD></TR> <TD><DIV ALIGN=RIGHT>K. Total Labor</DIV></TD> <TD><DIV ALIGN=CENTER></DIV> </TD> <TD><DIV ALIGN=CENTER><INPUT TYPE=TEXT NAME=TOTLAB SIZE=15></DIV> </TD></TR> </Table><br><br> <A NAME="help"> (If you have difficulty running this worksheet on your Netscape 2.0b6a browser, [ic:ccc]<A HREF="ccasratehelp.html">click here</A>.) <BR><BR> <H2>Step 3-Click on Compute for Rate Calculation Results</H2> <INPUT TYPE="button" VALUE="Compute" onClick=computeForm(this.form)> <INPUT TYPE="reset" VALUE="Reset" onClick=clearForm(this.form)> <BR><BR> <TABLE BORDER=6 CELLSPACING=2 CELLPADDING=3 ALIGN=MIDDLE> <TR> <TD><DIV ALIGN=CENTER>Fringe Benefit Rate</DIV></TD> <TD><DIV ALIGN=CENTER><INPUT TYPE=TEXT NAME=FBR SIZE=15> </DIV></TD> <TD><DIV ALIGN=CENTER>The Fringe Benefit Rate rate is generated to build the [ic:ccc]Overhead and G&A rates and is not separately stated for pricing or [ic:ccc]billing. See formulas, below.</DIV></TD></TR> <TR> <TD>Overhead Rate</TD> <TD></TD> <TD><DIV ALIGN=CENTER><INPUT TYPE=TEXT NAME=OHR SIZE=15></DIV> </TD></TR> <TR> <TD>G&A Rate</TD> <TD></TD> <TD><DIV ALIGN=CENTER><INPUT TYPE=TEXT NAME=GAR SIZE=15> </DIV></TD></TR> </TABLE> <BR><BR> <H2>The Proof of the Calculated Rates</H2> <TABLE BORDER=6 CELLSPACING=2 CELLPADDING=3 ALIGN=MIDDLE> <TR> <TD><DIV ALIGN=CENTER><B>COST ITEM</B></DIV></TD> <TD><DIV ALIGN=CENTER><B>RATE%</B></DIV></TD> <TD><DIV ALIGN=CENTER><B>AMOUNT</B></DIV></TD></TR> <TR><TD> Direct Labor</TD> <TD><DIV ALIGN=CENTER> </TD> <TD><DIV ALIGN=CENTER><INPUT TYPE=TEXT NAME=DLB SIZE=15> </DIV></TD> </TR> <TR> <TD> Overhead on Direct Labor</TD> <TD><DIV ALIGN=CENTER><INPUT TYPE=TEXT NAME=OHRR SIZE=15> </DIV></TD> <TD><DIV ALIGN=CENTER><INPUT TYPE=TEXT NAME=OHRB SIZE=15> </DIV></TD> </TR> <TR><TD> Other Direct Costs</TD> <TD><DIV ALIGN=CENTER> </TD> <TD><DIV ALIGN=CENTER><INPUT TYPE=TEXT NAME=ODCB SIZE=15> </DIV></TD> </TR> <TR> <TD> G&A on Subtotal of Costs</TD> <TD><DIV ALIGN=CENTER><INPUT TYPE=TEXT NAME=GARR SIZE=15> </DIV></TD> <TD><DIV ALIGN=CENTER><INPUT TYPE=TEXT NAME=GARB SIZE=15> </DIV></TD> </TR> <TR><TD> Total Costs (see Step 1, above)</TD> <TD><DIV ALIGN=CENTER> </TD> <TD><DIV ALIGN=CENTER><INPUT TYPE=TEXT NAME=TCB SIZE=15> </DIV></TD> </TR> </Table><br><br> <H2>The Indirect Cost Rate Calculation Formulas <BR> [ic:ccc](Keyed to Cost Elements Above)</H2> </CENTER> <BR> <B>Fringe Benefit Rate (FBR)</B>= C / K<BR><BR> <B>Overhead Rate (OHR)</B>= (((A + H + J) * FBR) + D) / (A + J)<BR><BR> <B>G&A Rate</B>= ((I * FBR) + E + F + (J *OHR)) / [ic:ccc](G - ((I * FBR) + E + F + (J *OHR))) <BR><BR> </FORM> <H5> <img src="back.gif"><A HREF="ccassw.html">Back to CCAS Software</A><BR> <P> <CENTER> <HR SIZE="6"> <A HREF="Default.html">CCAS's home page</A><P> <A HREF="mailto:info@ccas.com"><IMG SRC="mbox.gif" [ic:ccc]ALIGN=bottom WIDTH="32" HEIGHT= "32" NATURALSIZEFLAG="3" Border="0"></A><BR> Forward inquiries to <BR> <A HREF="mailto:info@ccas.com">info@ccas.com</A> <BR> <BR> (c) 1996 CCAS, Inc. All rights reserved. </H5> </CENTER> </BODY> </HTML>
Output
The worksheet looks like Figures W6.1 through W6.4.
Figure W6.1. The first form allows users to enter their total costs.
Figure W6.2. Next, users enter their total labor costs.
Figure W6.3. The third form allows users to compute the results.
Figures W6.4. The fourth form provides breakdown proofs of the calculations.
Analysis
The Indirect Cost Rate Sheet is built out of four functions. The HTML form itself is rather simple consisting of a number of text input fields spanning four tables with a compute button and a reset button. Only three of the text field have event
handlers, which all call the same function: computeField(). This function makes calls to two of the other functions: checkNumber() and computeForm(). clearForm() is invoked when the user clicks on the reset button.
This function takes four arguments and checks that a given number falls within a specified range. If not, it warns the user that a particular field contains invalid data.
function checkNumber(input, min, max, msg) { msg = msg + " field has invalid data: " + input.value;
The function starts by building the message that will be displayed if there is an error.
var str = input.value; for (var i = 0; i < str.length; i++) { var ch = str.substring(i, i + 1) if ((ch < "0" || "9" < ch) && ch != '.') { alert(msg); return false; } }
Next, the function scans each character of the input string to make sure it is a numeric value. This program was written before the parseInt() function was available in JavaScript, which could also be used, with certain
limitations, to check if a value was numeric.
If the value is not numeric, the user is alerted and a false value is returned by the function.
var num = 0 + str if (num < min || max < num) { alert(msg + " not in range [" + min + ".." + max + "]"); return false; } input.value = str; return true; }
The final step is to check if the value falls within the specified range, and if not, to alert the user and return a false value.
This function is called by the event handler in three of the form fields. It ensures that the value stored in a field is a string by adding an empty string to the start of the field and then calling
computeForm() to evaluate the whole form based on the new value of the field.
This function performs all the work of calculating the results of the three formulas.
function computeForm(form) { if ((form.DL.value == null || form.DL.value.length == 0) || (form.ODC.value == null || form.ODC.value.length == 0) || (form.TFB.value == null || form.TFB.value.length == 0) || (form.TOH.value == null || form.TOH.value.length == 0) || (form.TGA.value == null || form.TGA.value.length == 0) || (form.TBP.value == null || form.TBP.value.length == 0) || (form.FBR.value == null || form.TBP.value.length == 0) || (form.OHL.value == null || form.OHL.value.length == 0) || (form.GAL.value == null || form.GAL.value.length == 0) || (form.BPL.value == null || form.BPL.value.length == 0)) { form.FBR.value = "Incomplete data"; form.OHR.value = "Incomplete data"; form.GAR.value = "Incomplete data"; return; }
The function starts by checking that certain critical fields contain valid data. If not, error messages are displayed in selected fields and the function returns.
if (!checkNumber(form.DL, 1,99999999, "Direct Labor") || !checkNumber(form.ODC,0,99999999, "Other Direct Costs") || !checkNumber(form.TFB,1,99999999, "Total Fringe Benefits") || !checkNumber(form.TOH,1,99999999, "Total Overhead") || !checkNumber(form.TGA,0,99999999, "Total G&A") || !checkNumber(form.TBP,0,99999999, "Total B&P") || !checkNumber(form.TBP,0,99999999, "Total B&P") || !checkNumber(form.DLL,0,99999999, "Total B&P") || !checkNumber(form.OHL,1,99999999, "Total Overhead Labor") || !checkNumber(form.GAL,0,99999999, "Total G&A Labor") || !checkNumber(form.BPL,0,99999999, "Total B&P Labor")) { form.FBR.value = "Invalid"; form.OHR.value = "Invalid"; form.GAR.value = "Invalid"; return; }
Next, the function checks that the values in selected fields fall within the desired range using checkNumber(). Again, if there is a problem, a message to that effect is displayed in selected text fields and the function exits.
var i=form.DL.value *1 var j=form.ODC.value*1 form.TOTDIR.value=i + j form.DLL.value=i var k=form.TFB.value *1 var l=form.TOH.value *1 var m=form.TGA.value *1 var n=form.TBP.value *1 form.TOTIND.value=k + l + m + n var z=i + j + k + l + m + n form.TC.value=z var o=form.OHL.value *1 var p=form.GAL.value *1 var q=form.BPL.value *1 var r=i + o + p + q form.TOTLAB.value= r var s=(k / r) form.FBR.value=s * 100 var t=(((i + o + q) * s) + l) / (i + q) form.OHR.value= t * 100 var u=(m + n+ (p * s) + (t * q)) var z=z - u var z= u / z form.GAR.value=z * 100 form.DLB.value=i var v=i * t form.OHRB.value=v form.OHRR.value=t * 100 form.ODCB.value=j form.GARR.value=z * 100 var w=(i + v + j) * z form.GARB.value=w form.TCB.value=w + i + v + j }
Finally, the function makes all the mathematical calculations and stores the results in the relevant fields.
The clearForm() function simply clears three critical fields in the form by assigning empty strings to them.