/* (c) Copyright Washington University 2001. All rights reserved. */
function script_is_live() {
    return true; // uncomment this line if this is the live script
    return false; //  comment out the above line in the dev script
    /*  BE CAREFUL WITH THIS:
        
    ALWAYS UNCOMMENT THE 'return true;' IN THE LIVE CALCULATOR!
        
    In an effort to simplify the development of this tool,
    portions of the HTML page which calls this javascript file
    are generated by code in this script. Those HTML sections
    should have different contents for the developmental copy
    of the tool than for the live in-use copy. In particular,
    the developmental tool should call a developmental perl
    script on the server side to generate an order sheet, but
    the live in-use script should NEVER do that... because the
    developmental perl script may not yet be in a useful state.
    Also, the developmental HTML page will expose certain hidden
    fields which we don't want to display on the live in-use
    tool.
        
    The relevant HTML-generating functions are near the end of
    this script.
    */
}
function interface_version() {
    return 0.6;
    /*  BE CAREFUL WITH THIS:
        
    This needs to be in sync with the perl script which generates
    order sheets. If the two are ever not equal, order sheets will
    not be generated.
        
    The number only needs to be updated when the interface between
    the two changes. If the perl script is expecting some different
    CGI input, then the interface version should be bumped up in
    both the perl file, and right here in the javascript.
        
    This allows us to catch cases where users may have a cached
    version of the TPN Calculator and give them an appropriate
    error message.
        
    */
}

/*
!!! TODO list
see status document, and any !!! marks in source
Right now (2001 Dec 13), status document is located at
http://peds.wustl.edu/div/gi/spec/tpn/tpn_calc_bak/status.html
    
Overview:
    
The first few functions are basic math utility functions,
followed by functions which serve simply as constants.
The rest of the functions are presented in an order which
coresponds roughly with their use in the associated HTML
document. There are some exceptions to this general rule.
    
The bulk of the main tnpcalc form in the HTML document is broken
up into major sections, refered to as "calculation groups".
The idea is that you can make changes in earlier calculation
groups and those changes will automatically cause updated values
to appear in all subsequent calculation groups. You can then move
down to one of those subsequent calculation groups and customize
the default calculated values. Your changes will be taken in and
any calculation groups beyond that point will be updated based
on the just-changed value.
    
So, each input needs to belong to a calculation group. When that
input is changed, a function is called to handle that change.
First, local concerns will be addressed. If the value appears
in the form in two units, and you update one, then the value in
the other units needs to be updated to match. If the value has
certain max/min values, we need to make sure that the new value
is in range, and bump it up/down as indicated. Once local concerns
are addressed, the calculation group as a whole is "run".
    
Running a calculation group means looking to see if all of the
required information for that group has been provided. If not,
then we can't very well fill in defaults for any subsequent groups.
So, we clear out the subsequent groups' values. If all the data is
provided, then we initialize the next calc group.
    
When a calc group is initialized, default values are filled in for
that group's fields. One that is done, the calc group is "run". As
explained in the last paragraph, since we have good values in our
fields, this will cause a chain reaction initialzing the next group
and so on and so on.
    
So normally, a user simply changes fields and things get updated.
    
Sometimes, you'll see a function called with "skip_calcgroup_cascade"
which means "just do the local stuff you're responsible for without
causing a chain reaction of calculations in subsequent calc groups.
This argument is used to prevent duplicate calculations.
    
For example....
:
:   function calc_group_x_init() {
calc_group_x_clear(); // clear out x's current values
// this will then cascade through whole calculator
// resulting in cleared out values below group 'x'
set_field_a( 'some_units', 'some_value' );
// translates 'a' into other units, also cascades
// resulting in cleared out values below group 'x'
set_field_b( 'some_units', 'some_value' );
// translates 'b' into other units, also cascades
// resulting in cleared out values below group 'x'
calc_group_x_run(); // derives stuff from 'a' and 'b'
// also causes a cascade of calculations
// resulting in actual useful values below group 'x'
}
    
By initializing calc group 'x', we cascade through the whole
calculator *four* (!!!!) times. Each of the first three times is
basically wasted effort. So, many functions are modified like this:
:
:   function calc_group_x_init() {
calc_group_x_clear( 'skip_calcgroup_cascade' );
set_field_a( 'some_units', 'some_value', 'skip_calcgroup_cascade' );
set_field_b( 'some_units', 'some_value', 'skip_calcgroup_cascade' );
calc_group_x_run(); // *now* we let things cascade
}
    
If a user wants to back out their customizations, there are a few
reset buttons after key calculation groups. Clicking one of those
buttons will cause the subsequent calculation groups' values to be
re-initialized (which will cascade down through the rest of the form)
over-writing any user customizations. If one of these buttons is
clicked when there is not enough data to initialize the next calc
group (ie: you hit a reset button when the form is empty) then an
error message will be given.
    
Functions for running calc-groups therefor have a verbose parameter
which indicates whether to squawk when data is missing. Normally,
we don't squawk. If the user hits the button, the verbose paramter
will be set, and we will squawk if there is a problem.
    
So, after the first few math utility functions, you will find
functions grouped roughly by their associated field order in
the HTML document...

for reference, there are six calculation groups:
1 age, weight, height, surface area, and bmi
2 fluids, energy, infusion, fat emulsion
3 dextrose and amino acids
4 summary info (not user editable, no reset button after group)
appears to the right of the electrolytes, but actually
gets calcuated first... could have gone in either order
with these two, and happened to go with this one
User can't change these values... they're simply copies
of earlier fields
5 electrolytes and minerals (no reset button after group)
these values are derived from earlier fields, and can
be customized, but nothing is in turn derived from the
electrolytes, so there is no need for a reset button
6 user-configurable extra fluids, constituents, etc (no button)
these values are set to default values in the HTML source
and are user-customizable with certain limits.
    
some odd things you may encounter...
    
javascript has a Majorly Annoying Flaw. Well, perhaps more than
one, but only one worth mentioning here. It uses the + sign to
mean both numeric addition and string concatenation. However,
HTML form fields are not typed to be strings or ints or floats,
so the intended use of + is often not determinable from the
surrounding syntax. Should fieldA + fieldB contenate or add?
In my experience, you'll frequently get concatenation when you
want addition. So, I often force numeric context by doing
things like ( fieldA*1 + fieldB*1 ). Majorly Annoying, but it
seems to be necessary. You'll see quite a bit of multiplication
by one in the code below. Oh, another reason for *1 all over:
it turns out that javascript also overloads comparison operators
to do both numeric and string comparison. So if javascript feels
like doing a string comparison, then 111 < 22 < 3. Neat, eh?
Throwing in the *1 will force numeric context. Sheesh!
Silly language.
        
In the electrolytes section: you may notice an obsesion with
units. For the most part, all calculations are coded to follow
the units changed by the user. Why not convert to a canonical set
of units, and do all calculations in that set? I started off with
that approach, but ran into trouble. Because the user-visible
values are rounded off to a lower degree of precision than the
underlying salt values, it is possible for the user to make a
change in one set of units, which gets translated into a change
in the other set of units, which is calculated to have certain
effects on the salt levels, and then the resulting levels are
converted into the user's original units, and rounding errors
result in small differences between the user's requested change
and the resulting value. This could be frustrating for users who
are trying to obtain a specific value in the units not used for
calculation. Under certain circumstances, they may be off just
a tiny bit, and not able to fix things. They change the value,
calculations are made, and new totals are derived, and the total
for the value they changed reverts to it's previous value. By
doing as much math in the user's units as we possibly can, we
avoid two sets of conversion, and resulting rounding errors, and
get totals that match the user's indicated preference. All of
the rounding/conversion error gets shifted to the other units,
about which the user is less concerned.
    
    
The electrolytes section is particularly thorny and deserves a good
discussion of the overall strategy.
    
There are four basic electrolyte constituents: sodium, potassium,
acetate, and chloride. Physicians typically want control over them
in that order as well. They are most likely to want to control the
amount of sodium or potassium intake, and not likely to care about
the chloride intake so much (in the majority of cases). Also, sodium
and potassium are cations (positive charge) while acetate and chloride
are anions (negative charge). In order to keep the mixture balanced,
electrolytes must be added in salts composed of a cation and an anion.
So, if you remove sodium, you decrease positive charge and must somehow
add other cations, or remove some anions as well. And you want to do
this in a way which allows electrolyte constituents to be put into
the mix as salts, and you want to have minimal impact on the amounts
of the other electrolytes, especially the 'higher priority' ones.
    
To make things messier still, phosphate and amino acids are added
with some electrolytes in their mixtures. These must be included in
the totals that the physician sees for each electrolyte, but cannot
be removed by modifying electrolyte values in the calculator. Instead
the physician gets an alert about where the remainder is comming from,
and what they can do to reduce it if doing so is critical.
    
So, how does this work out in the code?
    
At the outset, we figure out our 'electrolyte inheritance' (ie: the
electrolytes which came from phosphate and amino acids) and we figure
out our desired electrolyte levels. We then start adding salts to
bring the inherited levels up to our desired levels. We add sodium
acetate until either our sodium or acetate goal is reached. If we
need more sodium we add sodium chloride. Repeat with potassium.
If our desired acetate level hasn't been reached, we alert the user
(but this should never happen). Chloride has no desired level, and
is fine at whatever level it ends up at.
    
From here, we have only to accomodate any change the user makes to
the individual electrolyte levels. Our strategy is to meet the user's
request by pushing as much of the balancing side effect into chloride
as we possibly can. Our tactics are this: if they change a cation,
add/remove the chloride salt first. If we ever have to change an
acetate salt in balancing a cation request, see if we can restore the
acetate salt through a salt shift somewhere else. IE: if the user
wants to decrease sodium so much that we remove all sodium chloride
and a bit of sodium acetate. See if we can move some potassium chloride
into potassium acetate to restore the previous overall acetate level,
thereby shifting the whole side effect into chloride.
    
All of this round-about 'shifting the side effect into chloride' stuff
makes the code a bit hard to follow unless you're forewarned about the
strategy. The code is further complicated by the need to do as much
math as possible in the user's units of choice, thereby shifting as
much rounding/conversion slop into the units they're less concerned with.
    
    
*/


function is_good_number(n) {
    if (n * 1 == 1 / 0) return false; // Infinity is no good
    if (isNaN(n)) return false; // NaN is no good
    var temp_string = "" + n; // turn n into it's string form...
    if (!temp_string.length) return false; // empty string is no good
    if (isFinite(n)) return true; // numbers in ok range *are* good
    return false; // strings, numbers too big or small, etc are all bad
}
function is_good_positive_number(n) {
    if (!is_good_number(n)) return false;
    if (n * 1 > 0) return true;
    return false;
}
function is_good_nonnegative_number(n) {
    if (!is_good_number(n)) return false;
    if (n * 1 >= 0) return true;
    return false;
}

function not_pos_num(n) { return !is_good_positive_number(n) };
// these two (above and below) are just easier-to-type/read convenience functions
function not_nonneg_num(n) { return !is_good_nonnegative_number(n) };


function round_n_to_x_decimals(n, x) {
    // utility function to round off the decimal part of a number 'n'
    // to show 'x' many places after the decimal point.
    var decimal_mover = 1;
    if (x * 1 < 0) x = 0;
    for (var i = 1; i * 1 <= x * 1; i++) {
        decimal_mover = decimal_mover * 10;
    }
    return (Math.round(n * decimal_mover) / decimal_mover);
}
function drop_precision_but_remain_positive(raw_value) {
    /*
    utility function used in reporting approximate values to user.
    Rather than give them a big long decimal number, we try to give
    them an approximate number with only as much precision as is
    required to prevent the value from appearing to be zero
    */
    if (not_pos_num(raw_value)) return raw_value;
    var try_value = Math.round(raw_value);
    if (try_value * 1 > 0) return try_value;
    for (var i = 1; i * 1 <= 10; i++) { // if ten won't do, just give raw value back
        try_value = round_n_to_x_decimals(raw_value, i);
        if (try_value * 1 > 0) return try_value;
    }
    return raw_value;
}



function c_min_allowable_age_yr() { return (1 / 24) }; // ie: half a month
// c_foo functions (like the one above and those below) are contstants...
// not all constants are defined this way, but many are.
// (It isn't necessary to define months_per_year as 12, for example)
function c_min_allowable_weight_kg() { return .1 };
function c_min_allowable_height_cm() { return 10 };
function c_max_years_for_which_bmi_percentile_is_sex_agnostic() { return 10 };
function c_bmi_limit_for_youngest_agegroup() { return 20 };
function c_bmi_shift_for_older_males() { return 14 };
function c_bmi_shift_for_older_females() { return 13 };
function c_ideal_kg_per_m2_ratio() { return 22 };
function c_warn_unless_fluids_exceed_this_percent_of_recomended_value() { return 50 };
function c_growth_related_age_max_for_esttee_multiplier_in_years() { return 1 };
function c_first_growth_related_age_max_for_ree_in_years() { return 3 };
function c_second_growth_related_age_max_for_ree_in_years() { return 10 };
function c_esttee_multiplier_if_not_over_max() { return 1.2 };
function c_dextrose_kcal_p_ml() { return 3.4 };
function c_dextrose_percent_allowed_increments() { return 2.5 };
function c_aminoacids_percent_allowed_increments() { return .5 };
function c_fatemul_fluid_content_ml_p_g() { return 5 };
function c_fatemul_kcal_p_g() { return 9 };
function c_warn_if_cals_from_fat_exceed_this_percent() { return 51 };
function c_max_dex_percent_periph() { return 12.5 };  //todo:  ask about dextrose max
function c_max_dex_percent_centrl() { return 30 };  //used to be 40 (9/15/2008 *KL)
function c_max_dex_mg_p_kg_p_min() { return 25 };
function c_max_aminoacid_percent() { return 4.5 };  //used to be 4 (9/15/2008 *KL)
function c_max_aminoacid_mg_p_kg_p_day() { return 4 };  //used to be 3.5 (9/15/2008 *KL)
function c_initial_phos_mmol_p_l() { return 12 };
function c_max_years_for_which_trophamine_used_for_aminoacid() { return 1 };  // 1 year: used to be .25 (9/15/2008 *KL)
function c_younger_default_cations__meq_p_kg_p_day() { return 3 };
function c_younger_default_acetate__meq_p_kg_p_day() { return 4 };
function c_older_default_cations__meq_p_kg_p_day() { return 2 };
function c_older_default_acetate__meq_p_kg_p_day() { return 3 };
function c_acetate_meq_p_l__given_per__aminoacid_percent() { return 9 }; // no trav/troph diff
function c_chloride_meq_p_l__given_per__trophamine_percent() { return .5 };
function c_chloride_meq_p_l__given_per__travasol_percent() { return 4 };
function c_sodium_meq__given_per__mmol_phos() { return 1.3 };
function c_salt_precision() { return 2 };
function c_max_sodium_meq_p_l() { return 150 };
function c_max_potassium_meq_p_kg_p_h() { return .3 };
function c_max_potassium_meq_p_l_centrl() { return 200 }; //jr
function c_max_potassium_meq_p_l_periph() { return 80 };
function c_max_phosphate_mmol_p_l() { return 30 }; //*KL used to be 20
function c_max_calcium_meq_p_l() { return 50 }; //*KL used to be 40
function c_max_magnesium_meq_p_l() { return 20 };
//function c_initial_famotidine_mg_p_kg_p_day()                           { return   2    };  //*KL commented out (removing famotidine)
//function c_max_famotidine_mg_p_kg_p_day()                               { return  40    };  //*KL commented out (removing famotidine)
function c_coeficient_for_nonprot_cal_p_grams_nitro_ratio() { return 6.25 };
function c_warn_if_changed_sodium_exceeds_this_meq_p_kg_d() { return 5 };
function c_warn_if_changed_potassium_exceeds_this_meq_p_kg_d() { return 3 };
function c_warn_if_changed_potassium_exceeds_this_meq_p_l() { return 80 };
function debug() { return document.tpncalc.debug.value }; // for debuging, of course!
/*
See also the following functions which contain many constants
(or where I didn't know how to name the constants, so left them as numbers)
calc_group_2_init()       -> fluid and ree from age, height, weight, sex
calc_group_1_run()        -> determine surface area of patient (Mosteller's Formula)
calc_group_3_init()       -> amino needs determination (has a couple of coeficients)
calc_group_5_init()       -> default calcium, magnesium (has a couple of coeficients)
check_for_caphos_precip() -> check/correct for calcium/phosphate precipitate problem
*/





// No more constants, moving on to calc group one...
// .... some calc group one local field handlers:


function set_age_number() {
    var f = document.tpncalc; // shortcut to tpncalc form, used VERY frequently
    // standardizes the age value from raw value to years
    // called when user changes raw age or age units
    if (not_pos_num(f.raw_age.value)) {
        // bad raw age, clear both raw age and canonical age in years
        f.raw_age.value = "";
        f.age_yrs.value = "";
    } else { // we have a decent raw age value
        if (f.selected_age_type.value == "months") {
            if (f.raw_age.value * 1 < (12 * c_min_allowable_age_yr())) {
                f.raw_age.value = round_n_to_x_decimals(
                    12 * c_min_allowable_age_yr(), 3
                );
            } else { // round to nearest .5 months
                f.raw_age.value = Math.round(f.raw_age.value * 2) / 2;
            }
            f.age_yrs.value = f.raw_age.value / 12;
        } else { // f.selected_age_type.value == "years"
            if (f.raw_age.value * 1 < c_min_allowable_age_yr() * 1) {
                f.raw_age.value = c_min_allowable_age_yr();
            }
            f.age_yrs.value = f.raw_age.value;
        }
    }
	
    calc_group_1_run(); // cascade through the rest of the calculator
}
/*

javascript makes it annoying to get at the currently
selected values of radio groups and select lists.
Accordingly, rather than jump through hoops to get
the values whenever we want them, we use hidden
fields to keep track of the selected value. Whenever
a value is changed, we update that hidden value.
    
Age type is set by radio buttons, as is sex...

*/
function set_age_type(type) {
    // stashes a value in a hidden so we can get
    // to it easier than we could from a radio group
    document.tpncalc.selected_age_type.value = type;
    set_age_number(); // address more global concerns
    // set_age_number() then calls calc_group_1_run()
}
function set_sex(sex) {
    // stashes a value in a hidden so we can get
    // to it easier than we could from a radio group
    document.tpncalc.selected_sex.value = sex;
    calc_group_1_run();
}
function set_weight() {
    var f = document.tpncalc;
    if (not_pos_num(f.weight_kg.value)) {
        f.weight_kg.value = ""; // clear bad input
    }
    else { // we have a good weight value
        if (f.weight_kg.value < c_min_allowable_weight_kg()) {
            f.weight_kg.value = c_min_allowable_weight_kg()
        }
        else if (f.weight_kg.value * 1 <= 1.25) {
            f.weight_kg.value = round_n_to_x_decimals(f.weight_kg.value, 2);
        }
        else if (f.weight_kg.value * 1 < 10) {
            f.weight_kg.value = round_n_to_x_decimals(f.weight_kg.value, 1);
        }
        // *KL this else statement should round weights greater than or 10kg, to the closest whole number.
        else {
            f.weight_kg.value = round_n_to_x_decimals(f.weight_kg.value, 0);
        }
    }
          
    calc_group_1_run();
}
function set_height() {
    var f = document.tpncalc;
    if (not_pos_num(f.height_cm.value)) {
        f.height_cm.value = "";
    } else { // we have a good height value
        f.height_cm.value = Math.round(f.height_cm.value);
        if (f.height_cm.value * 1 < c_min_allowable_height_cm() * 1) {
            f.height_cm.value = c_min_allowable_height_cm();
        }
    }
    calc_group_1_run();
}
function calc_group_1_run(verbose) {
    var f = document.tpncalc;
    run_sanity_check(); // ensure that defaults will never be dangerous
    // try to figure out surface area and bmi
    var bad_data = not_pos_num(f.age_yrs.value); // bad age is bad input
    if (not_pos_num(f.height_cm.value) || not_pos_num(f.weight_kg.value)) {
        bad_data = true; // bad height or weight is bad input
        // and there's no way for us to have a valid bmi or surface area:
        f.bmi.value = "";
        f.surface_area__m2.value = "";
    } else { // we should be able to calculate bmi and surface area
        f.bmi.value = round_n_to_x_decimals(
             f.weight_kg.value / ((f.height_cm.value / 100) * (f.height_cm.value / 100)), 1
        );
        f.surface_area__m2.value = round_n_to_x_decimals( // Mosteller's Formula.
        // Yes, that is supposed to be weight * height, not height squared.
             Math.sqrt((f.weight_kg.value * f.height_cm.value) / 3600), 4
        );
        f.surface_area_for_display__m2.value = round_n_to_x_decimals(
        // per Dr. R., user sees only two decimal places, but we use 4 in our math
            f.surface_area__m2.value, 2
        );
    }
    if (bad_data) { // user needs to give us some data still...
        if (verbose) {
            // user used the button. Silently clearing out
            // bad fields below is not enough. Let them
            // know what's up.
            alert(
                "Please ensure that age, sex, weight, and"
                + " length/height have all been entered into"
                + " the fields provided in the first section."
            );
        }
        calc_group_2_clear();
        return;
    } // else, we have all the info in the first group...
    // check for high BMI so we can alert user
    if ( // if we have a bmi and it's over 95th percentile
        is_good_positive_number(f.bmi.value)
        && ( // we haven't already alerted for this combination of values
            document.tpncalc.last_bmi_alert_given.value != ( // we want string operators
                f.bmi.value + document.tpncalc.selected_sex.value + f.age_yrs.value
            )
        ) && ( // percentile is different depending on age
            ( // for the young...
                f.age_yrs.value * 1 <= c_max_years_for_which_bmi_percentile_is_sex_agnostic() * 1
                &&
                f.bmi.value * 1 > c_bmi_limit_for_youngest_agegroup() * 1
            ) || ( // for the older, percentile also depends on sex
                f.age_yrs.value * 1 > c_max_years_for_which_bmi_percentile_is_sex_agnostic() * 1
                && (
                    (document.tpncalc.selected_sex.value == "male"
                        &&
                        f.bmi.value * 1 > f.age_yrs.value * 1 + c_bmi_shift_for_older_males() * 1
                    )
                    ||
                    (document.tpncalc.selected_sex.value == "female"
                        &&
                        f.bmi.value * 1 > f.age_yrs.value * 1 + c_bmi_shift_for_older_females() * 1
                    )
                )
            )
        )
    ) { // if ...(bmi over 95th %tile)... then:
        alert(
            "BMI is over 95th percentile for age. Check weight, "
            + "length, and age for accuracy. If values are correct, "
            + "consult the BMI link for further guidance."
        );
        // and now ensure that we don't alert again as they click
        // between fields without changing anything:
        document.tpncalc.last_bmi_alert_given.value // we want string concatenation
            = f.bmi.value + document.tpncalc.selected_sex.value + f.age_yrs.value
    }
    // now set initial values for the next group:
    calc_group_2_init();
}
function run_sanity_check() {
    var f = document.tpncalc;
    /*
    this script does a whole bunch of limit-checking of user
    values to ensure that they don't cross certain thresholds.
    However, we don't always check on our default values because
    we assume that the default values will be within limits. For
    the conceivable defaults at the creation of this tool, that
    is the case. However, one day a constant could be changed, or
    an item added to an HTML pulldown menu which invalidates that
    assumption and makes it possible for a default value to be
    over some limit. To prevent these accidents from happening,
    this routine will examine the worst-case scenario for each of
    our limits. If a constant is changed, or a menu item added,
    and that modification makes it possible for a default value
    to go out of bounds, then this routine should catch it as
    soon as the user enters their first value into the calculator.
        
    Note that this sanity check is only run once per session.
        
    Also note that this routine should be updated any time a
    limit is added to the calculator, and that limit is not
    ever checked against the default values for the limited field.
    */
    if (f.did_sanity_check.value * 1 == 1) {
        return; // we already did this once
    } // else we haven't done it yet, so get busy:
    // first, check potassium mEq/kg/hour limits...
    var duration = 24; // infusion hours per day, best case
    // now look for smaller durations (worse cases) in menu
    for (var i = 0; i * 1 < f.infusion_duration_h.options.length * 1; i++) {
        if (f.infusion_duration_h.options[i].value * 1 < duration * 1) {
            duration = f.infusion_duration_h.options[i].value;
        }
    }
    // now get the largest default amount of potassium given:
    var amount = c_younger_default_cations__meq_p_kg_p_day();
    if (c_older_default_cations__meq_p_kg_p_day() * 1 > amount * 1) {
        // shouldn't happen, but you never know.
        amount = c_older_default_cations__meq_p_kg_p_day();
    }
    if ((amount / duration) * 1 > c_max_potassium_meq_p_kg_p_h() * 1) {
        // possible problems under fluid-restricted situations:
        alert(
            "WARNING!! Under extreme conditions, the default"
            + " potassium infusion rate may exceed "
            + c_max_potassium_meq_p_kg_p_h() + "mEq/kg/hour."
            + " Please notify the webmaster of this problem."
        );
    }
    // moving on to sodium...
    amount = c_initial_phos_mmol_p_l() * c_sodium_meq__given_per__mmol_phos();
    if (amount * 1 > c_max_sodium_meq_p_l() * 1) {
        alert(
            "WARNING!! The default sodium infusion rate"
            + " (based only on sodium phosphate) will exceed "
            + c_max_sodium_meq_p_l() + "mEq/l."
            + " Please notify the webmaster of this problem."
        );
    }
    /*
    NOTE: the above is only checking the sodium with phosphate and the
    sodium from amino acids. It does not check the sodium from salts.
    The difficulty with checking sodium from salts is that the limits
    are in terms of concentration, and we have to know how much fluid
    is involved. To get a worst-case, we need to take the minimum fluid
    level and assume that the salts will be *very* concentrated. However,
    we don't know *how* minimal to go. One ml of fluid per day? Less?
    Until and unless we have a lower limit on fluids (which is not likely
    given that there are many fluid-restricted TPN cases), we cannot include
    a check for that part of the TPN. Instead, we have cautions which pop up
    when users use high lipid amounts or low fluid amounts. These cautions
    ask the user to check all concentrations, as they will likely be out of
    normal bounds. Note that if they *edit* those out-of-whack values, then
    our limit-checking code kicks in and pulls the values down to normal.
    20020107 Dr. R. and I discussed this and decided that this is appropriate
    behavior. For future reference, the following input will reveal this odd
    situation: 1mo;3kg;50cm with 4g/kg/day IL and 35 ml/kg/day fluids. Scroll
    down to see how high the sodium mEq/L is. Note that if you modify the
    value by just a pinch, it snaps down to a reasonable value. (Also note
    that in the process of creating this situation, before you edited Sodium,
    you were cautioned to double-check your concentrations). Also, in the end
    a doctor will have to review and sign the order and the pharmacy will be
    double-checking it too.
    */
    // checking phosphate...
    if (c_initial_phos_mmol_p_l() * 1 > c_max_phosphate_mmol_p_l() * 1) {
        alert(
            "WARNING!! The default phosphate level will exeed"
            + c_max_phosphate_mmol_p_l() + "mMol/l."
            + " Please notify the webmaster of this problem."
        );
    }


    /* KL commented out this block.  removing famotidine
    // checking famotidine...
    if ( c_initial_famotidine_mg_p_kg_p_day()*1 > c_max_famotidine_mg_p_kg_p_day()*1 ) {
    alert(
    "WARNING!! The default famotidine level will exeed"
    + c_max_famotidine_mg_p_kg_p_day() + "mg/kg/day."
    + " Please notify the webmaster of this problem."
    );
    }
    end of famotidine block */



    /*
    calc_group_3_init() ensures that the following get checked
    against both user input and initial values:
    c_max_dex_percent_periph()
    c_max_dex_percent_centrl()
    c_max_dex_mg_p_kg_p_min()
    c_max_aminoacid_percent()
    c_max_aminoacid_mg_p_kg_p_day()
    it does this by calling calc_group_3_check()
        
    calc_group_5_init() ensures that the following are checked
    against default values:
    c_max_calcium_meq_p_l()
    c_max_magnesium_meq_p_l()
    check_for_caphos_precip()
    */
    f.did_sanity_check.value = 1; // so we don't do it again
}

