/*

File: calculator_classes.js

SaeSolved::sitewidgets.com(TM) JavaScript Class Library for
Calculators -- Version 1.211, 20020607
Copyright (C) 2001 by SaeSolved::(TM), http://www.sitewidgets.com.

This Library provides a set of classes for use in building calculators.
It handles the basic input and output issues such as formatting and
data validation. Calculator algorithms need to be incorporated in an
instance of the method OperateOnValues() to create a specific calculator.
An example at the end of this library illustrates how this may be done.

This Library is open source software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License
(http://www.gnu.org/copyleft/lesser.txt) as published by the Free
Software Foundation; either version 2.1 of the License, or (at your
option) any later version.

In particular you may copy and distribute verbatim copies of the
Library's complete source code as you receive it, in any medium,
provided that you conspicuously and appropriately publish on each
copy an appropriate copyright notice and disclaimer of warranty;
keep intact all the notices that refer to this License and to the
absence of any warranty; and distribute a copy of this License along
with the Library.

This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License (http://www.gnu.org/copyleft/lesser.txt)
for more details.

A copy of the GNU Lesser General Public License may be obtained from
the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307, USA.

It is requested, but not required, that you use the statement in the
variable "this.License" in the function Calculator below in a
document.write statement in such a way as to conspicuously and
appropriately publish on each web page where the calculator is used
the hyperlinked credits, copyright notice, and disclaimer of warranty
contained in the variable "this.License."

SaeSolved::(TM) may be contacted at 1552 Beachview Drive,
Virginia Beach, VA 23464-7225, USA; email: webmaster@saesolved.com.

Version change history:
1.211 20020607 Corrected function Validate for initial non-nomeric characters
1.21  20001120 Added method ValidateSubmit().
                Corrected handling of radio element names.
                Added ability to use form and table styles.
1.2   20000822 Added radio and select elements.
1.18  20000817 Added checkbox element, getArgs, font color.
                Element font family, size, and color
                'inherited' from calculator.
1.11  20000214 Fixed Opera-specific bug in SetLayout(), tidied
                ShowRows(), corrected validation for values between
                plus and and minus one.
1.1   20000212 Added SetLayout(), which gives greater flexibilty to
                calculator layout without having to override ShowRows().
                In addition fields can now be specified as input or
                output and fields not having the type 'text' will be
                ignored for both input and output.
1.02  20000209 Check for unwanted commas and extra decimal points,
                provide for footnotes, individual row background colors
1.01  20000201 Allow customizing of background colors
1.00  20000124 Base release
*/

js_version = 1.1;

function Calculator(name, title, helpUsed) {
    this.CalculatorName   = name;
    this.CalculatorTitle  = title;
    if (helpUsed == null){
        this.HelpUsed     = false;
    }else{
        this.HelpUsed     = helpUsed;
    }
    if (this.HelpUsed){
        this.TotalColumns = 3;
    }else{
        this.TotalColumns = 2;
    }
    this.License          = 'This calculator is based on the ' +
        'SaeSolved::<A HREF="http://www.sitewidgets.com" ' +
        'target="_top">sitewidgets.com</A>&#153; JavaScript Class ' +
        'Library for Calculators, which is copyrighted &copy; ' +
        '2001 by SaeSolved::&#153; and provided WITHOUT WARRANTY ' +
        'either expressed or implied.';
    this.FontFamily       = 'Arial, Helvetica, sans-serif';
    this.FontPoint        = '10 pt';
    this.FontSize         = '2';
    this.FontColor        = '#000000';
    this.FormStyle        = null;
    this.TableStyle       = null;
    this.TableFormat      = null;
    this.TitleFormatBegin = null;
    this.TitleFormatEnd   = null;
    this.TitleBGColor     = '#CCCCCC';
    this.HelpFormat       = null;
    this.HelpBGColor      = '#E6E6E6';
    this.RowBGColor       = new Array();
    this.DefaultBGColr    = new Array();
    this.DefaultBGColr[0] = '#E6E6E6';
    this.DefaultBGColr[1] = '#F1F1F1';
    this.RowFormat        = new Array();
    this.RowFormatEnd     = new Array();
    this.LabelAlign       = 'right';
    this.ValueAlign       = 'left';
    this.LicenseFormatted = null;
    this.index            = 0;
    this.rowindex         = -1;
    this.Element          = new Object();
    this.Calculate        = Calculate;
    this.ValidateSubmit   = ValidateSubmit;
    this.AddElement       = AddElement;
    this.SetLayout        = SetLayout;
    this.SetStyles        = SetStyles;
    this.ShowRows         = ShowRows;
    this.ShowCalculator   = ShowCalculator;
    this.GetValues        = GetValues;
    this.PutValues        = PutValues;
}