function calc_group_2_init() {
    var f = document.tpncalc;
    calc_group_2_clear("skip_calcgroup_cascade");
    // begin calculating our fluid needs and resting energy expenditure
    // start with fluids... they go by weight
    if (f.weight_kg.value <= .75) {
        f.fluid__ml_p_d.value = 80 * f.weight_kg.value;
        f.ree__kcal_p_d.value = 30 * f.weight_kg.value;
    }
    if (f.weight_kg.value >= .75 && f.weight_kg.value * 1 < 1.25) {
        f.fluid__ml_p_d.value = 80 * f.weight_kg.value;
        f.ree__kcal_p_d.value = 40 * f.weight_kg.value;
    }
    if (f.weight_kg.value >= 1.25 && f.weight_kg.value * 1 < 2) {
        f.fluid__ml_p_d.value = 100 * f.weight_kg.value;
        f.ree__kcal_p_d.value = 50 * f.weight_kg.value;
    }
    if (f.weight_kg.value >= 2 && f.weight_kg.value * 1 <= 3) {
        f.fluid__ml_p_d.value = 100 * f.weight_kg.value;
        f.ree__kcal_p_d.value = 50 * f.weight_kg.value;
    }
    if (f.weight_kg.value > 3 && f.weight_kg.value * 1 <= 10) {
        f.fluid__ml_p_d.value = 100 * f.weight_kg.value;
         f.ree__kcal_p_d.value = 60 * f.weight_kg.value;
    }
    if (f.weight_kg.value * 1 > 10) {
        // if not light, use this instead:
        f.fluid__ml_p_d.value = 2000 * f.surface_area__m2.value;
     // else we're still at our original default for very light patients
    f.fluid__ml_p_d.value = Math.round(f.fluid__ml_p_d.value);
    // also, save a backup so we can warn if they change it too low of a value:
    f.recmd_fluid__ml_p_d.value = f.fluid__ml_p_d.value;
    // now do the ree... by age/sex/height/weight
    // start with the assumption that ( f.age_yrs.value <= c_first_growth_related_age_max_for_ree_in_years() )
    f.ree__kcal_p_d.value = 60 * f.weight_kg.value;
    // now replace f.ree__kcal_p_d.value, depending on age:
    }
    if (f.age_yrs.value * 1 > c_first_growth_related_age_max_for_ree_in_years() * 1) {
        // ree varies by age and sex:
        if (f.age_yrs.value * 1 > c_second_growth_related_age_max_for_ree_in_years() * 1) {
            if (document.tpncalc.selected_sex.value == "female") {
                f.ree__kcal_p_d.value = (
                    655
                    + (1.85 * f.height_cm.value)
                    + (9.6 * f.weight_kg.value)
                    - (4.7 * f.age_yrs.value)
                );
            } else { // document.tpncalc.selected_sex.value == "male"
                f.ree__kcal_p_d.value = (
                    66.5
                    + (5.00 * f.height_cm.value)
                    + (13.8 * f.weight_kg.value)
                    - (6.8 * f.age_yrs.value)
                );
            }
        } else { // f.age_yrs.value between first and second max
            if (document.tpncalc.selected_sex.value == "female") {
                f.ree__kcal_p_d.value = 499 + (22.5 * f.weight_kg.value);
            } else { // document.tpncalc.selected_sex.value == "male"
                f.ree__kcal_p_d.value = 495 + (22.7 * f.weight_kg.value);
            }
        }
    }
    // an extra argument to match_fluid_from() prevents calc_group_2_run() from
    // being called after the fluids are set. We do this to avoid some extra work
    // since match_ree_from() is going to call calc_group_2_run() as well.
    match_fluid_from("ml_p_d", "skip_calcgroup_cascade");
    match_ree_from("kcal_p_d"); // this one ensures the cascade
}

/*  *KL  New function calc_group_2_init() in place to set new defaults for little babies

function calc_group_2_init() {  var f = document.tpncalc;
calc_group_2_clear( "skip_calcgroup_cascade" );
// begin calculating our fluid needs and resting energy expenditure
// start with fluids... they go by weight
f.fluid__ml_p_d.value = 125 * f.weight_kg.value; // assume they're very light
if ( f.weight_kg.value*1 > 1 && f.weight_kg.value*1 <= 10) {
// if not quite that light, use this instead:
f.fluid__ml_p_d.value = 100 * f.weight_kg.value;
} else if ( f.weight_kg.value*1 > 10 ) {
// if not light, use this instead:
f.fluid__ml_p_d.value = 2000 * f.surface_area__m2.value;
} // else we're still at our original default for very light patients
f.fluid__ml_p_d.value = Math.round(f.fluid__ml_p_d.value);
// also, save a backup so we can warn if they change it too low of a value:
f.recmd_fluid__ml_p_d.value = f.fluid__ml_p_d.value;
// now do the ree... by age/sex/height/weight
// start with the assumption that ( f.age_yrs.value <= c_first_growth_related_age_max_for_ree_in_years() )
f.ree__kcal_p_d.value = 60 * f.weight_kg.value;
// now replace f.ree__kcal_p_d.value, depending on age:
if ( f.age_yrs.value*1 > c_first_growth_related_age_max_for_ree_in_years()*1 ) {
// ree varies by age and sex:
if ( f.age_yrs.value*1 > c_second_growth_related_age_max_for_ree_in_years()*1 ) {
if ( document.tpncalc.selected_sex.value == "female" ) {
f.ree__kcal_p_d.value = (
655
+ (  1.85 * f.height_cm.value )
+ (  9.6  * f.weight_kg.value )
- (  4.7  * f.age_yrs.value   )
);
} else { // document.tpncalc.selected_sex.value == "male"
f.ree__kcal_p_d.value = (
66.5
+ (  5.00 * f.height_cm.value )
+ ( 13.8  * f.weight_kg.value )
- (  6.8  * f.age_yrs.value   )
);
}
} else { // f.age_yrs.value between first and second max
if ( document.tpncalc.selected_sex.value == "female" ) {
f.ree__kcal_p_d.value = 499 + (22.5 * f.weight_kg.value);
} else { // document.tpncalc.selected_sex.value == "male"
f.ree__kcal_p_d.value = 495 + (22.7 * f.weight_kg.value);
}
}
}
// an extra argument to match_fluid_from() prevents calc_group_2_run() from
// being called after the fluids are set. We do this to avoid some extra work
// since match_ree_from() is going to call calc_group_2_run() as well.
match_fluid_from( "ml_p_d", "skip_calcgroup_cascade");
match_ree_from( "kcal_p_d" ); // this one ensures the cascade
}

end of function that was replaced
*/

function match_fluid_from(units, skip_calcgroup_cascade) {
    var f = document.tpncalc;
    // given the name of one fluid input field, set the other two
    // round them all at the end to reduce snowballing of round errors
    if (not_pos_num(f.age_yrs.value)
            ||
            not_pos_num(f.surface_area__m2.value)
    ) {
        // if top section isn't complete, user shouldn't mess with fluids yet
        calc_group_2_clear();
        return;
    }
    if (units == "ml_p_d") {
        if (not_pos_num(f.fluid__ml_p_d.value)) {
            clear_out_fluids();
            return;
        }
        derive_fluid__ml_p_kg_p_d__from__ml_p_d();
        derive_fluid__l_p_m2_p_d__from__ml_p_kg_p_d();
    } else if (units == "ml_p_kg_p_d") {
        if (not_pos_num(f.fluid__ml_p_kg_p_d.value)) {
            clear_out_fluids();
            return;
        }
        // first we derive_fluid__ml_p_d__from__ml_p_kg_p_d
        f.fluid__ml_p_d.value
            = f.fluid__ml_p_kg_p_d.value * f.weight_kg.value;
        // and then we
        derive_fluid__l_p_m2_p_d__from__ml_p_kg_p_d();
    } else { // units == "l_p_m2_p_d"
        if (not_pos_num(f.fluid__l_p_m2_p_d.value)) {
            clear_out_fluids();
            return;
        }
        // first we derive_fluid__ml_p_d__from__l_p_m2_p_d
        f.fluid__ml_p_d.value
            = 1000 * f.fluid__l_p_m2_p_d.value * f.surface_area__m2.value;
        // and then we
        derive_fluid__ml_p_kg_p_d__from__ml_p_d();
    }
    // now that we've set all of them, round them off.
    // that way we only round them one time and we cut down
    // on the snowballing of rounding errors
    f.fluid__ml_p_d.value = Math.round(f.fluid__ml_p_d.value);
    f.fluid__ml_p_kg_p_d.value = round_n_to_x_decimals(f.fluid__ml_p_kg_p_d.value, 1);
    f.fluid__l_p_m2_p_d.value = round_n_to_x_decimals(f.fluid__l_p_m2_p_d.value, 2);
    if (f.fluid__ml_p_d.value * 1 <= 1 * (
            f.recmd_fluid__ml_p_d.value
            * c_warn_unless_fluids_exceed_this_percent_of_recomended_value() / 100
        )
    ) {
        alert(
            "Warning:  Fluid volume low.  Review all concentrations. "
            + "Calculated values may exceed usual maximums."
        );
    }
    if (!skip_calcgroup_cascade) calc_group_2_run();
}
function derive_fluid__ml_p_kg_p_d__from__ml_p_d() {
    var f = document.tpncalc;
    // called at a point when ml_p_d is updated and ml_p_kg_p_d needs
    // to be updated to match ml_p_d
    f.fluid__ml_p_kg_p_d.value = f.fluid__ml_p_d.value / f.weight_kg.value;
}
function derive_fluid__l_p_m2_p_d__from__ml_p_kg_p_d() {
    var f = document.tpncalc;
    // called at a point when ml_p_kg_p_d is updated and l_p_m2_p_d needs
    // to be updated to match ml_p_kg_p_d
    f.fluid__l_p_m2_p_d.value = (
        ((f.fluid__ml_p_kg_p_d.value * f.weight_kg.value) / 1000)
        /
        f.surface_area__m2.value
    );
}
function match_ree_from(units) {
    var f = document.tpncalc;
    // given the name of one ree input field, set the other one
    // and derive our other ee fields from that
    if (
            not_pos_num(f.age_yrs.value)
            ||
            not_pos_num(f.bmi.value)
    ) {
        calc_group_2_clear();
        return;
    }
    if (units == "kcal_p_d") {
        if (not_pos_num(f.ree__kcal_p_d.value)) {
            clear_out_energy_expenditures();
            return;
        }
        f.ree__kcal_p_kg_p_d.value = f.ree__kcal_p_d.value / f.weight_kg.value;
    } else { // units == "kcal_p_kg_p_d"
        if (not_pos_num(f.ree__kcal_p_kg_p_d.value)) {
            clear_out_energy_expenditures();
            return;
        }
        f.ree__kcal_p_d.value = f.ree__kcal_p_kg_p_d.value * f.weight_kg.value;
    }
    derive_energy_expenditures_from("ree");
}
function match_esttee_from(units) {
    var f = document.tpncalc;
    // given the name of one esttee input field, set the other one
    // and derive our other ee fields from that
    if (not_pos_num(f.age_yrs.value)
            ||
            not_pos_num(f.bmi.value)
    ) {
        calc_group_2_clear();
        return;
    }
    if (units == "kcal_p_d") {
        if (not_pos_num(f.esttee__kcal_p_d.value)) {
            clear_out_energy_expenditures();
            return;
        }
        f.esttee__kcal_p_kg_p_d.value = f.esttee__kcal_p_d.value / f.weight_kg.value;
    } else { // units == "kcal_p_kg_p_d"
        if (not_pos_num(f.esttee__kcal_p_kg_p_d.value)) {
            clear_out_energy_expenditures();
            return;
        }
        f.esttee__kcal_p_d.value = f.esttee__kcal_p_kg_p_d.value * f.weight_kg.value;
    }
    derive_energy_expenditures_from("esttee");
}
function derive_energy_expenditures_from(source) {
    var f = document.tpncalc;
    // given the prefix for a pair of updated ee fields,
    // update the other two pairs of ee fields to match.
    // then round all three pairs off at the very end
    if (source == "ree") {           // resting ee has been updated
        // update esttee to match
        f.esttee__kcal_p_d.value = f.ree__kcal_p_d.value * f.stress_ree_multiplier.value;
        if (f.age_yrs.value * 1 <= c_growth_related_age_max_for_esttee_multiplier_in_years() * 1) {
            f.esttee__kcal_p_d.value
                = f.esttee__kcal_p_d.value * c_esttee_multiplier_if_not_over_max();
        }
        f.esttee__kcal_p_kg_p_d.value = f.esttee__kcal_p_d.value / f.weight_kg.value;
    } else { // source == "esttee"    // estimated total ee has been updated
        // update ree to match
        f.ree__kcal_p_d.value = f.esttee__kcal_p_d.value / f.stress_ree_multiplier.value;
        if (f.age_yrs.value * 1 <= c_growth_related_age_max_for_esttee_multiplier_in_years() * 1) {
            f.ree__kcal_p_d.value
                = f.ree__kcal_p_d.value / c_esttee_multiplier_if_not_over_max();
        }
        f.ree__kcal_p_kg_p_d.value = f.ree__kcal_p_d.value / f.weight_kg.value;
    }
    // now that we've set all of them, round them off.
    // that way we only round them one time and we cut down
    // on the snowballing of rounding errors
    f.ree__kcal_p_d.value = Math.round(f.ree__kcal_p_d.value);
    f.ree__kcal_p_kg_p_d.value = Math.round(f.ree__kcal_p_kg_p_d.value);
    f.esttee__kcal_p_d.value = Math.round(f.esttee__kcal_p_d.value);
    f.esttee__kcal_p_kg_p_d.value = Math.round(f.esttee__kcal_p_kg_p_d.value);
    calc_group_2_run();
}
function set_stress_ree_multiplier() {
    var f = document.tpncalc;
    // stashes a value in a hidden so we can get
    // to it easier than we could from a select list
    f.stress_ree_multiplier.value
        = f.stress_factor.options[f.stress_factor.selectedIndex].value;
    derive_energy_expenditures_from("ree");
}
function set_infusion_duration() {
    var f = document.tpncalc;
    // stashes a value in a hidden so we can get
    // to it easier than we could from a select list
    f.infusion_duration_value_h.value
        = f.infusion_duration_h.options[f.infusion_duration_h.selectedIndex].value;
    calc_group_2_run();
}
function set_line_type() {
    var f = document.tpncalc;
    // stashes a value in a hidden so we can get
    // to it easier than we could from a select list
    f.selected_line_type.value = f.line_type.options[f.line_type.selectedIndex].value;
    calc_group_2_run();
}
function set_fat_emulsion() {
    var f = document.tpncalc;
    f.fat_emulsion_value__g_p_kg_p_d.value
        = f.fat_emulsion_menu__g_p_kg_p_d.options[f.fat_emulsion_menu__g_p_kg_p_d.selectedIndex].value;
    // set a flag to check energy source later in calcgroup4run:
    f.flag_check_energy_source_ratio.value = 1;
    calc_group_2_run();
}
function calc_group_2_run(verbose) {
    var f = document.tpncalc;
    var bad_data = false; // no bad data yet
    if (not_pos_num(f.ree__kcal_p_d.value)) {
        clear_out_energy_expenditures();
        bad_data = true;
    }
    if (not_pos_num(f.fluid__ml_p_d.value)) {
        clear_out_fluids("skip_calcgroup_cascade");
        bad_data = true;
    }
    if (bad_data) {
        if (verbose) {
            alert(
                "Please ensure that fluid and energy values"
                + " have all been entered into the fields"
                + " provided in the second section. Either"
                + " recalculate these values with the button"
                + " labeled 'Reset #1', or enter them manually."
            );
        }
        calc_group_3_clear();
        return;
    } // else, good data: calculate some stuff
    f.fat_emulsion__kcal_p_day.value = (
        f.fat_emulsion_value__g_p_kg_p_d.value
        * c_fatemul_kcal_p_g()
        * f.weight_kg.value
    );
    calc_group_3_init();
}
function calc_group_2_clear(skip_calcgroup_cascade) {
    var f = document.tpncalc;
    // reset the menus/checkboxes/radiogroups in this area
    f.stress_factor.selectedIndex = 1;
    f.stress_ree_multiplier.value = f.stress_factor.options[1].value;
    f.infusion_duration_h.selectedIndex = 2;
    f.infusion_duration_value_h.value = f.infusion_duration_h.options[2].value;
    f.line_type.selectedIndex = 1;
    f.selected_line_type.value = f.line_type.options[1].value;
    

    f.fat_emulsion_menu__g_p_kg_p_d.selectedIndex = 2;
    f.fat_emulsion_value__g_p_kg_p_d.value =
    f.fat_emulsion_menu__g_p_kg_p_d.options[2].value;

    set_default_fat_emulsion_value();

    clear_out_energy_expenditures("skip_calcgroup_cascade");
    clear_out_fluids("skip_calcgroup_cascade");
    if (!skip_calcgroup_cascade) calc_group_3_init();
}

//Set emulsion menu 
function set_default_fat_emulsion_value() {
    var f = document.tpncalc;
    var dd = document.getElementById('fat_emulsion_menu__g_p_kg_p_d');

    if (f.weight_kg.value < .75) {

        dd.selectedIndex = 1;
        dd.value = 0.5;

    } else {

        dd.selectedIndex = 2;
        dd.value = 1;
    }

    set_fat_emulsion();
}

function clear_out_energy_expenditures(skip_calcgroup_cascade) {
    var f = document.tpncalc;
    f.ree__kcal_p_d.value = "";
    f.ree__kcal_p_kg_p_d.value = "";
    f.esttee__kcal_p_d.value = "";
    f.esttee__kcal_p_kg_p_d.value = "";
    // and clear out anything derived from previous good values:
    if (!skip_calcgroup_cascade) calc_group_3_init();
}
function clear_out_fluids(skip_calcgroup_cascade) {
    var f = document.tpncalc;
    f.fluid__ml_p_d.value = "";
    f.recmd_fluid__ml_p_d.value = "";
    f.fluid__ml_p_kg_p_d.value = "";
    f.fluid__l_p_m2_p_d.value = "";
    // and clear out anything derived from previous good values:
    if (!skip_calcgroup_cascade) calc_group_3_init();
}
function calc_group_3_init() {
    var f = document.tpncalc;
    if (not_pos_num(f.fluid__ml_p_d.value)) {
        // bad data... can't do our calculation...
        // reset anything which might have been set by
        // previously good data
        calc_group_3_clear();
        return;
    } // else, good data...
    /*
    first, derive our non-fat fluids
    This non-flat fluids notion is fairly important. You'll see this
    value referenced in a large number of subsequent calculations. When
    giving TPN, we're basically giving two things. One thing is a bunch
    of fat (the intralipid stuff), and the other thing is "all the rest"
    of the TPN. The intralipd includes some fluid, and that fluid does
    count toward meeting the patient's fluid requirements. So, our base
    for the rest of the TPN starts off with whatever fluid we need to
    meet the patient's fluid needs (after subtracting the needs met by
    the intralipid). This non-fat fluid is what we'll be using as the
    base for mixing in amino acids, dextrose, electrolytes and minerals.
    */
    f.nonfat_fluid__ml_p_d.value = round_n_to_x_decimals(
        (f.fluid__ml_p_d.value - (
                c_fatemul_fluid_content_ml_p_g()
                * f.fat_emulsion_value__g_p_kg_p_d.value
                * f.weight_kg.value
            )
        ), 1
    );
    // determine the initial *desired* amino acid values...
    // younger folks are growing faster and need more amino acids

    if (f.weight_kg.value < .75)
    { f.aminoacids__g_p_kg_p_day.value = 3.5; }

    if (f.weight_kg.value >= .75 && f.weight_kg.value * 1 < 1.25)
    { f.aminoacids__g_p_kg_p_day.value = 3.5; }

    if (f.weight_kg.value >= 1.25 && f.weight_kg.value * 1 < 2)
    { f.aminoacids__g_p_kg_p_day.value = 3.0; }

    if (f.weight_kg.value >= 2 && f.weight_kg.value * 1 <= 3)
    { f.aminoacids__g_p_kg_p_day.value = 3.0; }

    if (f.weight_kg.value >= 3 && f.weight_kg.value * 1 <= 10)
    { f.aminoacids__g_p_kg_p_day.value = 2.5; }

    if (f.weight_kg.value > 10)
    { f.aminoacids__g_p_kg_p_day.value = 2.5; }
    /*  Trying to fix the Protien Defaults  KL - 5/26
    
    if ((f.age_yrs.value * 1 > c_growth_related_age_max_for_esttee_multiplier_in_years() * 1)
        &&
        (f.age_yrs.value * 1 <= c_first_growth_related_age_max_for_ree_in_years() * 1)
    ) {
        f.aminoacids__g_p_kg_p_day.value = 1.8;
    } else if (
        (f.age_yrs.value * 1 > c_first_growth_related_age_max_for_ree_in_years() * 1)
        &&
        (f.age_yrs.value * 1 <= c_second_growth_related_age_max_for_ree_in_years() * 1)
    ) {
        f.aminoacids__g_p_kg_p_day.value = 1.5;
    } else if (f.age_yrs.value * 1 > c_second_growth_related_age_max_for_ree_in_years() * 1) {
        f.aminoacids__g_p_kg_p_day.value = 1.2; 
    
    }    
    */
        
     // else we stick with our original default for youngest youngster
    // now determine the appropriate percent value (in allowable increments)
    // The increment will shift us slightly from our desired levels
    f.aminoacids_percent.value = round_aminoacids_percent(
        100 * f.aminoacids__g_p_kg_p_day.value
            * f.weight_kg.value
            / f.nonfat_fluid__ml_p_d.value
    );
    // now force the g/kg/day value to match those allowable increments too,
    // so that we're reporting the actual delivered aminos (not desired aminos)
    f.aminoacids__g_p_kg_p_day.value = round_n_to_x_decimals(
        (f.nonfat_fluid__ml_p_d.value * f.aminoacids_percent.value / 100
            / f.weight_kg.value
        ), 1
    );
    // save this value to compare to user changes (in the progress note):
    f.recmnded_aminoacids__g_p_kg_p_d.value = f.aminoacids__g_p_kg_p_day.value;
    // and now start our dextrose calculations...
    f.dextrose_percent.value = round_dextrose_percent(
        (((f.esttee__kcal_p_d.value - f.fat_emulsion__kcal_p_day.value)
                / c_dextrose_kcal_p_ml()
            ) / f.nonfat_fluid__ml_p_d.value
        ) * 100
    );
    derive_dextrose_mg_p_kg_p_min__from__dextrose_percent();
    check_dextrose("silent", "skip_calcgroup_cascade");
    check_aminoacids("silent", "skip_calcgroup_cascade");
    calc_group_3_run(); // now run it after both of the above are done
}
function round_dextrose_percent(percent) {
    // pharmacy and tpn docs indicate that dextrose only avail in certain % increments
    return (
        Math.round(percent / c_dextrose_percent_allowed_increments())
        * c_dextrose_percent_allowed_increments()
    );
}
function round_aminoacids_percent(percent) {
    // pharmacy and tpn docs indicate that amino acids only avail in certain % increments
    return (
        Math.round(percent / c_aminoacids_percent_allowed_increments())
        * c_aminoacids_percent_allowed_increments()
    );
}
function match_dextrose_from(units, silent) {
    var f = document.tpncalc;
    // given the name of one dextrose input field, set the other one
    // and derive our other dependant fields from that
    if (not_pos_num(f.nonfat_fluid__ml_p_d.value)) {
        calc_group_3_clear();
        return;
    }
    if (units == "percent") {
        if (not_pos_num(f.dextrose_percent.value)) {
            calc_group_3_clear();
            return;
        }
        f.dextrose_percent.value = round_dextrose_percent(f.dextrose_percent.value);
        derive_dextrose_mg_p_kg_p_min__from__dextrose_percent();
    } else { // units == "mg_p_kg_p_min"
        if (not_pos_num(f.dextrose__mg_p_kg_p_min.value)) {
            calc_group_3_clear();
            return;
        }
        derive_dextrose_percent__from__dextrose_mg_p_kg_p_min();
    }
    check_dextrose(silent, "skip_calcgroup_cascade");
    // set a flag to check energy source later in calc_group_4_run():
    f.flag_check_energy_source_ratio.value = 1;
    calc_group_3_run();
}
function derive_dextrose_mg_p_kg_p_min__from__dextrose_percent() {
    var f = document.tpncalc;
    f.dextrose__mg_p_kg_p_min.value = Math.round(
        (f.dextrose_percent.value / 100)
        * f.nonfat_fluid__ml_p_d.value
        * (1000 / f.weight_kg.value)
        / (f.infusion_duration_value_h.value * 60)
    );
}
function derive_dextrose_percent__from__dextrose_mg_p_kg_p_min() {
    var f = document.tpncalc;
    f.dextrose_percent.value = round_dextrose_percent(
        100
        * f.dextrose__mg_p_kg_p_min.value
        * (f.infusion_duration_value_h.value * 60)
        * (f.weight_kg.value / 1000)
        / f.nonfat_fluid__ml_p_d.value
    );
}
function check_dextrose(silent, skip_calcgroup_cascade) {
    var f = document.tpncalc;
    var alert_text = "";
    // *KL added for Dextrose Min Value of 5 just one line
    if (f.dextrose_percent.value * 1 < 5) { f.dextrose_percent.value = 5 }

    if (f.selected_line_type.value == "p") { // peripheral line
        if (f.dextrose_percent.value * 1 > c_max_dex_percent_periph() * 1) {
            alert_text = (
                "The maximum dextrose concentration through a peripheral line of "
                + c_max_dex_percent_periph()
                + "% has been exceeded - value set to maximal limit"
            );
            f.dextrose_percent.value = c_max_dex_percent_periph();
            derive_dextrose_mg_p_kg_p_min__from__dextrose_percent();
        }
    } else { // central line
        if (f.dextrose_percent.value * 1 > c_max_dex_percent_centrl() * 1) {
            alert_text = (
                "The maximum dextrose concentration through a central line of "
                + c_max_dex_percent_centrl()
                + "% has been exceeded - value set to maximal limit"
            );
            f.dextrose_percent.value = c_max_dex_percent_centrl();
            derive_dextrose_mg_p_kg_p_min__from__dextrose_percent();
        }
    }
    if (f.dextrose__mg_p_kg_p_min.value * 1 > c_max_dex_mg_p_kg_p_min() * 1) {
        alert_text = (
            "The maximum Glucose Infusion Rate limit of "
            + c_max_dex_mg_p_kg_p_min()
            + "mg/kg/min has been exceeded - GIR set to maximal limit"
        );
        f.dextrose__mg_p_kg_p_min.value = c_max_dex_mg_p_kg_p_min();
        derive_dextrose_percent__from__dextrose_mg_p_kg_p_min();
    }
    if (alert_text.length) { // we found and fixed some problem
        // we may need to notify the user:
        if (!silent) alert(alert_text);
        // we may need to re-initialize dependant values:
        if (!skip_calcgroup_cascade) calc_group_3_run();
    }
}
function match_aminoacids_from(units, silent, skip_calcgroup_cascade) {
    var f = document.tpncalc;
    // given the name of one aminoacid input field, set the other one
    // and derive our other dependant fields from that
    if (not_pos_num(f.nonfat_fluid__ml_p_d.value)) {
        calc_group_3_clear();
        return;
    }
    if (units == "percent") {
        if (not_pos_num(f.aminoacids_percent.value)) {
            calc_group_3_clear();
            return;
        }
        f.aminoacids_percent.value = round_aminoacids_percent(f.aminoacids_percent.value);
        f.aminoacids__g_p_kg_p_day.value = round_n_to_x_decimals(
            ((f.aminoacids_percent.value / 100)
                * f.nonfat_fluid__ml_p_d.value
                / f.weight_kg.value
            ), 1
        );
    } else { // units == "g_p_kg_p_day"
        if (not_pos_num(f.aminoacids__g_p_kg_p_day.value)) {
            calc_group_3_clear();
            return;
        }
        f.aminoacids__g_p_kg_p_day.value = round_n_to_x_decimals(f.aminoacids__g_p_kg_p_day.value, 1);
        f.aminoacids_percent.value = round_aminoacids_percent(
            (f.aminoacids__g_p_kg_p_day.value * 100) / f.nonfat_fluid__ml_p_d.value * f.weight_kg.value
        );
    }
    check_aminoacids(silent, skip_calcgroup_cascade);
    if (!skip_calcgroup_cascade) calc_group_3_run();
}
function check_aminoacids(silent, skip_calcgroup_cascade) {
    var f = document.tpncalc;
    var alert_text = "";
    if (f.aminoacids_percent.value * 1 > c_max_aminoacid_percent() * 1) {
        alert_text = (
            "Maximum amino acids limit of "
            + c_max_aminoacid_percent()
            + "% has been exceeded - value reduced to limit"
        );
        f.aminoacids_percent.value = c_max_aminoacid_percent();
        match_aminoacids_from("percent", silent, "yes__skip_calcgroup_cascade")
    }
    if (f.aminoacids__g_p_kg_p_day.value * 1 > c_max_aminoacid_mg_p_kg_p_day() * 1) {
        alert_text = (
            "Maximum amino acids limit of "
            + c_max_aminoacid_mg_p_kg_p_day()
            + " grams/kg/day has been exceeded - value reduced to limit."
        );
        f.aminoacids__g_p_kg_p_day.value = c_max_aminoacid_mg_p_kg_p_day();
        match_aminoacids_from("g_p_kg_p_day", silent, skip_calcgroup_cascade)
    }
    if (alert_text.length) { // we found and fixed some problem
        // we may need to notify the user:
        if (!silent) alert(alert_text);
        // we may need to re-initialize dependant values:
        if (!skip_calcgroup_cascade) calc_group_3_run();
    }
}
function calc_group_3_run(verbose) {
    var f = document.tpncalc;
    if (not_pos_num(f.aminoacids_percent.value)
            ||
            not_pos_num(f.dextrose_percent.value)
    ) {
        calc_group_3_clear();
        calc_group_4_run();
        if (verbose) {
            alert(
                "Please ensure that amino acid and dextrose values"
                + " have all been entered into the fields"
                + " provided in the third section. Either"
                + " recalculate these values with the button"
                + " labeled 'Reset #2', or enter them manually."
            );
        }
        return;
    } // else, good data: calculate some stuff
    calc_group_4_init();
}
function calc_group_3_clear() {
    var f = document.tpncalc;
    f.dextrose_percent.value = "";
    f.dextrose__mg_p_kg_p_min.value = "";
    f.aminoacids_percent.value = "";
    f.aminoacids__g_p_kg_p_day.value = "";
    calc_group_4_init();
}
function calc_group_4_init() {
    duplicate_values_into_summary_fields()
    calc_group_4_run();
}
function duplicate_values_into_summary_fields() {
    var f = document.tpncalc;
    if (not_pos_num(f.aminoacids_percent.value)
            ||
            not_pos_num(f.dextrose_percent.value)
    ) {
        return;
    }
    f.repeat_estimated_tee__kcal_p_day.value = f.esttee__kcal_p_d.value;
    f.fat__kcal_p_day.value = f.fat_emulsion__kcal_p_day.value;
    if (is_good_nonnegative_number(f.fat__kcal_p_day.value)) {
        f.fat__kcal_p_day.value = Math.round(f.fat__kcal_p_day.value);
    } else { // it's a bad number, so clear it:
        f.fat__kcal_p_day.value = "";
    }
    // a couple of these aren't duplications, but require minor calculation:
    f.dextrose__kcal_p_day.value = (
        (f.dextrose_percent.value / 100)
        * f.nonfat_fluid__ml_p_d.value
        * c_dextrose_kcal_p_ml()
    );
    f.provided_e__kcal_p_day.value = Math.round(
        1 * f.fat__kcal_p_day.value + 1 * f.dextrose__kcal_p_day.value
    );
    f.fat_rate.value = (
        f.fat_emulsion_value__g_p_kg_p_d.value
        * f.weight_kg.value
        * c_fatemul_fluid_content_ml_p_g()
        / f.infusion_duration_value_h.value
    );
    // fat rate precision varies depending on value
    // (neonate pumps can deliver with .01 ml/hr precision)
    if (f.fat_rate.value * 1 > 1) { // use a regular pump for tpn fat:
        f.fat_rate.value = round_n_to_x_decimals(f.fat_rate.value, 1);
    } else { // give tpn fat with a neonate pump:
        f.fat_rate.value = round_n_to_x_decimals(f.fat_rate.value, 2);
    }
    if (f.weight_kg.value >= 10){
        f.fat_rate.value  = round_n_to_x_decimals(f.fat_rate.value, 0);
    }
    // tpn rate also varies...
    // (I don't know if this would ever be an issue in a clinical case)
    f.tpn_rate.value = f.nonfat_fluid__ml_p_d.value / f.infusion_duration_value_h.value;
    if (f.tpn_rate.value * 1 > 1) { // use a regular pump for tpn fluid:
        f.tpn_rate.value = round_n_to_x_decimals(f.tpn_rate.value, 1);
    } else { // give tpn fluid with a neonate pump:
        f.tpn_rate.value = round_n_to_x_decimals(f.tpn_rate.value, 2);
    }
    if (f.weight_kg.value >= 10){
        f.tpn_rate.value  = round_n_to_x_decimals(f.tpn_rate.value, 0);
    }
    f.repeat_aminos__g_p_kg_p_d.value = f.aminoacids__g_p_kg_p_day.value;
    f.dextrose__kcal_p_day.value = Math.round(f.dextrose__kcal_p_day.value);
    f.repeat_infusion_hours_a.value = f.infusion_duration_value_h.value;
    f.repeat_infusion_hours_b.value = f.infusion_duration_value_h.value;
    f.repeat_dextrose_percent.value = f.dextrose_percent.value;
    f.repeat_aminoacids_percent.value = f.aminoacids_percent.value;
}
function prevent_change_to_summary_value() {
    var f = document.tpncalc;
    // called when the user tries to change a summary value.
    // we alert them not to the first time they try, and thereafter
    // we just ignore their attempts.
    if (f.user_has_been_warned_not_to_change_summary.value != "yes") {
        alert(
            "These values are copied from earlier form fields."
            + " Please make any required changes in the source fields above."
        );
        f.user_has_been_warned_not_to_change_summary.value = "yes";
    }
    duplicate_values_into_summary_fields();
}
function prevent_change_to_administration_value() {
    var f = document.tpncalc;
    // called when the user tries to change an administration value.
    // we alert them not to the first time they try, and thereafter
    // we just ignore their attempts.
    if (f.user_has_been_warned_not_to_change_rates.value != "yes") {
        alert(
            "These values are copied from earlier form fields."
            + " Please make any required changes in the source fields above."
        );
        f.user_has_been_warned_not_to_change_rates.value = "yes";
    }
    duplicate_values_into_summary_fields();
}
function calc_group_4_run() {
    var f = document.tpncalc;
    // we have passed the last reset button in the form,
    // so no verbose parameter will be required
    if (not_pos_num(f.aminoacids_percent.value)
            ||
            not_pos_num(f.dextrose_percent.value)
    ) {
        calc_group_4_clear();
        return;
    } // else, good data: calculate some stuff
    if (f.flag_check_energy_source_ratio.value * 1 == 1) {
        // intralipid or dextrose was modified by user...
        if (f.fat__kcal_p_day.value * 1 > 1 * (
                f.provided_e__kcal_p_day.value
                * c_warn_if_cals_from_fat_exceed_this_percent() / 100
            )
        ) {
            alert(
                "Warning:  High lipid infusion.  Review all concentrations. "
                + "Calculated values may exceed usual maximums."
            );
        }
        f.flag_check_energy_source_ratio.value = 0; // clear the flag
    }
    calc_group_5_init();
}
function calc_group_4_clear() {
    var f = document.tpncalc;
    f.repeat_estimated_tee__kcal_p_day.value = "";
    f.provided_e__kcal_p_day.value = "";
    f.fat__kcal_p_day.value = "";
    f.dextrose__kcal_p_day.value = "";
    f.repeat_aminos__g_p_kg_p_d.value = "";
    f.tpn_rate.value = "";
    f.fat_rate.value = "";
    f.repeat_dextrose_percent.value = "";
    f.repeat_aminoacids_percent.value = "";
    f.repeat_infusion_hours_a.value = "";
    f.repeat_infusion_hours_b.value = "";
    calc_group_5_run();
}
function per_liter__to__per_kg_per_day(p_l, p_kg_p_day, precision__p_l, precision__p_kg_p_day) {
    var f = document.tpncalc;
    /*
    this function is used in many places to change a value from one unit to the other
    (with precision as indicated by the last two arguments)
    Note that the first two arguments are not numbers, but are rather actual form
    input objects. The values in those actual fields are modified by this function.
    */
    if (is_good_nonnegative_number(precision__p_l)) {
        p_l.value = round_n_to_x_decimals(p_l.value, precision__p_l);
    }
    p_kg_p_day.value = p_l.value * f.nonfat_fluid__ml_p_d.value / 1000 / f.weight_kg.value;
    if (is_good_nonnegative_number(precision__p_kg_p_day)) {
        p_kg_p_day.value = round_n_to_x_decimals(p_kg_p_day.value, precision__p_kg_p_day);
    }
}
function per_kg_per_day__to__per_liter(p_kg_p_day, p_l, precision__p_kg_p_day, precision__p_l) {
    var f = document.tpncalc;
    // like the above per_liter__to__per_kg_per_day(), but does the opposite conversion
    // see comments there for additional details
    if (is_good_nonnegative_number(precision__p_kg_p_day)) {
        p_kg_p_day.value = round_n_to_x_decimals(p_kg_p_day.value, precision__p_kg_p_day);
    }
    p_l.value = p_kg_p_day.value / (f.nonfat_fluid__ml_p_d.value / 1000 / f.weight_kg.value);
    if (is_good_nonnegative_number(precision__p_l)) {
        p_l.value = round_n_to_x_decimals(p_l.value, precision__p_l);
    }
}
function set_phosphate(units, quantity) {
    var f = document.tpncalc;
    /*
    this function is called by our own code to set phosphate,
    and assumes that all dependant values will be recalculated
    by the code calling this function.
    If the user changes phosphate, then phosphate_change() would
    be called instead, and that code does much more than this:
    */
    if (units == "mmol_p_l") {
        f.phosphate__mmol_p_l.value = quantity;
        f.bak_phosphate__mmol_p_l.value = quantity;
        per_liter__to__per_kg_per_day(
            f.phosphate__mmol_p_l,
            f.phosphate__mmol_p_kg_p_day,
            0, 1
        );
        f.bak_phosphate__mmol_p_kg_p_day.value = f.phosphate__mmol_p_kg_p_day.value;
    } else { // units == "mmol_p_kg_p_day"
        f.phosphate__mmol_p_kg_p_day.value = quantity;
        f.bak_phosphate__mmol_p_kg_p_day.value = quantity;
        per_kg_per_day__to__per_liter(
            f.phosphate__mmol_p_kg_p_day,
            f.phosphate__mmol_p_l,
            1, 0
        );
        f.bak_phosphate__mmol_p_l.value = f.phosphate__mmol_p_l.value;
    }
}
function set_desired_sodium(units, quantity) {
    var f = document.tpncalc;
    // there are a fair number of functions very very similar to this one.
    // They all work like set_phosphate() above. (see those comments if needed)
    var precision = c_salt_precision();
    if (units == "meq_p_kg_p_day") {
        units = "meq_p_l"; // translate to per liter values for limit checking
        quantity = quantity / (f.nonfat_fluid__ml_p_d.value / 1000 / f.weight_kg.value);
    }
    if (quantity * 1 > c_max_sodium_meq_p_l() * 1) {
        alert(
                "The maximum sodium of "
                + c_max_sodium_meq_p_l()
                + " mEq/L has been exceeded - value set to maximal limit."
           );
        quantity = c_max_sodium_meq_p_l();
    }
    // now we have the correct (or corrected) value. Apply it:
    f.desired_sodium__meq_p_l.value = quantity;
    per_liter__to__per_kg_per_day(
        f.desired_sodium__meq_p_l,
        f.desired_sodium__meq_p_kg_p_day,
        precision, precision
    );
}
function set_desired_potassium(units, quantity) {
    var f = document.tpncalc;
    // there are a fair number of functions very very similar to this one.
    // They all work like set_phosphate() above. (see those comments if needed)
    var precision = c_salt_precision();
    if (units == "meq_p_kg_p_day") {
        units = "meq_p_l"; // translate to per liter values for limit checking
        quantity = quantity / (f.nonfat_fluid__ml_p_d.value / 1000 / f.weight_kg.value);
    }
    // assume a central line by default:
    var max_potassium_meq_p_l = c_max_potassium_meq_p_l_centrl();
    var line_type = "central";
    if (f.selected_line_type.value == "p") { // peripheral line
        // correct our assumption
        max_potassium_meq_p_l = c_max_potassium_meq_p_l_periph();
        line_type = "peripheral";
    }
    if (quantity * 1 > max_potassium_meq_p_l * 1) {
        alert(
                "The maximum potassium through a "
                + line_type
                + " line of "
                + max_potassium_meq_p_l * 1
                + " mEq/L has been exceeded - value set to maximal limit."
           );
        quantity = max_potassium_meq_p_l * 1;
    }
    // now we have the correct (or corrected) value. Apply it:
    f.desired_potassium__meq_p_l.value = quantity;
    per_liter__to__per_kg_per_day(
        f.desired_potassium__meq_p_l,
        f.desired_potassium__meq_p_kg_p_day,
        precision, precision
    );
}
function set_desired_acetate(units, quantity) {
    var f = document.tpncalc;
    var precision = c_salt_precision();
    if (units == "meq_p_l") {
        f.desired_acetate__meq_p_l.value = quantity;
        per_liter__to__per_kg_per_day(
            f.desired_acetate__meq_p_l,
            f.desired_acetate__meq_p_kg_p_day,
            precision, precision
        );
    } else { // units == "meq_p_kg_p_day"
        f.desired_acetate__meq_p_kg_p_day.value = quantity;
        per_kg_per_day__to__per_liter(
            f.desired_acetate__meq_p_kg_p_day,
            f.desired_acetate__meq_p_l,
            precision, precision
        );
    }
}
function set_sodium_acetate(units, quantity) {
    var f = document.tpncalc;
    var precision = c_salt_precision();
    if (units == "meq_p_l") {
        f.sodium_acetate__meq_p_l.value = quantity;
        per_liter__to__per_kg_per_day(
            f.sodium_acetate__meq_p_l,
            f.sodium_acetate__meq_p_kg_p_day,
            precision, precision
        );
    } else { // units == "meq_p_kg_p_day"
        f.sodium_acetate__meq_p_kg_p_day.value = quantity;
        per_kg_per_day__to__per_liter(
            f.sodium_acetate__meq_p_kg_p_day,
            f.sodium_acetate__meq_p_l,
            precision, precision
        );
    }
}
function set_sodium_chloride(units, quantity) {
    var f = document.tpncalc;
    var precision = c_salt_precision();
    if (units == "meq_p_l") {
        f.sodium_chloride__meq_p_l.value = quantity;
        per_liter__to__per_kg_per_day(
            f.sodium_chloride__meq_p_l,
            f.sodium_chloride__meq_p_kg_p_day,
            precision, precision
        );
    } else { // units == "meq_p_kg_p_day"
        f.sodium_chloride__meq_p_kg_p_day.value = quantity;
        per_kg_per_day__to__per_liter(
            f.sodium_chloride__meq_p_kg_p_day,
            f.sodium_chloride__meq_p_l,
            precision, precision
        );
    }
}
function set_potassium_acetate(units, quantity) {
    var f = document.tpncalc;
    var precision = c_salt_precision();
    if (units == "meq_p_l") {
        f.potassium_acetate__meq_p_l.value = quantity;
        per_liter__to__per_kg_per_day(
            f.potassium_acetate__meq_p_l,
            f.potassium_acetate__meq_p_kg_p_day,
            precision, precision
        );
    } else { // units == "meq_p_kg_p_day"
        f.potassium_acetate__meq_p_kg_p_day.value = quantity;
        per_kg_per_day__to__per_liter(
            f.potassium_acetate__meq_p_kg_p_day,
            f.potassium_acetate__meq_p_l,
            precision, precision
        );
    }
}
function set_potassium_chloride(units, quantity) {
    var f = document.tpncalc;
    var precision = c_salt_precision();
    if (units == "meq_p_l") {
        f.potassium_chloride__meq_p_l.value = quantity;
        per_liter__to__per_kg_per_day(
            f.potassium_chloride__meq_p_l,
            f.potassium_chloride__meq_p_kg_p_day,
            precision, precision
        );
    } else { // units == "meq_p_kg_p_day"
        f.potassium_chloride__meq_p_kg_p_day.value = quantity;
        per_kg_per_day__to__per_liter(
            f.potassium_chloride__meq_p_kg_p_day,
            f.potassium_chloride__meq_p_l,
            precision, precision
        );
    }
}
function set_calcium(units, quantity) {
    var f = document.tpncalc;
    if (units == "meq_p_l") {
        f.calcium__meq_p_l.value = quantity;
        f.bak_calcium__meq_p_l.value = quantity;
        per_liter__to__per_kg_per_day(
            f.calcium__meq_p_l,
            f.calcium__meq_p_kg_p_day,
            0, 1
        );
        f.bak_calcium__meq_p_kg_p_day.value = f.calcium__meq_p_kg_p_day.value;
    } else { // units == "meq_p_kg_p_day"
        f.calcium__meq_p_kg_p_day.value = quantity;
        f.bak_calcium__meq_p_kg_p_day.value = quantity;
        per_kg_per_day__to__per_liter(
            f.calcium__meq_p_kg_p_day,
            f.calcium__meq_p_l,
            1, 0
        );
        f.bak_calcium__meq_p_l.value = f.calcium__meq_p_l.value;
    }
}
function set_magnesium(units, quantity) {
    var f = document.tpncalc;
    if (units == "meq_p_l") {
        f.magnesium__meq_p_l.value = quantity;
        f.bak_magnesium__meq_p_l.value = quantity;
        per_liter__to__per_kg_per_day(
            f.magnesium__meq_p_l,
            f.magnesium__meq_p_kg_p_day,
            0, 1
        );
        f.bak_magnesium__meq_p_kg_p_day.value = f.magnesium__meq_p_kg_p_day.value;
    } else { // units == "meq_p_kg_p_day"
        f.magnesium__meq_p_kg_p_day.value = quantity;
        f.bak_magnesium__meq_p_kg_p_day.value = quantity;
        per_kg_per_day__to__per_liter(
            f.magnesium__meq_p_kg_p_day,
            f.magnesium__meq_p_l,
            1, 0
        );
        f.bak_magnesium__meq_p_l.value = f.magnesium__meq_p_l.value;
    }
}
function sodium_change(units) {
    var f = document.tpncalc;
    // called when the *user* tries to change sodium
    // default to units == "meq_p_kg_p_day"
    var field = f.sodium__meq_p_kg_p_day;
    var f_bak = f.bak_sodium__meq_p_kg_p_day;
    if (units == "meq_p_l") {
        field = f.sodium__meq_p_l;
        f_bak = f.bak_sodium__meq_p_l;
        if (not_nonneg_num(f_bak.value)) {
            field.value = f_bak.value;
            return; // no backup value means user shouldn't be changing these yet
        }
        if (not_nonneg_num(field.value)) {
            field.value = f_bak.value;
            return; // don't allow bad input
        }
        field.value = Math.round(field.value);
        if (field.value * 1 == f_bak.value * 1) {
            return; // user didn't even change the value
            // added because macNN4.76 calls onChange handler for onBlur event
        }
    } else { // units == "meq_p_kg_p_day"
        if (not_nonneg_num(f_bak.value)) {
            field.value = f_bak.value;
            return; // no backup value means user shouldn't be changing these yet
        }
        if (not_nonneg_num(field.value)) {
            field.value = f_bak.value;
            return; // don't allow bad input
        }
        if (field.value * 1 == f_bak.value * 1) {
            return; // user didn't even change the value
            // added because macNN4.76 calls onChange handler for onBlur event
        }
        // and translate request into per liter terms for limit checking...
        per_kg_per_day__to__per_liter(field, f.sodium__meq_p_l, 1, 0);
    }
    var sodium_max_meq_p_l = c_max_sodium_meq_p_l();
    if (f.sodium__meq_p_l.value * 1 > sodium_max_meq_p_l * 1) {
        alert(
            "Sodium level has been reduced from the requested "
            + f.sodium__meq_p_l.value
            + " mEq/L to the maximum allowable " + sodium_max_meq_p_l + " mEq/L."
        );
        if (units == "meq_p_kg_p_day") { // we need to change
            field.value = f_bak.value;
            units = "meq_p_l";
            field = f.sodium__meq_p_l;
            f_bak = f.bak_sodium__meq_p_l;
        }
        field.value = sodium_max_meq_p_l;
    }
    var delta = field.value - f_bak.value;
    if (delta * 1 == 0) {
        return; // no appreciable change
    } // else, we have a change to consider
    // Abtract from units in salts... start by assuming units == "meq_p_l"
    var sodium_chloride = f.sodium_chloride__meq_p_l;
    var sodium_acetate = f.sodium_acetate__meq_p_l;
    var unit_text = " mEq/L";
    if (units == "meq_p_kg_p_day") {
        sodium_chloride = f.sodium_chloride__meq_p_kg_p_day;
        sodium_acetate = f.sodium_acetate__meq_p_kg_p_day;
        unit_text = " mEq/kg/day";
    }
    if (delta * 1 > 0) { // add sodium
        // adding sodium is easy, just use sodium chloride
        alert("Sodium will be added as sodium chloride.");
        set_sodium_chloride(units, sodium_chloride.value * 1 + delta * 1);
    } else { // remove sodium
        // trickier than adding sodium. try to remove it all as sodium chloride
        // if we have to, pull some from sodium acetate
        // if we have any left, user will need to cut down the phosphate
        delta = Math.abs(delta);
        if (sodium_chloride.value * 1 >= delta * 1) {
            alert("Sodium will be removed as sodium chloride.");
            set_sodium_chloride(units, sodium_chloride.value - delta);
        } else { // not enough sodium chloride to remove all sodium that way
            // looks like we'll have to dip into the acetate a bit as well...
            var acetate_change = 0; // track acetate changes
            /*
            will get set to how much we decrease acetate,
            we'll try to restore that, then this will be set
            to how much of our restore failed
            Since that value will be zero on success, we use the
            following flag to distinguish when it *started as zero
            and no restore was required (so we can keep use apraised)
            */
            var ignore_acetate = false; // flag set if acetate not changed
            if (sodium_acetate.value * 1 == 0) {
                ignore_acetate = true; // don't try to restore what isn't there
            }
            if ((sodium_chloride.value * 1 + sodium_acetate.value * 1) >= delta * 1) {
                alert("Sodium will be removed as sodium chloride and sodium acetate.");
                delta = delta - sodium_chloride.value;
                set_sodium_chloride(units, 0);
                set_sodium_acetate(units, sodium_acetate.value - delta);
                // try to restore acetate values by trading potassium chloride for potassium acetate
                acetate_change = increase_acetate_from_chloride_shift(
                    "potassium", units, delta
                );
            } else { // can't do it... user will have to reduce phosphate
                // we can also end up here because of rounding issues
                // (we have .5 mEq/L NaAcetate and they want to remove 1 mEq/L Na which is really only .5)
                // Don't babble about removing salts if they are already all gone
                if ((sodium_acetate.value * 1 == 0) && (sodium_chloride.value * 1 == 0)) {
                    alert(
                        "To reduce sodium any further, you must"
                        + " remove phosphate. Phosphate is added as"
                        + " sodium phosphate, and this is the only"
                        + " source of sodium which remains."
                    );
                    sum_inheritance_and_salts();
                    return;
                }
                alert(
                    "All sodium chloride and sodium acetate will"
                    + " be removed. To reduce sodium any further,"
                    + " you must remove phosphate."
                );
                var initial_sodium_acetate = sodium_acetate.value;
                set_sodium_chloride(units, 0);
                set_sodium_acetate(units, 0);
                // try to restore acetate values by trading potassium chloride for potassium acetate
                acetate_change = increase_acetate_from_chloride_shift(
                    "potassium", units, initial_sodium_acetate
                );
            }
            if ((acetate_change * 1 == 0) && !ignore_acetate) {
                alert(
                    "Acetate level was held constant by replacing"
                    + " potassium chloride with potassium acetate."
                );
            } else if ((acetate_change * 1 > 0) && !ignore_acetate) {
                var approx_change = drop_precision_but_remain_positive(acetate_change);
                alert(
                    "Acetate level was held constant by replacing"
                    + " potassium chloride with potassium acetate."
                    + " However, there was insufficient potassium"
                    + " chloride to allow for a complete recovery"
                    + " of previous acetate levels. Acetate levels"
                    + " have been reduced about "
                    + approx_change + unit_text + "."
                );
            }
        }
    }
    // no need to error check
    // sodium already known to be ok, chloride and acetate have no limits
    sum_inheritance_and_salts();
    if (
        f.sodium__meq_p_kg_p_day.value * 1
        >
        c_warn_if_changed_sodium_exceeds_this_meq_p_kg_d() * 1
    ) {
        alert(
            "CAUTION:\n"
            + "Sodium levels exceed "
            + c_warn_if_changed_sodium_exceeds_this_meq_p_kg_d()
            + " mEq/kg/day."
        );
    }
}
function potassium_change(units) {
    var f = document.tpncalc;
    // called when the *user* tries to change potassium
    // default to units == "meq_p_kg_p_day"
    var unit_text = " mEq/kg/day"; // jr fast change
    var field = f.potassium__meq_p_kg_p_day;
    var f_bak = f.bak_potassium__meq_p_kg_p_day;
    var limit = f.potassium_limit__meq_p_kg_p_day;
    var round = 1; // jr fast change round to 1 decimal place if meq_p_kg_p_day
    if (units == "meq_p_l") {
        unit_text = " mEq/L"; // fast change
        field = f.potassium__meq_p_l;
        f_bak = f.bak_potassium__meq_p_l;
        limit = f.potassium_limit__meq_p_l;
        round = 0; //jr fast change round to nearest integer if meq_p_l
        if (not_nonneg_num(f_bak.value)) {
            field.value = f_bak.value;
            return; // no backup value means user shouldn't be changing these yet
        }
        if (not_nonneg_num(field.value)) {
            field.value = f_bak.value;
            return; // don't allow bad input
        }
        field.value = Math.round(field.value);
        if (field.value * 1 == f_bak.value * 1) {
            return; // user didn't even change the value
            // added because macNN4.76 calls onChange handler for onBlur event
        }
    } else { // units == "meq_p_kg_p_day"
        if (not_nonneg_num(f_bak.value)) {
            field.value = f_bak.value;
            return; // no backup value means user shouldn't be changing these yet
        }
        if (not_nonneg_num(field.value)) {
            field.value = f_bak.value;
            return; // don't allow bad input
        }
        if (field.value * 1 == f_bak.value * 1) {
            return; // user didn't even change the value
            // added because macNN4.76 calls onChange handler for onBlur event
        }
        // and translate request into per liter terms for limit checking...
        per_kg_per_day__to__per_liter(field, f.potassium__meq_p_l, 1, 0);
    }
    // assume a central line by default:
    var max_potassium_meq_p_l = c_max_potassium_meq_p_l_centrl();
    var line_type = "central";
    if (f.selected_line_type.value == "p") { // peripheral line
        // correct our assumption
        max_potassium_meq_p_l = c_max_potassium_meq_p_l_periph();
        line_type = "peripheral";
    }
    var limit_alert;
    if (f.potassium__meq_p_l.value * 1 > max_potassium_meq_p_l * 1) {
        limit_alert = (
            "Potassium level has been reduced from the requested "
            + f.potassium__meq_p_l.value
            + " mEq/L to the maximum allowable through a "
            + line_type
            + " line of "
            + max_potassium_meq_p_l
            + " mEq/L."
        );
        if (units == "meq_p_kg_p_day") { // we need to change
            field.value = f_bak.value;
            units = "meq_p_l";
            field = f.potassium__meq_p_l;
            f_bak = f.bak_potassium__meq_p_l;
            limit = f.potassium_limit__meq_p_l;
        }
        field.value = max_potassium_meq_p_l;
    }
    if (field.value * 1 > limit.value * 1) {
        // user requesting too much potassium
        var overage = field.value - limit.value;
        var takeout = round_n_to_x_decimals(overage, round);
        if (takeout * 1 == 0) {
            // overage is so small that rounding makes it vanish.
            // increase the takeout amount a pinch
            takeout = 6; // take 6 from 10 and it rounds down to 0
            for (var i = 0; i * 1 <= round * 1; i++) {
                takeout = takeout * .1; // adjust to appropriate rounding level
            }
        }
        limit_alert = (
            "Potassium infusion limit is "
            + c_max_potassium_meq_p_kg_p_h() + " mEq/kg/hour."
            + " Your request will be reduced by"
            + " about " + round_n_to_x_decimals(takeout, round + 1)
            + " " + unit_text + " to fall within that limit"
        );
        field.value = field.value - takeout;
    }
    if (limit_alert) { // at least one of the above was triggered
        alert(limit_alert); // tell the user about the most recent
    }
    var delta = field.value - f_bak.value;
    if (delta * 1 == 0) {
        return; // no appreciable change
    } // else, we have a change to consider
    // Abtract from units in salts... start by assuming units == "meq_p_l"
    var potassium_chloride = f.potassium_chloride__meq_p_l;
    var potassium_acetate = f.potassium_acetate__meq_p_l;
    if (units == "meq_p_kg_p_day") {
        potassium_chloride = f.potassium_chloride__meq_p_kg_p_day;
        potassium_acetate = f.potassium_acetate__meq_p_kg_p_day;
    }
    if (delta * 1 > 0) { // add potassium
        // adding potassium is easy, just use potassium chloride
        alert("Potassium will be added as potassium chloride.");
        set_potassium_chloride(units, potassium_chloride.value * 1 + delta * 1);
    } else { // remove potassium
        // trickier than adding potassium.
        // try to remove it all as potassium chloride
        // if we have to, pull some from potassium acetate
        delta = Math.abs(delta);
        if (potassium_chloride.value * 1 >= delta * 1) {
            alert("Potassium will be removed as potassium chloride.");
            set_potassium_chloride(units, potassium_chloride.value - delta);
        } else { // not enough potassium chloride to remove it all that way
            // looks like we'll have to dip into the acetate a bit as well...
            var acetate_change = 0; // track acetate changes
            /*
            will get set to how much we decrease acetate,
            we'll try to restore that, then this will be set
            to how much of our restore failed
            Since that value will be zero on success, we use the
            following flag to distinguish when it *started as zero
            and no restore was required (so we can keep use apraised)
            */
            var ignore_acetate = false; // flag set if acetate not changed
            if (potassium_acetate.value * 1 == 0) {
                ignore_acetate = true; // don't try to restore what isn't there
            }
            if ((potassium_chloride.value * 1 + potassium_acetate.value * 1) >= delta * 1) {
                alert("Potassium will be removed as potassium chloride and potassium acetate.");
                delta = delta - potassium_chloride.value;
                set_potassium_chloride(units, 0);
                set_potassium_acetate(units, potassium_acetate.value - delta);
                // try to restore acetate values by trading sodium chloride for sodium acetate
                acetate_change = increase_acetate_from_chloride_shift("sodium", units, delta);
            } else {
                // maybe a rounding issue
                // (we have .5 mEq/L KAcetate and they want to remove 1 mEq/L K which is really only .5)
                // Don't babble about removing salts if they are already all gone
                if ((potassium_acetate.value * 1 == 0) && (potassium_chloride.value * 1 == 0)) {
                    sum_inheritance_and_salts();
                    return;
                }
                alert(
                    "All potassium chloride and potassium acetate will be removed."
                );
                var initial_potassium_acetate = potassium_acetate.value;
                set_potassium_chloride(units, 0);
                set_potassium_acetate(units, 0);
                // try to restore acetate values by trading sodium chloride for sodium acetate
                acetate_change = increase_acetate_from_chloride_shift(
                    "sodium", units, initial_potassium_acetate
                );
            }
            if ((acetate_change * 1 == 0) && !ignore_acetate) {
                alert(
                    "Acetate level was held constant by replacing"
                    + " sodium chloride with sodium acetate."
                );
            } else if ((acetate_change * 1 > 0) && !ignore_acetate) {
                var approx_change = drop_precision_but_remain_positive(acetate_change);
                alert(
                    "Acetate level was held constant by replacing"
                    + " sodium chloride with sodium acetate."
                    + " However, there was insuficient sodium"
                    + " chloride to allow for a complete recovery"
                    + " of previous acetate levels. Acetate levels"
                    + " have been reduced about "
                    + approx_change + unit_text + "."
                );
            }
        }
    }
    // no need to error check
    // potassium already known to be ok, chloride and acetate have no limits
    sum_inheritance_and_salts();
    if (
        f.potassium__meq_p_kg_p_day.value * 1
        >
        c_warn_if_changed_potassium_exceeds_this_meq_p_kg_d() * 1
    ) {
        alert(
            "CAUTION:\n"
            + "Potassium levels exceed "
            + c_warn_if_changed_potassium_exceeds_this_meq_p_kg_d()
            + " mEq/kg/day."
        );
    }
    if (
        f.potassium__meq_p_l.value * 1
        >
        c_warn_if_changed_potassium_exceeds_this_meq_p_l() * 1
    ) {
        alert(
            "CAUTION:\n"
            + "Potassium levels exceed "
            + c_warn_if_changed_potassium_exceeds_this_meq_p_l()
            + " mEq/L."
        );
    }
}
function chloride_change(units) {
    var f = document.tpncalc;
    // called when the *user* tries to change chloride
    var s_delta; // used later
    var p_delta; // used later
    var difference; // used later
    // default to units == "meq_p_kg_p_day"
    var field = f.chloride__meq_p_kg_p_day;
    var f_bak = f.bak_chloride__meq_p_kg_p_day;
    var unit_text = " mEq/L";
    if (units == "meq_p_l") {
        field = f.chloride__meq_p_l;
        f_bak = f.bak_chloride__meq_p_l;
        if (not_nonneg_num(f_bak.value)) {
            field.value = f_bak.value;
            return; // no backup value means user shouldn't be changing these yet
        }
        if (not_nonneg_num(field.value)) {
            field.value = f_bak.value;
            return; // don't allow bad input
        }
        field.value = Math.round(field.value);
    } else { // units == "meq_p_kg_p_day"
        if (not_nonneg_num(f_bak.value)) {
            field.value = f_bak.value;
            return; // no backup value means user shouldn't be changing these yet
        }
        if (not_nonneg_num(field.value)) {
            field.value = f_bak.value;
            return; // don't allow bad input
        }
        unit_text = " mEq/kg/day";
    }
    if (field.value * 1 == f_bak.value * 1) {
        return; // user didn't even change the value
        // had to put this in because macNN4.76 called onChange handler for onBlur
    }
    var delta = field.value - f_bak.value;
    if (delta * 1 == 0) {
        return; // no appreciable change
    } // else, we have a change to consider
    if (delta * 1 > 0) {
        // positive change: move acetate salts over into chloride...
        var sodium_acetate = f.sodium_acetate__meq_p_l;
        var potassium_acetate = f.potassium_acetate__meq_p_l;
        if (units == "meq_p_kg_p_day") {
            sodium_acetate = f.sodium_acetate__meq_p_kg_p_day;
            potassium_acetate = f.potassium_acetate__meq_p_kg_p_day;
        }
        if ((sodium_acetate.value * 1 == 0) && (potassium_acetate.value * 1 == 0)) {
            alert(
                "Chloride levels cannot be raised any higher"
                + " without first adding sodium or potassium."
                + " Please increase one or both of those"
                + " ingredients before raising chloride."
            );
            field.value = f_bak.value; // undo their change
            return;
        } else if (sodium_acetate.value * 1 >= delta * 1) {
            alert(
                "Chloride levels will be increased by replacing"
                + " sodium acetate with sodium chloride."
            );
            increase_chloride_from_acetate_shift("sodium", units, delta);
        } else if (potassium_acetate.value * 1 >= delta * 1) {
            alert(
                "Chloride levels will be increased by replacing"
                + " potassium acetate with potassium chloride."
            );
            increase_chloride_from_acetate_shift("potassium", units, delta);
        } else if ((sodium_acetate.value * 1 + potassium_acetate.value * 1) >= delta * 1) {
            alert(
                "Chloride levels will be increased by replacing"
                + " potassium acetate with potassium chloride"
                + " and sodium acetate with sodium chloride."
            );
            s_delta = sodium_acetate.value;
            p_delta = delta - s_delta;
            increase_chloride_from_acetate_shift("sodium", units, s_delta);
            increase_chloride_from_acetate_shift("potassium", units, p_delta);
        } else { // we just can't do it all without modifying a more important electrolyte
            difference = delta - sodium_acetate.value - potassium_acetate.value;
            alert(
                "Chloride levels will be increased by replacing"
                + " acetate salts with chloride salts. However,"
                + " this will fall " + difference + unit_text + ""
                + " short of your request. Sodium or potassium"
                + " must be raised in order to raise chloride"
                + " levels any higher."
            );
            increase_chloride_from_acetate_shift("sodium", units, sodium_acetate.value);
            increase_chloride_from_acetate_shift("potassium", units, potassium_acetate.value);
        }
    } else { // ( delta < 0 )
        // negative change: move chloride salts over into acetate...
        delta = Math.abs(delta);
        var sodium_chloride = f.sodium_chloride__meq_p_l;
        var potassium_chloride = f.potassium_chloride__meq_p_l;
        if (units == "meq_p_kg_p_day") {
            sodium_chloride = f.sodium_chloride__meq_p_kg_p_day;
            potassium_chloride = f.potassium_chloride__meq_p_kg_p_day;
        }
        if ((sodium_chloride.value * 1 == 0) && (potassium_chloride.value * 1 == 0)) {
            alert("Chloride levels cannot be lowered any further. (Remaining chloride comes with amino acids.)");
            field.value = f_bak.value; // undo their change
            return;
        } else if (sodium_chloride.value * 1 >= delta * 1) {
            alert(
                "Chloride levels will be decreased by replacing"
                + " sodium chloride with sodium acetate."
            );
            increase_acetate_from_chloride_shift("sodium", units, delta);
        } else if (potassium_chloride.value * 1 >= delta * 1) {
            alert(
                "Chloride levels will be decreased by replacing"
                + " potassium chloride with potassium acetate."
            );
            increase_acetate_from_chloride_shift("potassium", units, delta);
        } else if ((sodium_chloride.value * 1 + potassium_chloride.value * 1) >= delta * 1) {
            alert(
                "Chloride levels will be decreased by replacing"
                + " potassium chloride with potassium acetate"
                + " and sodium chloride with sodium acetate."
            );
            s_delta = sodium_chloride.value;
            p_delta = delta - s_delta;
            increase_acetate_from_chloride_shift("sodium", units, s_delta);
            increase_acetate_from_chloride_shift("potassium", units, p_delta);
        } else { // we just can't do it all without modifying a more important electrolyte
            difference = drop_precision_but_remain_positive(
                delta - sodium_chloride.value - potassium_chloride.value
            );
            alert(
                "Chloride levels will be decreased by replacing"
                + " chloride salts with acetate salts. However,"
                + " this will fall about " + difference + unit_text
                + " short of your request. Chloride levels can't"
                + " be reduced any further. (remaining Cl is from amino acids)"
            );
            increase_acetate_from_chloride_shift("sodium", units, sodium_acetate.value);
            increase_acetate_from_chloride_shift("potassium", units, potassium_acetate.value);
        }
    }
    // no need to error check
    // sodium already known to be ok, chloride and acetate have no limits
    sum_inheritance_and_salts();
}
function acetate_change(units) {
    var f = document.tpncalc;
    // called when the *user* tries to change acetate
    var s_delta; // used later
    var p_delta; // used later
    var difference; // used later
    // default to units == "meq_p_kg_p_day"
    // default to units == "meq_p_kg_p_day"
    var field = f.acetate__meq_p_kg_p_day;
    var f_bak = f.bak_acetate__meq_p_kg_p_day;
    var unit_text = " mEq/L";
    if (units == "meq_p_l") {
        field = f.acetate__meq_p_l;
        f_bak = f.bak_acetate__meq_p_l;
        if (not_nonneg_num(f_bak.value)) {
            field.value = f_bak.value;
            return; // no backup value means user shouldn't be changing these yet
        }
        if (not_nonneg_num(field.value)) {
            field.value = f_bak.value;
            return; // don't allow bad input
        }
        field.value = Math.round(field.value);
    } else { // units == "meq_p_kg_p_day"
        if (not_nonneg_num(f_bak.value)) {
            field.value = f_bak.value;
            return; // no backup value means user shouldn't be changing these yet
        }
        if (not_nonneg_num(field.value)) {
            field.value = f_bak.value;
            return; // don't allow bad input
        }
        unit_text = " mEq/kg/day";
    }
    if (field.value * 1 == f_bak.value * 1) {
        return; // user didn't even change the value
        // had to put this in because macNN4.76 called onChange handler for onBlur
    }
    var delta = field.value - f_bak.value;
    if (delta * 1 == 0) {
        return; // no appreciable change
    } // else, we have a change to consider
    if (delta * 1 > 0) {
        // positive change: move chloride salts over into acetate...
        var sodium_chloride = f.sodium_chloride__meq_p_l;
        var potassium_chloride = f.potassium_chloride__meq_p_l;
        if (units == "meq_p_kg_p_day") {
            sodium_chloride = f.sodium_chloride__meq_p_kg_p_day;
            potassium_chloride = f.potassium_chloride__meq_p_kg_p_day;
        }
        if ((sodium_chloride.value * 1 == 0) && (potassium_chloride.value * 1 == 0)) {
            alert(
                "Acetate levels cannot be raised any higher"
                + " without first adding sodium, potassium, or"
                + " amino acids. Please increase one or more"
                + " of those ingredients before raising acetate."
            );
            field.value = f_bak.value; // undo their change
            return;
        } else if (sodium_chloride.value * 1 >= delta * 1) {
            alert(
                "Acetate levels will be increased by replacing"
                + " sodium chloride with sodium acetate."
            );
            increase_acetate_from_chloride_shift("sodium", units, delta);
        } else if (potassium_chloride.value * 1 >= delta * 1) {
            alert(
                "Acetate levels will be increased by replacing"
                + " potassium chloride with potassium acetate."
            );
            increase_acetate_from_chloride_shift("potassium", units, delta);
        } else if ((sodium_chloride.value * 1 + potassium_chloride.value * 1) >= delta * 1) {
            alert(
                "Acetate levels will be increased by replacing"
                + " potassium chloride with potassium acetate"
                + " and sodium chloride with sodium acetate."
            );
            s_delta = sodium_chloride.value;
            p_delta = delta - s_delta;
            increase_acetate_from_chloride_shift("sodium", units, s_delta);
            increase_acetate_from_chloride_shift("potassium", units, p_delta);
        } else { // just can't do it all without modifying a more important electrolyte
            difference = delta - sodium_chloride.value - potassium_chloride.value;
            alert(
                "Acetate levels will be increased by replacing"
                + " chloride salts with acetate salts. However,"
                + " this will fall " + difference + unit_text
                + " short of your request. Sodium, potassium,"
                + " or amino acids must be raised in order to"
                + " raise acetate levels any higher."
            );
            increase_acetate_from_chloride_shift("sodium", units, sodium_chloride.value);
            increase_acetate_from_chloride_shift("potassium", units, potassium_chloride.value);
        }
    } else { // ( delta < 0 )
        // negative change: move acetate salts over into chloride...
        delta = Math.abs(delta);
        var sodium_acetate = f.sodium_acetate__meq_p_l;
        var potassium_acetate = f.potassium_acetate__meq_p_l;
        if (units == "meq_p_kg_p_day") {
            sodium_acetate = f.sodium_acetate__meq_p_kg_p_day;
            potassium_acetate = f.potassium_acetate__meq_p_kg_p_day;
        }
        if ((sodium_acetate.value * 1 == 0) && (potassium_acetate.value * 1 == 0)) {
            alert(
                "Acetate levels cannot be lowered any further"
                + " without first reducing amino acids."
                + " Note that amino acid changes will result"
                + " in recalculation of all electroltyes."
            );
            field.value = f_bak.value; // undo their change
            return;
        } else if (sodium_acetate.value * 1 >= delta * 1) {
            alert(
                "Acetate levels will be decreased by replacing"
                + " sodium acetate with sodium chloride."
            );
            increase_chloride_from_acetate_shift("sodium", units, delta);
        } else if (potassium_acetate.value * 1 >= delta * 1) {
            alert(
                "Acetate levels will be decreased by replacing"
                + " potassium acetate with potassium chloride."
            );
            increase_chloride_from_acetate_shift("potassium", units, delta);
        } else if ((sodium_acetate.value * 1 + potassium_acetate.value * 1) >= delta * 1) {
            alert(
                "Acetate levels will be decreased by replacing"
                + " potassium acetate with potassium chloride"
                + " and sodium acetate with sodium chloride."
            );
            s_delta = sodium_acetate.value;
            p_delta = delta - s_delta;
            increase_chloride_from_acetate_shift("sodium", units, s_delta);
            increase_chloride_from_acetate_shift("potassium", units, p_delta);
        } else { // just can't do it all without modifying a more important electrolyte
            difference = delta - sodium_acetate.value - potassium_acetate.value;
            difference = drop_precision_but_remain_positive(difference);
            alert(
                "Acetate levels will be decreased by replacing"
                + " acetate salts with chloride salts. However,"
                + " this will fall about " + difference + unit_text
                + " short of your request. Acetate levels may be"
                + " reduced further by first lowering amino acid levels."
            );
            increase_chloride_from_acetate_shift("sodium", units, sodium_acetate.value);
            increase_chloride_from_acetate_shift("potassium", units, potassium_acetate.value);
        }
    }
    // no need to error check
    // sodium already known to be ok, chloride and acetate have no limits
    sum_inheritance_and_salts();
}
function calcium_change(units, supress_precip_check) {
    var f = document.tpncalc;
    // called when the *user* tries to change calcium
    // default to units == "meq_p_kg_p_day"
    var field = f.calcium__meq_p_kg_p_day;
    var f_bak = f.bak_calcium__meq_p_kg_p_day;
    if (units == "meq_p_l") {
        field = f.calcium__meq_p_l;
        f_bak = f.bak_calcium__meq_p_l;
        if (not_nonneg_num(f_bak.value)) {
            field.value = f_bak.value;
            return; // no backup value means user shouldn't be changing these yet
        }
        if (not_nonneg_num(field.value)) {
            field.value = f_bak.value;
            return; // don't allow bad input
        }
        field.value = Math.round(field.value);
        if (field.value * 1 == f_bak.value * 1) {
            return; // user didn't even change the value
            // added because macNN4.76 calls onChange handler for onBlur event
        }
    } else { // units == "meq_p_kg_p_day"
        if (not_nonneg_num(f_bak.value)) {
            field.value = f_bak.value;
            return; // no backup value means user shouldn't be changing these yet
        }
        if (not_nonneg_num(field.value)) {
            field.value = f_bak.value;
            return; // don't allow bad input
        }
        if (field.value * 1 == f_bak.value * 1) {
            return; // user didn't even change the value
            // added because macNN4.76 calls onChange handler for onBlur event
        }
        per_kg_per_day__to__per_liter(field, f.calcium__meq_p_l, 1, 0);
    }
    var calcium_max_meq_p_l = c_max_calcium_meq_p_l();
    if (f.calcium__meq_p_l.value * 1 > calcium_max_meq_p_l * 1) {
        alert(
            "Calcium level has been reduced from the requested "
            + f.calcium__meq_p_l.value
            + " mEq/L to the maximum allowable " + calcium_max_meq_p_l + " mEq/L."
        );
        if (units == "meq_p_kg_p_day") { // we need to change
            field.value = f_bak.value;
            units = "meq_p_l";
            field = f.calcium__meq_p_l;
            f_bak = f.bak_calcium__meq_p_l;
        }
        field.value = calcium_max_meq_p_l;
    }
    if ((field.value - f_bak.value) == 0) {
        return; // no appreciable change
    } // else, we have a change to implement
    set_calcium(units, field.value)
    if (!supress_precip_check) {
        check_for_caphos_precip();
    }
}
function magnesium_change(units) {
    var f = document.tpncalc;
    // called when the *user* tries to change magnesium
    // default to units == "meq_p_kg_p_day"
    var field = f.magnesium__meq_p_kg_p_day;
    var f_bak = f.bak_magnesium__meq_p_kg_p_day;
    if (units == "meq_p_l") {
        field = f.magnesium__meq_p_l;
        f_bak = f.bak_magnesium__meq_p_l;
        if (not_nonneg_num(f_bak.value)) {
            field.value = f_bak.value;
            return; // no backup value means user shouldn't be changing these yet
        }
        if (not_nonneg_num(field.value)) {
            field.value = f_bak.value;
            return; // don't allow bad input
        }
        field.value = Math.round(field.value);
        if (field.value * 1 == f_bak.value * 1) {
            return; // user didn't even change the value
            // added because macNN4.76 calls onChange handler for onBlur event
        }
    } else { // units == "meq_p_kg_p_day"
        if (not_nonneg_num(f_bak.value)) {
            field.value = f_bak.value;
            return; // no backup value means user shouldn't be changing these yet
        }
        if (not_nonneg_num(field.value)) {
            field.value = f_bak.value;
            return; // don't allow bad input
        }
        if (field.value * 1 == f_bak.value * 1) {
            return; // user didn't even change the value
            // added because macNN4.76 calls onChange handler for onBlur event
        }
        per_kg_per_day__to__per_liter(field, f.magnesium__meq_p_l, 1, 0);
    }
    var magnesium_max_meq_p_l = c_max_magnesium_meq_p_l();
    if (f.magnesium__meq_p_l.value * 1 > magnesium_max_meq_p_l * 1) {
        alert(
            "Magnesium level has been reduced from the requested "
            + f.magnesium__meq_p_l.value
            + " mEq/L to the maximum allowable " + magnesium_max_meq_p_l + " mEq/L."
        );
        if (units == "meq_p_kg_p_day") { // we need to change
            field.value = f_bak.value;
            units = "meq_p_l";
            field = f.magnesium__meq_p_l;
            f_bak = f.bak_magnesium__meq_p_l;
        }
        field.value = magnesium_max_meq_p_l;
    }
    if ((field.value - f_bak.value) == 0) {
        return; // no appreciable change
    } // else, we have a change to implement
    set_magnesium(units, field.value)
}
function phosphate_change(units, supress_precip_check) {
    var f = document.tpncalc;
    // called when the *user* tries to change phosphate
    // default to units == "mmol_p_kg_p_day"
    var field = f.phosphate__mmol_p_kg_p_day;
    var f_bak = f.bak_phosphate__mmol_p_kg_p_day;
    if (units == "mmol_p_l") {
        field = f.phosphate__mmol_p_l;
        f_bak = f.bak_phosphate__mmol_p_l;
        if (not_nonneg_num(f_bak.value)) {
            field.value = f_bak.value;
            return; // no backup value means user shouldn't be changing these yet
        }
        if (not_nonneg_num(field.value)) {
            field.value = f_bak.value;
            return; // don't allow bad input
        }
        field.value = Math.round(field.value);
        if (field.value * 1 == f_bak.value * 1) {
            return; // user didn't even change the value
            // had to put this in because macNN4.76 called onChange handler for onBlur
        }
        per_liter__to__per_kg_per_day(field, f.phosphate__mmol_p_kg_p_day, 0, 1);
    } else { // units == "mmol_p_kg_p_day"
        if (not_nonneg_num(f_bak.value)) {
            field.value = f_bak.value;
            return; // no backup value means user shouldn't be changing these yet
        }
        if (not_nonneg_num(field.value)) {
            field.value = f_bak.value;
            return; // don't allow bad input
        }
        if (field.value * 1 == f_bak.value * 1) {
            return; // user didn't even change the value
            // had to put this in because macNN4.76 called onChange handler for onBlur
        }
        per_kg_per_day__to__per_liter(field, f.phosphate__mmol_p_l, 1, 0);
    }
    var phosphate_max_mmol_p_l = c_max_phosphate_mmol_p_l();
    var sodium_max_meq_p_l = c_max_sodium_meq_p_l();
    var phos_alert = "";
    if (f.phosphate__mmol_p_l.value * 1 > phosphate_max_mmol_p_l * 1) {
        phos_alert = (
            "Phosphate level has been reduced from the"
            + " requested "
            + f.phosphate__mmol_p_l.value
            + " mMol/L to the maximum allowable "
            + phosphate_max_mmol_p_l + " mMol/L."
        );
    }
    if (sodium_from_phosphate(phosphate_max_mmol_p_l) > sodium_max_meq_p_l * 1) {
        var new_phosphate_max_mmol_p_l = (
            sodium_max_meq_p_l / c_sodium_meq__given_per__mmol_phos()
        );
        phos_alert = (
            "Phosphate level has been further reduced down to "
            + new_phosphate_max_mmol_p_l
            + " mMol/L because phosphate is added with."
            + " sodium. Sodium cannot exceed"
            + sodium_max_meq_p_l
            + " mEq/L."
        );
        phosphate_max_mmol_p_l = new_phosphate_max_mmol_p_l;
    }
    if (phos_alert.length) {
        alert(phos_alert);
        if (units == "mmol_p_kg_p_day") { // we need to change
            field.value = f_bak.value;
            units = "mmol_p_l";
            field = f.phosphate__mmol_p_l;
            f_bak = f.bak_phosphate__mmol_p_l;
        }
        field.value = phosphate_max_mmol_p_l;
    }
    var delta = field.value - f_bak.value;
    set_phosphate(units, field.value);
    if (delta * 1 == 0) {
        return; // no appreciable change
    } // else, we have a change to consider
    // modify our "sodium from phosphate" fields
    // move current sodium, potassium, acetate levels into desired* fields
    // then calculate new salt levels
    determine_initial_electrolyte_inheritance(); // re-does "sodium from phosphate"
    alert(
        "All other electrolytes are now re-calculated. We will"
        + " attempt to match your current values, but may be off"
        + " by small amounts. Chloride is the electrolyte"
        + " most likely to be affected."
    );
    if (units == "mmol_p_l") {
        set_desired_sodium("meq_p_l", f.sodium__meq_p_l.value);
        set_desired_potassium("meq_p_l", f.potassium__meq_p_l.value);
        set_desired_acetate("meq_p_l", f.acetate__meq_p_l.value);
        derive_four_main_salts_values_in_meq_p_l();
        f.bak_phosphate__mmol_p_l.value
          = f.phosphate__mmol_p_l.value;
    } else { // ( units == "mmol_p_kg_p_day" )
        set_desired_sodium("meq_p_kg_p_day", f.sodium__meq_p_kg_p_day.value);
        set_desired_potassium("meq_p_kg_p_day", f.potassium__meq_p_kg_p_day.value);
        set_desired_acetate("meq_p_kg_p_day", f.acetate__meq_p_kg_p_day.value);
        derive_four_main_salts_values_in_meq_p_kg_p_day();
        f.bak_phosphate__mmol_p_kg_p_day.value
          = f.phosphate__mmol_p_kg_p_day.value;
    }
    sum_inheritance_and_salts();
    if (!supress_precip_check) {
        check_for_caphos_precip();
    }
}
function check_for_caphos_precip(silent) {
    var f = document.tpncalc;
    // Calcium-Phosphate precipitate is a Bad Thing. We don't want any
    // chunks in our TPN. This routine checks and corrects for that...
    var ca_phos_sum
        = f.calcium__meq_p_l.value * 1 + f.phosphate__mmol_p_l.value * 1;
    var ppt_factor = (ca_phos_sum);
        //KL added with Chris  * 1000
      //KL added with Chris  / (f.nonfat_fluid__ml_p_d.value / f.weight_kg.value)
    

    //  var ppt_max = 50;  // Used to be 60  *KL changed 9/15/2008

    if (f.aminoacids_percent.value * 1 < 2) { //*KL added "="
        ppt_max = 48; //*KL used to be 30
    } else if (f.aminoacids_percent.value * 1 < 3) { //*KL added "="
        ppt_max = 62; //*KL used to be 40
    } else if (f.aminoacids_percent.value * 1 > 3) { //*KL added "="
        ppt_max = 80; //*KL used to be 50
    } // else leave at default ppt_max value
    if (ppt_factor * 1 < ppt_max * 1) { // no precipitate
        return;
    } // else ppt too high...
    var ca_phos_max = (ppt_max);
     //kl removed with chris   * (f.nonfat_fluid__ml_p_d.value / f.weight_kg.value)
    //    / 1000
    
    var delta = ca_phos_sum - ca_phos_max;
    if (delta * 1 == 0) { // difference too small to correct for, let it be
        return;
    } // else reduce the values proprotionately to correct the problem:
    set_calcium("meq_p_kg_p_day",
        f.calcium__meq_p_kg_p_day.value
        - (delta * (f.calcium__meq_p_kg_p_day.value / ca_phos_sum))
    );
    set_phosphate("mmol_p_kg_p_day",
        f.phosphate__mmol_p_kg_p_day.value
        - (delta * (f.phosphate__mmol_p_kg_p_day.value / ca_phos_sum))
    );
    if (!silent) {
        alert(" This is the message...Calcium/Phosphate precipitate likely. Values reduced proportionately.");
    }
}
function calc_group_5_init() {
    var f = document.tpncalc;
    // first phosphate (because it affects sodium)
    set_phosphate("mmol_p_l", c_initial_phos_mmol_p_l());
    // then the electrolytes:
    var units = "meq_p_kg_p_day";

    if (f.weight_kg.value < .75) {
        set_desired_sodium(units, 1);
        set_desired_potassium(units, 1);
        set_desired_acetate(units, 6);
        set_phosphate("mmol_p_l", 12);
    }
    if (f.weight_kg.value >= .75 && f.weight_kg.value * 1 < 1.25) {
        set_desired_sodium(units, 2);
        set_desired_potassium(units, 1);
        set_desired_acetate(units, 6);
        set_phosphate("mmol_p_l", 12);
    }
    if (f.weight_kg.value >= 1.25 && f.weight_kg.value * 1 < 2) {
        set_desired_sodium(units, 2);
        set_desired_potassium(units, 2);
        set_desired_acetate(units, 4);
        set_phosphate("mmol_p_l", 10);
    }
    if (f.weight_kg.value >= 2 && f.weight_kg.value * 1 < 3) {
        set_desired_sodium(units, 2);
        set_desired_potassium(units, 2);
        set_desired_acetate(units, 3);
        set_phosphate("mmol_p_l", 10);
    }
    if (f.age_yrs.value * 1 < c_first_growth_related_age_max_for_ree_in_years() * 1 && f.weight_kg.value >= 3 && f.weight_kg.value * 1 < 10) {
        set_desired_sodium(units, c_younger_default_cations__meq_p_kg_p_day());
        set_desired_potassium(units, c_younger_default_cations__meq_p_kg_p_day());
        set_desired_acetate(units, c_younger_default_acetate__meq_p_kg_p_day());
    }
    else if (f.age_yrs.value * 1 >= c_first_growth_related_age_max_for_ree_in_years() * 1 && f.weight_kg.value >= 3 && f.weight_kg.value * 1 < 10) {
        set_desired_sodium(units, c_older_default_cations__meq_p_kg_p_day());
        set_desired_potassium(units, c_older_default_cations__meq_p_kg_p_day());
        set_desired_acetate(units, c_older_default_acetate__meq_p_kg_p_day());
    }
    else if (f.age_yrs.value * 1 < c_first_growth_related_age_max_for_ree_in_years() * 1  && f.weight_kg.value * 1 > 10) {
        set_desired_sodium(units, c_younger_default_cations__meq_p_kg_p_day());
        set_desired_potassium(units, c_younger_default_cations__meq_p_kg_p_day());
        set_desired_acetate(units, c_younger_default_acetate__meq_p_kg_p_day());
    }
    else if (f.age_yrs.value * 1 >= c_first_growth_related_age_max_for_ree_in_years() * 1 && f.weight_kg.value * 1 > 10) {
        set_desired_sodium(units, c_older_default_cations__meq_p_kg_p_day());
        set_desired_potassium(units, c_older_default_cations__meq_p_kg_p_day());
        set_desired_acetate(units, c_older_default_acetate__meq_p_kg_p_day());
    }
    /* *KL this block is being replaced
    
    if (
    document.tpncalc.age_yrs.value*1
    <=
    c_first_growth_related_age_max_for_ree_in_years()*1
    ) {
    set_desired_sodium(    units, c_younger_default_cations__meq_p_kg_p_day() );
    set_desired_potassium( units, c_younger_default_cations__meq_p_kg_p_day() );
    set_desired_acetate(   units, c_younger_default_acetate__meq_p_kg_p_day() );
    } else { // age_yrs is > than c_first_growth_related_age_max_for_ree_in_years()
    set_desired_sodium(    units, c_older_default_cations__meq_p_kg_p_day()   );
    set_desired_potassium( units, c_older_default_cations__meq_p_kg_p_day()   );
    set_desired_acetate(   units, c_older_default_acetate__meq_p_kg_p_day()   );
    }
    end of replaced block */

    determine_initial_electrolyte_inheritance();
    derive_four_main_salts_values_in_meq_p_l("silent");
    sum_inheritance_and_salts();
    var precision = c_salt_precision();
    // Now translate potassium infusion limit (mEq/kg/hour) into more handy units.
    // Later, user changes will be checked against these limits.
    f.potassium_limit__meq_p_kg_p_day.value = (
        c_max_potassium_meq_p_kg_p_h() * f.infusion_duration_value_h.value
    );
    per_kg_per_day__to__per_liter(
        f.potassium_limit__meq_p_kg_p_day,
        f.potassium_limit__meq_p_l,
        precision, precision
    );
    // finally, initialize the minerals:
    // first desired magnesium...
    f.magnesium__meq_p_l.value = round_n_to_x_decimals(
        f.weight_kg.value * .5 * 1000 / f.nonfat_fluid__ml_p_d.value
    );
    // then desired calcium (varies with age)
    if (f.age_yrs.value * 1 < 1){ // KL changed per requirements //  c_first_growth_related_age_max_for_ree_in_years() * 1) {
        if (f.weight_kg.value < .75)
        { f.calcium__meq_p_l.value = 20; }
        if (f.weight_kg.value >= .75 && f.weight_kg.value * 1 < 1.25)
        { f.calcium__meq_p_l.value = 20; }
        if (f.weight_kg.value >= 1.25 && f.weight_kg.value * 1 < 2)
        { f.calcium__meq_p_l.value = 20; }
        if (f.weight_kg.value >= 2 && f.weight_kg.value * 1 <= 3)
        { f.calcium__meq_p_l.value = 20; }
        if (f.weight_kg.value > 3)
        { f.calcium__meq_p_l.value = 10; }  // KL changed per Chris McPherson
    }
    else if (f.age_yrs.value * 1 < c_first_growth_related_age_max_for_ree_in_years() * 1) {
    // KL commented per requirements  //  else if (f.age_yrs.value * 1 > c_first_growth_related_age_max_for_ree_in_years() * 1) {
        // same as magnesium
        f.calcium__meq_p_l.value = f.magnesium__meq_p_l.value;
    } else { // age_yrs <= c_first_growth_related_age_max_for_ree_in_years()
        // twice magnesium (1 mEq/L instead of .5 mEq/L)
        f.calcium__meq_p_l.value = 2 * f.magnesium__meq_p_l.value;
    }
    // ensure that desired amounts are within limits:
    if (f.magnesium__meq_p_l.value * 1 > c_max_magnesium_meq_p_l() * 1) {
        f.magnesium__meq_p_l.value = c_max_magnesium_meq_p_l();
    }
    if (f.calcium__meq_p_l.value * 1 > c_max_calcium_meq_p_l() * 1) {
        f.calcium__meq_p_l.value = c_max_calcium_meq_p_l();
    }
    // set them both (copies them into other units column)
    set_magnesium("meq_p_l", f.magnesium__meq_p_l.value);
    set_calcium("meq_p_l", f.calcium__meq_p_l.value);
    check_for_caphos_precip("silent");
    // initialization done, run the group:
    calc_group_5_run();
}
function determine_initial_electrolyte_inheritance() {
    var f = document.tpncalc;
    // amino acids include acetate and chloride, phosphate is added with sodium.
    // We need to consider these electrolytes part of our total electrolytes.
    var precision = c_salt_precision();
    // first determine acetate from amino acids
    f.initl_acetate_from_aminoacids__meq_p_l.value = (
        f.aminoacids_percent.value
        * c_acetate_meq_p_l__given_per__aminoacid_percent()
    );
    per_liter__to__per_kg_per_day(
        f.initl_acetate_from_aminoacids__meq_p_l,
        f.initl_acetate_from_aminoacids__meq_p_kg_p_day,
        precision, precision
    );
    // then determine chloride from amino acids
    // this varies depending on the specific amino acid solution used:
    var chloride_meq_p_l__given_per__aminoacid_percent;
    if (f.age_yrs.value * 1 > c_max_years_for_which_trophamine_used_for_aminoacid() * 1) {
        chloride_meq_p_l__given_per__aminoacid_percent
            = c_chloride_meq_p_l__given_per__travasol_percent();
    } else { // child is young enough to get trophamine instead of travasol
        chloride_meq_p_l__given_per__aminoacid_percent
            = c_chloride_meq_p_l__given_per__trophamine_percent();
    }
    f.initl_chloride_from_aminoacids__meq_p_l.value = (
        f.aminoacids_percent.value
        * chloride_meq_p_l__given_per__aminoacid_percent
    );
    per_liter__to__per_kg_per_day(
        f.initl_chloride_from_aminoacids__meq_p_l,
        f.initl_chloride_from_aminoacids__meq_p_kg_p_day,
        precision, precision
    );
    // and then sodium from phophate
    f.initl_sodium_from_phosphate__meq_p_l.value
        = sodium_from_phosphate(f.phosphate__mmol_p_l.value);
    per_liter__to__per_kg_per_day(
        f.initl_sodium_from_phosphate__meq_p_l,
        f.initl_sodium_from_phosphate__meq_p_kg_p_day,
        precision, precision
    );
}
function sodium_from_phosphate(phosphate__mmol_p_l) { // return value is in mEq/L
    return (phosphate__mmol_p_l * c_sodium_meq__given_per__mmol_phos());
}
function potassium_infusion__meq_p_kg_p_h__from(potassium_amount, units) {
    var f = document.tpncalc;
    // given some amount of potassium in either mEq/Liter or mEq/kg/day
    // figure out how much potassium would be delivered in mEq/kg/hour
    var infusion_result = potassium_amount;
    if (units == "meq_p_l") { // change it to "meq_p_kg_p_day"
        infusion_result
            = infusion_result * f.nonfat_fluid__ml_p_d.value / 1000 / f.weight_kg.value;
    } // else units == "meq_p_kg_p_day" to start with... no translation was required
    // change that into meq_p_kg_p_h value...
    infusion_result = infusion_result / f.infusion_duration_value_h.value;
    return round_n_to_x_decimals(infusion_result, c_salt_precision());
}
function sum_inheritance_and_salts() {
    var f = document.tpncalc;
    // called after inherited electrolytes (from aminos and phosphate) have been determined,
    // and salt values have been determined or changed. Totals them up for physician to see.
    f.sodium__meq_p_l.value = Math.round(
        f.initl_sodium_from_phosphate__meq_p_l.value * 1
         + f.sodium_acetate__meq_p_l.value * 1
         + f.sodium_chloride__meq_p_l.value * 1
    );
    f.bak_sodium__meq_p_l.value = f.sodium__meq_p_l.value;
    f.sodium__meq_p_kg_p_day.value = round_n_to_x_decimals(
        (f.initl_sodium_from_phosphate__meq_p_kg_p_day.value * 1
            + f.sodium_acetate__meq_p_kg_p_day.value * 1
            + f.sodium_chloride__meq_p_kg_p_day.value * 1
        ), 1
    );
    f.bak_sodium__meq_p_kg_p_day.value = f.sodium__meq_p_kg_p_day.value;
    f.potassium__meq_p_l.value = Math.round(
        f.potassium_acetate__meq_p_l.value * 1
         + f.potassium_chloride__meq_p_l.value * 1
    );
    f.bak_potassium__meq_p_l.value = f.potassium__meq_p_l.value;
    f.potassium__meq_p_kg_p_day.value = round_n_to_x_decimals(
        (f.potassium_acetate__meq_p_kg_p_day.value * 1
            + f.potassium_chloride__meq_p_kg_p_day.value * 1
        ), 1
    );
    f.bak_potassium__meq_p_kg_p_day.value = f.potassium__meq_p_kg_p_day.value;
    // we also slip in the following for use in error checking and debugging:
    f.potassium__meq_p_kg_h.value = potassium_infusion__meq_p_kg_p_h__from(
        f.bak_potassium__meq_p_kg_p_day.value, "meq_p_kg_p_day"
    );
    f.acetate__meq_p_l.value = Math.round(
        f.initl_acetate_from_aminoacids__meq_p_l.value * 1
         + f.sodium_acetate__meq_p_l.value * 1
         + f.potassium_acetate__meq_p_l.value * 1
    );
    f.bak_acetate__meq_p_l.value = f.acetate__meq_p_l.value;
    f.acetate__meq_p_kg_p_day.value = round_n_to_x_decimals(
        (f.initl_acetate_from_aminoacids__meq_p_kg_p_day.value * 1
            + f.sodium_acetate__meq_p_kg_p_day.value * 1
            + f.potassium_acetate__meq_p_kg_p_day.value * 1
        ), 1
    );
    f.bak_acetate__meq_p_kg_p_day.value = f.acetate__meq_p_kg_p_day.value;
    f.chloride__meq_p_l.value = Math.round(
        f.initl_chloride_from_aminoacids__meq_p_l.value * 1
         + f.sodium_chloride__meq_p_l.value * 1
         + f.potassium_chloride__meq_p_l.value * 1
    );
    f.bak_chloride__meq_p_l.value = f.chloride__meq_p_l.value;
    f.chloride__meq_p_kg_p_day.value = round_n_to_x_decimals(
        (f.initl_chloride_from_aminoacids__meq_p_kg_p_day.value * 1
            + f.sodium_chloride__meq_p_kg_p_day.value * 1
            + f.potassium_chloride__meq_p_kg_p_day.value * 1
        ), 1
    );
    f.bak_chloride__meq_p_kg_p_day.value = f.chloride__meq_p_kg_p_day.value;
}
function derive_four_main_salts_values_in_meq_p_l(silent) {
    var f = document.tpncalc;
    // determine how much of which salts to add to make up the difference between
    // our desired electrolytes and our electrolytes inherited from aminos and phosphate
    clear_salts(); // start with a clean slate (if didn't already have one)
    var units = "meq_p_l";
    var old_desired_acetate__meq_p_l; // used later in a couple of places...
    if (
        f.initl_sodium_from_phosphate__meq_p_l.value * 1
        >
        f.desired_sodium__meq_p_l.value * 1
    ) {
        // we've already exceeded our desired sodium: increase desired
        var old_desired_sodium__meq_p_l = f.desired_sodium__meq_p_l.value;
        set_desired_sodium(units, f.initl_sodium_from_phosphate__meq_p_l.value);
        if (!silent) {
            alert(
                "Sodium from phosphate exceeds your desired "
                + old_desired_sodium__meq_p_l + " mEq/L of sodium."
                + " You will have to decrease phosphate before lowering sodium."
            );
        }
    }
    if (
        f.initl_acetate_from_aminoacids__meq_p_l.value
        >
        f.desired_acetate__meq_p_l.value
    ) {
        // we've already exceeded our desired acetate: increase desired
        old_desired_acetate__meq_p_l = f.desired_acetate__meq_p_l.value;
        set_desired_acetate(units, f.initl_acetate_from_aminoacids__meq_p_l.value);
        if (!silent) {
            alert(
                "Acetate from amino acids exceeds your desired "
                + old_desired_acetate__meq_p_l + " mEq/L of acetate."
                + " You will have to decrease amino acids to lower acetate."
            );
        }
    }
    var sodium_acetate__meq_p_l = 0;
    var sodium_chloride__meq_p_l = 0;
    var potassium_acetate__meq_p_l = 0;
    var potassium_chloride__meq_p_l = 0;
    var missing_sodium__meq_p_l = round_n_to_x_decimals(
        (f.desired_sodium__meq_p_l.value
            -
            f.initl_sodium_from_phosphate__meq_p_l.value
        ), 1
    );
    var missing_acetate__meq_p_l = round_n_to_x_decimals(
        (f.desired_acetate__meq_p_l.value
            -
            f.initl_acetate_from_aminoacids__meq_p_l.value
        ), 1
    );
    var missing_potassium__meq_p_l = f.desired_potassium__meq_p_l.value;
    if (missing_sodium__meq_p_l * 1 > 0) {
        // add sodium
        // sodium must be added as sodium acetate or sodium chloride
        if (missing_acetate__meq_p_l * 1 > 0) {
            // add sodium acetate
            if (missing_acetate__meq_p_l * 1 >= missing_sodium__meq_p_l * 1) {
                // add all of it as sodium acetate
                missing_acetate__meq_p_l = round_n_to_x_decimals(
                    (missing_acetate__meq_p_l - missing_sodium__meq_p_l), 1
                );
                sodium_acetate__meq_p_l = missing_sodium__meq_p_l;
                missing_sodium__meq_p_l = 0;
            } else { // not enough missing acetate to do it all as sodium acetate
                // add some as sodium acetate, rest as sodium chloride
                sodium_acetate__meq_p_l = missing_acetate__meq_p_l;
                sodium_chloride__meq_p_l = round_n_to_x_decimals(
                    (missing_sodium__meq_p_l - missing_acetate__meq_p_l), 1
                );
                missing_acetate__meq_p_l = 0;
                missing_sodium__meq_p_l = 0;
            }
        } else { // not missing any acetate
            // add sodium chloride
            sodium_chloride__meq_p_l = missing_sodium__meq_p_l;
            missing_sodium__meq_p_l = 0;
        }
    }
    if (missing_potassium__meq_p_l * 1 > 0) {
        // add potassium
        // potassium must be added as potassium acetate or postassium chloride
        if (missing_acetate__meq_p_l * 1 > 0) {
            // add potassium acetate
            if (missing_acetate__meq_p_l * 1 >= missing_potassium__meq_p_l * 1) {
                // add all of it as potassium acetate
                missing_acetate__meq_p_l = round_n_to_x_decimals(
                    (missing_acetate__meq_p_l - missing_potassium__meq_p_l), 1
                );
                potassium_acetate__meq_p_l = missing_potassium__meq_p_l;
                missing_potassium__meq_p_l = 0;
            } else { // not missing enough aceteate to do it all as potassium acetate
                // add some as potassium acetate, rest as potassium chloride
                potassium_acetate__meq_p_l = missing_acetate__meq_p_l;
                potassium_chloride__meq_p_l = round_n_to_x_decimals(
                    (missing_potassium__meq_p_l - missing_acetate__meq_p_l), 1
                );
                missing_acetate__meq_p_l = 0;
                missing_potassium__meq_p_l = 0;
            }
        } else { // not missing any acetate
            // add potassium chloride
            potassium_chloride__meq_p_l = missing_potassium__meq_p_l;
            missing_potassium__meq_p_l = 0;
        }
    }
    if (missing_acetate__meq_p_l * 1 > 0) {
        old_desired_acetate__meq_p_l
            = f.desired_acetate__meq_p_l.value;
        set_desired_acetate(units,
            f.desired_acetate__meq_p_l.value
            - missing_acetate__meq_p_l
        );
        if (!silent) {
            alert(
                "Acetate levels fell " + missing_acetate__meq_p_l + " mEq/L short of desired "
                + old_desired_acetate__meq_p_l + " mEq/L level."
                + " You will have to increase amino acids,"
                + " sodium, or potassium in order to increase acetate."
            );
        }
        missing_acetate__meq_p_l = 0;
    }
    set_sodium_acetate("meq_p_l", sodium_acetate__meq_p_l);
    set_sodium_chloride("meq_p_l", sodium_chloride__meq_p_l);
    set_potassium_acetate("meq_p_l", potassium_acetate__meq_p_l);
    set_potassium_chloride("meq_p_l", potassium_chloride__meq_p_l);
}
function derive_four_main_salts_values_in_meq_p_kg_p_day(silent) {
    var f = document.tpncalc;
    // determine how much of which salts to add to make up the difference between
    // our desired electrolytes and our electrolytes inherited from aminos and phosphate
    clear_salts();
    var units = "meq_p_kg_p_day";
    var old_desired_acetate__meq_p_kg_p_day; // used later in a couple of places...
    if (
        f.initl_sodium_from_phosphate__meq_p_kg_p_day.value * 1
        >
        f.desired_sodium__meq_p_kg_p_day.value * 1
    ) {
        // we've already exceeded our desired sodium: increase desired
        var old_desired_sodium__meq_p_kg_p_day = f.desired_sodium__meq_p_kg_p_day.value;
        set_desired_sodium(units, f.initl_sodium_from_phosphate__meq_p_kg_p_day.value);
        if (!silent) {
            alert(
                "Sodium from phosphate exceed your desired "
                + old_desired_sodium__meq_p_kg_p_day + " mEq/kg/day of sodium."
                + " You will have to decrease phosphate before lowering sodium."
            );
        }
    }
    if (
        f.initl_acetate_from_aminoacids__meq_p_kg_p_day.value * 1
        >
        f.desired_acetate__meq_p_kg_p_day.value * 1
    ) {
        // we've already exceeded our desired acetate: increase desired
        old_desired_acetate__meq_p_kg_p_day = f.desired_acetate__meq_p_kg_p_day.value;
        set_desired_acetate(units, f.initl_acetate_from_aminoacids__meq_p_kg_p_day.value);
        if (!silent) {
            alert(
                "Acetate from amino acids exceed your desired "
                + old_desired_acetate__meq_p_kg_p_day + " mEq/kg/day of acetate."
                + " You will have to decrease amino acids to lower acetate."
            );
        }
    }
    var sodium_acetate__meq_p_kg_p_day = 0;
    var sodium_chloride__meq_p_kg_p_day = 0;
    var potassium_acetate__meq_p_kg_p_day = 0;
    var potassium_chloride__meq_p_kg_p_day = 0;
    var missing_sodium__meq_p_kg_p_day = round_n_to_x_decimals(
        (f.desired_sodium__meq_p_kg_p_day.value
            -
            f.initl_sodium_from_phosphate__meq_p_kg_p_day.value
        ), 1
    );
    var missing_acetate__meq_p_kg_p_day = round_n_to_x_decimals(
        (f.desired_acetate__meq_p_kg_p_day.value
            -
            f.initl_acetate_from_aminoacids__meq_p_kg_p_day.value
        ), 1
    );
    var missing_potassium__meq_p_kg_p_day = f.desired_potassium__meq_p_kg_p_day.value;
    if (missing_sodium__meq_p_kg_p_day * 1 > 0) {
        // add sodium
        // sodium must be added as sodium acetate or sodium chloride
        if (missing_acetate__meq_p_kg_p_day * 1 > 0) {
            // add sodium acetate
            if (missing_acetate__meq_p_kg_p_day * 1 >= missing_sodium__meq_p_kg_p_day * 1) {
                // add all of it as sodium acetate
                missing_acetate__meq_p_kg_p_day = round_n_to_x_decimals(
                    (missing_acetate__meq_p_kg_p_day - missing_sodium__meq_p_kg_p_day), 1
                );
                sodium_acetate__meq_p_kg_p_day = missing_sodium__meq_p_kg_p_day;
                missing_sodium__meq_p_kg_p_day = 0;
            } else { // not enough missing acetate to do it all as sodium acetate
                // add some as sodium acetate, rest as sodium chloride
                sodium_acetate__meq_p_kg_p_day = missing_acetate__meq_p_kg_p_day;
                sodium_chloride__meq_p_kg_p_day = round_n_to_x_decimals(
                    (missing_sodium__meq_p_kg_p_day - missing_acetate__meq_p_kg_p_day), 1
                );
                missing_acetate__meq_p_kg_p_day = 0;
                missing_sodium__meq_p_kg_p_day = 0;
            }
        } else { // not missing any acetate
            // add sodium chloride
            sodium_chloride__meq_p_kg_p_day = missing_sodium__meq_p_kg_p_day;
            missing_sodium__meq_p_kg_p_day = 0;
        }
    }
    if (missing_potassium__meq_p_kg_p_day * 1 > 0) {
        // add potassium
        // potassium must be added as potassium acetate or potassium chloride
        if (missing_acetate__meq_p_kg_p_day * 1 > 0) {
            // add potassium acetate
            if (missing_acetate__meq_p_kg_p_day * 1 >= missing_potassium__meq_p_kg_p_day * 1) {
                // add all of it as potassium acetate
                missing_acetate__meq_p_kg_p_day = round_n_to_x_decimals(
                    (missing_acetate__meq_p_kg_p_day - missing_potassium__meq_p_kg_p_day), 1
                );
                potassium_acetate__meq_p_kg_p_day = missing_potassium__meq_p_kg_p_day;
                missing_potassium__meq_p_kg_p_day = 0;
            } else { // not enough missing acetate to do it all as potassium acetate
                // add some as potassium acetate, rest as potassium chloride
                potassium_acetate__meq_p_kg_p_day = missing_acetate__meq_p_kg_p_day;
                potassium_chloride__meq_p_kg_p_day = round_n_to_x_decimals(
                    (missing_potassium__meq_p_kg_p_day - missing_acetate__meq_p_kg_p_day), 1
                );
                missing_acetate__meq_p_kg_p_day = 0;
                missing_potassium__meq_p_kg_p_day = 0;
            }
        } else { // not missing any acetate
            // add potassium chloride
            potassium_chloride__meq_p_kg_p_day = missing_potassium__meq_p_kg_p_day;
            missing_potassium__meq_p_kg_p_day = 0;
        }
    }
    if (missing_acetate__meq_p_kg_p_day * 1 > 0) {
        old_desired_acetate__meq_p_kg_p_day
            = f.desired_acetate__meq_p_kg_p_day.value;
        set_desired_acetate(units,
            f.desired_acetate__meq_p_kg_p_day.value
            - missing_acetate__meq_p_kg_p_day
        );
        if (!silent) {
            alert(
                "Acetate levels fell " + missing_acetate__meq_p_kg_p_day + " mEq/kg/day short of desired "
                + old_desired_acetate__meq_p_kg_p_day + " mEq/kg/day level."
                + " You will have to increase amino acids,"
                + " sodium, or potassium in order to increase acetate."
            );
        }
        missing_acetate__meq_p_kg_p_day = 0;
    }
    set_sodium_acetate("meq_p_kg_p_day", sodium_acetate__meq_p_kg_p_day);
    set_sodium_chloride("meq_p_kg_p_day", sodium_chloride__meq_p_kg_p_day);
    set_potassium_acetate("meq_p_kg_p_day", potassium_acetate__meq_p_kg_p_day);
    set_potassium_chloride("meq_p_kg_p_day", potassium_chloride__meq_p_kg_p_day);
}
function clear_salts() {
    var f = document.tpncalc;
    f.sodium_acetate__meq_p_l.value = "";
    f.sodium_acetate__meq_p_kg_p_day.value = "";
    f.sodium_chloride__meq_p_l.value = "";
    f.sodium_chloride__meq_p_kg_p_day.value = "";
    f.potassium_acetate__meq_p_l.value = "";
    f.potassium_acetate__meq_p_kg_p_day.value = "";
    f.potassium_chloride__meq_p_l.value = "";
    f.potassium_chloride__meq_p_kg_p_day.value = "";
}
function increase_acetate_from_chloride_shift(cation, units, delta) {
    var f = document.tpncalc;
    /*
    This function is called when acetate was modified in order to
    meed the user's requested change to sodium or potassium. We
    would prefer it if their change left acetate untouched, so we
    try to shift the change from acetate into chloride instead
    (because in most cases, chloride is less nutritionally significant).
        
    So, suppose they dropped potassium to zero. Some earlier code
    dealt with that by removing all of the Potassium Chloride first,
    because chloride is less important than acetate. However, we still
    had some potassium from Potassium Acetate, so we had to remove all
    of that too. ...but that changed our acetate total.
        
    So, that code calls this function to fix things. In this example,
    we haven't specified units, so lets pretend that we're working in
    mEq/L and that acetate had been reduced by 1 mEq/L. This function
    would be called as
    increase_acetate_from_chloride_shift( "sodium", "meq_p_l", 1 )
    meaning "Please try to move one mEq/L of sodium from Sodium Chloride
    to Sodium Acetate so that our acetate total will be restored, and
    all of the change will thereby be moved into Chloride."
        
    This function tries to do that, and returns a value indicating how
    much it failed to restore. So, if there wasn't 1 mEq available to
    move, but there was .7 mEq available, it would move the .7mEq, and
    return .3 so that the calling code would know to alert the user of
    the final change in acetate of .3 mEq/L. We always hope we can
    return 0 which means none of the request was left unfufilled.
    */
    if (delta * 1 == 0) return 0; // there's nothing for us to do here
    // Abtract from units and cation... start by assuming "sodium" and "meq_p_l"
    var chloride = f.sodium_chloride__meq_p_l;
    var acetate = f.sodium_acetate__meq_p_l;
    if (units == "meq_p_kg_p_day") {
        if (cation == "sodium") {
            chloride = f.sodium_chloride__meq_p_kg_p_day;
            acetate = f.sodium_acetate__meq_p_kg_p_day;
        } else { // cation == "potassium"
            chloride = f.potassium_chloride__meq_p_kg_p_day;
            acetate = f.potassium_acetate__meq_p_kg_p_day;
        }
    } else if (cation == "potassium") {
        chloride = f.potassium_chloride__meq_p_l;
        acetate = f.potassium_acetate__meq_p_l;
    }
    var difference = 0; // restore everything if we can
    if (delta * 1 > chloride.value * 1) {
        // restore what we can, return the difference
        difference = delta - chloride.value;
        delta = chloride.value; // we'll only remove what's there
    }
    if (cation == "sodium") {
        set_sodium_chloride(units, (chloride.value - delta));
        set_sodium_acetate(units, (acetate.value * 1 + delta * 1));
    } else { // cation == "potassium"
        set_potassium_chloride(units, (chloride.value - delta));
        set_potassium_acetate(units, (acetate.value * 1 + delta * 1));
    }
    return difference;
}
function increase_chloride_from_acetate_shift(cation, units, delta) {
    var f = document.tpncalc;
    // see the above comments for increase_acetate_from_chloride_shift()
    // this function works the same way to do the opposite type of shift
    if (delta * 1 == 0) return 0; // there's nothing for us to do here
    // Abtract from units and cation... start by assuming "sodium" and "meq_p_l"
    var acetate = f.sodium_acetate__meq_p_l;
    var chloride = f.sodium_chloride__meq_p_l;
    if (units == "meq_p_kg_p_day") {
        if (cation == "sodium") {
            acetate = f.sodium_acetate__meq_p_kg_p_day;
            chloride = f.sodium_chloride__meq_p_kg_p_day;
        } else { // cation == "potassium"
            acetate = f.potassium_acetate__meq_p_kg_p_day;
            chloride = f.potassium_chloride__meq_p_kg_p_day;
        }
    } else if (cation == "potassium") {
        acetate = f.potassium_acetate__meq_p_l;
        chloride = f.potassium_chloride__meq_p_l;
    }
    var difference = 0; // restore everything if we can
    if (delta * 1 > acetate.value * 1) {
        // restore what we can, return the difference
        difference = delta - acetate.value;
        delta = acetate.value; // we'll only remove what's there
    }
    if (cation == "sodium") {
        set_sodium_acetate(units, (acetate.value - delta));
        set_sodium_chloride(units, (chloride.value * 1 + delta * 1));
    } else { // cation == "potassium"
        set_potassium_acetate(units, (acetate.value - delta));
        set_potassium_chloride(units, (chloride.value * 1 + delta * 1));
    }
    return difference;
}
function calc_group_5_run() {
    var f = document.tpncalc;
    // we have passed the last reset button in the form,
    // so no verbose parameter will be required
    if (
            not_pos_num(f.aminoacids_percent.value)
            ||
            not_pos_num(f.dextrose_percent.value)
    ) {
        calc_group_5_clear();
        return;
    } // else, good data: pass on to the next batch...
    calc_group_6_clear();
}
function calc_group_5_clear() {
    var f = document.tpncalc;
    // clear sodium
    f.bak_sodium__meq_p_l.value = "";
    f.sodium__meq_p_l.value = "";
    f.bak_sodium__meq_p_kg_p_day.value = "";
    f.sodium__meq_p_kg_p_day.value = "";
    // clear potassium
    f.bak_potassium__meq_p_l.value = "";
    f.potassium__meq_p_l.value = "";
    f.bak_potassium__meq_p_kg_p_day.value = "";
    f.potassium__meq_p_kg_p_day.value = "";
    // clear chloride
    f.bak_chloride__meq_p_l.value = "";
    f.chloride__meq_p_l.value = "";
    f.bak_chloride__meq_p_kg_p_day.value = "";
    f.chloride__meq_p_kg_p_day.value = "";
    // clear acetate
    f.bak_acetate__meq_p_l.value = "";
    f.acetate__meq_p_l.value = "";
    f.bak_acetate__meq_p_kg_p_day.value = "";
    f.acetate__meq_p_kg_p_day.value = "";
    // clear calcium
    f.bak_calcium__meq_p_l.value = "";
    f.calcium__meq_p_l.value = "";
    f.bak_calcium__meq_p_kg_p_day.value = "";
    f.calcium__meq_p_kg_p_day.value = "";
    // clear magnesium
    f.bak_magnesium__meq_p_l.value = "";
    f.magnesium__meq_p_l.value = "";
    f.bak_magnesium__meq_p_kg_p_day.value = "";
    f.magnesium__meq_p_kg_p_day.value = "";
    // clear phosphate
    f.bak_phosphate__mmol_p_l.value = "";
    f.phosphate__mmol_p_l.value = "";
    f.bak_phosphate__mmol_p_kg_p_day.value = "";
    f.phosphate__mmol_p_kg_p_day.value = "";
    // cascade:
    calc_group_6_clear();
}
function calc_group_6_clear() {
    var f = document.tpncalc;
    f.sup_fluid_other.value = "";
    f.sup_fluid_i_rate.value = "";
    f.sup_fluid_i_duration.value = "";
    f.x__other_meds.value = " "; // darned bug in NN 4.79 ignores empty string
    f.sup_fluid_type[0].checked = true;
    f.sup_fluid_ir[0].checked = true;
    f.x__sup_fluid_r_source.selectedIndex = 0;
    f.x__sup_fluid_r_exchange.selectedIndex = 0;
    f.x__sup_fluid_r_freq.selectedIndex = 0;
    f.addcon_heparin.checked = false;
    f.addcon_heparin_qty.selectedIndex = 0;
    //f.addcon_famotidine.checked = false;  //**KL commented.  removing famotidine
    //f.addcon_famotidine_mg_p_kg_p_day.selectedIndex = 0;  //**KL commented.  removing famotidine
    f.x__vit_and_tm[0].checked = true;
}
function heparin_change(source) {
    var f = document.tpncalc;
    // if they change the heparin value, they probably want it checked too
    f.addcon_heparin.checked = true;
    if (not_pos_num(f.weight_kg.value)) {
        f.addcon_heparin.checked = false;
        return; // they shouldn't be here yet... just uncheck famotidine
    }
}