function AddElement(obj, indx){
    var ndx = indx;
    if (ndx == null)
        ndx = this.index;
    obj.RowLocn = ndx;
    if (obj.type == 'radio') {
        obj.name = obj.family_name + '_' + ndx;
    }
    this[obj.name] = obj;
    if(obj.BGColor == null)
        obj.BGColor = this.DefaultBGColr[ndx % 2];
    if (this.RowBGColor[ndx] == null)
        this.RowBGColor[ndx] = obj.BGColor;
    if (obj.FontFamily == null)
        obj.FontFamily = this.FontFamily;
    if (obj.FontSize == null)
        obj.FontSize = this.FontSize;
    if (obj.FontColor == null)
        obj.FontColor = this.FontColor;
    if (obj.LabelAlign == null)
        obj.LabelAlign = this.LabelAlign;
    if (obj.ValueAlign == null)
        obj.ValueAlign = this.ValueAlign;
    this.Element[this.index++] = obj;
}

function SetLayout(){
    var args    = new Array();
    if (navigator.userAgent.indexOf('Opera') == -1){
        args    = arguments;
    }else{
        args    = SetLayout.arguments;
        // hack for Opera -- this seems to be required, but the rationale eludes me...
        if (this.rowindex < 0) this.rowindex = 0;
    };
    for (var i = 0; i < args.length; i++){
        var temp = new String(args[i]);
        if (temp.charAt(0) == "#"){
            this.rowindex++;
            if (temp.length > 1){
                this.RowBGColor[this.rowindex] = args[i];
            }else{
                this.RowBGColor[this.rowindex] = this.DefaultBGColr[this.rowindex % 2];
            }
        }else{
            this.AddElement(args[i], this.rowindex);
        }
    }
}