/*  KL commented out.  Removing Famotidine

function famotidine_change( source ) {  var f = document.tpncalc;
// may be called from menu or checkbox
if ( source == "menu" ) {
// they selected something in the menu... check box if it isn't
f.addcon_famotidine.checked = true;
} // else twe're called from checkbox not menu
if ( f.addcon_famotidine.checked == false ) {
return; // not checked, no need to verify value
} // else checked, so verify value
var famotidine_mg_p_kg_p_day = (
f.addcon_famotidine_mg_p_kg_p_day.options[
f.addcon_famotidine_mg_p_kg_p_day.selectedIndex
].value
);
if (    not_pos_num( f.weight_kg.value )
||
not_pos_num( famotidine_mg_p_kg_p_day )
) {
f.addcon_famotidine.checked = false;
return; // bad data... just uncheck famotidine
} // else reasonable data, see if it's in acceptable range
var f_per_day = famotidine_mg_p_kg_p_day * f.weight_kg.value;
var max_per_day = c_max_famotidine_mg_p_kg_p_day();
if ( f_per_day*1 > max_per_day*1 ) {
var max_per_kg_per_day = round_n_to_x_decimals( max_per_day / f.weight_kg.value, 2 );
f.addcon_famotidine.checked = false;
alert(
famotidine_mg_p_kg_p_day
+" mg/kg/day of famotindine for a child of "
+ f.weight_kg.value
+" kg will exceed the maximum of "
+ max_per_day
+" mg/day. Famotidine has been unchecked."
);
alert(            
"The usual maximum dose of famotidine is 40 mg/day.  "
+"If you wish that dose or higher, type the desired order "
+"under the Medications heading."
);
}
}
End Famotidine Block  */

function require_good_infusion_rate() {
    var f = document.tpncalc;
    // ensure that supplemental fluids are infused at a possible rate
    f.sup_fluid_i_rate.value = round_n_to_x_decimals(f.sup_fluid_i_rate.value, 1);
    if (not_pos_num(f.sup_fluid_i_rate.value)) {
        f.sup_fluid_i_rate.value = "";
    }
}
function require_good_infusion_duration() {
    var f = document.tpncalc;
    // ensure that supplemental fluids are infused for a possible number of hours
    f.sup_fluid_i_duration.value = Math.round(f.sup_fluid_i_duration.value);
    if (not_pos_num(f.sup_fluid_i_duration.value) || f.sup_fluid_i_duration.value > 24) {
        f.sup_fluid_i_duration.value = "";
    }
}
function get_order_sheet() {
    var f = document.tpncalc;
    /*
    this function checks for any remaining user input problems
    and if none are found, it opens a new window for an order sheet,
    and clears out the calculator in the existing window, for the
    next patient data...
    */
    f.provided_e__kcal_p_kg_day.value = Math.round(
        f.provided_e__kcal_p_day.value / f.weight_kg.value
    );
    // look for any inconsistancies not caught by other code...
    var alert_text = "";
    // Start with selection of supplemental fluid.
    if (not_pos_num(f.aminoacids_percent.value)
            ||
            not_pos_num(f.dextrose_percent.value)
    ) {
        return (
            "An order sheet can be generated once the above form is completed."
        );
    }
    if (
        f.sup_fluid_type[4].checked // user selected "other" as fluid
        &&
        !f.sup_fluid_other.value.length // where they type in the "other" fluid
    ) {
        alert_text = (
            "Please specify the supplemental fluid you wish to order. "
        );
    }
    if (
        !f.sup_fluid_type[0].checked // "none" isn't checked as fluid
        &&
        f.sup_fluid_ir[1].checked // user selected "infuse" not replace
    ) {
        if (!f.sup_fluid_i_rate.value.length) {
            alert_text = (alert_text +
                "Please specify the supplemental fluid infusion rate. "
            );
        }
        if (!f.sup_fluid_i_duration.value.length) {
            alert_text = (alert_text +
                "Please specify the supplemental fluid infusion duration. "
            );
        }
    }
    /*
    in nine out of about 238 order sheet requests from MCIS, all of the
    visible fields are filled in, but the hidden fields are not. So, the
    order sheet script can't see an age_yrs value (because that's a hidden
    field, with a value derived from raw_age and age_type).
    (this 9/238 figure is circa 20011122, when this code was added)
    See if we can catch that problem at this point:
    */
    if (is_good_positive_number(f.raw_age.value)
            &&
            not_pos_num(f.age_yrs.value)
    ) {
        alert_text = (alert_text +
            "Your web browser failed to set the hidden fields. This bug"
            + " occurs occasionally in Netscape after using your 'back'"
            + " button. Netscape restores the visible field values, but not the"
            + " hidden ones. Please reload this page and begin again."
        );
    }
    // This function is called from a submit button.
    // if we return true, then the form will submit itself
    // if we return false, then the form will not submit itself
    if (alert_text.length) {
        alert(alert_text);
        return false; // because of whatever error we alerted the user about
    } else { // no alert
        document.tpncalc.submit();
        form_run();
        return false; // to avoid a second submission of the same form
    }
}
function draw_graph(file, window) {
    var f = document.tpncalc;
    // the "graph page" is now refered to as a "Progress Note" in the caculator GUI
    var g = document.graph; // shortcut to graph form
    // first ensure that all of the graph data will be available:
    // The graph will need an age string (code simmilar to perl order sheet script)
    var display_age = f.age_yrs.value;
    var display_unit = "year";
    // f.selected_age_type.value is either months or years
    if (f.age_yrs.value * 1 <= (11.5 / 12)) { // age won't round up to a year
        display_unit = "month";
        if (f.selected_age_type.value == "months") {
            // user entered months as months
            display_age = f.raw_age.value;
        } else { // f.selected_age_type.value == "years"
            // user entered months as fraction of a year
            display_age = display_age * 12 + .004;
            // ensure that .0833 years works out to be one month
        }
        // now ensure that we've got half-month increments, at least one half month
        display_age = Math.round(display_age * 2) / 2; // .5 month increments
        if (display_age * 1 == 0) {
            display_age = .5;
        }
        // do we need to worry about initial/terminal zeros?
        // or will the above not introduce any?
    } else { // age will round to at least one year
        if (display_age * 1 < 1) { // 11.9 months or something
            display_age = 1; // round up in this case
        }
        display_age = parseInt(display_age, 10);
        // truncate, not round: 4 years, 9 months is still "four years old"
    }
    if (display_age * 1 != 1) {
        display_unit = display_unit + "s";
    }
    // copy a bunch of stuff over for use by the graph page...
    g.estimated_tee__kcal_p_day.value = f.esttee__kcal_p_d.value;
    g.provided_e__kcal_p_day.value = f.provided_e__kcal_p_day.value;
    g.dextrose__kcal_p_day.value = f.dextrose__kcal_p_day.value;
    g.fat__kcal_p_day.value = f.fat__kcal_p_day.value;
    g.recmnded_aminoacids__g_p_kg_p_d.value = f.recmnded_aminoacids__g_p_kg_p_d.value;
    g.provided_aminoacids__g_p_kg_p_d.value = f.aminoacids__g_p_kg_p_day.value;
    g.weight_kg.value = f.weight_kg.value;
    g.height_cm.value = f.height_cm.value;
    g.surface_area__m2.value = f.surface_area_for_display__m2.value;
    g.age_string.value = display_age + " " + display_unit;
    g.non_prot_cal_p_grams_nitro.value = Math.round(
        (
            1 * f.dextrose__kcal_p_day.value
            +
            1 * f.fat__kcal_p_day.value
        ) / (
            f.aminoacids__g_p_kg_p_day.value
            * f.weight_kg.value
            / c_coeficient_for_nonprot_cal_p_grams_nitro_ratio()
        )
    );
    // alert if values not found, don't try to graph bad data:
    if (
        not_pos_num(g.estimated_tee__kcal_p_day.value)
        ||
        not_pos_num(g.provided_e__kcal_p_day.value)
        ||
        not_nonneg_num(g.dextrose__kcal_p_day.value)
        ||
        not_pos_num(g.fat__kcal_p_day.value)
        ||
        not_pos_num(g.recmnded_aminoacids__g_p_kg_p_d.value)
        ||
        not_pos_num(g.provided_aminoacids__g_p_kg_p_d.value)
    ) {
        alert(
            "Unable to graph data until calculator"
            + " fields have been set to valid values."
        );
        return;
    }
    // good data, graph it:
    graphWindow = open(progress_note_url(), "tpn_graph_window");
    if (graphWindow.opener == null) {
        graphWindow.opener = self;
    }
    graphWindow.focus();
}