function SetStyles(){
    // This uses defaults for each of the variables unless they have
    // been given explicit values after an object is instantiated
    if(this.FormStyle == null) {
        this.FormStyle = '';
    } else {
        this.FormStyle = ' style="' + this.FormStyle + '"';
    }
    if(this.TableStyle == null) {
        this.TableStyle = '';
    } else {
        this.TableStyle = ' style="' + this.TableStyle + '"';
    }
    if(this.TableFormat == null) this.TableFormat =
        '<span><table width="230" border="0" ' +
        'cellspacing="2" cellpadding="3" align="left" ' +
        'bgcolor="#FFFFFF"' + this.TableStyle + '>';
    if(this.TitleFormatBegin == null) this.TitleFormatBegin =
        '<tr bgcolor="' + this.TitleBGColor + '" style="font-size: ' +
        this.FontPoint + ';  font-family: ' + this.FontFamily +
        '; color: ' + this.FontColor + '; font-style: normal; ' +
        'font-weight: normal; background-color: ' + this.TitleBGColor +
        '"><th colspan="' + this.TotalColumns + '">' +
        '<font face="' + this.FontFamily + '" color="' + this.FontColor + '" size="3">';
    if(this.TitleFormatEnd == null) this.TitleFormatEnd =
        '</font></td></tr>';
    if (this.rowindex < 0 ) this.rowindex = this.index;
    for (var RowNr = 0; RowNr < this.rowindex; RowNr++){
       if(this.RowFormat[RowNr] == null)
            this.RowFormat[RowNr] =
            this.RowFormat[RowNr] =
                '<tr bgcolor="' + this.RowBGColor[RowNr] +
                '" style="font-size: ' + this.FontPoint +
                '; font-family: ' + this.FontFamily +
                '; color: ' + this.FontColor +
                '; font-style: normal' +
                '; font-weight: normal' +
                '; background-color: ' + this.RowBGColor[RowNr] +
                ';">\n';
        if(this.RowFormatEnd[RowNr] == null)
            this.RowFormatEnd[RowNr] = '</tr>';
    }
    if(this.HelpFormat == null) this.HelpFormat =
        'bgcolor="' + this.HelpBGColor + '" style="font-size: ' +
        this.FontPoint + '; font-family: ' + this.FontFamily +
        '; color: ' + this.FontColor + '; font-style: normal; ' +
        'font-weight: normal; background-color: ' +
        this.HelpBGColor + ';';
    if(this.LicenseFormatted == null) this.LicenseFormatted =
        '<tr bgcolor="' + this.TitleBGColor + '" style="font-size: ' +
        '8 pt; font-family: ' + this.FontFamily + '; color: ' +
        this.FontColor + '; font-style: normal; font-weight: ' +
        'normal; background-color: ' + this.TitleBGColor + ';">' +
        '<td colspan="' + this.TotalColumns + '"><font face="' +
        this.FontFamily + '" size="1" color="' + this.FontColor + '">' + this.License +
        '</font></td></tr>\n';
}

function Calculate() {
    var obj = self.document[this.CalculatorName];
    this.GetValues(obj);
    // function OperateOnValues must be supplied in the implementation
    this.OperateOnValues();
    this.PutValues(obj);
}

function ValidateSubmit() {
    var obj = self.document[this.CalculatorName];
    this.GetValues(obj);
    // function ValidateValues must be supplied in the implementation
    if (this.ValidateValues()) {
        obj.submit();
    }
}

function ShowCalculator() {
    this.SetStyles();
    document.write('<form name="' + this.CalculatorName + '" id="' +
        this.CalculatorName + '" target="_self" action="' +
        window.location + '" method="get"' + this.FormStyle + '>\n');
    document.write(this.TableFormat,'\n');
    document.write(this.TitleFormatBegin,'\n',this.CalculatorTitle,
        '\n', this.TitleFormatEnd,'\n');
    this.ShowRows();
    document.write(this.LicenseFormatted, '</table></span>\n</form>');
}

function ShowRows(){
    var i = 0;
    for (var RowNr = 0; RowNr < this.rowindex; RowNr++){
        document.write(this.RowFormat[RowNr]);
        for (i; i < this.index; i++){
            if (this.Element[i].RowLocn != RowNr) break;
            this.Element[i].ShowElement(this.HelpUsed,
                                        this.TotalColumns);
            if (i == 0 && this.HelpUsed){
                document.write(
'       <td rowspan="' + (this.rowindex - 1).toString() +
                        '" align="center" valign="middle" ' +
                        this.HelpFormat + '">\n',
'           <font face="' + this.FontFamily + '" color="' + this.FontColor + '" size="1">\n',
'           <b>Click on the &quot;?&quot; next to the input box ' +
                'for an item to get help on that item.</b>\n',
'           </font>\n',
'       </td>\n');
            }
        }
        document.write('   ' + this.RowFormatEnd[RowNr] + '\n');
    }
}