function html_tpncalc_form_start_tag() {
    var version_info = "<input type='hidden' value='" + interface_version() + "' name='interface_version'>";
    var form_tag_etc = "onsubmit='get_order_sheet();' name='tpncalc' id='tpncalc' method='POST'";
    if (script_is_live()) { // call the live order sheet script
        return "<form action=form_run() " + form_tag_etc + ">" + version_info;
    } else { // dev calculator calls the dev order sheet script
        return "<form action=form_run() " + form_tag_etc + ">" + version_info;
    }
}
//function html_tpncalc_form_start_tag() {
//    var version_info = "<input type='hidden' value='"+interface_version()+"' name='interface_version'>";
//    var form_tag_etc = "onsubmit='get_order_sheet();return(false);' name='tpncalc' id='tpncalc' method='POST'";
//    if ( script_is_live() ) { // call the live order sheet script
//        return "<form action='form_run.js' +>";
//    } else { // dev calculator calls the dev order sheet script
//        return "<form action='form_run.js' + >";
//    }
//}


function html_tpncalc_form_debug_field() {
    if (script_is_live()) { // hide the debug field
        return "<input type='hidden' name='debug' value=''>";
    } else { // dev calculator shows debug field for developer use
        return ("\n"
            + "<strong>debug:</strong>&#160;"
            + "<input type='text' size='3' name='debug' value='' onchange='check_console_redirection()'> "
            + "<small>(this will not show in the live script)</small>"
            + "<p>"
            + "This is the <font color='#FF0000'>developemental version</font> of the tpn calculator. "
            + "The code behind this version is under active development. "
            + "</p>"
        );
    }
}

function html_tpncalc_form_hidden_electrolytes() {
    if (script_is_live()) { // salt stuff is hidden from view
        return ("\n"
            + "<input type='hidden' value='' name='initl_acetate_from_aminoacids__meq_p_l'>\n"
            + "<input type='hidden' value='' name='initl_acetate_from_aminoacids__meq_p_kg_p_day'>\n"
            + "<input type='hidden' value='' name='initl_chloride_from_aminoacids__meq_p_l'>\n"
            + "<input type='hidden' value='' name='initl_chloride_from_aminoacids__meq_p_kg_p_day'>\n"
            + "<input type='hidden' value='' name='initl_sodium_from_phosphate__meq_p_l'>\n"
            + "<input type='hidden' value='' name='initl_sodium_from_phosphate__meq_p_kg_p_day'>\n"
            + "<input type='hidden' value='' name='desired_sodium__meq_p_l'>\n"
            + "<input type='hidden' value='' name='desired_sodium__meq_p_kg_p_day'>\n"
            + "<input type='hidden' value='' name='desired_potassium__meq_p_l'>\n"
            + "<input type='hidden' value='' name='desired_potassium__meq_p_kg_p_day'>\n"
            + "<input type='hidden' value='' name='desired_acetate__meq_p_l'>\n"
            + "<input type='hidden' value='' name='desired_acetate__meq_p_kg_p_day'>\n"
            + "<input type='hidden' value='' name='sodium_acetate__meq_p_l'>\n"
            + "<input type='hidden' value='' name='sodium_acetate__meq_p_kg_p_day'>\n"
            + "<input type='hidden' value='' name='sodium_chloride__meq_p_l'>\n"
            + "<input type='hidden' value='' name='sodium_chloride__meq_p_kg_p_day'>\n"
            + "<input type='hidden' value='' name='potassium_acetate__meq_p_l'>\n"
            + "<input type='hidden' value='' name='potassium_acetate__meq_p_kg_p_day'>\n"
            + "<input type='hidden' value='' name='potassium_chloride__meq_p_l'>\n"
            + "<input type='hidden' value='' name='potassium_chloride__meq_p_kg_p_day'>\n"
            + "<input type='hidden' value='' name='potassium_limit__meq_p_l'>\n"
            + "<input type='hidden' value='' name='potassium_limit__meq_p_kg_p_day'>\n"
            + "<input type='hidden' value='' name='potassium__meq_p_kg_h'>\n"
        );
    } else { // dev calculator displays this stuff for debugging purposes
        return ("\n"
            + "<table border='0' cellpadding='2' cellspacing='0' align='left' bgcolor='#FFFFCC'>\n"
            + "    <tr bgcolor='#FFFFFF' valign='top'>\n"
            + "        <td bgcolor='#FFFFFF' colspan='5'>\n"
            + "            <hr noshade><br>\n"
            + "        </td>\n"
            + "    </tr><tr bgcolor='#FFFFCC' valign='top'>\n"
            + "        <td bgcolor='#FFFFCC' align='right'>\n"
            + "            <br><strong><big><big>Note:&#160;&#160;&#160;</big></big></strong>\n"
            + "        </td><td bgcolor='#FFCCCC' align='left' colspan='4'>\n"
            + "            The following group of fields are only here to help me see what is going on\n"
            + "            in the electrolytes section. These values will not be visible in the\n"
            + "            finished calculator (although some of these values will appear in the order\n"
            + "            sheet printed from the finished calculator).<br>\n"
            + "            <strong><font color='#FF0000'>Do not edit these values!</font></strong>\n"
            + "            If you edit them, your calculations will be all fouled up.\n"
            + "        </td>\n"
            + "    </tr><tr bgcolor='#FFFFCC' valign='middle'>\n"
            + "        <td bgcolor='#FFCCCC' align='left'>\n"
            + "            <strong>Initial Values:</strong>\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            &#160;\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            <small>mEq/L</small>\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            <small>mEq/kg/day</small>\n"
            + "        </td><td bgcolor='#FFFFCC' rowspan='13' align='left'>\n"
            + "            &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;\n"
            + "        </td>\n"
            + "    </tr><tr bgcolor='#FFFFCC' valign='middle'>\n"
            + "        <td bgcolor='#FFFFCC' align='right' colspan='2'>\n"
            + "            Acetate from Amino Acids\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            <input onFocus='this.blur()' type='text' size='5' name='initl_acetate_from_aminoacids__meq_p_l' value=''>\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            <input onFocus='this.blur()' type='text' size='5' name='initl_acetate_from_aminoacids__meq_p_kg_p_day' value=''>\n"
            + "        </td>\n"
            + "    </tr><tr bgcolor='#FFFFCC' valign='middle'>\n"
            + "        <td bgcolor='#FFFFCC' align='right' colspan='2'>\n"
            + "            Chloride from Amino Acids\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            <input onFocus='this.blur()' type='text' size='5' name='initl_chloride_from_aminoacids__meq_p_l' value=''>\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            <input onFocus='this.blur()' type='text' size='5' name='initl_chloride_from_aminoacids__meq_p_kg_p_day' value=''>\n"
            + "        </td>\n"
            + "    </tr><tr bgcolor='#FFFFCC' valign='middle'>\n"
            + "        <td bgcolor='#FFFFCC' align='right' colspan='2'>\n"
            + "            Sodium from Phosphate\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            <input onFocus='this.blur()' type='text' size='5' name='initl_sodium_from_phosphate__meq_p_l' value=''>\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            <input onFocus='this.blur()' type='text' size='5' name='initl_sodium_from_phosphate__meq_p_kg_p_day' value=''>\n"
            + "        </td>\n"
            + "    </tr><tr bgcolor='#FFFFCC' valign='middle'>\n"
            + "        <td bgcolor='#FFCCCC' align='left'>\n"
            + "            <strong>Desired Values:</strong>\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            &#160;\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            <small>mEq/L</small>\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            <small>mEq/kg/day</small>\n"
            + "        </td>\n"
            + "    </tr><tr bgcolor='#FFFFCC' valign='middle'>\n"
            + "        <td bgcolor='#FFFFCC' align='right' colspan='2'>\n"
            + "            Sodium\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            <input onFocus='this.blur()' type='text' size='5' name='desired_sodium__meq_p_l' value=''>\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            <input onFocus='this.blur()' type='text' size='5' name='desired_sodium__meq_p_kg_p_day' value=''>\n"
            + "        </td>\n"
            + "    </tr><tr bgcolor='#FFFFCC' valign='middle'>\n"
            + "        <td bgcolor='#FFFFCC' align='right' colspan='2'>\n"
            + "            Potassium\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            <input onFocus='this.blur()' type='text' size='5' name='desired_potassium__meq_p_l' value=''>\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            <input onFocus='this.blur()' type='text' size='5' name='desired_potassium__meq_p_kg_p_day' value=''>\n"
            + "        </td>\n"
            + "    </tr><tr bgcolor='#FFFFCC' valign='middle'>\n"
            + "        <td bgcolor='#FFFFCC' align='right' colspan='2'>\n"
            + "            Acetate\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            <input onFocus='this.blur()' type='text' size='5' name='desired_acetate__meq_p_l' value=''>\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            <input onFocus='this.blur()' type='text' size='5' name='desired_acetate__meq_p_kg_p_day' value=''>\n"
            + "        </td>\n"
            + "    </tr><tr bgcolor='#FFFFCC' valign='middle'>\n"
            + "        <td bgcolor='#FFCCCC' align='left'>\n"
            + "            <strong>Resulting Salts:</strong>\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            &#160;\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            <small>mEq/L</small>\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            <small>mEq/kg/day</small>\n"
            + "        </td>\n"
            + "    </tr><tr bgcolor='#FFFFCC' valign='middle'>\n"
            + "        <td bgcolor='#FFFFCC' align='right' colspan='2'>\n"
            + "            Sodium Acetate\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            <input onFocus='this.blur()' type='text' size='5' name='sodium_acetate__meq_p_l' value=''>\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            <input onFocus='this.blur()' type='text' size='5' name='sodium_acetate__meq_p_kg_p_day' value=''>\n"
            + "        </td>\n"
            + "    </tr><tr bgcolor='#FFFFCC' valign='middle'>\n"
            + "        <td bgcolor='#FFFFCC' align='right' colspan='2'>\n"
            + "            Sodium Chloride\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            <input onFocus='this.blur()' type='text' size='5' name='sodium_chloride__meq_p_l' value=''>\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            <input onFocus='this.blur()' type='text' size='5' name='sodium_chloride__meq_p_kg_p_day' value=''>\n"
            + "        </td>\n"
            + "    </tr><tr bgcolor='#FFFFCC' valign='middle'>\n"
            + "        <td bgcolor='#FFFFCC' align='right' colspan='2'>\n"
            + "            Potassium Acetate\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            <input onFocus='this.blur()' type='text' size='5' name='potassium_acetate__meq_p_l' value=''>\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            <input onFocus='this.blur()' type='text' size='5' name='potassium_acetate__meq_p_kg_p_day' value=''>\n"
            + "        </td>\n"
            + "    </tr><tr bgcolor='#FFFFCC' valign='middle'>\n"
            + "        <td bgcolor='#FFFFCC' align='right' colspan='2'>\n"
            + "            Potassium Chloride\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            <input onFocus='this.blur()' type='text' size='5' name='potassium_chloride__meq_p_l' value=''>\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            <input onFocus='this.blur()' type='text' size='5' name='potassium_chloride__meq_p_kg_p_day' value=''>\n"
            + "        </td>\n"
            + "    </tr><tr bgcolor='#FFFFCC' valign='middle'>\n"
            + "        <td bgcolor='#FFCCCC' align='left'>\n"
            + "            <strong>Potassium Infusion:</strong>\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            &#160;\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            <small>mEq/L</small>\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            <small>mEq/kg/day</small>\n"
            + "        </td><td bgcolor='#FFFFCC' align='left'>\n"
            + "            maximum value = " + c_max_potassium_meq_p_kg_p_h() + "<small> mEq/kg/hour</small>\n"
            + "        </td>\n"
            + "    </tr><tr bgcolor='#FFFFCC' valign='middle'>\n"
            + "        <td bgcolor='#FFFFCC' align='right' colspan='2'>\n"
            + "            Current Limits:\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            <input onFocus='this.blur()' type='text' size='5' name='potassium_limit__meq_p_l' value=''>\n"
            + "        </td><td bgcolor='#FFFFCC' align='center'>\n"
            + "            <input onFocus='this.blur()' type='text' size='5' name='potassium_limit__meq_p_kg_p_day' value=''>\n"
            + "        </td><td bgcolor='#FFFFCC' align='left'>\n"
            + "            current value = <input onFocus='this.blur()' type='text' size='5' value='' name='potassium__meq_p_kg_h'><small>mEq/kg/hour</small>\n"
            + "        </td>\n"
            + "    </tr>\n"
            + "</table><br clear='all'>\n"
        );
    }
}




// some code to assist in debugging
function errorHandler(e, f, l) {
    alert(
        "An error has ocurred in the JavaScript on this page."
        + "\nFile: " + f
        + "\nLine: " + l
        + "\nError:" + e
    );
    return false;
    // false means browser also does it's own error handling
    // true means that browser won't do it's own error handling
}
function check_console_redirection() {
    return; // fuction disabled for now
    if (debug()) {
        if (navigator.appName == "Netscape") window.onerror = errorHandler;
    } else {
        if (navigator.appName == "Netscape") window.onerror = null;
    }
}
function progress_note_url() {
    /*
    this function is called only from draw_graph() and *could* be
    in-lined there. However, it is convenient to have these URLs
    at the very end for debugging purposes. Normally, we only have
    two versions of the script: live and developmental. However,
    sometimes users need to test the developmental version, so I end
    up creating a second developmental version if I need to continue
    development while they do their testing. In those cases, I may
    want to change the second URL below to my second dev graph page
    rather than the normal dev graph page (if my development involves
    changes to the progress note). In those cases, it is very handy
    to have the URL at the end of the file where I can find it without
    looking very hard.
    */
    if (script_is_live()) { // use normal graph page
        return SITE_ROOT + "graph.html"
    } else { // dev calculator uses developmental graph page
        return SITE_ROOT + "graph.html";
    }
}


function campus() {
    var off_campus = 1;
    // local users are asked for Dr/Patient name, and get order sheet
    // off campus users aren't asked and get only an informational sheet
    var ip1 = 128.252;
    var ip2 = 159.251;
    var ip3 = 10.39;
    var ip4 = 10.34;

    var ip = 0 	//yourAddress2.getHostAddress();




    var ip_short = ip.substring(0, 6);
    ip_short = ip_short * 1;

    var ip_shorter = ip.substring(0, 5);
    ip_shorter = ip_shorter * 1;

    if ((ip_short == ip1 || ip_short == ip2) || (ip_shorter == ip3 || ip_shorter == ip4)) {
        off_campus = 0;
    };
    return off_campus;
}


function age_display_string() {
    var f = document.tpncalc;

    // kids 11.5 months or older should have ages of X years (integer value)
    // kids younger than 11.5 months should have ages of X months (integer value)
    // kids younger than .5 months should still be listed as one month old

    var display_age = f.age_yrs.value;
    var units = 'years';
    if (f.age_yrs.value <= 11.5 / 12) {
        units = 'months';

        if (f.age_type.value == 'months' &&
    	     f.raw_age.value != "" &&
    	     f.raw_age.value * 1 >= 1 &&
    	    (f.raw_age.value / 12 - f.age_yrs.value) <= .5 / 12) {  // max .5 months diff between the two

            display_age = f.raw_age.value;  // user entered months as months

        } else {
            // user entered months as fraction of year
            display_age = (display_age * 12);

        }

        if (display_age == 0) { display_age = '0.5'; }
        if (display_age == 1) { units = 'month'; }
    } else { // years...

        if (display_age < 1) { display_age = 1; } // 11.9 months or something
        if (display_age == 1) { units = 'year'; }

    }



    display_age = display_age + " " + units;

    return (display_age);
}