function GetValues(obj){
    for (var i = 0; i < this.index; i++){
        if (this.Element[i].in_out.indexOf('input') != -1 || this.Element[i].in_out == ''){
            if (this.Element[i].type == 'text'){
                var numFieldVal = obj[this.Element[i].value_name].value;
                //get rid of leading and trailing spaces.
                while (numFieldVal.charAt(0) == ' '){
                    numFieldVal = numFieldVal.substring(1)
                }
                while (numFieldVal.charAt(numFieldVal.length - 1) == ' '){
                    numFieldVal = numFieldVal.substring(0, numFieldVal.length - 1)
                }
                if (numFieldVal == null || numFieldVal.length == 0){
                    //assume empty or blank fields are zero
                    this.Element[i].value = 0.0;
                }else{
                    //strip out any commas
                    this.Element[i].value =
                        parseFloat(numFieldVal.toString().split(',').join(''));
                }
            }else if (this.Element[i].type == 'checkbox'){
                var checkboxVal = '';
                if(obj[this.Element[i].value_name].checked == true){
                    checkboxVal = obj[this.Element[i].value_name].value;
                }
                if (this.Element[i].decimals == null) {
                    this.Element[i].value = checkboxVal;
                }else{
                    if (checkboxVal == '') {
                        checkboxVal = '0';
                    }
                    if (this.Element[i].decimals == 0) {
                        this.Element[i].value = parseInt(checkboxVal);
                    }else{
                        this.Element[i].value = parseFloat(checkboxVal);
                    }
                }
            }else if (this.Element[i].type == 'radio_parent'){
                var radioVal = '';
                var radioNam = new Array();
                radioNam = obj[this.Element[i].value_name];
                for (var j = 0; j < radioNam.length; j++){
                    if(radioNam[j].checked == true){
                        radioVal = radioNam[j].value;
                    }
                }
                if (this.Element[i].decimals == null) {
                    this.Element[i].value = radioVal;
                }else{
                    if (radioVal == '') {
                        radioVal = '0';
                    }
                    if (this.Element[i].decimals == 0) {
                        this.Element[i].value = parseInt(radioVal);
                    }else{
                        this.Element[i].value = parseFloat(radioVal);
                    }
                }
            }else if (this.Element[i].type == 'select'){
                this.Element[i].value = this.Element[i].options[obj[this.Element[i].value_name].selectedIndex][0];
            }
        }
    }
}

function PutValues(obj){
    for (var i = 0; i < this.index; i++){
        if (this.Element[i].in_out == 'output' || this.Element[i].in_out == ''){
            if (this.Element[i].type == 'text'){
                obj[this.Element[i].value_name].value = this.Element[i].ShowDecimals();
            }else if (this.Element[i].type == 'checkbox'){
                if(this.Element[i].value == obj[this.Element[i].value_name].value){
                    obj[this.Element[i].value_name].checked = true;
                }else{
                    obj[this.Element[i].value_name].checked = false;
                }
            }else if (this.Element[i].type == 'radio_parent'){
                var radioNam = new Array();
                radioNam = obj[this.Element[i].value_name];
                for (var j = 0; j < radioNam.length; j++){
                    if(this.Element[i].value == radioNam[j].value){
                        radioNam[j].checked = true;
                    }else{
                        radioNam[j].checked = false;
                    }
                }
            }else if (this.Element[i].type == 'select'){
                for (var j = 0; j < this.options.length; j++){
                    if (this.Element[i].value == this.options[j][0]){
                        obj[this.Element[i].value_name].selectedIndex = j;
                    }
                }
            }
        }
    }
}