function amino_acid_comment2_string() {
    return 'includes acetate and';

}
function amino_acid_comment3_string() {
    return 'chloride.';

}

function linetype_string(line_type) {

    if (line_type == 'c') {
        return 'Central IV Line';
    }
    else {
        return 'Peripheral IV Line';
    }

}

function standard_constituent_string() {
    return ' ';
}

function amino_acid_string(age_yrs) {

    var age_in_yrs = age_yrs * 1;

    if (age_in_yrs > 1) {        //max_years_for_which_trophamine_used_for_aminoacid (*KL Changed from .25 to 1 on 9/15)
        return 'Travasol';
    } else {
    
        return 'Trophamine';
    }
}


function cysteine_calc(aminoacids_percent) {
    // % Trophamine x 0.04 = % Cysteine
   var cysteine_percent = aminoacids_percent * 0.04;
   return cysteine_percent;
}

function cysteine_print(aminoacids_percent, age_yrs) {
    var age_in_yrs = age_yrs * 1;
    
    if(age_in_yrs > 1){
	                return "&#160;";
	}
	else{           //+ "Cysteine is added by the Pharmacy at 40 mg L-cysteine per gram of " + amino_acid_string(age_yrs.value) + ". <br><br>" //KL remove
	                return "<tr valign='bottom'>"
	            + "                <td align='right'><small>Cysteine:</small></td>"
	            + "                <td align='right'><tt>" + cysteine_calc(aminoacids_percent) + "</tt></td>"
	            + "                <td align='left'><small>%</small></td>"
	            + "                <td align='right'><small>&#160;</small></td>"
	            + "                <td align='right'><tt>&#160;</tt></td>"
	            + "                <td align='left'><small>&#160;</small></td>"
	            + "            </tr>";
	               
	}
}

	           
function amino_acid_comment_string(age_yrs) {

    var age_in_yrs = age_yrs * 1;

    if (age_in_yrs > 1) {        //max_years_for_which_trophamine_used_for_aminoacid (*KL Changed from .25 to 1 on 9/15) 
        return 'Travasol solution';
    } else {
        return 'Trophamine solution';
    }
}

function vitamins_and_tma_string(vit_and_tm) {
    var f = document.tpncalc;
    var order1;
    var order;

    for (i = 0; i < f.x__vit_and_tm.length; i++) {
        if (f.x__vit_and_tm[i].checked) {
            vit_and_tm = f.x__vit_and_tm[i].value;
        }
    }

    if (vit_and_tm == 'contact') {
        return 'Physician will contact pharmacy with special requirements.';

    } // else
    // first add vitamins to the order
    if (f.age_yrs.value > 10) {
        order = 'MVI-Adult: 10 ml/day <br>';
    } else {
        var dose = 1.5; // assume weight <= 1.5 kg
        if (f.weight_kg.value > 1.5) {
            if (f.weight_kg.value >= 3) {
                dose = 5;
            } else { // between 1.5 and 3+
                dose = 3.25;
            }
        }
        order = 'MVI-Ped: ' + dose + ' ml/day<br>';
    }
    // then add trace metals to the order

    var trace_calc = (.2 * f.weight_kg.value);

    trace_calc = Math.round(trace_calc * 100) / 100


    if (f.weight_kg.value > 20) {
        order1 = 'Trace Metal Additive: 5 ml/day';
    } else if (f.weight_kg.value >= 3) {
        order1 = ('Pediatric Trace Element Mixture:' + trace_calc + ' ml/day');
    } else { // less than or equal to 3 kg
        order1 = ('Premature Trace Element Mixture: ' + trace_calc + 'ml/day');
    }



    order = order + order1

    return order;
}

function medications_string() {
    var meds = '';
    var f = document.tpncalc;
    var other = '';

    if (f.addcon_heparin.checked == true) {
        // add heparin
        meds = 'Heparin: ' + f.addcon_heparin_qty.value + ' units/L<br>';
    }

    /* *KL commented out to remove famotidine
    
    if (f.addcon_famotidine.checked == true) {
    //add famotidine addcon_famotidine_mg_p_kg_p_day
    meds += 'Famotidine: ' + f.addcon_famotidine_mg_p_kg_p_day.value + ' mg/kg/day<br>';
    }
    end of famotidine block */

    //Added Selenium 9/15/08 **KL**
    if (f.addcon_selenium.checked == true) {
        //add selenium for patients above 20kg
        if (f.weight_kg.value >= 20) {
        meds += 'Selenium: 40mcg/day<br> ';
        }
        if (f.weight_kg.value < 20) {
        meds += 'Selenium:  2 mcg/kg/day<br> ';
        }
        //add selenium addcon_selenium_2mcg/kg/day
        
        
    }
        // add others
        other = f.x__other_meds.value;

        other = other.replace(/\r/g, '<br>');
        //other = other.replace(/\n/g,'<br>');

        if (other != ' ' && other != '') {
            meds += '<u>Other Medications:</u><br>' + other;
        }

    

    return meds;
}
function supfluids_string() {
    var f = document.tpncalc;
    var sft = '';
    var src = '';
    var sf = '';
    var exc = '';
    var freq = '';

    if (f.sup_fluid_type[0].checked == true) { return ''; }

    if (f.sup_fluid_type[0].checked == false) {
        if (f.sup_fluid_type[1].checked == true) { sft = 'Lactated Ringers'; }
        if (f.sup_fluid_type[2].checked == true) { sft = '1/2 NS + 20 mEq KCl/L (NG Replacement)'; }
        if (f.sup_fluid_type[3].checked == true) { sft = '5% Albumin in Normal Saline'; }
        if (f.sup_fluid_type[4].checked == true) { sft = ''; }

        if (f.sup_fluid_type[4].checked == true) { sft += f.sup_fluid_other.value; }

        if (f.sup_fluid_ir[0].checked == true) {
            src = f.x__sup_fluid_r_source.value;
            exc = f.x__sup_fluid_r_exchange.value;
            freq = f.x__sup_fluid_r_freq.value;

            sf = 'Replace every 1 ml fluid from ' + src + ' with<br>' + exc + ' ml of ' + sft + ' every ' + freq + ' hours.';
        } else //
        {
            sf = 'Infuse ' + sft + ' at ' + f.sup_fluid_i_rate.value + ' ml/hr for ' + f.sup_fluid_i_duration.value + ' hours.';
        }
    }
    return sf;
}

function form_run() {

var time_stamp = new Date();


//var off_campus = campus()

var f = document.tpncalc;

var left_header = 'St. Louis Children\'s Hospital<br>Patient Order Sheet<br><big><strong>Parenteral Nutrition</strong></big><br>Permanent Medical Record<br><small><small>Order must be written by 1200 hours<br>and will be delivered to floor by 1600 hours.<br></small></small>';
                
var right_header = ("<br><small><small>Stamp for " + f.pat_name.value + " above</small></small>");
        
var auth_note = ("<small>"
                + "<small>"
                + "Authorization is hereby given to dispense the generic or chemical equivalent unless otherwise indicated by the words <b>No Substitute<b>. "
                + "<br><br>"
                + "</small>"
                + "</small>");

var doctor_name = "&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160" + f.doc_name.value;              

var footer = ("<table border='0' cellpadding='1' cellspacing='0' align='left'>"
		     + "  <tr valign='bottom'>"
                     + "       <td align='right'>"
                     + "           <big><strong>Ordered by</strong>:</big>"
                     + "       </td>"
                     + "       <td align='left'>"
                     + "           &#160;<small>" + doctor_name + ", M.D.</small>"
                     + "       </td>"
                     + "        <td align='right'>"
                     + "           &#160;<small>" + time_stamp + "</small>"
                     + "       </td>"
                     + "   </tr>"
                     + "   <tr valign='top'>"
                     + "       <td align='right'>"
                     + "           <br>M.D.:"
                     + "       </td>"
                     + "       <td align='left' colspan='2'>"
                     + "           <br>&#160;______________________________________________________ "
                     + "       </td>"
                     + "   </tr>"
                     + "   <tr valign='top'>"
                     + "       <td align='right'>"
                     + "           <br>Transcribed&#160;by:"
                     + "       </td>"
                     + "       <td align='left' colspan='2'>"
                     + "           <br>&#160;______________________________________________________ "
                     + "       </td>"
                     + "   </tr>"
                     + " </table>");

	var left_margin_footer = ("<small><small>"

                        + " Form&#160;#ECN0001<br>"
                        + " Revised:<br>"
                        + " &#160;&#160;&#160;2002&#160;Sep&#160;12<br>"
                        + " Tab:<br>"
                        + "    &#160;&#160;&#160;Order&#160;Sheets"
                    	+ "	</small></small>");
	
	document.write("<html>"
		+ "<head>"
		+ "<title></title><!-- intentionally blank: tidier printing in MCISs Netscape -->"
	    	+ "</head>"
	    	+ "<body link='#0000FF' vlink='#7700FF' alink='#FF0000' text='#000000' bgcolor='#FFFFFF'>"    	
	        + "<table border='0' cellpadding='0' cellspacing='1' width='100%' align='center'>"
	        + "<tr align='left'>"
	        + "<td rowspan='13' valign='bottom'>"
	        + left_margin_footer
	        + "</td>"
	        + "<td valign='top' align='left' colspan='3'>"
	    	+ "<table border='0' cellpadding='1' cellspacing='0' width='100%'>"
	        + "<tr align='center'>"
	        + "<td valign='top'>"
		+ left_header
		+ "</td>"
		+ "<td valign='bottom'>"
		+ right_header
		+ "</td>"
		+ "</tr>"
		+ "</table>"
		+ "</td>"
		+ "</tr>"
		+ "<tr align='left' valign='top'>"
		+ "<td colspan='3'>"
		+ "<table border='0' cellpadding='1' cellspacing='0' align='left'>"
		+ "<tr valign='top' align='left'>"
		+ "    <td>"
		+ "<small>"
		+ "<br>Age: " + age_display_string() + "&#160;&#160;"
		+ "Weight: " + f.weight_kg.value + "kg &#160;&#160;"
		+ "Height/Length: " + f.height_cm.value + "cm &#160;&#160;"
		+ "Surface Area: " + f.surface_area_for_display__m2.value + " m<sup>2</sup> &#160;&#160;"
		+ "Allergies: "
		+ "</small>"
		+ "</td>"
		+ "</tr>"
		+ "</table><br clear='all'><br>"
		+ "</td>"
		+ "</tr>"
		+ "<tr align='left' valign='top'>"
		+ "    <td colspan='3'>"
		
		+ "        <strong>Constituents</strong>:<br clear='all'>"
		
		+ "        <table border='0' cellpadding='0' cellspacing='1' align='left'>"
		+ "            <tr valign='bottom'>"
		+ "                <td rowspan='6'>&#160;&#160;&#160;&#160; </td>"
		+ "                <td align='right'><small>" + amino_acid_string(f.age_yrs.value) + ":</small></td>"
		+ "                <td rowspan='6'><small>&#160;</small></td>"
		+ "                <td align='right'><tt>" + f.aminoacids_percent.value + "</tt></td>"
		+ "                <td rowspan='6'><small>&#160;</small></td>"
		+ "                <td align='left'><small>%</small></td>"
		+ "                <td rowspan='6'>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</td>"
		+ "                <td align='right'><small>Calcium Gluconate:</small></td>"
		+ "                <td rowspan='6'><small>&#160;</small></td>"
		+ "                <td align='right'><tt>" + f.calcium__meq_p_l.value + "</tt></td>"
		+ "                <td rowspan='6'><small>&#160;</small></td>" 
		+ "                <td align='left'><small>mEq/L</small></td>"
		+ "                <td rowspan='6'><small>&#160;&#160;&#160;&#160;&#160;&#160;</small></td>"
		+ "                <td align='left' rowspan='5'>"
           	+ "                    <small><small>"
	        +  amino_acid_comment_string(f.age_yrs.value) + " <br> "
	           +  amino_acid_comment2_string() +" <br> "
	           +  amino_acid_comment3_string()
	           
	           + "<br><br>"
	           
	            + "                    </small></small>"
	            + "                </td>"
	            + "            </tr>"
	            
	            + cysteine_print(f.aminoacids_percent.value, f.age_yrs.value) 
	            
	            + "            <tr valign='bottom'>"
	            + "                <td align='right'><small>Dextrose:</small></td>"
	            + "                <td align='right'><tt>" + f.dextrose_percent.value + "</tt></td>"
	            + "                <td align='left'><small>%</small></td>"
	            + "                <td align='right'><small>Sodium Phosphate:</small></td>"
	            + "                <td align='right'><tt>" + f.phosphate__mmol_p_l.value + "</tt></td>"
	            + "                <td align='left'><small>mM/L</small></td>"
	            + "            </tr>"
	            + "            <tr valign='bottom'>"
	            + "                <td align='right'><small>Sodium Acetate:</small></td>"
	            + "                <td align='right'><tt>" + f.sodium_acetate__meq_p_l.value + "</tt></td>"
	            + "                <td align='left'><small>mEq/L</small></td>"
	            + "                <td align='right'><small>Sodium Chloride:</small></td>"
	            + "                <td align='right'><tt>" + f.sodium_chloride__meq_p_l.value + "</tt></td>"
	            + "                <td align='left'><small>mEq/L</small></td>"
	            + "            </tr>"
	            + "            <tr valign='bottom'>"
	            + "                <td align='right'><small>Potassium Chloride:</small></td>"
	            + "                <td align='right'><tt>" + f.potassium_chloride__meq_p_l.value + "</tt></td>"
	            + "                <td align='left'><small>mEq/L</small></td>"
	            + "                <td align='right'><small>Potassium Acetate:</small></td>"
	            + "                <td align='right'><tt>" + f.potassium_acetate__meq_p_l.value + "</tt></td>"
	            + "                <td align='left'><small>mEq/L</small></td>"
	            + "            </tr>"
	            + "            <tr valign='bottom'>"
	            + "                <td align='right'><small>Magnesium Sulfate:</small></td>"
	            + "                <td align='right'><tt>" + f.magnesium__meq_p_l.value + "</tt></td>"
	            + "                <td align='left'><small>mEq/L</small></td>"
	                          
	            + "            </tr>"
	            + "        </table>"
	            + "    </td>"
	            + "</tr>"
                    + "<tr align='left' valign='top'>"
	            + "    <td colspan='3'>"
	            + "        <br>"
	            + "        <strong>Administration Rates via " + linetype_string(f.line_type.value) + "</strong>:<br clear='all'>"
	            + "        <table border='0' cellpadding='1' cellspacing='0' align='left'>"
	            + "            <tr valign='top' align='left'>"
	            + "                <td>&#160;&#160;&#160;&#160;</td>"
	            + "                <td>"
	            + "                    <small>"
	            + "                        <strong><u>TPN:</u></strong> "
	            +  f.dextrose_percent.value + "% dextrose with "
	            +  f.aminoacids_percent.value + "% " + amino_acid_string(f.age_yrs.value) + " at"
	            + "                        <strong><u>" + f.tpn_rate.value + "</u></strong> ml/hr"
	            + "                        for " + f.infusion_duration_value_h.value + " hr/day"
	            + "                        <small><br><br></small>"
	            + "                        <strong><u>IL:</u></strong>&#160;&#160;20% Intralipid at"
	            + "                        <strong><u>" + f.fat_rate.value + "</u></strong> ml/hr"
	            + "                        for " + f.infusion_duration_value_h.value + " hr/day"
	            + "                    </small>"
	            + "                </td>"
	            + "            </tr>"
	            + "        </table><br clear='all'><br>"
	            + "    </td>"
	            + "</tr>"
	            + "<tr align='left' valign='top'>"
	            + "    <td rowspan='2'>"
	            + "        <strong>Vitamins and Trace Elements</strong>:<br clear='all'>"
	            + "        <table border='0' cellpadding='1' cellspacing='0' align='left'>"
	            + "            <tr valign='top' align='left'>"
	            + "                <td>&#160;&#160;&#160;&#160;</td>"
	            + "                <td>"
	            + "                    <small>"
	            +                     vitamins_and_tma_string(f.x__vit_and_tm.value) 
	            + "                    </small>"
	            + "                </td>"
	            + "            </tr>"
	            + "        </table><br clear='all'><br>"
	            + "        <strong>Resulting Levels</strong>: <small><!-- ~[~pharmacy_use_only~]~ --></small><br clear='all'>"
	            + "        <table border='0' cellpadding='0' cellspacing='1' align='left'>"
	            + "            <tr valign='bottom'>"
	            + "                <td rowspan='9'>&#160;&#160;&#160;&#160;</td>"
	            + "                <td align='right'><small><u>Constituent</u></small></td>"
	            + "                <td rowspan='8'><small>&#160;&#160;</small></td>"
	            + "                <td align='center' colspan='2'><small><u>mEq/L</u><sup>*</sup></small></td>"
	            + "                <td rowspan='8'><small>&#160;&#160;</small></td>"
	            + "                <td align='center' colspan='2'><small><u>mEq/kg/day</u><sup>*</sup></small></td>"
	            + "            </tr>"
	            + "            <tr valign='bottom'>"
	            + "                <td align='right'><small>Sodium:</small></td>"
	            + "                <td align='right'><tt>" + f.sodium__meq_p_l.value + "</tt></td>"
	            + "                <td rowspan='7'>&#160;&#160;</td>"
	            + "                <td align='right'><tt>" + f.sodium__meq_p_kg_p_day.value + "</tt></td>"
	            + "                <td rowspan='7'>&#160;&#160;&#160;&#160;</td>"
	            + "            </tr>"
	            + "            <tr valign='bottom'>"
	            + "                <td align='right'><small>Potassium:</small></td>"
	            + "                <td align='right'><tt>" + f.potassium__meq_p_l.value + "</tt></td>"
	            + "                <td align='right'><tt>" + f.potassium__meq_p_kg_p_day.value + "</tt></td>"
	            + "            </tr>"
	            + "            <tr valign='bottom'>"
	            + "                <td align='right'><small>Calcium:</small></td>"
	            + "                <td align='right'><tt>" + f.calcium__meq_p_l.value + "</tt></td>"
	            + "                <td align='right'><tt>" + f.calcium__meq_p_kg_p_day.value + "</tt></td>"
	            + "            </tr>"
	            + "            <tr valign='bottom'>"
	            + "                <td align='right'><small>Magnesium:</small></td>"
	            + "                <td align='right'><tt>" + f.magnesium__meq_p_l.value + "</tt></td>"
	            + "                <td align='right'><tt>" + f.magnesium__meq_p_kg_p_day.value + "</tt></td>"
	            + "            </tr>"
	            + "            <tr valign='bottom'>"
	            + "                <td align='right'><small><sup>*</sup>Phosphorus:</small></td>"
	            + "                <td align='right'><tt>" + f.phosphate__mmol_p_l.value + "</tt></td>"
	            + "                <td align='right'><tt>" + f.phosphate__mmol_p_kg_p_day.value + "</tt></td>"
	            + "            </tr>"
	            + "            <tr valign='bottom'>"
	            + "                <td align='right'><small>Acetate:</small></td>"
	            + "                <td align='right'><tt>" + f.acetate__meq_p_l.value + "</tt></td>"
	            + "                <td align='right'><tt>" + f.acetate__meq_p_kg_p_day.value + "</tt></td>"
	            + "            </tr>"
	            + "            <tr valign='bottom'>"
	            + "                <td align='right'><small>Chloride:</small></td>"
	            + "                <td align='right'><tt>" + f.chloride__meq_p_l.value + "</tt></td>"
	            + "                <td align='right'><tt>" + f. chloride__meq_p_kg_p_day.value + "</tt></td>"
	            + "            </tr>"
	            + "            <tr valign='top'>"
	            + "                <td align='left' colspan='7'>"
	            + "                    <small><small>"
	            + "                        <sup>*</sup>Phosphorus values are in mM/L and mM/kg/day."
	            + "                    </small></small>"
	            + "                </td>"
	            + "            </tr>"
	            + "        </table>"
	            + "    </td>"
	            + "    <td rowspan='2'>&#160;&#160;&#160;&#160;</td>"
	            + "    <td>"
	            + "        <strong>Medications</strong>:<br clear='all'>"
	            + "        <table border='0' cellpadding='0' cellspacing='1' align='left'>"
	            + "            <tr valign='top' align='left'>"
	            + "                <td>&#160;&#160;&#160;&#160;</td>"
	            + "                <td>"
	            + "                    <small>"
	            +                         medications_string()
	            + "                    </small>"
	            + "                </td>"
	            + "            </tr>"
	            + "        </table>"
	            + "    </td>"
	            + "</tr>"
	            + "<tr valign='bottom' align='left'>"
	            + "    <td>"
	            + "        <br>"
	            + "<strong>Nutritional Summary</strong>: <br clear='all'>"
	            + "        <table border='0' cellpadding='0' cellspacing='1' align='left'>"
	            + "            <tr valign='bottom'>"
	            + "                <td rowspan='7'>&#160;&#160;&#160;&#160;</td>"
	            + "                <td align='right'><small>Fluids:</small></td>"
	            + "                <td rowspan='2' align='left'><small>&#160;</small></td>"
	            + "                <td align='right'><tt>" + f.fluid__ml_p_kg_p_d.value + "</tt></td>"
	            + "                <td rowspan='2' align='left'><small>&#160;</small></td>"
	            + "                <td align='left'><small>ml/kg/day</small></td>"
	            + "            </tr>"
	            + "            <tr valign='bottom'>"
	            + "                <td align='right'><small>...and:</small></td>"
	            + "                <td align='right'><tt>" + f.fluid__l_p_m2_p_d.value + "</tt></td>"
	            + "                <td align='left'><small>L/m<sup>2</sup>/day</small></td>"
	            + "            </tr>"
	            + "            <tr><td colspan='5'><small><small><small>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</small></small></small></td></tr>"
	            + "            <tr valign='bottom'>"
	            + "                <td align='right'><small>Energy:</small></td>"
	            + "                <td rowspan='4' align='left'><small>&#160;</small></td>"
	            + "                <td align='right'><tt>" + f.provided_e__kcal_p_kg_day.value + "</tt></td>"
	            + "                <td rowspan='4' align='left'><small>&#160;</small></td>"
	            + "                <td align='left'><small>Kcal/kg/day</small></td>"
	            + "            </tr>"
	            + "            <tr valign='bottom'>"
	            + "                <td align='right'><small>Amino&#160;Acids:</small></td>"
	            + "                <td align='right'><tt>" + f.aminoacids__g_p_kg_p_day.value + "</tt></td>"
	            + "                <td align='left'><small>g/kg/day</small></td>"
	            + "            </tr>"
	            + "            <tr valign='bottom'>"
	            + "                <td align='right'><small>Lipid:</small></td>"
	            + "                <td align='right'><tt>" + f.fat_emulsion_value__g_p_kg_p_d.value + "</tt></td>"
	            + "                <td align='left'><small>g/kg/day</small></td>"
	            + "            </tr>"
	            + "            <tr valign='bottom'>"
	            + "                <td align='right'><small>GIR:</small></td>"			
	            + "                <td align='right'><tt>" + f.dextrose__mg_p_kg_p_min.value + "</tt></td>"
	            + "                <td align='left'><small>mg/kg/min</small></td>"					
	            + "            </tr>"
	            + "        </table>"								
	            + "    </td>"
	            + "</tr>"
	            + "<tr align='left' valign='top'>"
	            + "    <td colspan='3'>"
	            + "        <br>"								
	            + "        <strong>"
	            + "            Supplemental Fluid</strong>:<br clear='all'>"
	            + "        <table border='0' cellpadding='1' cellspacing='0' align='left'>"
	            + "            <tr valign='top' align='left'>"
	            + "                <td>&#160;&#160;&#160;&#160;</td>"
	            + "                <td>"
	            + "                    <small>"
	            +                       supfluids_string()
	            + "                    </small>"							
	            + "                </td>"
	            + "            </tr>"
	            + "        </table>"
	            + "    </td>"
	            + "</tr>"
	            + "<tr align='left' valign='top'>"
	            + "    <td colspan='3'>"
	            + "        <br>"
	            + "        <table border='0' cellpadding='1' cellspacing='0' align='left' width='100%'>"
	            + "            <tr valign='top' align='left'>"
	            + "                <td colspan='2'>"
	            + auth_note
	            + "                </td>"
	            + "            </tr>"
	            + "        </table><br clear='all'>"
	            + footer				
	            + "    </td>"
	            + "</tr>"
	        + "</table>"										
	    + "</body>"
	+ "</html>" );


    return true;
}

	