function CalculatorElement(type, name, label, in_out){
    this.type = type;
    if (this.type == 'radio') {
        this.family_name = name;
    } else {
        this.name        = name;
    }
    this.value_name  = name + '_value';
    this.help_name   = name + '_help';
    if (label == null){
        this.label = '';
    }else{
        this.label = label;
    }
    this.alert_label = this.label.replace(/<[^>]+>/g, '');
    if (in_out == null){
        this.in_out = '';
    }else{
        this.in_out = in_out;
    }
    this.value             = '';
    this.decimals          = null;
    this.size              = 5;
    this.checked           = false;
    this.options           = new Array();
    this.help              = '';
    this.max_value         = null;
    this.min_value         = null;
    this.isHeader          = false;
    this.ColSpan           = null;
    this.RowLocn           = 0;
    this.BGColor           = null;
    this.FontFamily        = null;
    this.FontSize          = null;
    this.FontColor         = null;
    this.LabelAlign        = null;
    this.LabelFormatBegin  = null;
    this.LabelFormatMid    = null;
    this.LabelFormatEnd    = null;
    this.ValuePrefix       = '';
    this.ValuePostfix      = '';
    this.ValueFormatBegin  = null;
    this.ValueFormatMid    = null;
    this.ValueFormatEnd    = null;
    this.HelpFormatBegin   = null;
    this.HelpFormatEnd     = null;
    this.NoteFormatBegin   = null;
    this.NoteFormatMid     = null;
    this.NoteFormatEnd     = null;
    this.ButtonFormatBegin = null;
    this.ButtonFormatMid   = null;
    this.ButtonFormatEnd   = null;
    this.SetFormats        = SetFormats;
    this.ShowElement       = ShowElement;
    this.ShowDecimals      = ShowDecimals;
    this.Validate          = Validate;
    this.HelpScreen        = HelpScreen;
}

function SetFormats(){
    // This uses defaults for each of the variables unless they have
    // been given explicit values after an object is instantiated
    if(this.LabelFormatBegin == null){
        if(this.isHeader){
            this.LabelFormatBegin = '<th';
        }else{
            this.LabelFormatBegin = '<td align="' + this.LabelAlign + '"';
        }
    }
    if(this.LabelFormatMid == null) this.LabelFormatMid =
        '><font face="' + this.FontFamily +
        '" size="' + this.FontSize + '" color="' + this.FontColor + '">';
    if(this.LabelFormatEnd == null){
        this.LabelFormatEnd = '</font>';
        if(this.isHeader){
            this.LabelFormatEnd += '</th>';
        }else{
            this.LabelFormatEnd += '</td>';
        }
    }
    if(this.ValueFormatBegin == null) this.ValueFormatBegin =
        '<td nowrap align="' + this.ValueAlign + '" valign="top"';
    if(this.ValueFormatMid == null) this.ValueFormatMid =
        '><font face="' + this.FontFamily + '" color="' + this.FontColor + '" size="' +
        this.FontSize + '">' + this.ValuePrefix;
    if(this.ValueFormatEnd == null) this.ValueFormatEnd =
        this.ValuePostfix + '</font>';
    if(this.HelpFormatBegin == null) this.HelpFormatBegin =
        '<font face="' + this.FontFamily + '" color="' + this.FontColor + '" size="1">';
    if(this.HelpFormatEnd == null) this.HelpFormatEnd =
        '</font></td>';
    if(this.NoteFormatBegin == null) this.NoteFormatBegin =
        '<td align="left"';
    if(this.NoteFormatMid == null) this.NoteFormatMid =
        '><font face="' + this.FontFamily + '" color="' + this.FontColor + '" size="1">';
    if(this.NoteFormatEnd == null) this.NoteFormatEnd =
        '</font></td>';
    if(this.ButtonFormatBegin == null) this.ButtonFormatBegin =
        '<td align="center"';
    if(this.ButtonFormatMid == null) this.ButtonFormatMid =
        '><font face="' + this.FontFamily + '" color="' + this.FontColor + '" size="' +
        this.FontSize + '">';
    if(this.ButtonFormatEnd == null) this.ButtonFormatEnd =
        '</font></td>';
}

function ShowElement(withHelp, TotalColumns){
    this.SetFormats();
    var ValueColumns = 1;
    if (       this.type == 'text'
            || this.type == 'checkbox'
            || this.type == 'radio'
            || this.type == 'select'
            || this.type == 'string'){
        if (this.label == ''){
            ValueColumns++;
        }else{
            document.write(
'       ' + this.LabelFormatBegin);
            if (this.ColSpan != null){
                document.write(' colspan="', this.ColSpan, '"');
            }
            document.write(this.LabelFormatMid + '\n',
'           ', this.label, '\n',
'       ' + this.LabelFormatEnd + '\n');
        }
        document.write(
'       ' + this.ValueFormatBegin)
        if (this.ColSpan != null){
            document.write(' colspan="', this.ColSpan, '"');
        }else if (ValueColumns > 1){
            document.write(' colspan="', TotalColumns, '"');
        }
        document.write(this.ValueFormatMid + '\n');
        if (this.type == 'checkbox'){
            document.write('           <input type="checkbox' +
                '" name="'    + this.value_name + '"');
            if (this.checked){
                document.write(' checked');
            }
            document.write(' value="' + this.value);
        }else if (this.type == 'radio'){
            document.write('           <input type="radio' +
                '" name="'    + this.value_name + '"');
            if (this.checked){
                document.write(' checked');
            }
            document.write(' value="' + this.value);
        }else if (this.type == 'select'){
            document.write('<select ' +
                'name="'    + this.value_name);
        }else{
            document.write('           <input type="text' +
                '" name="'  + this.value_name +
                '" size="'  + this.size  +
                '" value="' + this.value);
            if (this.type == 'text'){
                document.write('" onChange="' + this.name +
                            '.Validate(this);');
            }
        }
        if (this.in_out == 'output'){
            document.write('" readonly');
        }else{
            document.write('"');
        }
        if (this.type == 'select'){
            document.write('>');
            for (var i = 0; i < this.options.length; i++){
                document.write('<option value="', this.options[i][0], '"');
                if (this.value == this.options[i][0]){
                    document.write(' selected');
                }
                document.write('>', this.options[i][1], '</option>');
            }
            document.write('</select');
        }
        document.write('>', this.ValueFormatEnd, this.HelpFormatBegin);
        if (withHelp){
            if (this.help != null && this.help.length > 0){
                document.write('<input type="button' +
                    '" name="'     + this.help_name +
                    '" value=" ? ' +
                    '" onClick="' + this.name + '.HelpScreen();">\n');
            }else{
                document.write('&nbsp;\n');
            }
        }
        document.write(
'       ' + this.HelpFormatEnd + '\n');
    }else if (this.type == 'label_only' || (this.type == 'radio_parent' && this.label != '')){
        document.write(
'           ' + this.LabelFormatBegin);
        if (this.ColSpan != null){
            document.write(' colspan="', this.ColSpan, '"');
        }
        document.write(this.LabelFormatMid + '\n',
'               '   + this.label + '\n',
'           ' + this.LabelFormatEnd + '\n');
    }else if (this.type == 'note'){
        document.write(
'           ' + this.NoteFormatBegin);
        if (this.ColSpan != null){
            document.write(' colspan="', this.ColSpan, '"');
        }else if (TotalColumns > 0){
            document.write(' colspan="', TotalColumns, '"');
        }
        document.write(this.NoteFormatMid + '\n',
'               '   + this.label + '\n',
'           ' + this.NoteFormatEnd + '\n');
    }else{
        document.write(
'           ' + this.ButtonFormatBegin);
        if (this.ColSpan != null){
            document.write(' colspan="', this.ColSpan, '"');
        }else if (TotalColumns > 0){
            document.write(' colspan="', TotalColumns, '"');
        }
        document.write(this.ButtonFormatMid + '\n',
'               <input type="button' +
                    '" name="'    + this.value_name  +
                    '" value="'   + this.label +
                    '" onClick="' + this.type +
                    '">\n',
'           ' + this.ButtonFormatEnd + '\n');
    }
}

function HelpScreen(){
    alert(this.help);
    return true;
}

function ShowDecimals(){
    if (this.decimals == null
        || parseFloat(this.value).toString().length
            < this.value.toString().length)
            return this.value;
    var factr = 1;
    for (var i = 0; i < this.decimals; i++){
        factr *= 10;
    }
    var outputStr = Math.round(factr * this.value).toString();
    while (outputStr.length - this.decimals < 1){
        outputStr = '0' + outputStr;
    }
    if (this.decimals == 0)
        return outputStr;
    var pos = outputStr.length - this.decimals;
    return outputStr.substring(0, pos) + '.' +
                outputStr.substring(pos);
}

function Validate(obj){
    if (this.in_out == 'output'){
        alert('"' + this.alert_label + '" is an output value.');
        obj.value = '';
        return true;
    }
    var val = obj.value;
    //strip out any commas
    var val1 = val.toString().split(',').join('');
    var val2 = val1;
    //remove decimal point(s) -- check if there were too many
    val2 = val1.toString().split('.').join('');
    //get rid of leading signs and zeros
    var val3 = val2;
    if (val3.charAt(0) == '+' || val3.charAt(0) == '-'){
        val3 = val3.substring(1)
    }
    while (val3.charAt(0) == '0'){
        val3 = val3.substring(1)
    }
    if (val1.length - val2.length > 1){
       alert('The value of "' + this.alert_label
            + '" appears to contain more than one decimal point.');
    }else if (isNaN(parseInt(val3)) || parseInt(val3).toString().length
            < val3.toString().length){
       //check for valid numerical value
       alert('You have entered an invalid value (' + val + ') for "'
                + this.alert_label + '."');
    }else if (this.max_value != null && val > this.max_value){
       alert('The value of "' + this.alert_label
            + '" must not be greater than ' + this.max_value + '.');
    }else if (this.min_value != null && val < this.min_value){
       alert('The value of "' + this.alert_label
            + '" must not be less than ' + this.min_value + '.');
    }else{
        return true;
    }
    obj.focus();
    obj.select();
    return false;
}

function getArgs(){
/*  Based on Example 13-5 in "JavaScript: The Definitive Guide," 3rd ed.,
    by David Flanagan, O'Reilly (1998) p. 245.                            */
    var args = new Object();
    var query = window.location.search.substring(1);
    var pairs = new Array();
    if ((pairs = query.split("&")) == null) pairs = localSplit(query, "&");
    for (var i = 0; i < pairs.length; i++){
        var pos = pairs[i].indexOf('=');
        if (pos == -1) continue;
        var argname = pairs[i].substring(0,pos);
        var value = pairs[i].substring(pos+1);
        args[argname] = unescape(value);
    }
    return args;
}

//  The following is a demo implementation of the above classes
//  which can be uncommented and placed between script tags in an
//  HTML page after including these classes.
/*
    var TextBoxSize    = 7;
    // New Calculator object
    var Demo           = new Calculator('DemoCalculator',
                                        'Demo Calculator', true);
    // First element used in calculator
    var A              = new CalculatorElement('text', 'A', 'A');
    // Some properties of the first element
        A.size         = TextBoxSize;
        A.help         = 'Value for A.';
        A.max_value    = 110;
        A.min_value    = -1234;
    // Second element used in calculator
    var B              = new CalculatorElement('text', 'B', 'B');
    // Some properties of the second element
        B.size         = TextBoxSize;
        B.help         = 'Value for B.';
        B.min_value    = 0;
    // Third element used in calculator
    var C              = new CalculatorElement('text', 'C',
                                                'C = A + B');
    // Some properties of the third element
        C.decimals     = 2;
        C.size         = TextBoxSize;
        C.help         = 'The demo calculation is simply for C ' +
                            '= A + B.';
    // The command element
    var CommandElement = new CalculatorElement('Demo.Calculate()',
                                    'commandElement', 'Calculate');
    // Add the elements to the calculator
    Demo.AddElement(A);
    Demo.AddElement(B);
    Demo.AddElement(C);
    Demo.AddElement(CommandElement);
    // Define the operation(s) that will be done using the elements
    function OperateOnValues(){
        this.C.value = this.A.value + this.B.value;
    }
    // Add this operation to the calculator
    Demo.OperateOnValues = OperateOnValues;
    // -->
    // Display the calculator
    Demo.ShowCalculator();
*/
