www/js/prod_edit.js

Fri, 06 Sep 2019 22:59:59 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Fri, 06 Sep 2019 22:59:59 +0200
changeset 469
3d532097860d
parent 464
fbd2a7cecaaa
child 470
94a69f6b0f35
permissions
-rw-r--r--

Code optimisation for compressed javascript in the product editor

/*****************************************************************************
 * Copyright (C) 2018-2019
 *
 * Michiel Broek <mbroek at mbse dot eu>
 *
 * This file is part of BMS
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2, or (at your option) any
 * later version.
 *
 * BrewCloud is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with ThermFerm; see the file COPYING.  If not, write to the Free
 * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 *****************************************************************************/


function createDelElements(){

	$('#eventWindow').jqxWindow({
		theme:theme,
		position:{x:490,y:210},
		width:300,
		height:175,
		resizable:false,
		isModal:true,
		modalOpacity:0.4,
		okButton:$('#delOk'),
		cancelButton:$('#delCancel'),
		initContent:function(){
			$('#delOk').jqxButton({template:"danger",width:'65px',theme:theme});
			$('#delCancel').jqxButton({template:"success",width:'65px',theme:theme});
			$('#delCancel').focus();
		}
	});
	$('#eventWindow').jqxWindow('hide');
}



$(document).ready(function () {

    var i,
	to_100 = false,		// Fermentables adjust to 100%
	preboil_sg = 0,
	aboil_sg = 0,
	est_mash_sg = 0,
	psugar = 0,		// Percentage real sugars
	pcara = 0,		// Percentage cara/crystal malts
	svg = 77,               // Default attenuation
        mashkg = 0,             // Malt in mash weight
	pitchrate = 0.75,	// Yeast pitch rate default
	initcells = 0,		// Initial yeast cell count

	ok_fermentables = 1,	// Fermentables are in stock
	ok_hops = 1,		// Hops are in stock
	ok_miscs = 1,		// Miscs are in stock
	ok_yeasts = 1,		// Yeasts are in stock
	ok_waters = 1,		// Waters are in stock

        hop_flavour = 0,
        hop_aroma = 0,
        mash_infuse = 0,
        last_base = '',
        last_acid = '',

        MMCa = 40.048,
        MMMg = 24.305,
        MMNa = 22.98976928,
        MMCl = 35.453,
        MMSO4 = 96.0626,
        MMHCO3 = 61.01684,
        MMCaSO4 = 172.171,
        MMCaCl2 = 147.015,
        MMCaCO3 = 100.087,
        MMMgSO4 = 246.475,
        MMNaHCO3 = 84.007,
        MMNa2CO3 = 105.996,
        MMNaCl = 58.443,
        MMCaOH2 = 74.06268,

	fermentableRow = 0,
	fermentableData = {},
	fermentableInit = 1,
	hopRow = 0,
	hopData = {},
	miscRow = 0,
	miscData = {},
	yeastRow = 0,
	yeastData = {},
	mashRow = 0,
	mashData = {},
	Ka1 = 0.0000004445,
	Ka2 = 0.0000000000468,
	dataRecord = {},
	url = "includes/db_product.php",

	// Prepare the data
	source = {
		datatype: "json",
		cache: false,
		datafields: [
			// From prod_main
			{ name: 'record', type: 'number' },
			{ name: 'uuid', type: 'string' },
			{ name: 'name', type: 'string' },
			{ name: 'code', type: 'string' },
			{ name: 'birth', type: 'string' },
			{ name: 'stage', type: 'int' },
			{ name: 'notes', type: 'string' },
			{ name: 'log_brew', type: 'int' },
			{ name: 'log_fermentation', type: 'int' },
			{ name: 'inventory_reduced', type: 'int' },
			{ name: 'locked', type: 'int' },
			{ name: 'eq_name', type: 'string' },
			{ name: 'eq_boil_size', type: 'float' },
			{ name: 'eq_batch_size', type: 'float' },
			{ name: 'eq_tun_volume', type: 'float' },
			{ name: 'eq_tun_weight', type: 'float' },
			{ name: 'eq_tun_specific_heat', type: 'float' },
			{ name: 'eq_tun_material', type: 'int' },
			{ name: 'eq_tun_height', type: 'float' },
			{ name: 'eq_top_up_water', type: 'float' },
			{ name: 'eq_trub_chiller_loss', type: 'float' },
			{ name: 'eq_evap_rate', type: 'float' },
			{ name: 'eq_boil_time', type: 'float' },
			{ name: 'eq_calc_boil_volume', type: 'int' },
			{ name: 'eq_top_up_kettle', type: 'float' },
			{ name: 'eq_hop_utilization', type: 'float' },
			{ name: 'eq_notes', type: 'string' },
			{ name: 'eq_lauter_volume', type: 'float' },
			{ name: 'eq_lauter_height', type: 'float' },
			{ name: 'eq_lauter_deadspace', type: 'float' },
			{ name: 'eq_kettle_volume', type: 'float' },
		        { name: 'eq_kettle_height', type: 'float' },
			{ name: 'eq_mash_volume', type: 'float' },
			{ name: 'eq_mash_max', type: 'float' },
			{ name: 'eq_efficiency', type: 'float' },
			{ name: 'brew_date_start', type: 'string' },
			{ name: 'brew_mash_ph', type: 'float' },
			{ name: 'brew_mash_sg', type: 'float' },
			{ name: 'brew_mash_efficiency', type: 'float' },
			{ name: 'brew_sparge_est', type: 'float' },
			{ name: 'brew_sparge_ph', type: 'float' },
			{ name: 'brew_preboil_volume', type: 'float' },
			{ name: 'brew_preboil_sg', type: 'float' },
			{ name: 'brew_preboil_ph', type: 'float' },
			{ name: 'brew_preboil_efficiency', type: 'float' },
			{ name: 'brew_aboil_volume', type: 'float' },
			{ name: 'brew_aboil_sg', type: 'float' },
			{ name: 'brew_aboil_ph', type: 'float' },
			{ name: 'brew_aboil_efficiency', type: 'float' },
			{ name: 'brew_cooling_method', type: 'int' },
			{ name: 'brew_cooling_time', type: 'float' },
			{ name: 'brew_cooling_to', type: 'float' },
			{ name: 'brew_whirlpool9', type: 'float' },
			{ name: 'brew_whirlpool7', type: 'float' },
			{ name: 'brew_whirlpool6', type: 'float' },
			{ name: 'brew_whirlpool2', type: 'float' },
			{ name: 'brew_fermenter_volume', type: 'float' },
			{ name: 'brew_fermenter_extrawater', type: 'float' },
			{ name: 'brew_fermenter_tcloss', type: 'float' },
			{ name: 'brew_aeration_time', type: 'float' },
			{ name: 'brew_aeration_speed', type: 'float' },
			{ name: 'brew_aeration_type', type: 'int' },
			{ name: 'brew_fermenter_sg', type: 'float' },
			{ name: 'brew_fermenter_ibu', type: 'float' },
			{ name: 'brew_fermenter_color', type: 'float' },
			{ name: 'brew_date_end', type: 'string' },
			{ name: 'og', type: 'float' },
			{ name: 'fg', type: 'float' },
			{ name: 'primary_start_temp', type: 'float' },
			{ name: 'primary_max_temp', type: 'float' },
			{ name: 'primary_end_temp', type: 'float' },
			{ name: 'primary_end_sg', type: 'float' },
			{ name: 'primary_end_date', type: 'string' },
			{ name: 'secondary_temp', type: 'float' },
			{ name: 'secondary_end_sg', type: 'float' },
			{ name: 'secondary_end_date', type: 'string' },
			{ name: 'tertiary_temp', type: 'float' },
			{ name: 'package_date', type: 'string' },
			{ name: 'package_volume', type: 'float' },
			{ name: 'package_infuse_amount', type: 'float' },
			{ name: 'package_infuse_abv', type: 'float' },
			{ name: 'package_infuse_notes', type: 'string' },
			{ name: 'package_abv', type: 'float' },
			{ name: 'package_ph', type: 'float' },
			{ name: 'bottle_amount', type: 'float' },
			{ name: 'bottle_carbonation', type: 'float' },
			{ name: 'bottle_priming_water', type: 'float' },
			{ name: 'bottle_priming_amount', type: 'float' },
			{ name: 'bottle_carbonation_temp', type: 'float' },
			{ name: 'keg_amount', type: 'float' },
			{ name: 'keg_carbonation', type: 'float' },
			{ name: 'keg_priming_water', type: 'float' },
			{ name: 'keg_priming_amount', type: 'float' },
			{ name: 'keg_carbonation_temp', type: 'float' },
			{ name: 'keg_forced_carb', type: 'int' },
			{ name: 'keg_pressure', type: 'float' },
			{ name: 'taste_notes', type: 'string' },
			{ name: 'taste_rate', type: 'float' },
			{ name: 'taste_date', type: 'string' },
			{ name: 'taste_color', type: 'string' },
			{ name: 'taste_transparency', type: 'string' },
			{ name: 'taste_head', type: 'string' },
			{ name: 'taste_aroma', type: 'string' },
			{ name: 'taste_taste', type: 'string' },
			{ name: 'taste_mouthfeel', type: 'string' },
			{ name: 'taste_aftertaste', type: 'string' },
			{ name: 'st_name', type: 'string' },
			{ name: 'st_letter', type: 'string' },
			{ name: 'st_guide', type: 'string' },
			{ name: 'st_category', type: 'string' },
			{ name: 'st_category_number', type: 'float' },
			{ name: 'st_type', type: 'int' },
			{ name: 'st_og_min', type: 'float' },
			{ name: 'st_og_max', type: 'float' },
			{ name: 'st_fg_min', type: 'float' },
			{ name: 'st_fg_max', type: 'float' },
			{ name: 'st_ibu_min', type: 'float' },
			{ name: 'st_ibu_max', type: 'float' },
			{ name: 'st_color_min', type: 'float' },
			{ name: 'st_color_max', type: 'float' },
			{ name: 'st_carb_min', type: 'float' },
			{ name: 'st_carb_max', type: 'float' },
			{ name: 'st_abv_min', type: 'float' },
			{ name: 'st_abv_max', type: 'float' },
			{ name: 'type', type: 'int' },
			{ name: 'batch_size', type: 'float' },
			{ name: 'boil_size', type: 'float' },
			{ name: 'boil_time', type: 'float' },
			{ name: 'efficiency', type: 'float' },
			{ name: 'est_og', type: 'float' },
			{ name: 'est_fg', type: 'float' },
			{ name: 'est_abv', type: 'float' },
			{ name: 'est_color', type: 'float' },
			{ name: 'color_method', type: 'int' },
			{ name: 'est_ibu', type: 'float' },
			{ name: 'ibu_method', type: 'int' },
			{ name: 'est_carb', type: 'float' },
			{ name: 'sparge_temp', type: 'float' },
			{ name: 'sparge_ph', type: 'float' },
			{ name: 'sparge_volume', type: 'float' },
			{ name: 'sparge_source', type: 'int' },
			{ name: 'sparge_acid_type', type: 'int' },
			{ name: 'sparge_acid_perc', type: 'float' },
			{ name: 'sparge_acid_amount', type: 'float' },
			{ name: 'mash_ph', type: 'float' },
			{ name: 'mash_name', type: 'string' },
			{ name: 'calc_acid', type: 'int' },
			{ name: 'w1_name', type: 'string' },
			{ name: 'w1_amount', type: 'float' },
			{ name: 'w1_calcium', type: 'float' },
			{ name: 'w1_sulfate', type: 'float' },
			{ name: 'w1_chloride', type: 'float' },
			{ name: 'w1_sodium', type: 'float' },
			{ name: 'w1_magnesium', type: 'float' },
			{ name: 'w1_total_alkalinity', type: 'float' },
			{ name: 'w1_ph', type: 'float' },
			{ name: 'w1_cost', type: 'float' },
			{ name: 'w2_name', type: 'string' },
			{ name: 'w2_amount', type: 'float' },
			{ name: 'w2_calcium', type: 'float' },
			{ name: 'w2_sulfate', type: 'float' },
			{ name: 'w2_chloride', type: 'float' },
			{ name: 'w2_sodium', type: 'float' },
			{ name: 'w2_magnesium', type: 'float' },
			{ name: 'w2_total_alkalinity', type: 'float' },
			{ name: 'w2_ph', type: 'float' },
			{ name: 'w2_cost', type: 'float' },
			{ name: 'wg_amount', type: 'float' },
                        { name: 'wg_calcium', type: 'float' },
                        { name: 'wg_sulfate', type: 'float' },
                        { name: 'wg_chloride', type: 'float' },
                        { name: 'wg_sodium', type: 'float' },
                        { name: 'wg_magnesium', type: 'float' },
                        { name: 'wg_total_alkalinity', type: 'float' },
                        { name: 'wg_ph', type: 'float' },
                        { name: 'wb_calcium', type: 'float' },
                        { name: 'wb_sulfate', type: 'float' },
                        { name: 'wb_chloride', type: 'float' },
                        { name: 'wb_sodium', type: 'float' },
                        { name: 'wb_magnesium', type: 'float' },
                        { name: 'wb_total_alkalinity', type: 'float' },
                        { name: 'wb_ph', type: 'float' },
			{ name: 'wa_acid_name', type: 'int' },
			{ name: 'wa_acid_perc', type: 'int' },
			{ name: 'wa_base_name', type: 'int' },
			{ name: 'starter_enable', type: 'int' },
			{ name: 'starter_type', type: 'int' },
			{ name: 'starter_sg', type: 'float' },
			{ name: 'starter_viability', type: 'int' },
			{ name: 'prop1_type', type: 'int' },
			{ name: 'prop1_volume', type: 'float' },
			{ name: 'prop2_type', type: 'int' },
			{ name: 'prop2_volume', type: 'float' },
			{ name: 'prop3_type', type: 'int' },
			{ name: 'prop3_volume', type: 'float' },
			{ name: 'prop4_type', type: 'int' },
			{ name: 'prop4_volume', type: 'float' },
			{ name: 'fermentables', type: 'array' },
			{ name: 'hops', type: 'array' },
			{ name: 'miscs', type: 'array' },
			{ name: 'yeasts', type: 'array' },
			{ name: 'mashs', type: 'array' }
		],
		id: 'record',
		url: url + '?record=' + my_record
	},
	// Load data and select one record.
	dataAdapter = new $.jqx.dataAdapter(source, {
		loadComplete: function () {
			var records = dataAdapter.records;
			dataRecord = records[0];
			// Hidden record uuid
			$("#name").val(dataRecord.name);
			$("#code").val(dataRecord.code);
			$("#birth").val(dataRecord.birth);
			$("#stage").val(StageData[dataRecord.stage].nl);
			$("#notes").val(dataRecord.notes);
			$("#locked").val(dataRecord.locked);
			$("#eq_name").val(dataRecord.eq_name);
			$("#eq_notes").val(dataRecord.eq_notes);
			$("#eq_boil_size").val(dataRecord.eq_boil_size);
			$("#eq_batch_size").val(dataRecord.eq_batch_size);
			$("#eq_tun_volume").val(dataRecord.eq_tun_volume);
			$("#eq_top_up_water").val(dataRecord.eq_top_up_water);
			$("#eq_trub_chiller_loss").val(dataRecord.eq_trub_chiller_loss);
			$("#eq_evap_rate").val(dataRecord.eq_evap_rate);
			$("#eq_boil_time").val(dataRecord.eq_boil_time);
			$("#eq_top_up_kettle").val(dataRecord.eq_top_up_kettle);
			$("#eq_hop_utilization").val(dataRecord.eq_hop_utilization);
			$("#eq_lauter_volume").val(dataRecord.eq_lauter_volume);
			$("#eq_lauter_deadspace").val(dataRecord.eq_lauter_deadspace);
			$("#eq_kettle_volume").val(dataRecord.eq_kettle_volume);
			$("#eq_mash_volume").val(dataRecord.eq_mash_volume);
			$("#eq_mash_max").val(dataRecord.eq_mash_max);
			$("#eq_efficiency").val(dataRecord.eq_efficiency);
			// Brewdate
			$("#brew_date_start").val(dataRecord.brew_date_start);
			$("#brew_mash_ph").val(dataRecord.brew_mash_ph);
			$("#brew_mash_sg").val(dataRecord.brew_mash_sg);
			$("#brew_mash_efficiency").val(dataRecord.brew_mash_efficiency);
			// Header Spoelen en filteren
			$("#brew_sparge_temperature").val(dataRecord.sparge_temp);
			$("#brew_sparge_volume").val(dataRecord.sparge_volume);
			$("#brew_sparge_est").val(dataRecord.brew_sparge_est);
			$("#brew_sparge_ph").val(dataRecord.brew_sparge_ph);
			// Header Beluchten
			$("#brew_aeration_type").val(dataRecord.brew_aeration_type);
			$("#brew_aeration_time").val(dataRecord.brew_aeration_time);
			$("#brew_aeration_speed").val(dataRecord.brew_aeration_speed);

			$("#brew_preboil_ph").val(dataRecord.brew_preboil_ph);
			$("#brew_preboil_sg").val(dataRecord.brew_preboil_sg);
			$("#brew_preboil_volume").val(dataRecord.brew_preboil_volume);
			$("#brew_preboil_efficiency").val(dataRecord.brew_preboil_efficiency);
			// Header Koelen en whirlpoolen
			$("#brew_whirlpool9").val(dataRecord.brew_whirlpool9);
			$("#brew_whirlpool7").val(dataRecord.brew_whirlpool7);
			$("#brew_whirlpool6").val(dataRecord.brew_whirlpool6);
			$("#brew_whirlpool2").val(dataRecord.brew_whirlpool2);
			// Header Naar gistvat
			$("#brew_fermenter_volume").val(dataRecord.brew_fermenter_volume);
			$("#brew_fermenter_sg").val(dataRecord.brew_fermenter_sg);
			$("#brew_fermenter_sg2").val(dataRecord.brew_fermenter_sg);
			$("#brew_fermenter_ibu").val(dataRecord.brew_fermenter_ibu);
			$("#brew_fermenter_color").val(dataRecord.brew_fermenter_color);
			$("#brew_fermenter_extrawater").val(dataRecord.brew_fermenter_extrawater);
			$("#brew_fermenter_tcloss").val(dataRecord.brew_fermenter_tcloss);

			$("#brew_aboil_ph").val(dataRecord.brew_aboil_ph);
			$("#brew_aboil_sg").val(dataRecord.brew_aboil_sg);
			$("#brew_aboil_volume").val(dataRecord.brew_aboil_volume);
			$("#brew_aboil_efficiency").val(dataRecord.brew_aboil_efficiency);
			// Header Koelen en whirlpoolen
			$("#brew_cooling_to").val(dataRecord.brew_cooling_to);
			$("#brew_cooling_method").val(dataRecord.brew_cooling_method);
			$("#brew_cooling_time").val(dataRecord.brew_cooling_time);
			// Niks
			$("#brew_date_end").val(dataRecord.brew_date_end);
			$("#og").val(dataRecord.og);
			$("#fg").val(dataRecord.fg);
			$("#primary_start_temp").val(dataRecord.primary_start_temp);
			$("#primary_max_temp").val(dataRecord.primary_max_temp);
			$("#primary_end_temp").val(dataRecord.primary_end_temp);
			$("#primary_end_sg").val(dataRecord.primary_end_sg);
			$("#primary_end_date").val(dataRecord.primary_end_date);
			$("#secondary_temp").val(dataRecord.secondary_temp);
			$("#secondary_end_sg").val(dataRecord.secondary_end_sg);
			$("#secondary_end_date").val(dataRecord.secondary_end_date);
			$("#tertiary_temp").val(dataRecord.tertiary_temp);
			$("#package_date").val(dataRecord.package_date);
			$("#package_volume").val(dataRecord.package_volume);
			$("#package_infuse_amount").val(dataRecord.package_infuse_amount);
			$("#package_infuse_abv").val(dataRecord.package_infuse_abv);
			$("#package_infuse_notes").val(dataRecord.package_infuse_notes);
			$("#package_abv").val(dataRecord.package_abv);
			$("#package_ph").val(dataRecord.package_ph);
			$("#bottle_amount").val(dataRecord.bottle_amount);
			$("#bottle_carbonation").val(dataRecord.bottle_carbonation);
			$("#bottle_priming_water").val(dataRecord.bottle_priming_water);
			$("#bottle_priming_amount").val(dataRecord.bottle_priming_amount);
			$("#bottle_carbonation_temp").val(dataRecord.bottle_carbonation_temp);
			$("#keg_amount").val(dataRecord.keg_amount);
			$("#keg_carbonation").val(dataRecord.keg_carbonation);
			$("#keg_priming_water").val(dataRecord.keg_priming_water);
			$("#keg_priming_amount").val(dataRecord.keg_priming_amount);
			$("#keg_carbonation_temp").val(dataRecord.keg_carbonation_temp);
			$("#keg_forced_carb").val(dataRecord.keg_forced_carb);
			$("#keg_pressure").val(dataRecord.keg_pressure);
			$("#taste_notes").val(dataRecord.taste_notes);
			$("#taste_rate").val(dataRecord.taste_rate);
			$("#taste_date").val(dataRecord.taste_date);
			$("#taste_color").val(dataRecord.taste_color);
			$("#taste_transparency").val(dataRecord.taste_transparency);
			$("#taste_head").val(dataRecord.taste_head);
			$("#taste_aroma").val(dataRecord.taste_aroma);
			$("#taste_taste").val(dataRecord.taste_taste);
			$("#taste_mouthfeel").val(dataRecord.taste_mouthfeel);
			$("#taste_aftertaste").val(dataRecord.taste_aftertaste);

			// Recipe
			$("#st_name").val(dataRecord.st_name);
			$("#st_letter").val(dataRecord.st_letter);
			$("#st_guide").val(dataRecord.st_guide);
			$("#st_category").val(dataRecord.st_category);
			$("#st_category_number").val(dataRecord.st_category_number);
			$("#st_type").val(StyleTypeData[dataRecord.st_type].nl);
			$("#st_og_min").val(dataRecord.st_og_min);
			$("#st_og_max").val(dataRecord.st_og_max);
			$("#st_fg_min").val(dataRecord.st_fg_min);
			$("#st_fg_max").val(dataRecord.st_fg_max);
			$("#st_abv_min").val(dataRecord.st_abv_min);
			$("#st_abv_max").val(dataRecord.st_abv_max);
			$("#st_color_min").val(dataRecord.st_color_min);
			$("#st_color_max").val(dataRecord.st_color_max);
			$("#st_ibu_min").val(dataRecord.st_ibu_min);
			$("#st_ibu_max").val(dataRecord.st_ibu_max);
			$("#st_carb_min").val(dataRecord.st_carb_min);
			$("#st_carb_min2").val(dataRecord.st_carb_min);
			$("#st_carb_max").val(dataRecord.st_carb_max);
			$("#st_carb_max2").val(dataRecord.st_carb_max);
			$("#type").val(dataRecord.type);
			$("#batch_size").val(dataRecord.batch_size);
			$("#est_a_vol").val(dataRecord.batch_size * 1.04);
			$("#boil_size").val(dataRecord.boil_size);
			$("#est_pre_vol").val(dataRecord.boil_size * 1.04);
			$("#boil_time").val(dataRecord.boil_time);
			$("#efficiency").val(dataRecord.efficiency);
			$("#est_og").val(dataRecord.est_og);
			$("#est_og2").val(dataRecord.est_og);
			$("#est_og3").val(0);
			$("#est_fg").val(dataRecord.est_fg);
			$("#est_fg2").val(dataRecord.est_fg);
			$("#est_fg3").val(dataRecord.est_fg);
			$("#est_color").val(dataRecord.est_color);
			$("#est_color2").val(dataRecord.est_color);
			$("#est_abv").val(dataRecord.est_abv);
			$("#color_method").val(dataRecord.color_method);
			$("#est_ibu").val(dataRecord.est_ibu);
			$("#est_ibu2").val(dataRecord.est_ibu);
			$("#ibu_method").val(dataRecord.ibu_method);
			$("#est_carb").val(dataRecord.est_carb);
			$("#mash_name").val(dataRecord.mash_name);
			$("#mash_ph").val(dataRecord.mash_ph);
			$("#sparge_temp").val(dataRecord.sparge_temp);
			$("#sparge_ph").val(dataRecord.sparge_ph);
			$("#sparge_volume").val(dataRecord.sparge_volume);
			$("#sparge_source").val(dataRecord.sparge_source);
			$("#sparge_acid_type").val(dataRecord.sparge_acid_type);
			$("#sparge_acid_perc").val(dataRecord.sparge_acid_perc);
			$("#sparge_acid_amount").val(dataRecord.sparge_acid_amount * 1000);
			$("#calc_acid").val(dataRecord.calc_acid);
			$("#w1_name").val(dataRecord.w1_name);
			$("#w1_amount").val(dataRecord.w1_amount);
			$("#w1_calcium").val(dataRecord.w1_calcium);
			$("#w1_sulfate").val(dataRecord.w1_sulfate);
			$("#w1_chloride").val(dataRecord.w1_chloride);
			$("#w1_sodium").val(dataRecord.w1_sodium);
			$("#w1_magnesium").val(dataRecord.w1_magnesium);
			$("#w1_total_alkalinity").val(dataRecord.w1_total_alkalinity);
			$("#w1_ph").val(dataRecord.w1_ph);
			$("#w1_cost").val(dataRecord.w1_cost);
			$("#w2_name").val(dataRecord.w2_name);
			$("#w2_amount").val(dataRecord.w2_amount);
			$("#w2_calcium").val(dataRecord.w2_calcium);
			$("#w2_sulfate").val(dataRecord.w2_sulfate);
			$("#w2_chloride").val(dataRecord.w2_chloride);
			$("#w2_sodium").val(dataRecord.w2_sodium);
			$("#w2_magnesium").val(dataRecord.w2_magnesium);
			$("#w2_total_alkalinity").val(dataRecord.w2_total_alkalinity);
			$("#w2_ph").val(dataRecord.w2_ph);
			$("#w2_cost").val(dataRecord.w2_cost);
			$("#wg_amount").val(dataRecord.wg_amount);
                        $("#wg_calcium").val(dataRecord.wg_calcium);
                        $("#wg_sulfate").val(dataRecord.wg_sulfate);
                        $("#wg_chloride").val(dataRecord.wg_chloride);
                        $("#wg_sodium").val(dataRecord.wg_sodium);
                        $("#wg_magnesium").val(dataRecord.wg_magnesium);
                        $("#wg_total_alkalinity").val(dataRecord.wg_total_alkalinity);
                        $("#wg_ph").val(dataRecord.wg_ph);
                        $("#wb_calcium").val(dataRecord.wb_calcium);
                        $("#wb_sulfate").val(dataRecord.wb_sulfate);
                        $("#wb_chloride").val(dataRecord.wb_chloride);
                        $("#wb_sodium").val(dataRecord.wb_sodium);
                        $("#wb_magnesium").val(dataRecord.wb_magnesium);
                        $("#wb_total_alkalinity").val(dataRecord.wb_total_alkalinity);
                        $("#wb_ph").val(dataRecord.wb_ph);
			$("#wa_acid_name").val(dataRecord.wa_acid_name);
			$("#wa_acid_perc").val(dataRecord.wa_acid_perc);
			$("#wa_base_name").val(dataRecord.wa_base_name);
			$("#starter_enable").val(dataRecord.starter_enable);
			$("#starter_type").val(dataRecord.starter_type);
			$("#starter_sg").val(dataRecord.starter_sg);
			$("#starter_viability").val(dataRecord.starter_viability);
			$("#prop1_type").val(dataRecord.prop1_type);
			$("#prop1_volume").val(dataRecord.prop1_volume);
			$("#prop2_type").val(dataRecord.prop2_type);
			$("#prop2_volume").val(dataRecord.prop2_volume);
			$("#prop3_type").val(dataRecord.prop3_type);
			$("#prop3_volume").val(dataRecord.prop3_volume);
			$("#prop4_type").val(dataRecord.prop4_type);
			$("#prop4_volume").val(dataRecord.prop4_volume);
			editFermentable(dataRecord);
			editHop(dataRecord);
                        editMisc(dataRecord);
                        editYeast(dataRecord);
                        editMash(dataRecord);
			calcStage();
			$('#jqxTabs').jqxTabs('select', 2);
		},
		loadError: function (jqXHR, status, error) {
		},
                beforeLoadComplete: function (records) {
                        $('#jqxLoader').jqxLoader('open');
                }
	}),

        // Inline fermentables editor
        editFermentable = function (data) {
                var fermentableSource = {
                        localdata: data.fermentables,
                        datatype: "local",
			cache: false,
			async: false,
                        datafields: [
                                { name: 'f_name', type: 'string' },
                                { name: 'f_origin', type: 'string' },
                                { name: 'f_supplier', type: 'string' },
                                { name: 'f_amount', type: 'float' },
                                { name: 'f_cost', type: 'float' },
                                { name: 'f_type', type: 'int' },
                                { name: 'f_yield', type: 'float' },
                                { name: 'f_color', type: 'float' },
                                { name: 'f_coarse_fine_diff', type: 'float' },
                                { name: 'f_moisture', type: 'float' },
                                { name: 'f_diastatic_power', type: 'float' },
                                { name: 'f_protein', type: 'float' },
                                { name: 'f_max_in_batch', type: 'float' },
                                { name: 'f_graintype', type: 'int' },
                                { name: 'f_added', type: 'int' },
                                { name: 'f_dissolved_protein', type: 'float' },
                                { name: 'f_recommend_mash', type: 'int' },
                                { name: 'f_add_after_boil', type: 'int' },
                                { name: 'f_adjust_to_total_100', type: 'int' },
                                { name: 'f_percentage', type: 'float' },
                                { name: 'f_di_ph', type: 'float' },
				{ name: 'f_acid_to_ph_57', type: 'float' },
				{ name: 'f_inventory', type: 'float' },
				{ name: 'f_avail', type: 'int' }
                        ],
                        addrow: function (rowid, rowdata, position, commit) {
				//console.log("fermentable addrow "+rowid);
                                commit(true);
                        },
                        deleterow: function (rowid, commit) {
				//console.log("fermentable deleterow "+rowid);
                                commit(true);
                        },
			updaterow: function (rowid, rowdata, commit) {
				//console.log("fermentable updaterow "+rowid);
				commit(true);
			}
                },
                fermentableAdapter = new $.jqx.dataAdapter(fermentableSource);

                $("#fermentableGrid").jqxGrid({
                        width: 1240,
                        height: 470,
                        source: fermentableAdapter,
                        theme: theme,
                        selectionmode: 'singlerow',
                        showtoolbar: true,
                        rendertoolbar: function (toolbar) {
                                var container = $("<div style='overflow: hidden; position: relative; margin: 5px;'></div>");
                                toolbar.append(container);
                                container.append('<div style="float: left; margin-left: 165px;" id="faddrowbutton"></div>');
                                container.append('<div style="float: left; margin-left: 10px; margin-top: 5px;">In voorraad:</div>');
                                container.append('<div style="float: left; margin-left: 10px;" id="finstockbutton"></div>');
                                container.append('<input style="float: left; margin-left: 400px;" id="fdeleterowbutton" type="button" value="Verwijder mout" />');
                                // add fermentable from dropdownlist.
                                $("#faddrowbutton").jqxDropDownList({
                                        placeHolder: "Kies mout:",
                                        theme: theme,
					template: "primary",
                                        source: fermentablelist,
                                        displayMember: "name",
					disabled: (dataRecord.stage > 3),
                                        width: 150,
                                        height: 27,
                                        dropDownWidth: 500,
                                        dropDownHeight: 500,
                                        renderer: function (index, label, value) {
                                                var datarecord = fermentablelist.records[index];
                                                return datarecord.supplier+ " / " + datarecord.name + " (" + datarecord.color + " EBC)";
                                        }
                                });
                                $("#faddrowbutton").on('select', function (event) {
                                        if (event.args) {
                                                var index, datarecord, row = {}, rowscount = $("#fermentableGrid").jqxGrid('getdatainformation').rowscount;
                                                index = event.args.index;
                                                datarecord = fermentablelist.records[index];
                                                row["f_name"] = datarecord.name;
                                                row["f_origin"] = datarecord.origin;
                                                row["f_supplier"] = datarecord.supplier;
                                                row["f_amount"] = 0;
                                                row["f_cost"] = datarecord.cost;
                                                row["f_type"] = datarecord.type;
                                                row["f_yield"] = datarecord.yield;
                                                row["f_color"] = datarecord.color;
                                                row["f_coarse_fine_diff"] = datarecord.coarse_fine_diff;
                                                row["f_moisture"] = datarecord.moisture;
                                                row["f_diastatic_power"] = datarecord.diastatic_power;
                                                row["f_protein"] = datarecord.protein;
                                                row["f_max_in_batch"] = datarecord.max_in_batch;
                                                row["f_graintype"] = datarecord.graintype;
                                                if (datarecord.add_after_boil) {
                                                        row["f_added"] = 2;	// Fermentation
                                                } else if ((datarecord.type == 1) || (datarecord.type == 4)) {	// Sugar or Adjunct
                                                        row["f_added"] = 1;	// Boil
                                                } else {
                                                        row["f_added"] = 0;	// Mash
                                                }
                                                row["f_dissolved_protein"] = datarecord.dissolved_protein;
                                                row["f_recommend_mash"] = datarecord.recommend_mash;
                                                row["f_add_after_boil"] = datarecord.add_after_boil;
                                                if (rowscount == 0) {
                                                        // The first fermentable
                                                        row["f_adjust_to_total_100"] = 1;
                                                        row["f_percentage"] = 100;
                                                } else {
                                                        row["f_adjust_to_total_100"] = 0;
                                                        row["f_percentage"] = 0;
                                                }
                                                row["f_di_ph"] = datarecord.di_ph;
						row["f_acid_to_ph_57"] = datarecord.acid_to_ph_57;
						row["f_inventory"] = datarecord.inventory;
                                                $("#fermentableGrid").jqxGrid('addrow', null, row);
                                        }
                                });

                                $("#finstockbutton").jqxCheckBox({ theme: theme, height: 27, disabled: (dataRecord.stage > 3) });
                                $("#finstockbutton").on('change', function (event) {
                                        fermentableinstock = event.args.checked;
                                        fermentablelist.dataBind();
                                });

                                // delete selected fermentable.
                                $("#fdeleterowbutton").jqxButton({ template: "danger", theme: theme, height: 27, width: 150, disabled: (dataRecord.stage > 3) });
                                $("#fdeleterowbutton").on('click', function () {
					var rowscount, id, percent, amount, i, rowdata,
                                        selectedrowindex = $("#fermentableGrid").jqxGrid('getselectedrowindex');
                                        rowscount = $("#fermentableGrid").jqxGrid('getdatainformation').rowscount;
                                        if (selectedrowindex >= 0 && selectedrowindex < rowscount) {
                                                id = $("#fermentableGrid").jqxGrid('getrowid', selectedrowindex);
                                                percent = $('#fermentableGrid').jqxGrid('getcellvalue', id, "f_percentage");
                                                amount = $('#fermentableGrid').jqxGrid('getcellvalue', id, "f_amount");
                                                $("#fermentableGrid").jqxGrid('deleterow', id);
                                        }
                                        rowscount = $("#fermentableGrid").jqxGrid('getdatainformation').rowscount;
                                        if (rowscount > 1) {
                                                if (to_100) {
                                                        for (i = 0; i < rowscount; i++) {
                                                                rowdata = $("#fermentableGrid").jqxGrid('getrowdata', i);
                                                                if (rowdata.f_adjust_to_total_100) {
                                                                        rowdata.f_percentage += percent;
                                                                        rowdata.f_amount += amount;
                                                                }
                                                        }
                                                } else {
							calcPercentages();
                                                }
                                        } else {
                                                $("#fermentableGrid").jqxGrid('setcellvalue', 0, "f_percentage", 100);
                                        }
                                        calcFermentables();
                                        calcIBUs();
                                });
                        },
                        ready: function() {
				calcFermentables();
                                $('#jqxTabs').jqxTabs('next');
                        },
                        columns: [
                                { text: 'Vergistbaar ingredi&euml;nt', datafield: 'f_name',
                                  cellsrenderer:  function (index, datafield, value, defaultvalue, column, rowdata) {
                                        return "<span style='margin: 3px; margin-top: 6px; float: left;'>" +
						rowdata.f_supplier+" / "+rowdata.f_name+" ("+rowdata.f_color+" EBC)</span>";
                                  }
                                },
                                { text: 'Type', width: 100, datafield: 'f_type',
				  cellsrenderer: function (index, datafield, value, defaultvalue, column, rowdata) {
					return "<span style='margin: 3px; margin-top: 6px; float: left;'>" + FermentableTypeData[value].nl + "</span>";
				  }
			       	},
                                { text: 'Moment', width: 110, datafield: 'f_added',
				  cellsrenderer: function (index, datafield, value, defaultvalue, column, rowdata) {
					return "<span style='margin: 3px; margin-top: 6px; float: left;'>" + AddedData[value].nl + "</span>";
                                  }
                                },
				{ text:'Maxinbatch', datafield: 'f_max_in_batch', hidden: true },
                                { text: 'Opbrengst', datafield: 'f_yield', width: 90, align: 'right', cellsalign: 'right', cellsformat: 'p1' },
                                { text: 'Gewicht Kg', datafield: 'f_amount', width: 120, align: 'right', cellsalign: 'right', cellsformat: 'f3' },
				{ text: 'Voorraad Kg', datafield: 'f_inventory', width: 120, align: 'right',
				  cellsrenderer:  function (row, columnfield, value, defaulthtml, columnproperties, rowdata) {
					var color = '#ffffff';
					if (((dataRecord.inventory_reduced <= 2) && (rowdata.f_added <= 1)) ||	// Mash or boil
					    ((dataRecord.inventory_reduced <= 3) && (rowdata.f_added == 2)) ||	// Primary
					    ((dataRecord.inventory_reduced <= 5) && (rowdata.f_added == 3)) ||	// Secondary or Tertiary
					    ((dataRecord.inventory_reduced <= 6) && (rowdata.f_added == 4)) ||	// Bottle
					    ((dataRecord.inventory_reduced <= 6) && (rowdata.f_added == 5))) {	// Kegs
						if (value < rowdata.f_amount)
							color = '#ff4040';
						return  '<span style="margin: 4px; margin-top: 6px; float: right; color: ' +
							color + ';">' +fermentableAdapter.formatNumber(value, "f3") + '</span>';
					} else {
						return  '<span></span>';
					}
				  }
				},
                                { text: 'Procent', datafield: 'f_percentage', width: 90, align: 'right',
				  cellsrenderer:  function (row, columnfield, value, defaulthtml, columnproperties, rowdata) {
					if (rowdata.f_added >= 4)
						return '<span></span>';
					var color = '#ffffff';
					if (value > rowdata.f_max_in_batch)
						color = '#ff4040';
					return  '<span style="margin: 4px; margin-top: 6px; float: right; color: ' +
						color + ';">' +fermentableAdapter.formatNumber(value, "p1") + '</span>';
				  }
				},
                                { text: '100%', datafield: 'f_adjust_to_total_100', width: 70, align: 'center', cellsalign: 'center',
				  cellsrenderer:  function (index, datafield, value, defaultvalue, column, rowdata) {
					if (value == 0)
						return '<span></span>';
					return  '<span><img style="float:left; margin-left:25px; margin-top:4px;" src="images/dialog-ok-apply.png"></span>';
				  }
				},
				{ text: '', datafield: 'Edit', columntype: 'button', width: 100, align: 'center', cellsrenderer: function () {
					return "Wijzig";
					}, buttonclick: function (row) {
						fermentableRow = row;
						fermentableData = $("#fermentableGrid").jqxGrid('getrowdata', fermentableRow);
						if (fermentableData.f_added >= 4) {
							alert("Wijzig dit in de Verpakken tab");
						} else if (dataRecord.stage > 3) {
							alert("Ingredieënt is al verwerkt.");
						} else {
							$("#wf_name").val(fermentableData.f_name);
							$("#wf_amount").val(fermentableData.f_amount);
							$("#wf_percentage").val(fermentableData.f_percentage);
							$("#wf_max_in_batch").val(fermentableData.f_max_in_batch);
							$("#wf_adjust_to_total_100").val(fermentableData.f_adjust_to_total_100);
							$("#wf_added").val(fermentableData.f_added);
							// show the popup window.
							$("#popupFermentable").jqxWindow('open');
						}
					}
				}
                        ]
                });
        },

        // Inline hops editor
        editHop = function (data) {
                var hopSource = {
                        localdata: data.hops,
                        datatype: "local",
                        cache: false,
			async: false,
                        datafields: [
                                { name: 'h_name', type: 'string' },
                                { name: 'h_origin', type: 'string' },
                                { name: 'h_amount', type: 'float' },
                                { name: 'h_cost', type: 'float' },
                                { name: 'h_type', type: 'int' },
                                { name: 'h_form', type: 'int' },
                                { name: 'h_useat', type: 'int' },
                                { name: 'h_time', type: 'float' },
                                { name: 'h_alpha', type: 'float' },
                                { name: 'h_beta', type: 'float' },
                                { name: 'h_hsi', type: 'float' },
                                { name: 'h_humulene', type: 'float' },
                                { name: 'h_caryophyllene', type: 'float' },
                                { name: 'h_cohumulone', type: 'float' },
                                { name: 'h_myrcene', type: 'float' },
                                { name: 'h_total_oil', type: 'float' },
				{ name: 'h_inventory', type: 'float' },
				{ name: 'h_avail', type: 'int' }
                        ],
                        addrow: function (rowid, rowdata, position, commit) {
				console.log("hop addrow "+rowid);
				commit(true);
			},
                        deleterow: function (rowid, commit) {
				console.log("hop deleterow "+rowid);
				commit(true);
			},
			updaterow: function (rowid, rowdata, commit) {
				console.log("hop updaterow "+rowid);
				commit(true);
			}
                },
                hopAdapter = new $.jqx.dataAdapter(hopSource);

                $("#hopGrid").jqxGrid({
                        width: 1240,
                        height: 560,
                        source: hopAdapter,
                        theme: theme,
                        selectionmode: 'singlerow',
                        showtoolbar: true,
                        rendertoolbar: function (toolbar) {
                                var container = $("<div style='overflow: hidden; position: relative; margin: 5px;'></div>");
                                toolbar.append(container);
                                container.append('<div style="float: left; margin-left: 165px;" id="haddrowbutton"></div>');
                                container.append('<div style="float: left; margin-left: 10px; margin-top: 5px;">In voorraad:</div>');
                                container.append('<div style="float: left; margin-left: 10px;" id="hinstockbutton"></div>');
                                container.append('<input style="float: left; margin-left: 400px;" id="hdeleterowbutton" type="button" value="Verwijder hop" />');
                                // add hop from dropdownlist.
                                $("#haddrowbutton").jqxDropDownList({
                                        placeHolder: "Kies hop:",
                                        theme: theme,
					template: "primary",
                                        source: hoplist,
					disabled: (dataRecord.stage > 3),
                                        displayMember: "name",
                                        width: 150,
                                        height: 27,
                                        dropDownWidth: 500,
                                        dropDownHeight: 500,
                                        renderer: function (index, label, value) {
                                                var datarecord = hoplist.records[index];
                                                return datarecord.origin+ " - " + datarecord.name + " / " + HopFormData[datarecord.form].nl +
							" (" + datarecord.alpha + "% &alpha;)";
                                        }
                                });
                                $("#haddrowbutton").on('select', function (event) {
                                        if (event.args) {
                                                var datarecord, row = {}, index = event.args.index;
                                                datarecord = hoplist.records[index];
                                                row["h_name"] = datarecord.name;
                                                row["h_origin"] = datarecord.origin;
                                                row["h_amount"] = 0;
                                                row["h_cost"] = datarecord.cost;
                                                row["h_type"] = datarecord.type;
                                                row["h_form"] = datarecord.form;
                                                row["h_useat"] = 2;	// Boil
                                                row["h_time"] = 0;
                                                row["h_alpha"] = datarecord.alpha;
                                                row["h_beta"] = datarecord.beta;
                                                row["h_hsi"] = datarecord.hsi;
                                                row["h_humulene"] = datarecord.humulene;
                                                row["h_caryophyllene"] = datarecord.caryophyllene;
                                                row["h_cohumulone"] = datarecord.cohumulone;
                                                row["h_myrcene"] = datarecord.myrcene;
                                                row["h_total_oil"] = datarecord.total_oil;
						row["h_inventory"] = datarecord.inventory;
                                                $("#hopGrid").jqxGrid('addrow', null, row);
                                        }
					$("#haddrowbutton").jqxDropDownList('clearSelection');
                                });

                                $("#hinstockbutton").jqxCheckBox({ theme: theme, height: 27, disabled: (dataRecord.stage > 3) });
                                $("#hinstockbutton").on('change', function (event) {
                                        hopinstock = event.args.checked;
                                        hoplist.dataBind();
                                });

                                // delete selected hop.
                                $("#hdeleterowbutton").jqxButton({ template: "danger", theme: theme, height: 27, width: 150, disabled: (dataRecord.stage > 3) });
                                $("#hdeleterowbutton").on('click', function () {
                                        var rowscount, id, selectedrowindex = $("#hopGrid").jqxGrid('getselectedrowindex');
                                        rowscount = $("#hopGrid").jqxGrid('getdatainformation').rowscount;
                                        if (selectedrowindex >= 0 && selectedrowindex < rowscount) {
                                                id = $("#hopGrid").jqxGrid('getrowid', selectedrowindex);
                                                $("#hopGrid").jqxGrid('deleterow', id);
                                        }
					calcIBUs();
                                });
                        },
                        ready: function() {
				calcIBUs();
                                $('#jqxTabs').jqxTabs('next');
                        },
                        columns: [
                                { text: 'Hop', datafield: 'h_name',
                                  cellsrenderer: function (index, datafield, value, defaultvalue, column, rowdata) {
                                        return "<span style='margin: 3px; margin-top: 6px; float: left;'>" +rowdata.h_origin+" / "+rowdata.h_name+"</span>";
                                  },
                                },
                                { text: 'Type', width: 90, datafield: 'h_type',
				  cellsrenderer: function (index, datafield, value, defaultvalue, column, rowdata) {
					return  '<span style="margin: 4px; margin-top: 6px; float: left;">' + HopTypeData[value].nl + '</span>';
				  }
			       	},
                                { text: 'Vorm', width: 90, datafield: 'h_form',
				  cellsrenderer: function (index, datafield, value, defaultvalue, column, rowdata) {
					return  '<span style="margin: 4px; margin-top: 6px; float: left;">' + HopFormData[value].nl + '</span>';
				  }
			       	},
                                { text: 'Alpha', datafield: 'h_alpha', width: 80, align: 'right', cellsalign: 'right', cellsformat: 'p1' },
				{ text: 'Gebruik', width: 110, datafield: 'h_useat',
				  cellsrenderer: function (index, datafield, value, defaultvalue, column, rowdata) {
					return  '<span style="margin: 4px; margin-top: 6px; float: left;">' + HopUseData[value].nl + '</span>';
				  }
				},
				{ text: 'Tijdsduur', datafield: 'h_time', width: 90, align: 'right',
				  cellsrenderer: function (index, datafield, value, defaultvalue, column, rowdata) {
					var duration = '';
					if ((rowdata.h_useat == 2) || (rowdata.h_useat == 4))   // Boil, Whirlpool
						duration = dataAdapter.formatNumber(value, "f0")+" min.";
					else if (rowdata.h_useat == 5)       // Dry hop
						duration = dataAdapter.formatNumber(value/1440, "f0")+" dagen";
					return  '<span style="margin: 4px; margin-top: 6px; float: right;">' + duration + '</span>';
				  }
				},
                                { text: 'IBU', datafield: 'ibu', width: 80, align: 'right',
                                  cellsrenderer: function (index, datafield, value, defaultvalue, column, rowdata) {
                                        var ibu = toIBU(rowdata.h_useat, rowdata.h_form, preboil_sg, parseFloat($("#batch_size").jqxNumberInput('decimal')),
                                                          parseFloat(rowdata.h_amount), parseFloat(rowdata.h_time),
                                                          parseFloat(rowdata.h_alpha), $("#ibu_method").val());
					return  '<span style="margin: 4px; margin-top: 6px; float: right;">' + dataAdapter.formatNumber(ibu, "f1") + '</span>';
                                  }
                                },
				{ text: 'Gewicht', datafield: 'h_amount', width: 110, align: 'right',
				  cellsrenderer: function (index, datafield, value, defaultvalue, column, rowdata) {
					var amount = dataAdapter.formatNumber(value, "f1") + ' kg';
					if (value < 1)
						amount = dataAdapter.formatNumber(value * 1000, "f1") + ' gr';
					return  '<span style="margin: 4px; margin-top: 6px; float: right;">' + amount + '</span>';
				  }
				},
				{ text: 'Voorraad', datafield: 'h_inventory', width: 110, align: 'right',
				  cellsrenderer: function (index, datafield, value, defaultvalue, column, rowdata) {
					if (((dataRecord.inventory_reduced <= 2) && (rowdata.h_useat <= 4)) ||  // Mash, FW, Boil, Aroma, Whirlpool
                                            ((dataRecord.inventory_reduced <= 6) && (rowdata.h_useat == 5))) {	// Dry hop
						var amount, color = '#ffffff';
						if (value < rowdata.h_amount)
							color = '#ff4040';
						amount = dataAdapter.formatNumber(value, "f1") + ' kg';
						if (value < 1)
							amount = dataAdapter.formatNumber(value * 1000, "f1") + ' gr';
						return  '<span style="margin: 4px; margin-top: 6px; float: right; color: '+color+';">'+amount+'</span>';
					} else {
						return '<span></span>';
					}
				  }
				},
				{ text: '', datafield: 'Edit', columntype: 'button', width: 100, align: 'center', cellsrenderer: function () {
					return "Wijzig";
					}, buttonclick: function (row) {
						if (dataRecord.stage > 3) {
                                                        alert("Ingredieënt is al verwerkt.");
                                                } else {
							console.log("edit button row "+row);
							hopRow = row;
							hopData = $("#hopGrid").jqxGrid('getrowdata', hopRow);
							$("#wh_name").val(hopData.h_name);
							$("#wh_amount").val(hopData.h_amount * 1000);
							var ibu = toIBU(hopData.h_useat, hopData.h_form, preboil_sg,
								parseFloat($("#batch_size").jqxNumberInput('decimal')),
								parseFloat(hopData.h_amount), parseFloat(hopData.h_time),
								parseFloat(hopData.h_alpha), $("#ibu_method").val()
							);
							$("#wh_ibu").val(ibu);
							if (hopData.h_useat == 5)       // Dry hop
								$("#wh_time").val(hopData.h_time / 1440);
							else
								$("#wh_time").val(hopData.h_time);
							$("#wh_useat").val(hopData.h_useat);
							// show the popup window.
							$("#popupHop").jqxWindow('open');
						}
					}
				}
                        ]
                });
        },

        // Inline miscs editor
        editMisc = function (data) {
                var miscSource = {
                        localdata: data.miscs,
                        datatype: "local",
                        cache: false,
			async: false,
                        datafields: [
                                { name: 'm_name', type: 'string' },
                                { name: 'm_amount', type: 'float' },
                                { name: 'm_cost', type: 'float' },
                                { name: 'm_type', type: 'int' },
                                { name: 'm_use_use', type: 'int' },
                                { name: 'm_time', type: 'float' },
                                { name: 'm_amount_is_weight', type: 'int' },
				{ name: 'm_inventory', type: 'float' },
				{ name: 'm_avail', type: 'int' }
                        ],
                        addrow: function (rowid, rowdata, position, commit) {
				console.log("misc addrow "+rowid);
                                commit(true);
                        },
                        deleterow: function (rowid, commit) {
				console.log("misc deleterow "+rowid);
                                commit(true);
                        },
			updaterow: function (rowid, rowdata, commit) {
				console.log("misc updaterow "+rowid);
				commit(true);
			}
                },
                miscAdapter = new $.jqx.dataAdapter(miscSource, {
                        beforeLoadComplete: function (records) {
                                var row, i, data = new Array();
                                for (i = 0; i < records.length; i++) {
                                        row = records[i];
                                        data.push(row);
                                        // Initial set water agent values.
                                        switch (row.m_name) {
                                                case 'CaCl2':           $("#wa_cacl2").val(row.m_amount * 1000);
                                                                        break;
                                                case 'CaSO4':           $("#wa_caso4").val(row.m_amount * 1000);
                                                                        break;
                                                case 'MgSO4':           $("#wa_mgso4").val(row.m_amount * 1000);
                                                                        break;
                                                case 'NaCl':            $("#wa_nacl").val(row.m_amount * 1000);
                                                                        break;
                                                case 'Melkzuur':        $("#wa_acid_name").val(0);
                                                                        $("#wa_acid").val(row.m_amount * 1000);
                                                                        $("#wa_acid_perc").val(80);
                                                                        last_acid = 'Melkzuur';
                                                                        break;
                                                case 'Zoutzuur':        $("#wa_acid_name").val(1);
                                                                        $("#wa_acid").val(row.m_amount * 1000);
                                                                        $("#wa_acid_perc").val(80);
                                                                        last_acid = 'Zoutzuur';
                                                                        break;
                                                case 'Fosforzuur':      $("#wa_acid_name").val(2);
                                                                        $("#wa_acid").val(row.m_amount * 1000);
                                                                        $("#wa_acid_perc").val(80);
                                                                        last_acid = 'Fosforzuur';
                                                                        break;
                                                case 'Zwavelzuur':      $("#wa_acid_name").val(3);
                                                                        $("#wa_acid").val(row.m_amount * 1000);
                                                                        $("#wa_acid_perc").val(80);
                                                                        last_acid = 'Zwavelzuur';
                                                                        break;
                                                case 'NaHCO3':          $("#wa_base_name").val(0);
                                                                        $("#wa_base").val(row.m_amount * 1000);
                                                                        last_base = 'NaHCO3';
                                                                        break;
                                                case 'Na2CO3':          $("#wa_base_name").val(1);
                                                                        $("#wa_base").val(row.m_amount * 1000);
                                                                        last_base = 'Na2CO3';
                                                                        break;
                                                case 'CaCO3':           $("#wa_base_name").val(2);
                                                                        $("#wa_base").val(row.m_amount * 1000);
                                                                        last_base = 'CaCO3';
                                                                        break;
                                                case 'Ca(OH)2':         $("#wa_base_name").val(3);
                                                                        $("#wa_base").val(row.m_amount * 1000);
                                                                        last_base = 'Ca(OH)2';
                                                                        break;
                                        }
                                }
                                return data;
                        },
                        loadError: function(jqXHR, status, error) {
                                $('#err').text(status + ' ' + error);
                        },
                });
                $("#miscGrid").jqxGrid({
                        width: 1240,
                        height: 575,
                        source: miscAdapter,
                        theme: theme,
                        selectionmode: 'singlerow',
                        showtoolbar: true,
                        rendertoolbar: function (toolbar) {
                                var container = $("<div style='overflow: hidden; position: relative; margin: 5px;'></div>");
                                toolbar.append(container);
                                container.append('<div style="float: left; margin-left: 165px;" id="maddrowbutton"></div>');
                                container.append('<div style="float: left; margin-left: 10px; margin-top: 5px;">In voorraad:</div>');
                                container.append('<div style="float: left; margin-left: 10px;" id="minstockbutton"></div>');
                                container.append('<input style="float: left; margin-left: 400px;" id="mdeleterowbutton" type="button" value="Verwijder ingredient" />');
                                // add misc from dropdownlist.
                                $("#maddrowbutton").jqxDropDownList({
                                        placeHolder: "Kies ingredi&euml;nt:",
                                        theme: theme,
					template: "primary",
                                        source: misclist,
					disabled: (dataRecord.stage > 3),
                                        displayMember: "name",
                                        width: 150,
                                        height: 27,
                                        dropDownWidth: 500,
                                        dropDownHeight: 500
                                });
                                $("#maddrowbutton").on('select', function (event) {
                                        if (event.args) {
                                                var datarecord, row = {}, index = event.args.index;
                                                datarecord = misclist.records[index];
                                                row["m_name"] = datarecord.name;
                                                row["m_amount"] = 0;
                                                row["m_cost"] = datarecord.cost;
                                                row["m_type"] = datarecord.type;
                                                row["m_use_use"] = datarecord.use_use;
                                                row["m_time"] = 0;
                                                row["m_amount_is_weight"] = datarecord.amount_is_weight;
						row["m_inventory"] = datarecord.inventory;
                                                $("#miscGrid").jqxGrid('addrow', null, row);
                                        }
                                });
                                $("#minstockbutton").jqxCheckBox({ theme: theme, height: 27, disabled: (dataRecord.stage > 3) });
                                $("#minstockbutton").on('change', function (event) {
                                        miscinstock = event.args.checked;
                                        misclist.dataBind();
                                });
                                // delete selected misc.
                                $("#mdeleterowbutton").jqxButton({ template: "danger", theme: theme, height: 27, width: 150, disabled: (dataRecord.stage > 3) });
                                $("#mdeleterowbutton").on('click', function () {
                                        var rowscount, type, id, selectedrowindex = $("#miscGrid").jqxGrid('getselectedrowindex');
                                        rowscount = $("#miscGrid").jqxGrid('getdatainformation').rowscount;
                                        type = $("#miscGrid").jqxGrid('getcellvalue', selectedrowindex, "m_type");
                                        if (selectedrowindex >= 0 && selectedrowindex < rowscount && type != 4)  {	// Water agent
                                                id = $("#miscGrid").jqxGrid('getrowid', selectedrowindex);
                                                $("#miscGrid").jqxGrid('deleterow', id);
                                        }
                                });
                        },
                        ready: function() {
				calcMiscs();
                                $('#jqxTabs').jqxTabs('next');
                        },
                        columns: [
                                { text: 'Ingredient', datafield: 'm_name' },
                                { text: 'Type', width: 140, datafield: 'm_type',
				  cellsrenderer: function (index, datafield, value, defaultvalue, column, rowdata) {
					return "<span style='margin: 3px; margin-top: 6px; float: left;'>" + MiscTypeData[value].nl + "</span>";
				  }
			       	},
                                { text: 'Gebruik', width: 140, datafield: 'm_use_use',
				  cellsrenderer: function (index, datafield, value, defaultvalue, column, rowdata) {
					return "<span style='margin: 3px; margin-top: 6px; float: left;'>" + MiscUseData[value].nl + "</span>";
                                  }
                               	},
                               	{ text: 'Tijd', datafield: 'm_time', width: 90, align: 'right',
				  cellsrenderer: function (index, datafield, value, defaultvalue, column, rowdata) {
					var duration = '';
					if (rowdata.m_use_use == 2)	// Boil
						duration = dataAdapter.formatNumber(value, "f0")+" min.";
					else if ((rowdata.m_use_use == 3) || (rowdata.m_use_use == 4))	// Primary or Secondary
						duration = dataAdapter.formatNumber(value/1440, "f0")+" dagen";
					return  '<span style="margin: 4px; margin-top: 6px; float: right;">' + duration + '</span>';
				  },
                                },
				{ text: 'Hoeveel', datafield: 'm_amount', width: 110, align: 'right',
				  cellsrenderer: function (index, datafield, value, defaultvalue, column, rowdata) {
					var vstr = rowdata.m_amount_is_weight ? "gr":"ml";
					return  '<span style="margin: 4px; margin-top: 6px; float: right;">' +
						dataAdapter.formatNumber(value * 1000,"f2")+" "+vstr + '</span>';
				  }
				},
				{ text: 'Voorraad', datafield: 'm_inventory', width: 110, align: 'right',
				  cellsrenderer: function (index, datafield, value, defaultvalue, column, rowdata) {
					var vstr, color, amount;
					if (((dataRecord.inventory_reduced <= 2) && (rowdata.m_use_use <= 2)) ||  // Starter, Mash, Boil
					    ((dataRecord.inventory_reduced <= 3) && (rowdata.m_use_use == 3)) ||  // Primary
					    ((dataRecord.inventory_reduced <= 5) && (rowdata.m_use_use == 4)) ||  // Secondary, Teriary
                                            ((dataRecord.inventory_reduced <= 6) && (rowdata.m_use_use == 5))) {  // Bottle
						vstr = rowdata.m_amount_is_weight ? "gr":"ml";
						color = '#ffffff';
						if (value < rowdata.m_amount)
							color = '#ff4040';
						amount = dataAdapter.formatNumber(value * 1000,"f2")+" "+vstr;
						return  '<span style="margin: 4px; margin-top: 6px; float: right; color: '+color+';">'+amount+'</span>';
					} else {
						return '<span></span>';
					}
				  }
				},
				{ text: '', datafield: 'Edit', columntype: 'button', width: 100, align: 'center', cellsrenderer: function () {
					return "Wijzig";
					}, buttonclick: function (row) {
						miscRow = row;
						miscData = $("#miscGrid").jqxGrid('getrowdata', miscRow);
						if (dataRecord.stage > 3) {
							alert("Ingredieënt is al verwerkt.");
						} else if (miscData.m_type == 4) {
							alert("Brouwzouten wijzigen in de water tab.");
						} else {
							console.log("edit button row "+row);
							if (miscData.m_amount_is_weight)
								$("#wm_pmpt_amount").html("Gewicht gram:");
							else
								$("#wm_pmpt_amount").html("Volume ml:");
							$("#wm_name").val(miscData.m_name);
							$("#wm_amount").val(miscData.m_amount * 1000);
							if ((miscData.m_use_use == 3) || (miscData.m_use_use == 4))     // Primary or Secondary
								$("#wm_time").val(miscData.m_time / 1440);
							else
								$("#wm_time").val(miscData.m_time);
							$("#wm_use_use").val(miscData.m_use_use);
							// show the popup window.
							$("#popupMisc").jqxWindow('open');
						}
					}
				}
                        ]
                });
        },

        // Inline yeasts editor
        editYeast = function (data) {
                var yeastSource = {
                        localdata: data.yeasts,
                        datatype: "local",
                        cache: false,
			async: false,
                        datafields: [
                                { name: 'y_name', type: 'string' },
                                { name: 'y_laboratory', type: 'string' },
                                { name: 'y_product_id', type: 'string' },
                                { name: 'y_amount', type: 'float' },
                                { name: 'y_cost', type: 'float' },
                                { name: 'y_type', type: 'int' },
                                { name: 'y_form', type: 'int' },
				{ name: 'y_flocculation', type: 'int' },
                                { name: 'y_min_temperature', type: 'float' },
                                { name: 'y_max_temperature', type: 'float' },
                                { name: 'y_attenuation', type: 'float' },
                                { name: 'y_use', type: 'int' },
				{ name: 'y_cells', type: 'float' },
				{ name: 'y_tolerance', type: 'float' },
				{ name: 'y_inventory', type: 'float' },
				{ name: 'y_avail', type: 'int' }
                        ],
                        addrow: function (rowid, rowdata, position, commit) {
				console.log("yeast addrow "+rowid);
                                commit(true);
                        },
                        deleterow: function (rowid, commit) {
				console.log("yeast deleterow "+rowid);
                                commit(true);
                        },
			updaterow: function (rowid, rowdata, commit) {
				console.log("yeast updaterow "+rowid);
				commit(true);
			}
                },
                yeastAdapter = new $.jqx.dataAdapter(yeastSource);

                $("#yeastGrid").jqxGrid({
                        width: 1240,
                        height: 350,
                        source: yeastAdapter,
                        theme: theme,
                        selectionmode: 'singlerow',
                        showtoolbar: true,
                        rendertoolbar: function (toolbar) {
                                var container = $("<div style='overflow: hidden; position: relative; margin: 5px;'></div>");
                                toolbar.append(container);
                                container.append('<div style="float: left; margin-left: 165px;" id="yaddrowbutton"></div>');
                                container.append('<div style="float: left; margin-left: 10px; margin-top: 5px;">In voorraad:</div>');
                                container.append('<div style="float: left; margin-left: 10px;" id="yinstockbutton"></div>');
                                container.append('<input style="float: left; margin-left: 400px;" id="ydeleterowbutton" type="button" value="Verwijder gist" />');
                                // add yeast from dropdownlist.
                                $("#yaddrowbutton").jqxDropDownList({
                                        placeHolder: "Kies gist:",
                                        theme: theme,
                                        source: yeastlist,
					disabled: (dataRecord.stage > 3),
					template: "primary",
                                        displayMember: "name",
                                        width: 150,
                                        height: 27,
                                        dropDownWidth: 500,
                                        dropDownHeight: 500,
                                        renderer: function (index, label, value) {
                                                var datarecord = yeastlist.records[index];
                                                return datarecord.laboratory+" "+datarecord.product_id+" "+datarecord.name;
                                        }
                                });
                                $("#yaddrowbutton").on('select', function (event) {
                                        if (event.args) {
                                                var datarecord, row = {}, index = event.args.index;
                                                datarecord = yeastlist.records[index];
                                                row["y_name"] = datarecord.name;
                                                row["y_laboratory"] = datarecord.laboratory;
                                                row["y_product_id"] = datarecord.product_id;
                                                row["y_type"] = datarecord.type;
                                                row["y_form"] = datarecord.form;
                                                row["y_amount"] = 0;
                                                row["y_cost"] = datarecord.cost;
                                                row["y_use"] = 0;
                                                row["y_min_temperature"] = datarecord.min_temperature;
                                                row["y_max_temperature"] = datarecord.max_temperature;
                                                row["y_attenuation"] = datarecord.attenuation;
						row["y_flocculation"] = datarecord.flocculation;
						row["y_cells"] = datarecord.cells;
						row["y_tolerance"] = datarecord.tolerance;
						row["y_inventory"] = datarecord.inventory;
                                                $("#yeastGrid").jqxGrid('addrow', null, row);
                                        }
					calcYeast();
					$("#yaddrowbutton").jqxDropDownList('clearSelection');
                                });
                                $("#yinstockbutton").jqxCheckBox({ theme: theme, height: 27, disabled: (dataRecord.stage > 3) });
                                $("#yinstockbutton").on('change', function (event) {
                                        yeastinstock = event.args.checked;
                                        yeastlist.dataBind();
                                });
                                // delete selected yeast.
                                $("#ydeleterowbutton").jqxButton({ template: "danger", theme: theme, height: 27, width: 150, disabled: (dataRecord.stage > 3) });
                                $("#ydeleterowbutton").on('click', function () {
                                        var id, rowscount, selectedrowindex = $("#yeastGrid").jqxGrid('getselectedrowindex');
                                        rowscount = $("#yeastGrid").jqxGrid('getdatainformation').rowscount;
                                        if (selectedrowindex >= 0 && selectedrowindex < rowscount) {
                                                id = $("#yeastGrid").jqxGrid('getrowid', selectedrowindex);
                                                $("#yeastGrid").jqxGrid('deleterow', id);
						calcYeast();
                                        }
                                });
                        },
                        ready: function() {
				calcFermentables();
				showStarter();
				calcYeast();
                                $('#jqxTabs').jqxTabs('next');
                        },
                        columns: [
                                { text: 'Gist', datafield: 'y_name' },
                                { text: 'Laboratorium', width: 150, datafield: 'y_laboratory' },
                                { text: 'Code', width: 90, datafield: 'y_product_id' },
                                { text: 'Soort', width: 100, datafield: 'y_form',
				  cellsrenderer: function (index, datafield, value, defaultvalue, column, rowdata) {
					return  '<span style="margin: 4px; margin-top: 6px; float: left;">' + YeastFormData[value].nl + '</span>';
				  }
			       	},
                                { text: 'Min. &deg;C', width: 70, align: 'right', cellsalign: 'right', datafield: 'y_min_temperature' },
                                { text: 'Max. &deg;C', width: 70, align: 'right', cellsalign: 'right', datafield: 'y_max_temperature' },
				{ text: 'Tol. %', width: 60, align: 'right', cellsalign: 'right', datafield: 'y_tolerance',
				  cellsrenderer: function (index, datafield, value, defaultvalue, column, rowdata) {
					var amount = "", color = '#ffffff';
					if (value > 0) {
						amount = dataAdapter.formatNumber(value, "f1");
						if (dataRecord.est_abv > value)
							color = '#ff4040';
					}
					return '<span style="margin: 4px; margin-top: 6px; float: right; color: ' + color + ';">' + amount + '</span>';
				  }
				},
                                { text: 'Attn. %', width: 70, align: 'right', cellsalign: 'right', datafield: 'y_attenuation', cellsformat: 'f1' },
                                { text: 'Voor', width: 120, datafield: 'y_use',
				  cellsrenderer: function (index, datafield, value, defaultvalue, column, rowdata) {
					return  '<span style="margin: 4px; margin-top: 6px; float: left;">' + YeastUseData[value].nl + '</span>';
                                  }
                                },
				{ text: 'Hoeveel', datafield: 'y_amount', width: 90, align: 'right',
				  cellsrenderer: function (index, datafield, value, defaultvalue, column, rowdata) {
					var amount = dataAdapter.formatNumber(value*1000, "f0")+" ml";
					if (rowdata.y_form == 0)	// Liquid
						amount = dataAdapter.formatNumber(value, "f0")+" pk";
					else if (rowdata.y_form == 1)	// Dry
						amount = dataAdapter.formatNumber(value*1000, "f1")+" gr";
					return  '<span style="margin: 4px; margin-top: 6px; float: right;">' + amount + '</span>';
				  }
				},
				{ text: 'Voorraad', datafield: 'y_inventory', width: 90, align: 'right',
				  cellsrenderer: function (index, datafield, value, defaultvalue, column, rowdata) {
					var color, amount;
					if (((dataRecord.inventory_reduced <= 3) && (rowdata.y_use == 0)) ||  // Primary
                                            ((dataRecord.inventory_reduced <= 4) && (rowdata.y_use == 1)) ||  // Secondary
                                            ((dataRecord.inventory_reduced <= 5) && (rowdata.y_use == 2)) ||  // Tertiary
                                            ((dataRecord.inventory_reduced <= 6) && (rowdata.y_use == 3))) {  // Bottle
						color = '#ffffff';
						if (value < rowdata.y_amount)
							color = '#ff4040';
						amount = dataAdapter.formatNumber(value*1000, "f0")+" ml";
						if (rowdata.y_form == 0)        // Liquid
							amount = dataAdapter.formatNumber(value, "f0")+" pk";
						else if (rowdata.y_form == 1)   // Dry
							amount = dataAdapter.formatNumber(value*1000, "f1")+" gr";
						return  '<span style="margin: 4px; margin-top: 6px; float: right; color: '+color+';">'+amount+'</span>';
					} else {
						return '<span></span>';
					}
				  }
				},
				{ text: '', datafield: 'Edit', columntype: 'button', width: 90, align: 'center', cellsrenderer: function () {
					return "Wijzig";
					}, buttonclick: function (row) {
						if (dataRecord.stage > 3) {
                                                        alert("Ingredieënt is al verwerkt.");
                                                } else {
							yeastRow = row;
							yeastData = $("#yeastGrid").jqxGrid('getrowdata', yeastRow);
							if (yeastData.y_form == 0) {
								$("#wy_pmpt_amount").html("Pak(ken):");
								$("#wy_amount").val(yeastData.y_amount);
								$("#wy_amount").jqxNumberInput({ decimalDigits: 0 });
							} else if (yeastData.y_form == 1) {
								$("#wy_pmpt_amount").html("Gewicht gram:");
								$("#wy_amount").val(yeastData.y_amount * 1000);
								$("#wy_amount").jqxNumberInput({ decimalDigits: 1 });
							} else {
								$("#wy_pmpt_amount").html("Volume ml:");
								$("#wy_amount").val(yeastData.y_amount * 1000);
								$("#wy_amount").jqxNumberInput({ decimalDigits: 0 });
							}
							$("#wy_name").val(yeastData.y_name);
							$("#wy_laboratory").val(yeastData.y_laboratory);
							$("#wy_product_id").val(yeastData.y_product_id);
							$("#wy_use").val(yeastData.y_use);
							// show the popup window.
							$("#popupYeast").jqxWindow('open');
						}
					}
				}
                        ]
                });
        },
        // inline mash editor
        editMash = function (data) {
                var mashSource = {
                        localdata: data.mashs,
                        datatype: "local",
                        cache: false,
			async: false,
                        datafields: [
                                { name: 'step_name', type: 'string' },
                                { name: 'step_type', type: 'int' },
                                { name: 'step_infuse_amount', type: 'float' },
                                { name: 'step_temp', type: 'float' },
                                { name: 'step_time', type: 'float' },
				{ name: 'step_thickness', type: 'float' },
                                { name: 'ramp_time', type: 'float' },
                                { name: 'end_temp', type: 'float' }
                        ],
                        addrow: function (rowid, rowdata, position, commit) {
                                commit(true);
                        },
                        deleterow: function (rowid, commit) {
                                commit(true);
                        }
                },
                mashAdapter = new $.jqx.dataAdapter(mashSource, {
                        beforeLoadComplete: function (records) {
                                mash_infuse = 0;
                                var i, row, data = new Array();
                                for (i = 0; i < records.length; i++) {
                                        row = records[i];
                                        if (row.step_type == 0)	// Infusion
                                                mash_infuse += parseFloat(row.step_infuse_amount);
					row.step_thickness = 0; // Init this field.
					data.push(row);
                                }
                        },
                });
                $("#mashGrid").jqxGrid({
                        width: 1240,
                        height: 400,
                        source: mashAdapter,
                        theme: theme,
                        selectionmode: 'singlerow',
                        showtoolbar: true,
                        rendertoolbar: function (toolbar) {
                                var container = $("<div style='overflow: hidden; position: relative; margin: 5px;'></div>");
                                toolbar.append(container);
                                container.append('<input style="float: left; margin-left: 165px;" id="saddrowbutton" type="button" value="Nieuwe stap" />');
                                container.append('<input style="float: left; margin-left: 565px;" id="sdeleterowbutton" type="button" value="Verwijder stap" />');
                                $("#saddrowbutton").jqxButton({ template: "primary", theme: theme, height: 27, width: 150, disabled: (dataRecord.stage > 3) });
                                $("#saddrowbutton").on('click', function () {
					var row = {}, rowscount = $("#mashGrid").jqxGrid('getdatainformation').rowscount;
					row["step_name"] = "Stap " + (rowscount + 1);
					if (rowscount > 0) {
						row["step_type"] = 1;
					} else {
						row["step_type"] = 0;
						row["step_infuse_amount"] = 15;
					}
					row["step_temp"] = 62.0;
					row['step_time'] = 20.0;
					row['step_thickness'] = 0;
					row['ramp_time'] = 1.0;
					row['end_temp'] = 62.0;
					$("#mashGrid").jqxGrid('addrow', null, row);
                                });
                                // delete selected step.
                                $("#sdeleterowbutton").jqxButton({ template: "danger", theme: theme, height: 27, width: 150, disabled: (dataRecord.stage > 3) });
                                $("#sdeleterowbutton").on('click', function () {
                                        var rowscount, id, selectedrowindex = $("#mashGrid").jqxGrid('getselectedrowindex');
                                        rowscount = $("#mashGrid").jqxGrid('getdatainformation').rowscount;
                                        if (selectedrowindex >= 0 && selectedrowindex < rowscount) {
                                                id = $("#mashGrid").jqxGrid('getrowid', selectedrowindex);
						$("#mashGrid").jqxGrid('deleterow', id);
                                        }
                                });
                        },
                        ready: function() {
                                calcInit();
				calcMash();
                                $('#jqxLoader').jqxLoader('close');
                                $('#jqxTabs').jqxTabs('first');
                        },
                        columns: [
                                { text: 'Stap naam', datafield: 'step_name' },
                                { text: 'Stap type', datafield: 'step_type', width: 175,
				  cellsrenderer: function (index, datafield, value, defaultvalue, column, rowdata) {
					return  '<span style="margin: 4px; margin-top: 6px; float: left;">' + MashStepTypeData[value].nl + '</span>';
                                  }
                                },
                                { text: 'Start &deg;C', datafield: 'step_temp', width: 90, align: 'right', cellsalign: 'right', cellsformat: 'f1' },
                                { text: 'Eind &deg;C', datafield: 'end_temp', width: 90, align: 'right', cellsalign: 'right', cellsformat: 'f1' },
                                { text: 'Rust min.', datafield: 'step_time', width: 90, align: 'right', cellsalign: 'right' },
                                { text: 'Stap min.', datafield: 'ramp_time', width: 90, align: 'right', cellsalign: 'right' },
                                { text: 'Infuse L.', datafield: 'step_infuse_amount', width: 90, align: 'right', cellsalign: 'right', cellsformat: 'f1' },
				{ text: 'L/Kg.', datafield: 'step_thickness', width: 90, align: 'right', cellsalign: 'right', cellsformat: 'f2' },
				{ text: '', datafield: 'Edit', columntype: 'button', width: 100, align: 'center', cellsrenderer: function () {
					return "Wijzig";
					}, buttonclick: function (row) {
						if (dataRecord.stage > 3) {
                                                        alert("Het maichen is al gedaan.");
                                                } else {
							mashRow = row;
							mashData = $("#mashGrid").jqxGrid('getrowdata', mashRow);
							$("#wstep_name").val(mashData.step_name);
							$("#wstep_type").val(mashData.step_type);
							$("#wstep_infuse_amount").val(mashData.step_infuse_amount);
							$("#wstep_temp").val(mashData.step_temp);
							$("#wend_temp").val(mashData.end_temp);
							$("#wstep_time").val(mashData.step_time);
							$("#wramp_time").val(mashData.ramp_time);
							if (mashData.step_type == 0) {
								$("#wstep_infuse_amount").show();
								$("#wstep_pmpt").show();
							} else {
								$("#wstep_infuse_amount").hide();
								$("#wstep_pmpt").hide();
							}
							// show the popup window.
							$("#popupMash").jqxWindow('open');
						}
					}
				}
                        ]
                });
        };

	/*
         * Remove the top menu so that we MUST use the buttons to leave the editor.
         */
        $('#jqxMenu').jqxMenu('destroy');
        console.log("record:" + my_record + "  return:" + my_return + "  theme:" + theme);
        $("#jqxLoader").jqxLoader({width:250,height:150,isModal:true,text:"Laden product ...",theme:theme});
	dataAdapter.dataBind();

	/*
	 * Generic functions
	 */
        function calcSupplies() {
                if (dataRecord.inventory_reduced > 6) {
                        $("#ok_pmpt").hide();
                        return;
                }
                if (ok_fermentables && ok_hops && ok_miscs && ok_yeasts && ok_waters)
                        $("#ok_supplies").html("<img src='images/dialog-ok-apply.png'>");
                else
                        $("#ok_supplies").html("<img src='images/dialog-error.png'>");
        }

        function calcPercentages() {

                console.log("calcPercentages()");
                var tw = 0, rowdata, percentage, rowscount = $("#fermentableGrid").jqxGrid('getdatainformation').rowscount;
                if (rowscount > 1) {
                        for (i = 0; i < rowscount; i++) {
                                rowdata = $("#fermentableGrid").jqxGrid('getrowdata', i);
                                if (rowdata.f_added < 4)
                                        tw += Round(rowdata.f_amount, 3);
                        };
                        tw = Round(tw, 3);

                        for (i = 0; i < rowscount; i++) {
                                rowdata = $("#fermentableGrid").jqxGrid('getrowdata', i);
                                if (rowdata.f_added < 4) {
                                        percentage = Round(rowdata.f_amount / tw * 100, 1);
                                        $("#fermentableGrid").jqxGrid('setcellvalue', i, "f_percentage", percentage);
                                } else {
                                        $("#fermentableGrid").jqxGrid('setcellvalue', i, "f_percentage", 0);
                                }
                        };
                } else {
                        $("#fermentableGrid").jqxGrid('setcellvalue', 0, "f_percentage", 100);
                }
        }

        /* 
         * All calculations that depend on changes in the fermentables,
         * volumes and equipments.
         */
        function calcFermentables() {

            var sugarsf = 0,		// fermentable sugars mash + boil
                sugarsm = 0,		// fermentable sugars in mash
                vol = 0,            	// Volume sugars after boil
                addedS = 0,         	// Added sugars after boil
                addedmass = 0,      	// Added mass after boil
                mvol = 0,           	// mash volume
                colort = 0,         	// Colors srm * vol totals
                colorh = 0,         	// Colors ebc * vol * kt
                colorn = 0,         	// Colors ebc * pt * pct
                my_100 = false,
                mashtime = 0,       	// Total mash time
                mashtemp = 0,       	// Average mash temperature
                bv = 0.925,         	// Bierverlies rendement
                sr = 0.95,          	// Mash en spoel rendement
                lintner = 0,        	// Total recipe lintner
		i, row, rows, org, timem, aboil_volume, spoelw, ogx, topw, s = 0, d, v, x,
		sug, alc, pt, cw, color, scolor, fig;

		/* Init global variables */
		psugar = 0;
                pcara = 0;
                mashkg = 0;
                ok_fermentables = 1;    // All is in stock.
                ok_yeasts = 1;

               	if ((rows = $('#mashGrid').jqxGrid('getrows'))){
                        for (i = 0; i <rows.length; i++){
                                row=rows[i];
                                if(row.step_type==0) // Infusion
                                        mvol+=parseFloat(row.step_infuse_amount);
                                if(row.step_temp<=75){ // Ignore mashout
                                        timem=row.step_time+row.ramp_time;
                                        mashtime+=timem;
                                        mashtemp+=timem*row.step_temp;
                                }
                        }
                        if(mashtime>5)
                                mashtime-=5;//Correct last ramp > 75
                        mashtemp=Round(mashtemp/mashtime,2);
                }

                if (!(rows = $('#fermentableGrid').jqxGrid('getrows'))) {
                        return; // grid not yet loaded.
                }

                for (i = 0; i < rows.length; i++) {
                        row = rows[i];
                        if (row.f_adjust_to_total_100)
                                my_100 = true;
                        if (row.f_type == 1 && row.f_added < 4) // Sugar
                                psugar += row.f_percentage;
                        if (row.f_graintype == 2 && row.f_added < 4)    // Crystal
                                pcara += row.f_percentage;
                        d = row.f_amount * (row.f_yield / 100) * (1 - row.f_moisture / 100);
                        if (row.f_added == 0) { // Mash
                                if (mvol > 0) { // Only if mash already known.
                                        mvol += row.f_amount * row.f_moisture / 100;
                                        s += d;
                                }
                                d = parseFloat(dataRecord.efficiency) / 100 * d;
                                sugarsm += d;
                                mashkg += parseFloat(row.f_amount);
                        }
                       	if (row.f_added == 0 || row.f_added == 1)       // Mash or Boil
                                sugarsf += d;
                        if (row.f_added == 2 || row.f_added == 3) {     // Fermentation or lagering
                                x = (row.f_yield / 100) * (1 - row.f_moisture / 100);
                                addedS += row.f_amount * x;
                                addedmass += row.f_amount;
                                vol += (x * sugardensity + (1 - x) * 1) * row.f_amount;
                        }
                        if (row.f_added < 4) {
                                colort += row.f_amount * ebc_to_srm(row.f_color);
                                colorh += row.f_amount * row.f_color * get_kt(row.f_color);
                                colorn += (row.f_percentage / 100) * row.f_color;       // For 8.6 Pt wort.
                        }
                        if (fermentableInit) {
                                if (row.f_added == 4) {
                                        $("#bottle_priming_total").val(row.f_amount * 1000);    // Prevent clearing
                                        $("#bottle_priming_sugar").jqxDropDownList('selectItem', row.f_name);
                                }
                                if (row.f_added == 5) {
                                        $("#keg_priming_total").val(row.f_amount * 1000);
                                        $("#keg_priming_sugar").jqxDropDownList('selectItem', row.f_name);
                                }
                        }
                        // Check supplies.
                        if ((((dataRecord.inventory_reduced <= 2) && (row.f_added <= 1)) ||  // Mash or boil
                             ((dataRecord.inventory_reduced <= 3) && (row.f_added == 2)) ||  // Primary
                             ((dataRecord.inventory_reduced <= 5) && (row.f_added == 3)) ||  // Secondary or Tertiary
                             ((dataRecord.inventory_reduced <= 6) && (row.f_added == 4)) ||  // Bottle
                             ((dataRecord.inventory_reduced <= 6) && (row.f_added == 5))) && row.f_inventory < row.f_amount) {
                                ok_fermentables = 0;
                        }
                        if (row.f_added == 0 && (row.f_type == 0 || row.f_type == 4) && row.f_color < 50) { // Mash and Grain/Adjunct and Color < 50
                                lintner += row.f_diastatic_power * row.f_amount;
                        }
                }
                fermentableInit = 0;
                $("#ferm_lintner").val(Math.round(parseFloat(lintner / mashkg)));
                $("#mash_kg").val(mashkg);
                console.log("calcFermentables() supplies:"+ok_fermentables+" moutsuiker:"+sugarsm+"/"+sugarsf);
                to_100 = my_100;
                if (to_100) {
                        $("#wf_amount").jqxNumberInput({ width: 90, readOnly: true, spinButtons: false  });
                } else {
                        $("#wf_amount").jqxNumberInput({ width: 110, readOnly: false, spinButtons: true });
                }

                if (mvol > 0) {
                        v = s / sugardensity + mvol;
                        s = 1000 * s / (v * 10); //deg. Plato
                        est_mash_sg = Round(plato_to_sg(s), 5);
                        $('#est_mash_sg').val(est_mash_sg);
                }

                // Estimate total recipe OG.
                dataRecord.est_og = estimate_sg(sugarsf + addedS, parseFloat(dataRecord.batch_size));
                $('#est_og').val(dataRecord.est_og);
                $('#est_og2').val(dataRecord.est_og);
                org = dataRecord.est_og;

                // Estimate SG in kettle after boil
                aboil_sg = estimate_sg(sugarsf, parseFloat(dataRecord.batch_size));
                $('#est_og3').val(aboil_sg);

                // Estimate SG in kettle before boil
                preboil_sg = estimate_sg(sugarsm, parseFloat(dataRecord.boil_size));
                $('#est_pre_sg').val(preboil_sg);

                // Recalculate volumes.
                aboil_volume = parseFloat(dataRecord.batch_size);
                if (dataRecord.brew_aboil_volume > 0)
                        aboil_volume = dataRecord.brew_aboil_volume / 1.04;     // volume @ 20 degrees
                if (dataRecord.brew_fermenter_tcloss == 0) {
                        dataRecord.brew_fermenter_tcloss = dataRecord.eq_trub_chiller_loss;
                        $("#brew_fermenter_tcloss").val(dataRecord.brew_fermenter_tcloss);
                }
                dataRecord.brew_fermenter_volume = aboil_volume - dataRecord.brew_fermenter_tcloss + dataRecord.brew_fermenter_extrawater;
                $("#brew_fermenter_volume").val(dataRecord.brew_fermenter_volume);
                // Estimated needed sparge water corrected for the temperature.
                spoelw = (dataRecord.boil_size - mash_infuse + (mashkg * my_grain_absorbtion) + dataRecord.eq_lauter_deadspace) * 1.03;
                $("#brew_sparge_est").val(spoelw);
                // Calculate SG in fermenter
                ogx = dataRecord.brew_aboil_sg;
                if (ogx < 1.002)
                        ogx = aboil_sg;
                topw = dataRecord.brew_fermenter_extrawater;

                if (dataRecord.brew_fermenter_volume > 0) {
                        sug = sg_to_plato(ogx) * dataRecord.brew_fermenter_volume * ogx / 100;  //kg of sugar in
                        sug += addedS; //kg

                        if ((dataRecord.brew_fermenter_volume * ogx + addedmass) > 0) {
                                pt = 100 * sug / (dataRecord.brew_fermenter_volume * ogx + addedmass + topw);
                                dataRecord.brew_fermenter_sg = Round(plato_to_sg(pt),4);
                                $("#brew_fermenter_sg").val(dataRecord.brew_fermenter_sg);
                                // color
                                if (dataRecord.color_method == 4) {
                                        dataRecord.brew_fermenter_color = Math.round(((pt / 8.6) * colorn) + (dataRecord.boil_time / 60));
                                } else if (dataRecord.color_method == 3) {
                                        dataRecord.brew_fermenter_color = Math.round((4.46 * bv * sr) /  (aboil_volume + topw) * colorh);
                                } else {
                                        cw = colort / (aboil_volume + topw) * 8.34436;
                                        dataRecord.brew_fermenter_color = kw_to_ebc(dataRecord.color_method, cw);
                                }
                                $("#brew_fermenter_color").val(dataRecord.brew_fermenter_color);
                                scolor = ebc_to_color(dataRecord.brew_fermenter_color);
                                $("#bcolorf").show();
                                document.getElementById("bcolorf").style.background = scolor;
                        }
                } else {
                        // Negative volume
                        dataRecord.brew_fermenter_sg = dataRecord.brew_fermenter_color = 0;
                        $("#brew_fermenter_sg").val(0);
                        $("#brew_fermenter_color").val(0);
                        $("#bcolorf").hide();
                }

                // Color of the wort
                if (dataRecord.color_method == 4) {
                        color = Math.round(((sg_to_plato(dataRecord.est_og) / 8.6) * colorn) + (dataRecord.boil_time / 60));
                } else if (dataRecord.color_method == 3) {      // Hans Halberstadt
                        color = Math.round((4.46 * bv * sr) /  parseFloat(dataRecord.batch_size) * colorh);
                } else {
                        cw = colort / parseFloat(dataRecord.batch_size) * 8.34436;
                        color = kw_to_ebc(dataRecord.color_method, cw);
                }
                dataRecord.est_color = color;
                $('#est_color').val(color);
                $('#est_color2').val(color);
                scolor = ebc_to_color(color);
                document.getElementById("bcolor").style.background= scolor;
                document.getElementById("bcolor2").style.background= scolor;

                // Progress bars
                pmalts = mashkg / dataRecord.eq_mash_max * 100;
                $("#perc_malts").jqxProgressBar('val', pmalts);
                $("#perc_sugars").jqxProgressBar('val', psugar);
                $("#perc_cara").jqxProgressBar('val', pcara);
                calcStage();

                // Calculate estimated svg.
                svg = 0; // default.
                initcells = 0;
                rows = $('#yeastGrid').jqxGrid('getrows');
                for (i = 0; i < rows.length; i++) {
                        row = rows[i];
                        if (row.y_use == 0) {   // Primary
                                if (parseFloat(row.y_attenuation) > svg)
                                        svg = parseFloat(row.y_attenuation);    // Take the highest if multiple yeasts.
                                if (row.y_form == 0)
                                        initcells += (parseFloat(row.y_cells) / 1000000000) * parseFloat(row.y_amount) * (dataRecord.starter_viability / 100);
                                else
                                        initcells += (parseFloat(row.y_cells) / 1000000) * parseFloat(row.y_amount);
                        }
                        // TODO: brett in secondary ??
                        if ((((dataRecord.inventory_reduced <= 3) && (row.y_use == 0)) ||  // Primary
                             ((dataRecord.inventory_reduced <= 4) && (row.y_use == 1)) ||  // Secondary
                             ((dataRecord.inventory_reduced <= 5) && (row.y_use == 2)) ||  // Tertiary
                             ((dataRecord.inventory_reduced <= 6) && (row.y_use == 3))) && // Bottle
                             (row.y_inventory < row.y_amount)) {
                                ok_yeasts = 0;
                        }
                }
               	calcSupplies();
                if (svg == 0)
                        svg = 77;

                if ((mashkg > 0) && (mash_infuse > 0) && (mashtime > 0) && (mashtemp > 0)) {
                        dataRecord.est_fg = estimate_fg(psugar, pcara, mash_infuse / mashkg, mashtime, mashtemp, svg, dataRecord.est_og);
                } else {
                        dataRecord.est_fg = estimate_fg(psugar, pcara, 0, 0, 0, svg, dataRecord.est_og);
                }
                $('#est_fg').val(dataRecord.est_fg);
                $('#est_fg2').val(dataRecord.est_fg);
                $('#est_fg3').val(dataRecord.est_fg);
                fig = dataRecord.est_fg;

                dataRecord.est_abv = abvol(dataRecord.est_og, dataRecord.est_fg);
                $("#est_abv").val(dataRecord.est_abv);
                $("#est_abv2").val(dataRecord.est_abv);

                // Calculate the final svg if available use the real value.
                if ((dataRecord.stage >= 6) && (dataRecord.fg > 0.990) && (dataRecord.fg < dataRecord.brew_fermenter_sg)) {
                        svg = 100 * (dataRecord.brew_fermenter_sg - dataRecord.fg) / (dataRecord.brew_fermenter_sg - 1);
                        org = dataRecord.brew_fermenter_sg;
                        fig = dataRecord.fg;
                }

                $("#yeast_cells").val(initcells);
                $("#need_cells").val(getNeededYeastCells());

                // Calculate the calories in kcal/l (from brouwhulp)
                alc = 1881.22 * fig * (org - fig) / (1.775 - org);
                sug = 3550 * fig * (0.1808 * org + 0.8192 * fig - 1.0004);
                $("#kcal").val(Math.round((alc + sug) / (12 * 0.0295735296)));
        };

        function calcMash() {

		var infused = 0, i, row;

                if (!(rows = $('#mashGrid').jqxGrid('getrows')))
                        return;
                if (mashkg == 0)
                        return;

                for (i = 0; i < rows.length; i++) {
                        row = $("#mashGrid").jqxGrid('getrowdata', i);
                        if (row.step_type == 0) // Infusion
                                infused += row.step_infuse_amount;
                        $("#mashGrid").jqxGrid('setcellvalue', i, "step_thickness", infused / mashkg);
                }
        }

       	/*
         * Change OG of recipe but keep the water volumes.
         */
        function calcFermentablesFromOG(OG) {

                console.log("calcFermentablesFromOG("+OG+")");
                var amount, row, d, i, sug, tot = 0, totmass = 0, rowscount, efficiency = parseFloat($("#efficiency").jqxNumberInput('decimal'));
                sug = sg_to_plato(OG) * parseFloat($("#batch_size").jqxNumberInput('decimal')) * OG / 100;      //total amount of sugars in kg
                rowscount = $("#fermentableGrid").jqxGrid('getdatainformation').rowscount;

                for (i = 0; i < rowscount; i++) {
                        row = $("#fermentableGrid").jqxGrid('getrowdata', i);
                        if (row.f_added < 4) {
                                d = row.f_percentage / 100 * (row.f_yield / 100) * (1 - row.f_moisture / 100);
                                if (row.f_added == 0)   // Mash
                                        d = efficiency / 100 * d;
                                tot += d;
                        }
                }
                if (tot)
                        totmass = Round(sug / tot,3);

                if (totmass) {
                        for (i = 0; i < rowscount; i++) {
                                row = $("#fermentableGrid").jqxGrid('getrowdata', i);
                                if (row.f_added < 4) {
                                        amount = Math.round(row.f_percentage * 10 * totmass) / 1000;
                                        $("#fermentableGrid").jqxGrid('setcellvalue', i, "f_amount", amount);
                                }
                        }
                }
        };

        function getNeededYeastCells() {

                var plato, volume, sg = dataRecord.brew_fermenter_sg;
                if (sg <= 1.0001 && dataRecord.fg > 1.000)
                        sg = dataRecord.fg;
                else if (sg <= 1.0001)
                        sg = dataRecord.est_og;
                plato = sg_to_plato(sg);

                volume = dataRecord.brew_fermenter_volume;
                if (volume <= 0)
                        volume = dataRecord.batch_size - dataRecord.eq_trub_chiller_loss;

                return pitchrate * volume * plato;
        }

        function hopFlavourContribution(bt, vol, use, amount) {
                var result;

                if (use == 1) { // First wort
                        result = 0.15;          // assume 15% flavourcontribution for fwh
                } else if (bt > 50) {
                        result = 0.10;          // assume 10% flavourcontribution as a minimum
                } else {
                        result = 15.25 / (6 * Math.sqrt(2 * Math.PI)) * Math.exp(-0.5 * Math.pow((bt - 21) /6, 2));
                        if (result < 0.10)
                                result = 0.10;  // assume 10% flavourcontribution as a minimum
                }
                return (result * amount * 1000) / vol;
        }

        function hopAromaContribution(bt, vol, use, amount) {
                var result = 0;

                if (use == 5) {         // Dry hop
                        result = 1.33;
                } else if (bt > 20) {
                        result = 0;
                } else if (bt > 7.5) {
                        result = 10.03 / (4 * Math.sqrt(2 * Math.PI)) * Math.exp(-0.5 * Math.pow((bt - 7.5) /4, 2));
                } else if (use == 2) {  // Boil
                        result = 1;
                } else if (use == 3) {  // Aroma
                        result = 1.2;
                } else if (use == 4) {  // Whirlpool
                        result = 1.2;
                }
                return (result * amount * 1000) / vol;
        }

        function calcIBUs() {
                var total_ibus = 0, ferm_ibus = 0, rows = {}, i, row;
                hop_aroma = hop_flavour = 0;
                if (!(rows = $('#hopGrid').jqxGrid('getrows'))) {
                        return;
                }
                ok_hops = 1;
                for (i = 0; i < rows.length; i++) {
                        row = rows[i];
                        total_ibus += toIBU(row.h_useat, row.h_form, preboil_sg, parseFloat(dataRecord.batch_size),
                                        parseFloat(row.h_amount), parseFloat(row.h_time), parseFloat(row.h_alpha), dataRecord.ibu_method);
                        ferm_ibus += toIBU(row.h_useat, row.h_form, preboil_sg,
                                        parseFloat(dataRecord.brew_fermenter_volume) + parseFloat(dataRecord.brew_fermenter_tcloss),
                                        parseFloat(row.h_amount), parseFloat(row.h_time), parseFloat(row.h_alpha), dataRecord.ibu_method);
                        hop_flavour += hopFlavourContribution(parseFloat(row.h_time), parseFloat(dataRecord.batch_size),
                                        row.h_useat, parseFloat(row.h_amount));
                        hop_aroma += hopAromaContribution(parseFloat(row.h_time), parseFloat(dataRecord.batch_size),
                                        row.h_useat, parseFloat(row.h_amount));
                        if ((((dataRecord.inventory_reduced <= 2) && (row.h_useat <= 4)) ||  // Mash, FW, Boil, Aroma, Whirlpool
                             ((dataRecord.inventory_reduced <= 6) && (row.h_useat == 5))) && // Dry-hop
                             (row.h_inventory < row.h_amount))
                                ok_hops = 0;
                }
                total_ibus = Math.round(total_ibus * 10) / 10;
                ferm_ibus = Math.round(ferm_ibus * 10) / 10;
                hop_flavour = Math.round(hop_flavour * 1000 / 5) / 10;
                hop_aroma = Math.round(hop_aroma * 1000 / 6) / 10;
                if (hop_flavour > 100)
                        hop_flavour = 100;
                if (hop_aroma > 100)
                        hop_aroma = 100;
                console.log("calcIBUs(): " + total_ibus + "  flavour: " + hop_flavour + "  aroma: " + hop_aroma+"  fermenter:"+ferm_ibus+" supplies:"+ok_hops);
                dataRecord.est_ibu = total_ibus;
                $('#est_ibu').val(total_ibus);
                $('#est_ibu2').val(total_ibus);
                $("#hop_flavour").jqxProgressBar('val', hop_flavour);
                $("#hop_aroma").jqxProgressBar('val', hop_aroma);
                $("#brew_fermenter_ibu").val(ferm_ibus);
                calcStage();
                calcSupplies();
        };

        /*
         * http://braukaiser.com/blog/blog/2012/11/03/estimating-yeast-growth/
         *
         * stype: 0=stirred, 1=shaken, 2=simple
         * totcells: initial cells
         * egrams: gram extract
         */
        function getGrowthRate(stype, totcells, egrams){

                /* Cells per grams extract (B/g) */
                var cpe = totcells / egrams;

                if (cpe > 3.5)
                        return 0;       // no growth
                if (stype == 2)
                        return 0.4;     // simple starter
                if (stype == 1)
                        return 0.62;    // shaken starter
                if (cpe <= 1.4)         // stirred starter
                        return 1.4;
                return 2.33 - (.67 * cpe );
        };

        function calcStep(svol, stype, start) {

            var gperpoint = 2.72715,  //number of grams of extract per point of starter gravity per liter
                prate = start/svol * 1000,
                irate = Round(prate,1),
                egrams = (dataRecord.starter_sg - 1) * svol * gperpoint;
                grate = getGrowthRate(stype, start, egrams),
                ncells = Round(egrams * grate, 1),
                totcells = parseFloat(ncells) + start;

                console.log("svol:"+svol+" start:"+start+" irate:"+irate+" egrams:"+egrams+" grate:"+grate+" ncells:"+ncells);
                return {
                        svol: svol,
                        irate: irate,
                        prate: Round(prate,1),
                        ncells: ncells,
                        totcells: totcells,
                        growf: Round(ncells/start, 2)
                };
        }

        /*
         * Calculate all starter steps.
         * stype: final starter type: 0 = stirred, 1 = shaked, 2 = simple.
         * start: initial cells in billions
         * needed: needed cells in billions
         *
         * result: all values updated.
         */
        function calcSteps(stype, start, needed) {

            var uvols  = [ 20, 40, 60,  80, 100, 150, 200, 250, 375, 500,  625, 750, 875, 1000, 1250, 1500, 2000, 2500, 3000, 4000, 5000 ],
                mvols  = uvols.length, svol = 0, lasti = 0, result = {}, i;

                /*
                 * If no values are set, auto calculate the starter.
                 */
                if ((parseFloat($("#prop1_volume").jqxNumberInput('decimal')) + parseFloat($("#prop2_volume").jqxNumberInput('decimal')) +
                     parseFloat($("#prop3_volume").jqxNumberInput('decimal')) + parseFloat($("#prop4_volume").jqxNumberInput('decimal'))) == 0) {
                        // clear by default
                        for (i = 1; i < 5; i++) {
                                $("#prop"+i+"_type").hide();
                                $("#r"+i+"_pmpt").show();
                                $("#prop"+i+"_type").val(stype);
                                $("#prop"+i+"_volume").hide();
                                $("#prop"+i+"_volume").val(0);
                                $("#prop"+i+"_irate").hide();
                                $("#prop"+i+"_ncells").hide();
                                $("#prop"+i+"_tcells").hide();
                                $("#prop"+i+"_growf").hide();
                        }
                        if (start > needed) {
                                return; // no starter needed
                        }
                        $("#prop1_type").show();
                        $("#r1_pmpt").hide();
                        $("#prop1_volume").show();
                        $("#prop1_irate").show();
                        $("#prop1_ncells").show();
                        $("#prop1_tcells").show();
                        $("#prop1_growf").show();
                        for (i = lasti; i <= mvols; i++) {
                                lasti = i;
                                svol = uvols[lasti];
                                result = calcStep(svol, stype, start);
                                if (result.irate < 25) {
                                        // inocculation rate too low, backup one step and break out.
                                        lasti = i - 1;
                                        svol = uvols[lasti];
                                        result = calcStep(svol, stype, start);
                                        break;
                                }
                                if (result.totcells > needed || i == mvols) { // hit the target or loops done
                                        break;
                                }
                        }
                        $("#prop1_volume").val(result.svol / 1000); // to liters
                        $("#prop1_irate").val(result.prate);
                        $("#prop1_ncells").val(result.ncells);
                        $("#prop1_tcells").val(result.totcells);
                        $("#prop1_growf").val(result.growf);
                        if (result.totcells > needed)
                                return; // hit the target

                        // second stage
                        $("#r2_pmpt").hide();
                        $("#prop2_type").val(stype);
                        $("#prop2_type").show();
                        $("#prop2_volume").show();
                        $("#prop2_irate").show();
                        $("#prop2_ncells").show();
                        $("#prop2_tcells").show();
                        $("#prop2_growf").show();
                        for (i = lasti; i <= mvols; i++) {
                                lasti = i;
                                svol = uvols[lasti];
                                result = calcStep(svol, stype, $("#prop1_tcells").val());
                                if (result.irate < 25) {
                                        lasti = i - 1;
                                        svol = uvols[lasti];
                                        result = calcStep(svol, stype, $("#prop1_tcells").val());
                                        break;
                                }
                                if (result.totcells > needed || i == mvols) { // hit the target or loops done
                                        break;
                                }
                        }
                        $("#prop2_volume").val(result.svol / 1000); // to liters
                        $("#prop2_irate").val(result.prate);
                        $("#prop2_ncells").val(result.ncells);
                        $("#prop2_tcells").val(result.totcells);
                        $("#prop2_growf").val(result.growf);
                        if (result.totcells > needed)
                                return; // hit the target

                        // third stage
                        $("#r3_pmpt").hide();
                        $("#prop3_type").val(stype);
                        $("#prop3_type").show();
                        $("#prop3_volume").show();
                        $("#prop3_irate").show();
                        $("#prop3_ncells").show();
                        $("#prop3_tcells").show();
                        $("#prop3_growf").show();
                        for (i = lasti; i <= mvols; i++) {
                                lasti = i;
                                svol = uvols[lasti];
                                result = calcStep(svol, stype, $("#prop2_tcells").val());
                                if (result.irate < 25) {
                                        lasti = i - 1;
                                        svol = uvols[lasti];
                                        result = calcStep(svol, stype, $("#prop2_tcells").val());
                                        break;
                                }
                                if (result.totcells > needed || i == mvols) { // hit the target or loops done
                                        break;
                                }
                        }
                        $("#prop3_volume").val(result.svol / 1000); // to liters
                        $("#prop3_irate").val(result.prate);
                        $("#prop3_ncells").val(result.ncells);
                        $("#prop3_tcells").val(result.totcells);
                        $("#prop3_growf").val(result.growf);
                        if (result.totcells > needed)
                                return; // hit the target

                        // fourth stage
                        $("#r4_pmpt").hide();
                        $("#prop4_type").val(stype);
                        $("#prop4_type").show();
                        $("#prop4_volume").show();
                        $("#prop4_irate").show();
                        $("#prop4_ncells").show();
                        $("#prop4_tcells").show();
                        $("#prop4_growf").show();
                        for (i = lasti; i <= mvols; i++) {
                                lasti = i;
                                svol = uvols[lasti];
                                result = calcStep(svol, stype, $("#prop3_tcells").val());
                                if (result.totcells > needed || i == mvols) { // hit the target or loops done
                                        $("#prop4_volume").val(result.svol / 1000); // to liters
                                        $("#prop4_irate").val(result.prate);
                                        $("#prop4_ncells").val(result.ncells);
                                        $("#prop4_tcells").val(result.totcells);
                                        $("#prop4_growf").val(result.growf);
                                        return;
                                }
                        }
                } else {
                        // recalculate
                        if (dataRecord.prop1_volume > 0) {
                                $("#r1_pmpt").hide();
                                $("#prop1_type").show();
                                $("#prop1_volume").show();
                                $("#prop1_irate").show();
                                $("#prop1_ncells").show();
                                $("#prop1_tcells").show();
                                $("#prop1_growf").show();
                                result = calcStep($("#prop1_volume").val() * 1000, dataRecord.prop1_type, start);
                                $("#prop1_irate").val(result.prate);
                                $("#prop1_ncells").val(result.ncells);
                                $("#prop1_tcells").val(result.totcells);
                                $("#prop1_growf").val(result.growf);
                        }
                        if (dataRecord.prop2_volume > 0) {
                                $("#r2_pmpt").hide();
                                $("#prop2_type").show();
                                $("#prop2_volume").show();
                                $("#prop2_irate").show();
                                $("#prop2_ncells").show();
                                $("#prop2_tcells").show();
                                $("#prop2_growf").show();
                                result = calcStep($("#prop2_volume").val() * 1000, dataRecord.prop2_type, $("#prop1_tcells").val());
                                $("#prop2_irate").val(result.prate);
                                $("#prop2_ncells").val(result.ncells);
                                $("#prop2_tcells").val(result.totcells);
                                $("#prop2_growf").val(result.growf);
                        }
                        if (dataRecord.prop3_volume > 0) {
                                $("#r3_pmpt").hide();
                                $("#prop3_type").show();
                                $("#prop3_volume").show();
                                $("#prop3_irate").show();
                                $("#prop3_ncells").show();
                                $("#prop3_tcells").show();
                                $("#prop3_growf").show();
                                result = calcStep($("#prop3_volume").val() * 1000, dataRecord.prop3_type, $("#prop2_tcells").val());
                                $("#prop3_irate").val(result.prate);
                                $("#prop3_ncells").val(result.ncells);
                                $("#prop3_tcells").val(result.totcells);
                                $("#prop3_growf").val(result.growf);
                        }
                        if (dataRecord.prop4_volume > 0) {
                                $("#r4_pmpt").hide();
                                $("#prop4_type").show();
                                $("#prop4_volume").show();
                                $("#prop4_irate").show();
                                $("#prop4_ncells").show();
                                $("#prop4_tcells").show();
                                $("#prop4_growf").show();
                                result = calcStep($("#prop4_volume").val() * 1000, dataRecord.prop4_type, $("#prop3_tcells").val());
                                $("#prop4_irate").val(result.prate);
                                $("#prop4_ncells").val(result.ncells);
                                $("#prop4_tcells").val(result.totcells);
                                $("#prop4_growf").val(result.growf);
                        }

                }
        }

        function calcYeast() {

                // Calculate needed cells.
		var plato, volume, rows, rowscount, row, i, needed, use_cells,
                sg = dataRecord.brew_fermenter_sg;
                if (sg <= 1.0001 && dataRecord.fg > 1.000)
                        sg = dataRecord.fg;
                else if (sg <= 1.0001)
                        sg = dataRecord.est_og;
                plato = sg_to_plato(sg);

                volume = dataRecord.brew_fermenter_volume;
                if (volume > 0) {
                        if (dataRecord.brew_fermenter_extrawater > 0)
                                volume += dataRecord.brew_fermenter_extrawater;
                } else {
                        volume = dataRecord.batch_size - dataRecord.eq_trub_chiller_loss;
                }

                // Also in calcFermentables()
                $("#yeast_cells").val(initcells);

                if (!(rows = $('#yeastGrid').jqxGrid('getrows'))) {
                        return; // grid not yet loaded.
                }
                rowscount = $("#yeastGrid").jqxGrid('getdatainformation').rowscount;
                if (rowscount == 0)
                        return; // no yeast in recipe

                for (i = 0; i < rowscount; i++) {
                        row = $("#yeastGrid").jqxGrid('getrowdata', i);
                        if (row.y_use == 0) { // primary
                                // pitchrate see https://www.brewersfriend.com/yeast-pitch-rate-and-starter-calculator/
                                // and http://braukaiser.com/blog/blog/2012/11/03/estimating-yeast-growth/
                                pitchrate = 0.75;
                                if (dataRecord.est_og > 1.060)
                                        pitchrate = 1.0;
//                              if (dataRecord.est_og > 1.076)
//                                      pitchrate = 1.25;       // Wyeast labs. http://www.wyeastlab.com/hb_pitchrates.cfm
                                if (row.y_type == 0) // lager yeast
                                        pitchrate *= 2;

                                if (row.y_form == 1) { // dry yeast
                                } else { // possible starter needed
                                }
                        }
                }
                needed = pitchrate * volume * plato;
                console.log("calcYeast() pitchrate:"+pitchrate+" start:"+initcells+" needed:"+needed+" volume:"+volume);
                $("#need_cells").val(needed);
                use_cells = initcells;

                if (dataRecord.starter_enable) {
                        calcSteps(dataRecord.starter_type, initcells, needed);

                        for (i = 1; i < 5; i++) {
                                $("#r"+i+"_irate").html("");
                                $("#r"+i+"_growf").html("");
                                $("#r"+i+"_tcells").html("");
                                if (parseFloat($("#prop"+i+"_volume").val()) > 0) {
                                        if ((parseFloat($("#prop"+i+"_irate").val()) < 25) || (parseFloat($("#prop"+i+"_irate").val()) > 100)) {
                                                $("#r"+i+"_irate").html("<img src='images/dialog-error.png'>");
                                        } else {
                                                $("#r"+i+"_irate").html("<img src='images/dialog-ok-apply.png'>");
                                        }
                                        if (parseFloat($("#prop"+i+"_growf").val()) < 1)
                                                $("#r"+i+"_growf").html("<img src='images/dialog-error.png'>");
                                        if (($("#prop"+i+"_type").val() > 0) && (parseFloat($("#prop"+i+"_growf").val()) > 3))
                                                $("#r"+i+"_growf").html("<img src='images/dialog-error.png'>");
                                        if (parseFloat($("#prop"+i+"_tcells").val()) > needed)
                                                $("#r"+i+"_tcells").html("<img src='images/dialog-ok-apply.png'>");
                                        use_cells = parseFloat($("#prop"+i+"_tcells").val());
                                } else {
                                        $("#r"+i+"_irate").html("");
                                }
                        }
                }
                $("#plato_cells").val(parseFloat(use_cells / (volume * plato) ));
        };

        function adjustHops(factor) {

                console.log("adjustHops("+factor+")");
                var row, i, amount, rowscount = $("#hopGrid").jqxGrid('getdatainformation').rowscount;
                if (rowscount == 0)
                        return;
                for (i = 0; i < rowscount; i++) {
                        row = $("#hopGrid").jqxGrid('getrowdata', i);
                        amount = row.h_amount * factor;
                        $("#hopGrid").jqxGrid('setcellvalue', i, "h_amount", amount);
                }
        };

        function calcMiscs() {

                ok_miscs = 1;
                var row, i, rowscount = $("#miscGrid").jqxGrid('getdatainformation').rowscount;
                if (rowscount == 0)
                        return;
                for (i = 0; i < rowscount; i++) {
                        row = $("#miscGrid").jqxGrid('getrowdata', i);
                        if ((((dataRecord.inventory_reduced <= 2) && (row.m_use_use <= 2)) ||  // Starter, Mash, Boil
                             ((dataRecord.inventory_reduced <= 3) && (row.m_use_use == 3)) ||  // Primary
                             ((dataRecord.inventory_reduced <= 5) && (row.m_use_use == 4)) ||  // Secondary, Teriary
                             ((dataRecord.inventory_reduced <= 6) && (row.m_use_use == 5))) && // Bottle
                             (row.m_inventory < row.m_amount)) {
                                ok_miscs = 0;
                        }
                }
                calcSupplies();
        };

        function adjustMiscs(factor) {

                console.log("adjustMiscs("+factor+")");
                var row, i, amount, rowscount = $("#miscGrid").jqxGrid('getdatainformation').rowscount;
                if (rowscount == 0)
                        return;
                for (i = 0; i < rowscount; i++) {
                        row = $("#miscGrid").jqxGrid('getrowdata', i);
                        amount = row.m_amount * factor;
                        $("#miscGrid").jqxGrid('setcellvalue', i, "m_amount", amount);
                        switch (row.m_name) {
                                case 'CaCl2':           $("#wa_cacl2").val(row.m_amount * 1000);
                                                        break;
                                case 'CaSO4':           $("#wa_caso4").val(row.m_amount * 1000);
                                                        break;
                                case 'MgSO4':           $("#wa_mgso4").val(row.m_amount * 1000);
                                                        break;
                                case 'NaCl':            $("#wa_nacl").val(row.m_amount * 1000);
                                                        break;
                                case 'Melkzuur':
                                case 'Zoutzuur':
                                case 'Fosforzuur':
                                case 'Zwavelzuur':      $("#wa_acid").val(row.m_amount * 1000);
                                                        break;
                                case 'NaHCO3':
                                case 'Na2CO3':
                                case 'CaCO3':
                                case 'Ca(OH)2':         $("#wa_base").val(row.m_amount * 1000);
                                                        break;
                        }
                }
        };

        function adjustYeasts(factor) {

                console.log("adjustYeasts("+factor+")");
                var row, i, amount, rowscount = $("#yeastGrid").jqxGrid('getdatainformation').rowscount;
                if (rowscount == 0)
                        return;
                for (i = 0; i < rowscount; i++) {
                        row = $("#yeastGrid").jqxGrid('getrowdata', i);
                        if (row.y_form == 1) { // Only adjust dry yeast
                                amount = row.y_amount * factor;
                                $("#yeastGrid").jqxGrid('setcellvalue', i, "y_amount", amount);
                        }
                }
                calcYeast();
        };

        function adjustWaters(factor) {

                console.log("adjustWaters("+factor+")");
                var amount, row, i, rowscount = $("#mashGrid").jqxGrid('getdatainformation').rowscount;
                if (rowscount == 0)
                        return;
                mash_infuse = 0;
                for (i = 0; i < rowscount; i++) {
                        row = $("#mashGrid").jqxGrid('getrowdata', i);
                        if (row.step_type == 0) { // Infusion
                                amount = Round(row.step_infuse_amount * factor, 1);
                                $("#mashGrid").jqxGrid('setcellvalue', i, "step_infuse_amount", amount);
                                mash_infuse += amount;
                        }
                }
                if (dataRecord.w2_amount == 0) {
                        dataRecord.w1_amount = mash_infuse;
                        $("#w1_amount").val(mash_infuse);
                } else {
                        dataRecord.w1_amount = (dataRecord.w1_amount / (dataRecord.w1_amount + dataRecord.w2_amount)) * mash_infuse;
                        dataRecord.w2_amount = (dataRecord.w2_amount / (dataRecord.w1_amount + dataRecord.w2_amount)) * mash_infuse;
                        $("#w1_amount").val(dataRecord.w1_amount);
                        $("#w2_amount").val(dataRecord.w2_amount);
                }
                $('#wg_amount').val(mash_infuse);
        };

        function calcMashEfficiency() {
		var c, m;
                if (parseFloat($("#brew_mash_sg").jqxNumberInput('decimal')) < 1.002)
                        return;
                c = sg_to_plato(est_mash_sg);
                m = sg_to_plato(parseFloat($("#brew_mash_sg").jqxNumberInput('decimal')));
                if (c > 0.5)
                        $("#brew_mash_efficiency").val(100 * m / c);
                else
                        $("#brew_mash_efficiency").val(0);
        };

        function calcEfficiencyBeforeBoil() {
                var m = 0, rows = {}, i, row, tot, result = 0;
                if (!(rows = $('#fermentableGrid').jqxGrid('getrows'))) {
                        return; // grid not yet loaded.
                }
                for (i = 0; i < rows.length; i++) {
                        row = rows[i];
                        if (row.f_added == 0) { // Mash
                                m += row.f_amount * (row.f_yield / 100) * (1 - row.f_moisture / 100);
                        }
                }
                tot = sg_to_plato(dataRecord.brew_preboil_sg) * (dataRecord.brew_preboil_volume / 1.04) * dataRecord.brew_preboil_sg * 10 / 1000;
                if (m > 0)
                        result = Round((tot / m * 100), 1);
                if (result < 0)
                        result = 0;
                $("#brew_preboil_efficiency").val(result);
        }

        function calcEfficiencyAfterBoil() {
                var m = 0,	// Sugars added at mash
                b = 0,		// Sugars added at boil
                rows = {}, i, row, tot, result = 0;
                if (!(rows = $('#fermentableGrid').jqxGrid('getrows'))) {
                        return; // grid not yet loaded.
                }
                for (i = 0; i < rows.length; i++) {
                        row = rows[i];
                        if (row.f_added == 0) { // Mash
                                m += row.f_amount * (row.f_yield / 100) * (1 - row.f_moisture / 100);
                        } else if (row.f_added == 1) { // Boil
                                b += row.f_amount * (row.f_yield / 100) * (1 - row.f_moisture / 100);
                        }
                }
                tot = sg_to_plato(dataRecord.brew_aboil_sg) * (dataRecord.brew_aboil_volume / 1.04) * dataRecord.brew_aboil_sg * 10 / 1000;
                tot -= b;       // total sugars in wort  minus added sugars.
                if (m > 0)
                        result = Round((tot / m * 100), 1);
                if (result < 0)
                        result = 0;
                dataRecord.brew_aboil_efficiency = result;
                $("#brew_aboil_efficiency").val(result);

        }

        function GetBUGU() {
                var gu = (dataRecord.est_og - 1) * 1000;
                if (gu > 0)
                        return dataRecord.est_ibu / gu;
                else
                        return 0.5;
        }

        function GetOptClSO4ratio() {
                var BUGU = GetBUGU();
                return (-1.2 * BUGU + 1.4);
        }

        function setWaterAgent(name, amount) {
                var row, i, id, found = false, miscs, rows = $('#miscGrid').jqxGrid('getrows');
                if (amount == 0) {
                        for (i = 0; i < rows.length; i++) {
                                row = rows[i];
                                if (row.m_name == name) {
                                        id = $("#miscGrid").jqxGrid('getrowid', i);
                                        $("#miscGrid").jqxGrid('deleterow', id);
                                }
                        }
                } else {
                        for (i = 0; i < rows.length; i++) {
                                row = rows[i];
                                if (row.m_name == name) {
                                        found = true;
                                        $("#miscGrid").jqxGrid('setcellvalue', i, 'm_amount', amount / 1000);
                                        break;
                                }
                        }
                        if (! found) {
                                miscs = new $.jqx.dataAdapter(miscInvSource, {
                                        loadComplete: function () {
                                                var record, i, row = {}, records = miscs.records;
                                                for (i = 0; i < records.length; i++) {
                                                        record = records[i];
                                                        if (record.name == name) {
                                                                row["m_name"] = record.name;
                                                                row["m_amount"] = amount / 1000;
                                                                row["m_cost"] = record.cost;
                                                                row["m_type"] = record.type;
                                                                row["m_use_use"] = record.use_use;
                                                                row["m_time"] = 0;
                                                                row["m_amount_is_weight"] = record.amount_is_weight;
                                                                row["m_inventory"] = record.inventory;
                                                                row["m_avail"] = 1;
                                                                $("#miscGrid").jqxGrid('addrow', null, row);
                                                        }
                                                }
                                        }
                                });
                                miscs.dataBind();
                                return;
                        }
                }
        }

        function setRangeIndicator(ion, rangeCode) {
                if ((rangeCode == "laag") || (rangeCode == "hoog"))
                        $("#wr_"+ion).html("<img src='images/dialog-error.png'><span style='vertical-align: top; font-size: 10px; font-style: italic;'>"+rangeCode + "</span>");
                else
                        $("#wr_"+ion).html("<img src='images/dialog-ok-apply.png'>");
        }

        function mix(v1, v2, c1, c2) {
                if ((v1 + v2) > 0) {
                        return ((v1 * c1) + (v2 * c2)) / (v1 + v2);
                }
                return 0;
        }

        // mg/l as CaCO3
        function ResidualAlkalinity(total_alkalinity, calcium, magnesium) {
                return total_alkalinity - (calcium / 1.4 + magnesium / 1.7);
        }

        function PartCO3(pH) {
                var H = Math.pow(10, -pH);
                return 100 * Ka1 * Ka2 / (H*H + H * Ka1 + Ka1 * Ka2);
        }

        function PartHCO3(pH) {
                var H = Math.pow(10, -pH);
                return 100 * Ka1 * H / (H*H + H * Ka1 + Ka1 * Ka2);
        }

        function Charge(pH) {
                return (-2 * PartCO3(pH) - PartHCO3(pH));
        }

        //Z alkalinity is the amount of acid (in mEq/l) needed to bring water to the target pH (Z pH)
        function ZAlkalinity(pHZ) {
                var C43 = Charge(4.3),
                Cw = Charge(parseFloat($("#wg_ph").jqxNumberInput('decimal'))),
                Cz = Charge(pHZ),
                DeltaCNaught = -C43+Cw,
                CT = parseFloat($("#wg_total_alkalinity").jqxNumberInput('decimal')) / 50 / DeltaCNaught,
                DeltaCZ = -Cz+Cw;
                return CT * DeltaCZ;
        }

        //Z Residual alkalinity is the amount of acid (in mEq/l) needed to bring the water in the mash to the target pH (Z pH)
        function ZRA(pHZ) {

                var Magn, Z, Calc = parseFloat($("#wg_calcium").jqxNumberInput('decimal')) / (MMCa / 2);
                Magn = parseFloat($("#wg_magnesium").jqxNumberInput('decimal')) / (MMMg / 2);
                Z = ZAlkalinity(pHZ);
                return Z - (Calc / 3.5 + Magn / 7);
        }

        function ProtonDeficit(pHZ) {

		var rows, i, C1, ebc, x, Result = ZRA(pHZ) * parseFloat($("#wg_amount").jqxNumberInput('decimal'));
                // proton deficit for the grist
                rows = $('#fermentableGrid').jqxGrid('getrows');
                for (i = 0; i < rows.length; i++) {
                        row = rows[i];
                        if (row.f_added == 0 && row.f_graintype != 6) { // Added == Mash && graintype != No Malt
                                // Check if acid is required
                                C1 = 0;
                                if ((row.f_di_ph != 5.7) && ((row.f_acid_to_ph_57 < - 0.1) || (row.f_acid_to_ph_57 > 0.1))) {
                                        C1 = row.f_acid_to_ph_57 / (row.f_di_ph - 5.7);
                                } else {
                                        // If the acid_to_ph_5.7 is unknown from the maltster, guess the required acid.
                                        ebc = row.f_color;
                                        switch (row.f_graintype) {
                                                case 0:                                 // Base, Special, Kilned
                                                case 3:
                                                case 5: C1 = 0.014 * ebc - 34.192;
                                                        break;
                                                case 2: C1 = -0.0597 * ebc - 32.457;    // Crystal
                                                        break;
                                                case 1: C1 = 0.0107 * ebc - 54.768;     // Roast
                                                        break;
                                                case 4: C1 = -149;                      // Sour malt
                                                        break;
                                        }
                                }
                                x = C1 * (pHZ - row.f_di_ph);   // AcidRequired(ZpH)
                                Result += x * row.f_amount;
                        }
                }
                return Result;
        }

        function MashpH() {
                var n = 0, pH = 5.4, deltapH = 0.001, deltapd = 0.1, pd = ProtonDeficit(pH);
                while (((pd < -deltapd) || (pd > deltapd)) && (n < 2000)) {
                        n++;
                        if (pd < -deltapd)
                                pH -= deltapH;
                        else if (pd > deltapd)
                                pH += deltapH;
                        pd = ProtonDeficit(pH);
                }
                console.log("MashpH() n: "+n+" pH: "+pH);
                return pH;
        }

        function GetAcidSpecs(AT) {
                switch(AT) {
                        case 0: return {        // Melkzuur
                                        pK1: 3.86,
                                        pK2: 20,
                                        pK3: 20,
                                        MolWt: 90.08,
                                        AcidSG: 1214,   // 1214  1209
                                        AcidPrc: 0.88   // 0.88  0.80
                                };
                        case 1: return {        // Zoutzuur
                                        pK1: -7,
                                        pK2: 20,
                                        pK3: 20,
                                        MolWt: 36.46,
                                        AcidSG: 1142,
                                        AcidPrc: 0.28
                                };
                        case 2: return {        // Fosforzuur
                                        pK1: 2.12,
                                        pK2: 7.20,
                                        pK3: 12.44,
                                        MolWt: 98.00,
                                        AcidSG: 1170,
                                        AcidPrc: 0.25
                                };
                        case 3: return {        // Zwavelzuur
                                        pK1: -1,
                                        pK2: 1.92,
                                        pK3: 20,
                                        MolWt: 98.07,
                                        AcidSG: 1700,
                                        AcidPrc: 0.93
                                };
                }
        }

        function calcWater() {

                console.log("calcWater()");
                var liters = 0,
                calcium = 0,
                magnesium = 0,
                sodium = 0,
                total_alkalinity = 0,
                bicarbonate = 0,
                chloride = 0,
                sulfate = 0,
                ph = 0,
                RA = 0,
                frac = 0,
                TpH = 0,
                protonDeficit = 0,
		AT, BT, result, pK1, pK2, pK3, MolWt, AcidSG, AcidPrc,
		r1d, r2d, f1d, f2d, f3d,
		deltapH, deltapd, pd, n,
		piCLSO4_low, piCLSO4_high, Res,
		wg_calcium, wg_sodium, wg_total_alkalinity, wg_chloride, wg_sulfate, wg_bicarbonate;

                if (dataRecord.w1_name == "") {
                        return;
                }

                // If there is a dillute water source, mix the waters.
                if (dataRecord.w2_name != "") {
                        liters = dataRecord.w1_amount + dataRecord.w2_amount;
                        calcium = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_calcium, dataRecord.w2_calcium);
                        magnesium = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_magnesium, dataRecord.w2_magnesium);
                        sodium = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_sodium, dataRecord.w2_sodium);
                        chloride = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_chloride, dataRecord.w2_chloride);
                        sulfate = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_sulfate, dataRecord.w2_sulfate);
                        total_alkalinity = mix(dataRecord.w1_amount, dataRecord.w2_amount, dataRecord.w1_total_alkalinity, dataRecord.w2_total_alkalinity);
                        ph = -Math.log10(((Math.pow(10, -dataRecord.w1_ph) * dataRecord.w1_amount) + (Math.pow(10, -dataRecord.w2_ph) * dataRecord.w2_amount))  / liters);
                } else {
                        liters = dataRecord.w1_amount;
                        calcium = dataRecord.w1_calcium;
                        magnesium = dataRecord.w1_magnesium;
                        sodium = dataRecord.w1_sodium;
                        chloride = dataRecord.w1_chloride;
                        sulfate = dataRecord.w1_sulfate;
                        total_alkalinity = dataRecord.w1_total_alkalinity;
                        ph = dataRecord.w1_ph;
                }
                $('#wg_amount').val(liters);
                wg_calcium = calcium;
                $('#wg_calcium').val(Math.round(calcium * 10) / 10);
                //var wg_magnesium = magnesium;
                $('#wg_magnesium').val(Math.round(magnesium * 10) / 10);
                wg_sodium = sodium;
                $('#wg_sodium').val(Math.round(sodium * 10) / 10);
                wg_total_alkalinity = total_alkalinity;
                $('#wg_total_alkalinity').val(Math.round(total_alkalinity * 10) / 10);
                wg_chloride = chloride;
                $('#wg_chloride').val(Math.round(chloride * 10) / 10);
                wg_sulfate = sulfate;
                $('#wg_sulfate').val(Math.round(sulfate * 10) / 10);
                // Note: brouwhulp has the malts included here in the result.
                //var wg_ph = ph;
                $('#wg_ph').val(Round(ph,1));
                $('#wb_ph').val(Round(MashpH(), 1));
                $('#est_mash_ph').val(Round(MashpH(), 1));
                bicarbonate = total_alkalinity * 1.22;
                wg_bicarbonate = bicarbonate;

                // Noot: de volgende berekeningen geven bijna gelijke resultaten in Brun'water.
                // Calculate Ca
                RA = parseFloat($("#wa_cacl2").jqxNumberInput('decimal')) * MMCa / MMCaCl2 +
                     parseFloat($("#wa_caso4").jqxNumberInput('decimal')) * MMCa / MMCaSO4;
                calcium += 1000 * RA / liters;

                // Calculate Mg
                RA = parseFloat($("#wa_mgso4").jqxNumberInput('decimal')) * MMMg / MMMgSO4;
                magnesium += 1000 * RA / liters;

                // Calculate Na
                RA = parseFloat($("#wa_nacl").jqxNumberInput('decimal')) * MMNa / MMNaCl +
                     parseFloat($("#wa_base").jqxNumberInput('decimal')) * MMNa / MMNaHCO3;
                sodium += 1000 * RA / liters;

                // Calculate SO4
                RA = parseFloat($("#wa_caso4").jqxNumberInput('decimal')) * MMSO4 / MMCaSO4 +
                     parseFloat($("#wa_mgso4").jqxNumberInput('decimal')) * MMSO4 / MMMgSO4;
                sulfate += 1000 * RA / liters;

                // Calculate Cl
                RA = 2 * parseFloat($("#wa_cacl2").jqxNumberInput('decimal')) * MMCl / MMCaCl2 +
                         parseFloat($("#wa_nacl").jqxNumberInput('decimal')) * MMCl / MMNaCl;
                chloride += 1000 * RA / liters;
                // Einde noot.

                if ($("#wa_acid_name").val() < 0 || $("#wa_acid_name").val() > 3) {
                        $("#wa_acid_name").val(0);
                        dataRecord.wa_acid_name = 0;
                }
                if (last_acid == '')
                        last_acid = AcidTypeData[$("#wa_acid_name").val()].nl;

                if ($("#wa_base_name").val() < 0 || $("#wa_base_name").val() > 3) {
                        $("#wa_base_name").val(0);
                        dataRecord.wa_base_name = 0;
                }
                if (last_base == '')
                        last_base = BaseTypeData[$("#wa_base_name").val()].nl;

                AT = dataRecord.wa_acid_name;
                BT = dataRecord.wa_base_name;

                result = GetAcidSpecs(AT);
                pK1 = result.pK1;
                pK2 = result.pK2;
                pK3 = result.pK3;
                MolWt = result.MolWt;
                AcidSG = result.AcidSG;
                AcidPrc = result.AcidPrc;

                if (dataRecord.calc_acid) {
                        TpH = parseFloat(dataRecord.mash_ph);
                        protonDeficit = ProtonDeficit(TpH);
                        console.log("calc_acid tgt: "+TpH+" protonDeficit: "+protonDeficit);
                        if (protonDeficit > 0) { // Add acid
                                $("#wa_base").val(0);
                                setWaterAgent(last_base, 0);
                                frac = CalcFrac(TpH, pK1, pK2, pK3);
                                Acid = protonDeficit / frac;
                                Acid *= MolWt; // mg
                                Acidmg = Acid;
                                Acid = Acid / AcidSG; // ml

                                if (parseFloat($("#wa_acid_perc").jqxNumberInput('decimal')) == 0)
                                        $("#wa_acid_perc").val(AcidPrc);
                                Acid = Acid * AcidPrc / (parseFloat($("#wa_acid_perc").jqxNumberInput('decimal')) / 100); // ml
                                console.log("Final ml: "+Acid);
                                $("#wa_acid").val(Round(Acid, 2));
                                setWaterAgent(AcidTypeData[AT].nl, Round(Acid, 2));

                                bicarbonate = bicarbonate - protonDeficit * frac / liters;
                                total_alkalinity = bicarbonate * 50 / 61;
                        } else if (protonDeficit < 0) { //Add base
                                $("#wa_acid").val(0);
                                setWaterAgent(last_acid, 0);
                                r1d = Math.pow(10, (TpH - 6.38));
                                r2d = Math.pow(10, (TpH - 10.38));
                                f1d = 1 / (1 + r1d + r1d * r2d);
                                f2d = f1d * r1d;
                                f3d = f2d * r2d;
                                switch (BT) {
                                        case 0:  RA = -protonDeficit / (f1d - f3d); // Sodiumbicarbonate, mmol totaal
                                                RA = RA * MMNaHCO3/1000; //gram
                                                $("#wa_base").val(Round(RA, 2));
                                                setWaterAgent('NaHCO3', Round(RA, 2));
                                                if (liters > 0) {
                                                        // Na
                                                        RA = parseFloat($("#wa_nacl").jqxNumberInput('decimal')) * MMNa / MMNaCl +
                                                             parseFloat($("#wa_base").jqxNumberInput('decimal')) * MMNa / MMNaHCO3;
                                                        RA = 1000 * RA / liters;
                                                        sodium = wg_sodium + RA;
                                                        // HCO3
                                                        RA = parseFloat($("#wa_base").jqxNumberInput('decimal')) * MMHCO3 / MMNaHCO3;
                                                        RA = 1000 * RA / liters;
                                                        bicarbonate = wg_bicarbonate + RA;
                                                        total_alkalinity = bicarbonate * 50 / 61;
                                                        RA = ResidualAlkalinity(wb_total_alkalinity, wb_calcium, wb_magnesium);
                                                }
                                                break;
                                        case 1: RA = -protonDeficit / (2 * f1d + f2d); // Sodiumcarbonate, mmol totaal
                                                RA = RA * MMNa2CO3/1000; //gram
                                                $("#wa_base").val(Round(RA, 2));
                                                setWaterAgent('Na2CO3', Round(RA, 2));
                                                if (liters > 0) {
                                                        RA = parseFloat($("#wa_nacl").jqxNumberInput('decimal')) * MMNa / MMNaCl +
                                                             parseFloat($("#wa_base").jqxNumberInput('decimal')) * 2 * MMNa / MMNa2CO3;
                                                        RA = 1000 * RA / liters;
                                                        sodium = wg_sodium + RA;
                                                        // HCO3
                                                        RA = parseFloat($("#wa_base").jqxNumberInput('decimal')) * MMHCO3 / MMNa2CO3;
                                                        RA = 1000 * RA / liters;
                                                        bicarbonate = wg_bicarbonate + RA;
                                                        total_alkalinity = bicarbonate * 50 / 61;
                                                        RA = ResidualAlkalinity(wb_total_alkalinity, wb_calcium, wb_magnesium);
                                                }
                                                break;
                                        case 2: RA = -protonDeficit * (f1d - f3d); // Calciumcarbonate, mmol totaal
                                                RA = RA * MMCaCO3/1000; //gram
                                                //but only 1/3 is effective, so add 3 times as much
                                                RA = 3 * RA;
                                                $("#wa_base").val(Round(RA, 2));
                                                setWaterAgent('CaCO3', Round(RA, 2));
                                                if (liters > 0) {
                                                        //Bicarbonate
                                                        RA = parseFloat($("#wa_base").jqxNumberInput('decimal')) / 3 * MMHCO3 / MMCaCO3;
                                                        RA = 1000 * RA / liters;
                                                        bicarbonate = wg_bicarbonate + RA;
                                                        total_alkalinity = bicarbonate * 50 / 61;
                                                        //Ca precipitates out as Ca10(PO4)6(OH)2
                                                        RA = parseFloat($("#wa_cacl2").jqxNumberInput('decimal')) * MMCa / MMCaCl2 +
                                                             parseFloat($("#wa_caso4").jqxNumberInput('decimal')) * MMCa / MMCaSO4 +
                                                             parseFloat($("#wa_base").jqxNumberInput('decimal')) * MMCa / MMCaCO3;
                                                        RA = 1000 * RA / liters;
                                                        calcium = wg_calcium + RA;
                                                        RA = ResidualAlkalinity(wb_total_alkalinity, wb_calcium, wb_magnesium);
                                                }
                                                break;
                                        case 3: RA = -protonDeficit / 19.3; // Calciumhydroxide
                                                $("#wa_base").val(Round(RA, 2));
                                                setWaterAgent('Ca(OH)2', Round(RA, 2));
                                                if (liters > 0) {
                                                        // Bicarbonate
                                                        RA = -protonDeficit / liters;
                                                        total_alkalinity = wg_total_alkalinity + RA;
                                                        bicarbonate = total_alkalinity * 61 / 50;
                                                        // Calcium
                                                        RA = parseFloat($("#wa_cacl2").jqxNumberInput('decimal')) * MMCa / MMCaCl2 +
                                                             parseFloat($("#wa_caso4").jqxNumberInput('decimal')) * MMCa / MMCaSO4 +
                                                             parseFloat($("#wa_base").jqxNumberInput('decimal')) * MMCa / MMCaOH2;
                                                        RA = 1000 * RA / liters;
                                                        calcium = wg_calcium + RA;
                                                        RA = ResidualAlkalinity(wb_total_alkalinity, wb_calcium, wb_magnesium);
                                                }
                                                break;
                                }
                        }
                        ph = TpH;
                        $('#wb_ph').val(Round(ph, 1));
                        $('#est_mash_ph').val(Round(ph, 1));
                } else { // Manual
                        console.log("calc_acid no");
                        // First add base salts
                        if (parseFloat($("#wa_base").jqxNumberInput('decimal')) > 0) {
                                if (liters > 0) {
                                        switch (BT) {
                                                case 0:  // Sodiumbicarbonate, Na
                                                        RA = parseFloat($("#wa_nacl").jqxNumberInput('decimal')) * MMNa / MMNaCl +
                                                             parseFloat($("#wa_base").jqxNumberInput('decimal')) * MMNa / MMNaHCO3;
                                                        RA = 1000 * RA / liters;
                                                        sodium = wg_sodium + RA;
                                                        // HCO3
                                                        RA = parseFloat($("#wa_base").jqxNumberInput('decimal')) * MMHCO3 / MMNaHCO3;
                                                        RA = 1000 * RA / liters;
                                                        bicarbonate = wg_bicarbonate + RA;
                                                        total_alkalinity = bicarbonate * 50 / 61;
                                                        RA = ResidualAlkalinity(wb_total_alkalinity, wb_calcium, wb_magnesium);
                                                        break;
                                                case 1: // Sodiumcarbonate
                                                        RA = parseFloat($("#wa_nacl").jqxNumberInput('decimal')) * MMNa / MMNaCl +
                                                             parseFloat($("#wa_base").jqxNumberInput('decimal')) * 2 * MMNa / MMNa2CO3;
                                                        RA = 1000 * RA / liters;
                                                        sodium = wg_sodium + RA;
                                                        // HCO3
                                                        RA = parseFloat($("#wa_base").jqxNumberInput('decimal')) * MMHCO3 / MMNa2CO3;
                                                        RA = 1000 * RA / liters;
                                                        bicarbonate = wg_bicarbonate + RA;
                                                        total_alkalinity = bicarbonate * 50 / 61;
                                                        RA = ResidualAlkalinity(wb_total_alkalinity, wb_calcium, wb_magnesium);
                                                        break;
                                                case 2: // Calciumcarbonate: Bicarbonate
                                                        RA = parseFloat($("#wa_base").jqxNumberInput('decimal')) / 3 * MMHCO3 / MMCaCO3;
                                                        RA = 1000 * RA / liters;
                                                        bicarbonate = wg_bicarbonate + RA;
                                                        total_alkalinity = bicarbonate * 50 / 61;
                                                        RA = ResidualAlkalinity(wb_total_alkalinity, wb_calcium, wb_magnesium);
                                                        // Ca
                                                        RA = parseFloat($("#wa_cacl2").jqxNumberInput('decimal')) * MMCa / MMCaCl2 +
                                                             parseFloat($("#wa_caso4").jqxNumberInput('decimal')) * MMCa / MMCaSO4 +
                                                             parseFloat($("#wa_base").jqxNumberInput('decimal')) * MMCa / MMCaCO3;
                                                        RA = 1000 * RA / liters;
                                                        calcium = wg_calcium + RA;
                                                        break;
                                        }
                                }
                        }

                        TpH = parseFloat(dataRecord.mash_ph);
                        pHa = MashpH(); // This one is in demi water, should be in adjusted water???
                        // Then calculate the new pH with added acids
                        if (parseFloat($("#wa_acid").jqxNumberInput('decimal')) > 0) {
                                console.log("TpH: "+TpH+" water: "+pHa);
                                Acid = parseFloat($("#wa_acid").jqxNumberInput('decimal'));
                                if (parseFloat($("#wa_acid_perc").jqxNumberInput('decimal')) == 0)
                                        $("#wa_acid_perc").val(AcidPrc);
                                Acid = Acid / AcidPrc * (parseFloat($("#wa_acid_perc").jqxNumberInput('decimal')) / 100); // ml
                                Acid *= AcidSG; // ml
                                Acid /= MolWt;  // mg
                                Acidmg = Acid;

                                //find the pH where the protondeficit = protondeficit by the acid
                                frac = CalcFrac(pHa, pK1, pK2, pK3);
                                protonDeficit = Acid * frac;

                                deltapH = 0.001;
                                deltapd = 0.1;
                                pd = ProtonDeficit(pHa);
                                n = 0;
                                while (((pd < (protonDeficit - deltapd)) || (pd > (protonDeficit + deltapd))) && (n < 2000)) {
                                        n++;
                                        if (pd < (protonDeficit-deltapd))
                                                pHa -= deltapH;
                                        else if (pd > (protonDeficit+deltapd))
                                                pHa += deltapH;
                                        frac = CalcFrac(pHa, pK1, pK2, pK3);
                                        protonDeficit = Acid * frac;
                                        pd = ProtonDeficit(pHa);
                                }
                                console.log("n: "+n+" pd: "+pd+" protonDeficit: "+protonDeficit+" frac: "+frac+" pHa: "+pHa);
                                RA = wg_bicarbonate - protonDeficit * frac / liters;
                                bicarbonate = RA;
                                total_alkalinity = RA * 50 / 61;
                                ph = pHa;
                                $('#wb_ph').val(Round(ph, 1));
                                $('#est_mash_ph').val(Round(ph, 1));
                        }
                }

                if ((AT == 3) && (liters > 0)) {        // Sulfuctic / Zwavelzuur
                        RA = parseFloat($("#wa_caso4").jqxNumberInput('decimal')) * MMSO4 / MMCaSO4 +
                             parseFloat($("#wa_mgso4").jqxNumberInput('decimal')) * MMSO4 / MMMgSO4 +
                             Acidmg / 1000 * MMSO4 / (MMSO4 + 2);
                        RA = 1000 * RA / liters;
                        sulfate = wg_sulfate + RA;      // Not add to sulfate??
                } else if ((AT == 1) && (liters > 0)) { // Hydrochloric, Zoutzuur
                        RA = parseFloat($("#wa_cacl2").jqxNumberInput('decimal')) * MMCl / MMCaCl2 +
                             parseFloat($("#wa_nacl").jqxNumberInput('decimal')) * MMCl / MMNaCl +
                             Acidmg / 1000 * MMCl / (MMCl + 1);
                        RA = 1000 * RA / liters;
                        chloride = wg_chloride + RA;
                }

                // 2:1 Sulfate to Chroride IPA's, Pale Ales.
                // 1:1 Sulfate to Chloride Balanced
                // 1:2 Sulfate to Chloride Malty
                // Note, values below are the other way, cl to so4!
                // So: 0.5 is IPA's, Pale Ales.
                //       1 Balanced
                //       2 Malty.
                $('#tgt_bu').val(Round(GetBUGU(), 2));
                // From brouwhulp.
                if (GetBUGU() < 0.32)
                        $('#wr_bu').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Zeer moutig en zoet</span>");
                else if (GetBUGU() < 0.43)
                        $('#wr_bu').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Moutig, zoet</span>");
                else if (GetBUGU() < 0.52)
                        $('#wr_bu').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Evenwichtig</span>");
                else if (GetBUGU() < 0.63)
                        $('#wr_bu').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Licht hoppig, bitter</span>");
                else
                        $('#wr_bu').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Extra hoppig, zeer bitter</span>");
                $('#tgt_cl_so4').val(Round(GetOptClSO4ratio(), 1));
                if (sulfate > 0)
                        RA = chloride / sulfate;
                else
                        RA = 10;
                $('#got_cl_so4').val(Round(RA, 1));
                piCLSO4_low = 0.8 * GetOptClSO4ratio();
                piCLSO4_high = 1.2 * GetOptClSO4ratio();
                Res = 'normaal';
                if (RA < piCLSO4_low)
                        Res = 'laag';
                else if (RA > piCLSO4_high)
                        Res = 'hoog';
                setRangeIndicator('cl_so4', Res);

                $('#wb_calcium').val(Round(calcium, 1));
                $('#wb_magnesium').val(Round(magnesium, 1));
                $('#wb_sodium').val(Round(sodium, 1));
                $('#wb_sulfate').val(Round(sulfate, 1));
                $('#wb_chloride').val(Round(chloride, 1));
                $('#wb_total_alkalinity').val(Round(total_alkalinity, 1));

                if (calcium < 40) {
                        setRangeIndicator("calcium", "laag");
                } else if (calcium > 150) {
                        setRangeIndicator("calcium", "hoog");
                } else {
                        setRangeIndicator("calcium", "normaal");
                }
                if (magnesium >= 0 && magnesium <= 30) {
                        setRangeIndicator("magnesium", "normaal");
                } else {
                        setRangeIndicator("magnesium", "hoog");
                }
                if (sodium <= 150) {
                        setRangeIndicator("sodium", "normaal");
                } else {
                        setRangeIndicator("sodium", "hoog");
                }
                // Both chloride and sulfate should be above 50 according to
                // John Palmer. So the Cl/SO4 ratio calculation will work.
                if (chloride <= 50) {
                        setRangeIndicator("chloride", "laag");
                } else if (chloride <= 100) {
                        setRangeIndicator("chloride", "normaal");
                } else {
                        setRangeIndicator("chloride", "hoog");
                }
                if (sulfate <= 50) {
                        setRangeIndicator("sulfate", "laag");
                } else if (sulfate <= 350) {
                        setRangeIndicator("sulfate", "normaal");
                } else {
                        setRangeIndicator("sulfate", "hoog");
                }
                if (ph < 5.2) {
                        setRangeIndicator("ph", "laag");
                } else if (ph > 5.6) {
                        setRangeIndicator("ph", "hoog");
                } else {
                        setRangeIndicator("ph", "normaal");
                }
                calcSparge();
                calcMiscs();
                calcSupplies();
        }

        function calcSparge() {

		var TargetpH, Source_pH, Source_alkalinity, r1, r2, d, f1, f3,
		r143, r243, d43, f143, f343, alkalinity, Ct, r1g, r2g, dg, f1g, f3g,
		Acid, AT, result, pK1, pK2, pK3, MolWt, AcidSG, AcidPrc, fract;

                // Code from BrewBuddy/Brouwhulp, who got it from http://www.brewery.org/brewery/library/Acidi0,00fWaterAJD0497.html
                TargetpH = dataRecord.sparge_ph;
                Source_pH = dataRecord.w1_ph;
                Source_alkalinity = dataRecord.w1_total_alkalinity;
                // Select watersource or fallback to the first source.
                if (dataRecord.sparge_source == 1) {    // Source 2
                        if (dataRecord.w2_ph > 0.0) {
                                Source_pH = dataRecord.w2_ph;
                                Source_alkalinity = dataRecord.w2_total_alkalinity;
                        } else {
                                dataRecord.sparge_source = 0;   // Source 1
                                $("#sparge_source").val(0);
                        }
                } else if (dataRecord.sparge_source == 2) {     // Mixed
                        if (dataRecord.w2_ph > 0.0) {
                                Source_pH = parseFloat($("#wg_ph").jqxNumberInput('decimal'));
                                Source_alkalinity = parseFloat($("#wg_total_alkalinity").jqxNumberInput('decimal'));
                        } else {
                                dataRecord.sparge_source = 0;
                                $("#sparge_source").val(0);
                        }
                }

                // Step 1: Compute the mole fractions of carbonic (f1o), bicarbonate (f2o) and carbonate(f3o) at the water pH
                r1 = Math.pow(10, Source_pH - 6.38);
                r2 = Math.pow(10, Source_pH - 10.373);
                d = 1 + r1 + r1*r2;
                f1 = 1/d;
                f3 = r1 * r2 / d;

                //Step 2. Compute the mole fractions at pH = 4.3 (the pH which defines alkalinity)
                r143 = Math.pow(10, 4.3 - 6.38);
                r243 = Math.pow(10, 4.3 - 10.373);
                d43 = 1 + r143 + r143*r243;
                f143 = 1/d43;
                f343 = r143 * r243 / d43;

                //Step 3. Convert the water alkalinity to milliequivalents/L
                alkalinity = Source_alkalinity / 50;
                
                //Step 4. Solve
                Ct = (alkalinity - 1000 * (Math.pow(10, -4.3) - Math.pow(10, -Source_pH))) / ((f143-f1)+(f3-f343));

                //Step 5. Compute mole fractions at desired pH
                r1g = Math.pow(10, TargetpH - 6.38);
                r2g = Math.pow(10, TargetpH - 10.373);
                dg = 1 + r1g + r1g*r2g;
                f1g = 1/dg;
                f3g = r1g * r2g / dg;

                //Step 6. Use these to compute the milliequivalents acid required per liter (mEq/L)
                Acid = Ct * ((f1g-f1)+(f3-f3g)) + Math.pow(10, -TargetpH) - Math.pow(10, -Source_pH);  //mEq/l
                Acid += 0.01;   // Add acid that would be required for distilled water.
                if (dataRecord.sparge_acid_type < 0 || dataRecord.sparge_acid_type > 3) {
                        dataRecord.sparge_acid_type = 0;
                        $("#sparge_acid_type").val(0);
                }

                //Step 8. Get the acid data.
                AT = dataRecord.sparge_acid_type;
                result = GetAcidSpecs(AT);
                pK1 = result.pK1;
                pK2 = result.pK2;
                pK3 = result.pK3;
                MolWt = result.MolWt;
                AcidSG = result.AcidSG;
                AcidPrc = result.AcidPrc;
                fract = CalcFrac(TargetpH, pK1, pK2, pK3);

                //Step 9. Now divide the mEq required by the "fraction". This is the required number of moles of acid.
                Acid /= fract;

                //Step 10. Multiply by molecular weight of the acid
                Acid *= MolWt; //mg

                Acid = Acid / AcidSG; //ml ; 88% lactic solution
                f1 = dataRecord.sparge_acid_perc;
                if (f1 <= 0.1)
                        f1 = AcidPrc;
                Acid = Acid * AcidPrc / (f1 / 100);

                Acid *= dataRecord.sparge_volume; //ml lactic acid total
                Acid = Round(Acid, 2);
                dataRecord.sparge_acid_amount = Acid / 1000;
                $("#sparge_acid_amount").val(Acid);
        }

        function calcFermentation(){

		var primary_svg, secondary_svg, final_svg, ABV;
                if (dataRecord.brew_fermenter_sg<1.020)
                        return;

                if ((dataRecord.primary_end_sg > 0.990) && (dataRecord.primary_end_sg < dataRecord.brew_fermenter_sg)) {
                        primary_svg = Round(100*(dataRecord.brew_fermenter_sg-dataRecord.primary_end_sg)/(dataRecord.brew_fermenter_sg-1),1);
                        $("#primary_svg").val(primary_svg);
                        if ((dataRecord.secondary_end_sg > 0.990) && (dataRecord.secondary_end_sg < dataRecord.brew_fermenter_sg)) {
                                secondary_svg = Round(100*(dataRecord.brew_fermenter_sg-dataRecord.secondary_end_sg)/(dataRecord.brew_fermenter_sg-1),1);
                                $("#secondary_svg").val(secondary_svg);
                                if ((dataRecord.fg > 0.990) && (dataRecord.fg < dataRecord.brew_fermenter_sg)) {
                                        final_svg = Round(100*(dataRecord.brew_fermenter_sg-dataRecord.fg)/(dataRecord.brew_fermenter_sg-1),1);
                                        $("#final_svg").val(final_svg);
                                        ABV = Round(abvol(dataRecord.brew_fermenter_sg,dataRecord.fg),2);
                                        $("#final_abv").val(ABV);
                                }
                        }
                }
        }

        function ResCO2(CO2,T){

                var F=T*1.8+32;
                return 3.0378-0.050062*F+0.00026555*F*F;
        }

        function CarbCO2toS(CO2,T,SFactor){
                var sugar=SFactor*(CO2-ResCO2(CO2,T))/0.286;
                if(sugar<0)
                        sugar=0;
                return Round(sugar,3);
        }

        function GetPressure(CO2, T1, T2) {
                var P, V = CO2 - ResCO2(CO2, T1);
                if (V < 0)
                        return 0;
                P = -1.09145427669121 + 0.00800006989646477 * T2 + 0.000260276315484684 * T2 * T2 + 0.0215142075945119 * T2 * V +
                        0.674996600795854 * V + -0.00471757220150754 * V * V;
                //console.log("CO2: "+CO2+" "+V+"  Temp: "+T1+" "+T2+"  Pressure: "+P);
                if (P < 0)
                        P = 0;
                P = P * 1.01325; // atm to bar
                return Round(P,1);
        }

        function CarbCO2ToPressure(CO2, T) {
                return (CO2-(-0.000005594056*Math.pow(T,4)+0.000144357886*Math.pow(T,3)+0.000362999168*T*T-0.064872987645*T+1.641145175049)) /
                         (0.00000498031*Math.pow(T,4)-0.00024358267*Math.pow(T,3)+0.00385867329*T*T-0.05671206825*T+1.53801423376);
        }

        function calcCarbonation() {

		var TSec, ABV, bvol, balc, babv, mvol, malc, tvol, talc,
		i, row, SFactor, pvol, pabv, Pressure, kabv;

                TSec=dataRecord.secondary_temp;
                if(TSec<1)
                        TSec=dataRecord.primary_end_temp;
                if(TSec<1)
                        TSec=18;

                if(dataRecord.fg==0.000)
                        ABV=abvol(dataRecord.brew_fermenter_sg,parseFloat($("#est_fg").jqxNumberInput('decimal')));
                else
                        ABV=abvol(dataRecord.brew_fermenter_sg,dataRecord.fg);

                /* Calculate new volume and alcohol. */
                bvol = dataRecord.package_volume-(ABV*dataRecord.package_volume)/100;
                balc = dataRecord.package_volume-bvol;
                mvol = dataRecord.package_infuse_amount-(dataRecord.package_infuse_abv*dataRecord.package_infuse_amount)/100;
                malc = dataRecord.package_infuse_amount-mvol;
                talc = balc+malc;
                tvol = bvol+mvol;
                ABV = Round(talc/(tvol+talc)*100,2);
                dataRecord.package_abv=ABV;
                $("#package_abv").val(ABV);

//              console.log("calcCarbonation() TSec:"+TSec+"  ABV:"+ABV);
                if (!(rows = $('#fermentableGrid').jqxGrid('getrows'))){
			return;
		}

                // Bottles
                dataRecord.bottle_priming_amount=0;
                dataRecord.bottle_priming_total=0;
                for (i = 0; i < rows.length; i++) {
                        row = rows[i];
                        if(row.f_added==4){
                                SFactor=1/((row.f_yield/100)*(1-row.f_moisture/100));
                                dataRecord.bottle_priming_amount=CarbCO2toS(dataRecord.bottle_carbonation,TSec,SFactor);
                                dataRecord.bottle_priming_total=Round(dataRecord.bottle_amount*dataRecord.bottle_priming_amount,2);
                                $("#fermentableGrid").jqxGrid('setcellvalue',i,'f_amount',dataRecord.bottle_priming_total/1000);
                        }
                }
                $("#bottle_priming_amount").val(Round(dataRecord.bottle_priming_amount,1));
                $("#bottle_priming_total").val(dataRecord.bottle_priming_total);
                pabv=ABV+dataRecord.bottle_priming_amount*0.47/7.907;
                pvol=dataRecord.bottle_amount-(pabv*dataRecord.bottle_amount)/100;
                talc=dataRecord.bottle_amount-pvol;
                tvol=pvol+dataRecord.bottle_priming_water;
                babv = Round(talc/(tvol+talc)*100,2);
                //console.log("bottle pabv:"+pabv+" pvol:"+pvol+" wvol:"+dataRecord.bottle_priming_water+" tvol:"+tvol+" talc:"+talc+" abv:"+babv);
                $("#bottle_abv").val(babv);
                $("#bottle_pressure").val(GetPressure(dataRecord.bottle_carbonation,TSec,dataRecord.bottle_carbonation_temp));

                // Kegs
                Pressure=CarbCO2ToPressure(dataRecord.keg_carbonation,dataRecord.keg_carbonation_temp);
                if(Pressure<0)Pressure=0;
                dataRecord.keg_pressure=Pressure;
                $("#keg_pressure").val(Round(Pressure,1));

                dataRecord.keg_priming_amount=0;
                dataRecord.keg_priming_total=0;
                if(!dataRecord.keg_forced_carb){
                        for(i = 0; i < rows.length; i++){
                                row=rows[i];
                                if(row.f_added==5){
                                        SFactor=1/((row.f_yield/100)*(1-row.f_moisture/100));
                                        dataRecord.keg_priming_amount=CarbCO2toS(dataRecord.keg_carbonation,TSec,SFactor);
                                        dataRecord.keg_priming_total=Round(dataRecord.keg_amount*dataRecord.keg_priming_amount,2);
                                        $("#fermentableGrid").jqxGrid('setcellvalue',i,'f_amount',dataRecord.keg_priming_total/1000);
                                }
                        }
                        $("#keg_priming_amount").val(Round(dataRecord.keg_priming_amount,1));
                        $("#keg_priming_total").val(dataRecord.keg_priming_total);
                        pabv=ABV+dataRecord.keg_priming_amount*0.47/7.907;
                        pvol=dataRecord.keg_amount-(pabv*dataRecord.keg_amount)/100;
                        talc=dataRecord.keg_amount-pvol;
                        tvol=pvol+dataRecord.keg_priming_water;
                        kabv=Round(talc/(tvol+talc)*100,2);
                        //console.log("kegs  pabv:"+pabv+" pvol:"+pvol+" wvol:"+dataRecord.keg_priming_water+" tvol:"+tvol+" talc:"+talc+" abv:"+kabv);
                        $("#keg_abv").val(kabv);
                } else {
                        $("#keg_priming_amount").val(0);
                        $("#keg_priming_total").val(0);
                        $("#keg_abv").val(ABV);
                }
        }

        function calcStage() {

                var newstage = dataRecord.stage, d, date1, date2, date1_unixtime, date2_unixtime,
		timeDifference, timeDifferenceInDays;

                if (newstage == 0 && dataRecord.est_og > 1.005 && dataRecord.est_color > 3 && dataRecord.est_ibu > 3)
                        newstage = 1;
                if (newstage == 1 && parseFloat($("#brew_date_start").val()) > 2000)
                        newstage = 2;   // Brewday
                if (newstage == 2 && ($("#brew_date_start").val() == ''))
                        newstage = 1;   // No brewday
                if (newstage == 2 && parseFloat($("#brew_date_end").val()) > 2000)
                        newstage = 3;   // Primary
                if (newstage == 3 && parseFloat($("#primary_end_date").val()) > 2000)
                        newstage = 4;   // Secondary
                if (newstage == 4 && parseFloat($("#secondary_end_date").val()) > 2000)
                        newstage = 5;   // Tertiary
                if (newstage == 5 && parseFloat($("#package_date").val()) > 2000)
                        newstage = 6;   // Package
                if (newstage >= 6 && newstage < 9) {
                        d = new Date();
                        date2 = $("#package_date").val();
                        date2 = date2.split('-');
                        // Now we convert the array to a Date object
                        date1 = new Date(d.getFullYear(), d.getMonth(), d.getDate());
                        date2 = new Date(date2[0], date2[1]-1, date2[2]);
                        // We use the getTime() method and get the unixtime
                        date1_unixtime = parseInt(date1.getTime() / 1000);
                        date2_unixtime = parseInt(date2.getTime() / 1000);
                        // This is the calculated difference in seconds
                        timeDifference = date1_unixtime - date2_unixtime;
                        timeDifferenceInDays = timeDifference / 60 / 60 / 24;
                        if (timeDifferenceInDays > 0) {                 // At least one day
                                if (timeDifferenceInDays >= 42)         // 6 weeks
                                        newstage = 9;                   // Ready to taste
                                else if (timeDifferenceInDays >= 14)    // 14 days
                                        newstage = 8;                   // Mature
                                else
                                        newstage = 7;                   // Carbonation
                        }
                }
                if (newstage == 9 && parseFloat($("#taste_date").val()) > 2000)
                        newstage = 10;  // Ready

                if (newstage != dataRecord.stage) {
                        console.log("calcStage() old: "+dataRecord.stage+" new: "+newstage);
                        dataRecord.stage = newstage;
                }

                /*
                 * Set stage and enable or disable parts of the screens.
                 */
                $("#stage").val(StageData[dataRecord.stage].nl);
                if (dataRecord.stage >= 10) {
                        $("#locked").jqxCheckBox({ disabled:false });
                }

                /*
                 * When the brew is in progress or done, block equipment select and delete.
                 */
                if (dataRecord.stage > 1) {
                        $("#equipmentSelect").jqxDropDownList({ disabled: true });
                        $("#Delete").jqxButton({ disabled: true });
                }

                if (dataRecord.stage < 1)       // Planning, no ingredients
                        $('#jqxTabs').jqxTabs('disableAt', 8);  // Brewday tab
                else
                        $('#jqxTabs').jqxTabs('enableAt', 8);

                if (dataRecord.stage < 3) {     // Primary
                        $('#jqxTabs').jqxTabs('disableAt', 9);  // Fermentation tab
                } else {
                        $('#jqxTabs').jqxTabs('enableAt', 9);
                        $("#name").jqxInput({ disabled: true });
                        $("#code").jqxInput({ disabled: true });
                        $("#batch_size").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#boil_size").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#boil_time").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#efficiency").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#est_og").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#type").jqxDropDownList({ disabled: true });
                        $("#styleSelect").jqxDropDownList({ disabled: true });
                        $("#color_method").jqxDropDownList({ disabled: true });
                        $("#ibu_method").jqxDropDownList({ disabled: true });
                        $("#mash_select").jqxDropDownList({ disabled: true });
                        $("#w1_name").jqxDropDownList({ disabled: true });
                        $("#w2_name").jqxDropDownList({ disabled: true });
                        $("#w2_amount").jqxNumberInput({ readOnly: true });
                        $("#pr_name").jqxDropDownList({ disabled: true });
                        $("#wa_cacl2").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#wa_caso4").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#wa_mgso4").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#wa_nacl").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#mash_ph").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#calc_acid").jqxCheckBox({ disabled: true });
                        $("#wa_base_name").jqxDropDownList({ disabled: true });
                        $("#wa_base").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#wa_acid_name").jqxDropDownList({ disabled: true });
                        $("#wa_acid").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#wa_acid_perc").jqxNumberInput({ spinButtons: false, readOnly: true, width: 70 });
                        $("#sparge_temp").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#sparge_volume").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#sparge_ph").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#sparge_source").jqxDropDownList({ disabled: true });
                        $("#sparge_acid_type").jqxDropDownList({ disabled: true });
                        $("#sparge_acid_perc").jqxNumberInput({ spinButtons: false, readOnly: true, width: false });
                        $("#starter_enable").jqxCheckBox({ disabled: true });
                        $("#starter_type").jqxDropDownList({ disabled: true });
                        $("#starter_try").jqxButton({ disabled: true });
                        $("#starter_sg").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#starter_viability").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                }
                if (dataRecord.stage > 3) { // Primary fermentation done
                        $("#brew_date_start").jqxDateTimeInput({ disabled: true });
                        $("#brew_date_end").jqxDateTimeInput({ disabled: true });
                        $("#brew_mash_ph").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#brew_preboil_ph").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#brew_aboil_ph").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#brew_mash_sg").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#brew_preboil_sg").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#brew_aboil_sg").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#brew_preboil_volume").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#brew_aboil_volume").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#brew_whirlpool9").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#brew_cooling_to").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#brew_whirlpool7").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#brew_cooling_method").jqxDropDownList({ disabled: true });
                        $("#brew_whirlpool6").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#brew_cooling_time").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#brew_sparge_ph").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#brew_whirlpool2").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#brew_aeration_type").jqxDropDownList({ disabled: true });
                        $("#brew_fermenter_tcloss").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#brew_aeration_time").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#brew_fermenter_extrawater").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#brew_aeration_speed").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                }
                if (dataRecord.stage == 5) // Lagering, allow packaging
                        $("#package_date").jqxDateTimeInput({ disabled: false });
                else
                        $("#package_date").jqxDateTimeInput({ disabled: true });
                if (dataRecord.stage >= 5) { // At least secondary
                        $("#primary_start_temp").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#primary_max_temp").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#primary_end_temp").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#primary_end_sg").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#primary_end_brix").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#primary_end_date").jqxDateTimeInput({ disabled: true });
                }
                if (dataRecord.stage >= 6) {    // Packaged
                        $("#secondary_temp").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#secondary_end_sg").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#secondary_end_date").jqxDateTimeInput({ disabled: true });
                        $("#tertiary_temp").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#fg").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#final_brix").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#package_date").jqxDateTimeInput({ disabled: true });
                        $("#package_volume").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#package_infuse_amount").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#package_infuse_abv").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#package_infuse_notes").jqxInput({ disabled: true });
                        $("#package_ph").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#bottle_amount").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#bottle_priming_water").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#keg_priming_water").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#keg_amount").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#bottle_carbonation").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#keg_carbonation").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#bottle_priming_sugar").jqxDropDownList({ disabled: true });
                        $("#keg_priming_sugar").jqxDropDownList({ disabled: true });
                        $("#keg_forced_carb").jqxCheckBox({ disabled : true });
                        $("#bottle_carbonation_temp").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#keg_carbonation_temp").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                }
                if (dataRecord.stage < 8) { // Taste when at least Mature.
                        $('#jqxTabs').jqxTabs('disableAt', 11); // Tasting tab
                } else {
                        $('#jqxTabs').jqxTabs('enableAt', 11);
                }

                if (dataRecord.stage == 11) { // Locked
                        $("#taste_date").jqxDateTimeInput({ disabled: true });
                        $("#taste_rate").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#taste_color").jqxInput({ disabled: true });
                        $("#taste_transparency").jqxInput({ disabled: true });
                        $("#taste_head").jqxInput({ disabled: true });
                        $("#taste_aroma").jqxInput({ disabled: true });
                        $("#taste_taste").jqxInput({ disabled: true });
                        $("#taste_aftertaste").jqxInput({ disabled: true });
                        $("#taste_mouthfeel").jqxInput({ disabled: true });
                        $("#taste_notes").jqxInput({ disabled: true });
                        $("#notes").jqxInput({ disabled: true });
                } else {
                        $("#notes").jqxInput({ disabled: false });
                }
        }

        function showStarter() {

                if (dataRecord.starter_enable) {
                        $("#propagator").show();
                        $("#starter_type").jqxDropDownList( {disabled: false });
                        $("#starter_try").jqxButton({ disabled: false });
                        $("#starter_sg").jqxNumberInput({ spinButtons: true, readOnly: false, width: 110 });
                        $("#starter_viability").jqxNumberInput({ spinButtons: true, readOnly: false, width: 110 });
                } else {
                        $("#propagator").hide();
                        $("#starter_type").jqxDropDownList( {disabled: true });
                        $("#starter_try").jqxButton({ disabled: true });
                        $("#starter_sg").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                        $("#starter_viability").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
                }
        }

        function calcInit () {
                console.log("calcInit()");

                calcMashEfficiency();
                calcEfficiencyBeforeBoil();
                calcEfficiencyAfterBoil();

                $("#starter_enable").on('checked', function (event) {
                        dataRecord.starter_enable = 1;
                        showStarter();
                        calcYeast();
                });
                $("#starter_enable").on('unchecked', function (event) {
                        dataRecord.starter_enable = 0;
                        showStarter();
                        calcYeast();
                });
                $("#starter_try").click(function () {
                        $("#prop1_volume").val(0);
                        $("#prop2_volume").val(0);
                        $("#prop3_volume").val(0);
                        $("#prop4_volume").val(0);
                        calcYeast();
                });
                $('#starter_type').on('change', function (event) {
                        if (event.args) {
                                var index = event.args.index;
                                dataRecord.starter_type = index;
                                calcYeast();
                        }
                });
                $('#starter_sg').on('change', function (event) {
                        if (event.args) {
                                dataRecord.starter_sg = event.args.value;
                                calcYeast();
                        }
                });
                $('#starter_viability').on('change', function (event) {
                        if (event.args) {
                                dataRecord.starter_viability = event.args.value;
                                calcFermentables();
                                calcYeast();
                        }
                });
                $('#prop1_type').on('change', function (event) {
                        if (event.args) {
                                var index = event.args.index;
                                dataRecord.prop1_type = index;
                                calcYeast();
                        }
                });
                $('#prop1_volume').on('change', function (event) {
                        if (event.args) {
                                dataRecord.prop1_volume = event.args.value;
                                calcYeast();
                        }
                });
                $('#prop2_type').on('change', function (event) {
                        if (event.args) {
                                var index = event.args.index;
                                dataRecord.prop2_type = index;
                                calcYeast();
                        }
                });
                $('#prop2_volume').on('change', function (event) {
                        if (event.args) {
                                dataRecord.prop2_volume = event.args.value;
                                calcYeast();
                        }
                });
                $('#prop3_type').on('change', function (event) {
                        if (event.args) {
                                var index = event.args.index;
                                dataRecord.prop3_type = index;
                                calcYeast();
                        }
                });
                $('#prop3_volume').on('change', function (event) {
                        if (event.args) {
                                dataRecord.prop3_volume = event.args.value;
                                calcYeast();
                        }
                });
                $('#prop4_type').on('change', function (event) {
                        if (event.args) {
                                var index = event.args.index;
                                dataRecord.prop4_type = index;
                                calcYeast();
                        }
                });
                $('#prop4_volume').on('change', function (event) {
                        if (event.args) {
                                dataRecord.prop4_volume = event.args.value;
                                calcYeast();
                        }
                });

                $("#calc_acid").on('checked', function (event) {
                        dataRecord.calc_acid = 1;
                        calcWater();
                });
                $("#calc_acid").on('unchecked', function (event) {
                        dataRecord.calc_acid = 0;
                        calcWater();
                });
                $("#w1_name").jqxDropDownList('selectItem', dataRecord.w1_name);
                $("#w2_name").jqxDropDownList('selectItem', dataRecord.w2_name);
                // Fix tap water if zero using mash infuse amount.
                if (parseFloat($("#w1_amount").jqxNumberInput('decimal')) == 0 && mash_infuse > 0) {
                        $("#w1_amount").val(mash_infuse);
                        dataRecord.w1_amount = mash_infuse;
                        $("#wg_amount").val(mash_infuse);
                        $("#w2_amount").val(0);
                        dataRecord.w2_amount = 0;
                }
                calcWater();
                $("#w2_amount").on('change', function (event) {
                        var newval = parseFloat(event.args.value);

                        if (newval > mash_infuse) {
                                $("#w2_amount").val(dataRecord.w2_amount);
                                return;
                        }
                        dataRecord.w1_amount = parseFloat($("#wg_amount").jqxNumberInput('decimal')) - newval;
                        $("#w1_amount").val(dataRecord.w1_amount);
                        dataRecord.w2_amount = newval;
                        console.log("new: "+event.args.value+" w1: "+dataRecord.w1_amount+"  w2: "+dataRecord.w2_amount);
                        calcWater();
                });
                $('#wa_cacl2').on('change', function (event) {
                        if (event.args) {
                                setWaterAgent('CaCl2', 0);      // This can prevent double entries.
                                setWaterAgent('CaCl2', event.args.value);
                                calcWater();
                        }
                });
                $('#wa_caso4').on('change', function (event) {
                        if (event.args) {
                                setWaterAgent('CaSO4', 0);
                                setWaterAgent('CaSO4', event.args.value);
                                calcWater();
                        }
                });
                $('#wa_mgso4').on('change', function (event) {
                        if (event.args) {
                                setWaterAgent('MgSO4', 0);
                                setWaterAgent('MgSO4', event.args.value);
                                calcWater();
                        }
                });
                $('#wa_nacl').on('change', function (event) {
                        if (event.args) {
                                setWaterAgent('NaCl', 0);
                                setWaterAgent('NaCl', event.args.value);
                                calcWater();
                        }
                });
                $('#wa_base_name').on('change', function (event) {
                        if (event.args) {
                                var index = event.args.index;
                                console.log("wa_base_name "+index);
                                setWaterAgent(last_base, 0);
                                last_base = BaseTypeData[index].nl;
                                setWaterAgent(last_base, parseFloat($("#wa_base").jqxNumberInput('decimal')));
                                dataRecord.wa_base_name = index;
                                calcWater();
                        }
                });
                $('#wa_base').on('change', function (event) {
                        var name = BaseTypeData[$("#wa_base_name").val()].nl;
                        setWaterAgent(name, parseFloat(event.args.value));
                        calcWater();
                });
                $('#wa_acid_name').on('change', function (event) {
                        if (event.args) {
                                var index = event.args.index;
                                console.log("wa_acid_name "+index);
                                setWaterAgent(last_acid, 0);
                                last_acid = AcidTypeData[index].nl;
                                setWaterAgent(last_acid, parseFloat($("#wa_acid").jqxNumberInput('decimal')));
                                dataRecord.wa_acid_name = index;
                                calcWater();
                        }
                });
                $('#wa_acid').on('change', function (event) {
                        var name = AcidTypeData[$("#wa_acid_name").val()].nl;
                        setWaterAgent(name, parseFloat(event.args.value));
                        calcWater();
                });
                $('#wa_acid_perc').on('change', function (event) { calcWater(); });

                $('#color_method').on('change', function (event) {
                        dataRecord.color_method = event.args.index;
                        calcFermentables();
                });
                $('#ibu_method').on('change', function (event) {
                        dataRecord.ibu_method = event.args.index;
                        calcFermentables();
                        calcIBUs();
                });

                $('#batch_size').on('change', function (event) {
                        console.log("batch_size change:"+event.args.value+" old:"+dataRecord.batch_size);
                        $("#est_a_vol").val(event.args.value * 1.04);
                        var factor, new_boil = parseFloat(event.args.value) + dataRecord.boil_size - dataRecord.batch_size;
                        factor = parseFloat(event.args.value) / dataRecord.batch_size;
                        dataRecord.boil_size = new_boil;
                        $("#boil_size").val(Round(new_boil, 2));
                        $("#est_pre_vol").val(Round(new_boil * 1.04, 2));
                        dataRecord.sparge_volume *= factor;
                        $("#sparge_volume").val(dataRecord.sparge_volume);
                        $("#brew_sparge_volume").val(dataRecord.sparge_volume);
                        dataRecord.batch_size = parseFloat(event.args.value);
                        calcFermentablesFromOG(parseFloat($("#est_og").jqxNumberInput('decimal')));     // Keep the OG
                        adjustWaters(factor);
                        calcFermentables();
                        adjustHops(factor);
                        adjustMiscs(factor);
                        adjustYeasts(factor);
                        calcIBUs();
                        calcWater();
                        calcSparge();
                        calcMash();
                });
                $('#boil_time').on('change', function (event) {
                        console.log("boil_time change:"+parseFloat(event.args.value)+" old:"+dataRecord.boil_time);
                        var new_boil, new_evap, old_evap = parseFloat(dataRecord.boil_size) - parseFloat(dataRecord.batch_size);
                        new_evap = old_evap * (parseFloat(event.args.value) / dataRecord.boil_time);
                        new_boil = parseFloat(dataRecord.batch_size) + new_evap;
                        dataRecord.boil_time = parseFloat(event.args.value);
                        dataRecord.boil_size = new_boil;
                        $("#est_pre_vol").val(Round(new_boil * 1.04, 2));
                        $("#boil_size").val(Round(new_boil, 2));
                        calcFermentables();
                        calcIBUs();
                        calcYeast();
                });
                $('#efficiency').on('change', function (event) {
                        var estog = parseFloat($("#est_og").jqxNumberInput('decimal'));
                        dataRecord.efficiency = parseFloat(event.args.value);
                        console.log("efficiency change:"+dataRecord.efficiency+" est_og:"+estog);
                        calcFermentablesFromOG(estog);     // Keep the OG
                        calcFermentables();
                        calcIBUs();
                        calcYeast();
                });
                $('#est_og').on('change', function (event) {
                        dataRecord.est_og = parseFloat(event.args.value);
                        console.log("est_og change:"+dataRecord.est_og);
                        $('#est_og2').val(dataRecord.est_og);
                        calcFermentablesFromOG(dataRecord.est_og);      // Adjust fermentables amounts
                        calcFermentables();                             // Update the recipe details
                        calcIBUs();                                     // and the IBU's.
                        calcMash();
                        calcYeast();
                });
                $('#mash_ph').on('change', function (event) {
                        dataRecord.mash_ph = parseFloat(event.args.value);
                        calcWater();
                });

                $('#sparge_ph').on('change', function (event) {
                        dataRecord.sparge_ph = parseFloat(event.args.value);
                        calcSparge();
                });
                $('#sparge_volume').on('change', function (event) {
                        dataRecord.sparge_volume = parseFloat(event.args.value);
                        $('#brew_sparge_volume').val(dataRecord.sparge_volume);
                        calcSparge();
                });
                $("#sparge_temp").on('change', function (event) {
                        dataRecord.sparge_temp = parseFloat(event.args.value);
                        $('#brew_sparge_temperature').val(dataRecord.sparge_temp);
                });
                $('#sparge_source').on('change', function (event) {
                        if (event.args) {
                                var index = event.args.index;
                                dataRecord.sparge_source= index;
                                calcSparge();
                        }
                });
                $('#sparge_acid_type').on('change', function (event) {
                        if (event.args) {
                                var index = event.args.index;
                                dataRecord.sparge_acid_type = index;
                                console.log("new sparge_acid_type: "+dataRecord.sparge_acid_type);
                                calcSparge();
                        }
                });
                $('#sparge_acid_perc').on('change', function (event) {
                        dataRecord.sparge_acid_perc = parseFloat(event.args.value);
                        calcSparge();
                });

                calcFermentation();
                calcCarbonation();
                $('#package_volume').on('change', function (event) {
                        var diff, tnew, told = dataRecord.package_volume + dataRecord.package_infuse_amount;
                        dataRecord.package_volume = parseFloat(event.args.value);
                        if (dataRecord.package_volume > dataRecord.brew_fermenter_volume) {
                                dataRecord.package_volume = dataRecord.brew_fermenter_volume;
                                $('#package_volume').val(dataRecord.package_volume);
                        }
                        tnew = dataRecord.package_volume + dataRecord.package_infuse_amount;
                        diff = tnew - told;
                        if (told > 0) {
                                dataRecord.bottle_amount += (dataRecord.bottle_amount / told) * diff;
                                dataRecord.keg_amount += (dataRecord.keg_amount / told) * diff;
                        } else {
                                dataRecord.bottle_amount = tnew;
                                dataRecord.keg_amount = 0;
                        }
                        console.log("diff:"+diff+" old:"+told+" bottle:"+dataRecord.bottle_amount+" keg:"+dataRecord.keg_amount);
                        $('#bottle_amount').val(parseFloat(dataRecord.bottle_amount * 1000) / 1000);
                        $('#keg_amount').val(parseFloat(dataRecord.keg_amount * 1000) / 1000);
                        calcCarbonation();
                });
                $('#package_infuse_amount').on('change', function (event) {
                        var diff, tnew, told = dataRecord.package_volume + dataRecord.package_infuse_amount;
                        dataRecord.package_infuse_amount = parseFloat(event.args.value);
                        tnew = dataRecord.package_volume + dataRecord.package_infuse_amount;
                        diff = tnew - told;
                        if (told > 0) {
                                dataRecord.bottle_amount += (dataRecord.bottle_amount / told) * diff;
                                dataRecord.keg_amount += (dataRecord.keg_amount / told) * diff;
                        } else {
                                dataRecord.bottle_amount = tnew;
                                dataRecord.keg_amount = 0;
                        }
                        console.log("diff:"+diff+" old:"+told+" bottle:"+dataRecord.bottle_amount+" keg:"+dataRecord.keg_amount);
                        $('#bottle_amount').val(parseFloat(dataRecord.bottle_amount * 1000) / 1000);
                        $('#keg_amount').val(parseFloat(dataRecord.keg_amount * 1000) / 1000);
                        calcCarbonation();
                });
                $('#package_infuse_abv').on('change', function (event) {
                        dataRecord.package_infuse_abv = parseFloat(event.args.value);
                        calcCarbonation();
                });
                $('#bottle_amount').on('change', function (event) {
                        var vtot, diff, vnew = parseFloat(event.args.value);
                        vtot = dataRecord.package_volume + dataRecord.package_infuse_amount;
                        if (vnew > vtot)
                                vnew = vtot;
                        diff = dataRecord.bottle_amount - vnew;
                        dataRecord.bottle_amount = Math.round((dataRecord.bottle_amount - diff) * 1000) / 1000;
                        dataRecord.keg_amount = Math.round((dataRecord.keg_amount + diff) * 1000) / 1000;
                        $('#bottle_amount').val(parseFloat(dataRecord.bottle_amount));
                        $('#keg_amount').val(parseFloat(dataRecord.keg_amount));
                        calcCarbonation();
                });
                $("#bottle_priming_water").on('change', function (event) {
                        dataRecord.bottle_priming_water = parseFloat(event.args.value);
                        calcCarbonation();
                });
                $('#keg_amount').on('change', function (event) {
                        var diff, vtot, vnew = parseFloat(event.args.value);
                        vtot = dataRecord.package_volume + dataRecord.package_infuse_amount;
                        if (vnew > vtot)
                                vnew = vtot;
                        diff = dataRecord.keg_amount - vnew;
                        dataRecord.bottle_amount = Math.round((dataRecord.bottle_amount + diff) * 1000) / 1000;
                        dataRecord.keg_amount = Math.round((dataRecord.keg_amount - diff) * 1000) / 1000;
                        $('#bottle_amount').val(parseFloat(dataRecord.bottle_amount));
                        $('#keg_amount').val(parseFloat(dataRecord.keg_amount));
                        calcCarbonation();
                });
                $("#keg_priming_water").on('change', function (event) {
                        dataRecord.keg_priming_water = parseFloat(event.args.value);
                        calcCarbonation();
                });
                $('#bottle_carbonation').on('change', function (event) {
                        dataRecord.bottle_carbonation = parseFloat(event.args.value);
                        calcCarbonation();
                });
                $('#bottle_carbonation_temp').on('change', function (event) {
                        dataRecord.bottle_carbonation_temp = parseFloat(event.args.value);
                        calcCarbonation();
                });
                $('#keg_carbonation').on('change', function (event) {
                        dataRecord.keg_carbonation = parseFloat(event.args.value);
                        calcCarbonation();
                });
                $("#keg_forced_carb").on('checked', function (event) {
                        dataRecord.keg_forced_carb = 1;
                        calcCarbonation();
                });
                $("#keg_forced_carb").on('unchecked', function (event) {
                        dataRecord.keg_forced_carb = 0;
                        calcCarbonation();
                });
                $('#keg_carbonation_temp').on('change', function (event) {
                        dataRecord.keg_carbonation_temp = parseFloat(event.args.value);
                        calcCarbonation();
                });

                $("#brew_fermenter_extrawater").on('change',function (event){
                        dataRecord.brew_fermenter_extrawater=parseFloat(event.args.value);calcFermentables();calcIBUs();calcYeast();
                });
                $("#brew_fermenter_tcloss").on('change',function (event){
                        dataRecord.brew_fermenter_tcloss=parseFloat(event.args.value);calcFermentables();calcIBUs();calcYeast();
                });
                $("#primary_end_sg").on('change',function (event){dataRecord.primary_end_sg=parseFloat(event.args.value);calcFermentation();});
                $("#primary_end_brix").on('change', function (event) {
			var OBrix, FBrix, FG;
                        if(dataRecord.brew_fermenter_sg>=1.020){
                                OBrix = sg_to_brix(dataRecord.brew_fermenter_sg);
                                FBrix = parseFloat(event.args.value);
				FG = Round(1.0031 - 0.002318474*OBrix - 0.000007775*(OBrix*OBrix) - 0.000000034*Math.pow(OBrix,3) +
					   0.00574*(FBrix) + 0.00003344*(FBrix*FBrix) + 0.000000086*Math.pow(FBrix,3), 4);
                                //console.log("OBrix:"+OBrix+" FBrix:"+FBrix+" FG:"+FG);
                                if (FBrix > 0.05) {
					$("#primary_end_sg").val(FG);
					dataRecord.primary_end_sg=FG;
				}
                                calcFermentation();
                        }
                });
                $("#secondary_end_sg").on('change',function (event){dataRecord.secondary_end_sg=parseFloat(event.args.value);calcFermentation();});
                $("#secondary_end_brix").on('change', function (event) {
			var OBrix, FBrix, FG;
                        if(dataRecord.brew_fermenter_sg>=1.020){
                                OBrix = sg_to_brix(dataRecord.brew_fermenter_sg);
                                FBrix = parseFloat(event.args.value);
				FG = Round(1.0031 - 0.002318474*OBrix - 0.000007775*(OBrix*OBrix) - 0.000000034*Math.pow(OBrix,3) +
					   0.00574*(FBrix) + 0.00003344*(FBrix*FBrix) + 0.000000086*Math.pow(FBrix,3), 4);
                                //console.log("OBrix:"+OBrix+" FBrix:"+FBrix+" FG:"+FG);
                                if (FBrix > 0.05) {
					$("#secondary_end_sg").val(FG);
					dataRecord.secondary_end_sg=FG;
				}
                                calcFermentation();
                        }
                });
                $("#final_brix").on('change',function (event){
			var OBrix, FBrix, FG;
                        if(dataRecord.brew_fermenter_sg>=1.020){
                                OBrix = sg_to_brix(dataRecord.brew_fermenter_sg);
                                FBrix = parseFloat(event.args.value);
				FG = Round(1.0031 - 0.002318474*OBrix - 0.000007775*(OBrix*OBrix) - 0.000000034*Math.pow(OBrix,3) +
					   0.00574*(FBrix) + 0.00003344*(FBrix*FBrix) + 0.000000086*Math.pow(FBrix,3), 4);
                                //console.log("OBrix:"+OBrix+" FBrix:"+FBrix+" FG:"+FG);
                                if (FBrix > 0.05) {
					$("#fg").val(FG);
					dataRecord.fg=FG;
				}
                                calcFermentation();
                        }
                });
                $("#fg").on('change',function (event){dataRecord.fg=parseFloat(event.args.value);calcFermentation();});
                $("#BLog").jqxButton({disabled:(dataRecord.log_brew)?false:true});
                $("#FLog").jqxButton({disabled:(dataRecord.log_fermentation)?false:true});
        }

        $("#styleSelect").jqxDropDownList({
                placeHolder: "Kies bierstijl:",
                theme: theme,
                source: styleslist,
                displayMember: "name",
                width: 180,
                height: 23,
                dropDownVerticalAlignment: 'top',
                dropDownWidth: 500,
                dropDownHeight: 380,
                renderer: function (index, label, value) {
                        var datarecord = styleslist.records[index];
                        return datarecord.style_guide + " " + datarecord.style_letter+ " " + datarecord.name;
                }
        });
        $("#styleSelect").on('select', function (event) {
                if (event.args) {
                        var datarecord, index = event.args.index;
                        datarecord = styleslist.records[index];
                        $("#st_name").val(datarecord.name);
                        $("#st_category").val(datarecord.category);
                        $("#st_category_number").val(datarecord.category_number);
                        $("#st_letter").val(datarecord.style_letter);
                        $("#st_guide").val(datarecord.style_guide);
                        $("#st_type").val(StyleTypeData[datarecord.type].nl);
                        $("#st_og_min").val(datarecord.og_min);
                        $("#st_og_max").val(datarecord.og_max);
                        $("#st_fg_min").val(datarecord.fg_min);
                        $("#st_fg_max").val(datarecord.fg_max);
                        $("#st_ibu_min").val(datarecord.ibu_min);
                        $("#st_ibu_max").val(datarecord.ibu_max);
                        $("#st_color_min").val(datarecord.color_min);
                        $("#st_color_max").val(datarecord.color_max);
                        $("#st_carb_min").val(datarecord.carb_min);
                        $("#st_carb_min2").val(datarecord.carb_min);
                        $("#st_carb_max").val(datarecord.carb_max);
                        $("#st_carb_max2").val(datarecord.carb_max);
                        $("#st_abv_min").val(datarecord.abv_min);
                        $("#st_abv_max").val(datarecord.abv_max);
                }
        });

        // Equipemnt dropdown list
        $("#equipmentSelect").jqxDropDownList({
                placeHolder: "Kies apparatuur:",
                theme: theme,
                source: equipmentlist,
                displayMember: "name",
                width: 170,
                height: 23,
                dropDownWidth: 300,
                renderer: function (index, label, value) {
                        var datarecord = equipmentlist.records[index];
                        return datarecord.batch_size + " liter " + datarecord.name;
                }
        });
        $("#equipmentSelect").on('select', function (event) {
                if (event.args) {
                        var datarecord, factor, index = event.args.index;
                        datarecord = equipmentlist.records[index];
                        factor = datarecord.batch_size / dataRecord.batch_size;
                        $("#eq_name").val(datarecord.name);
                        $("#eq_boil_size").val(datarecord.boil_size);
                        dataRecord.boil_size = datarecord.boil_size;
                        $("#boil_size").val(datarecord.boil_size);
                        $("#eq_batch_size").val(datarecord.batch_size);
                        dataRecord.batch_size = datarecord.batch_size;
                        $("#batch_size").val(datarecord.batch_size);
                        $("#est_a_vol").val(datarecord.batch_size * 1.04);
                        $("#eq_tun_volume").val(datarecord.tun_volume);
                        dataRecord.eq_tun_weight = datarecord.tun_weight;
                        dataRecord.eq_tun_specific_heat = datarecord.tun_specific_heat;
                        dataRecord.eq_tun_material = datarecord.tun_material;
                        dataRecord.eq_tun_height = datarecord.tun_height / 100.0;
                        $("#eq_top_up_water").val(datarecord.top_up_water);
                        dataRecord.eq_trub_chiller_loss = datarecord.trub_chiller_loss;
                        $("#eq_trub_chiller_loss").val(datarecord.trub_chiller_loss);
                        $("#eq_evap_rate").val(datarecord.evap_rate);
                        $("#eq_boil_time").val(datarecord.boil_time);
                        dataRecord.eq_calc_boil_volume = datarecord.calc_boil_volume;
                        $("#eq_top_up_kettle").val(datarecord.top_up_kettle);
                        $("#eq_hop_utilization").val(datarecord.hop_utilization);
                        $("#eq_notes").val(datarecord.notes);
                        $("#eq_lauter_volume").val(datarecord.lauter_volume);
                        dataRecord.eq_lauter_height = datarecord.lauter_height / 100.0;
                        $("#eq_lauter_deadspace").val(datarecord.lauter_deadspace);
                        $("#eq_kettle_volume").val(datarecord.kettle_volume);
                        dataRecord.eq_kettle_height = datarecord.kettle_height / 100.0;
                        $("#eq_mash_volume").val(datarecord.mash_volume);
                        $("#eq_mash_max").val(datarecord.mash_max);
                        dataRecord.eq_mash_max = datarecord.mash_max;
                        $("#mash_max").val(datarecord.mash_max);
                        $("#eq_efficiency").val(datarecord.efficiency);
                        dataRecord.efficiency = datarecord.efficiency;
                        $("#efficiency").val(datarecord.efficiency);

                        dataRecord.sparge_volume = Math.round(datarecord.boil_size * 5) / 10;
                        $("#sparge_volume").val(dataRecord.sparge_volume);
                        $("#brew_sparge_volume").val(dataRecord.sparge_volume);
                        $("#est_pre_vol").val(datarecord.boil_size * 1.04);
                        calcFermentablesFromOG(parseFloat($("#est_og").jqxNumberInput('decimal')));     // Keep the OG
                        adjustWaters(factor);
                        calcFermentables();
                        adjustHops(factor);
                        adjustMiscs(factor);
                        adjustYeasts(factor);
                        calcIBUs();
                        calcWater();
                        calcSparge();
                }
        });

        function saveRecord() {
                console.log("saveRecord()");
                var row = {
                        record: my_record,
                        uuid: dataRecord.uuid,
                        name: $("#name").val(),
                        code: $("#code").val(),
                        birth: $("#birth").val(),
                        stage: dataRecord.stage,
                        notes: $("#notes").val(),
                        log_brew: dataRecord.log_brew,
                        log_fermentation: dataRecord.log_fermentation,
                        inventory_reduced: dataRecord.inventory_reduced,
                        locked: dataRecord.locked,
                        eq_name: $("#eq_name").val(),
                        eq_boil_size: parseFloat($("#eq_boil_size").jqxNumberInput('decimal')),
                        eq_batch_size: parseFloat($("#eq_batch_size").jqxNumberInput('decimal')),
                        eq_tun_volume: parseFloat($("#eq_tun_volume").jqxNumberInput('decimal')),
                        eq_tun_weight: dataRecord.eq_tun_weight,
                        eq_tun_specific_heat: dataRecord.eq_tun_specific_heat,
                        eq_tun_material: dataRecord.eq_tun_material,
                        eq_tun_height: dataRecord.eq_tun_height,
                        eq_top_up_water: parseFloat($("#eq_top_up_water").jqxNumberInput('decimal')),
                        eq_trub_chiller_loss: parseFloat($("#eq_trub_chiller_loss").jqxNumberInput('decimal')),
                        eq_evap_rate: parseFloat($("#eq_evap_rate").jqxNumberInput('decimal')),
                        eq_boil_time: parseFloat($("#eq_boil_time").jqxNumberInput('decimal')),
                        eq_calc_boil_volume: dataRecord.eq_calc_boil_volume,
                        eq_top_up_kettle: parseFloat($("#eq_top_up_kettle").jqxNumberInput('decimal')),
                        eq_hop_utilization: parseFloat($("#eq_hop_utilization").jqxNumberInput('decimal')),
                        eq_notes: $("#eq_notes").val(),
                        eq_lauter_volume: parseFloat($("#eq_lauter_volume").jqxNumberInput('decimal')),
                        eq_lauter_height: dataRecord.eq_lauter_height,
                        eq_lauter_deadspace: parseFloat($("#eq_lauter_deadspace").jqxNumberInput('decimal')),
                        eq_kettle_volume: parseFloat($("#eq_kettle_volume").jqxNumberInput('decimal')),
                        eq_kettle_height: dataRecord.eq_kettle_height,
                        eq_mash_volume: parseFloat($("#eq_mash_volume").jqxNumberInput('decimal')),
                        eq_mash_max: parseFloat($("#eq_mash_max").jqxNumberInput('decimal')),
                        eq_efficiency: parseFloat($("#eq_efficiency").jqxNumberInput('decimal')),
                        brew_date_start: $("#brew_date_start").val(),
                        brew_mash_ph: parseFloat($("#brew_mash_ph").jqxNumberInput('decimal')),
                        brew_mash_sg: parseFloat($("#brew_mash_sg").jqxNumberInput('decimal')),
                        brew_mash_efficiency: parseFloat($("#brew_mash_efficiency").jqxNumberInput('decimal')),
                        brew_sparge_est: parseFloat($("#brew_sparge_est").jqxNumberInput('decimal')),
                        brew_sparge_ph: parseFloat($("#brew_sparge_ph").jqxNumberInput('decimal')),
                        brew_preboil_volume: parseFloat($("#brew_preboil_volume").jqxNumberInput('decimal')),
                        brew_preboil_sg: parseFloat($("#brew_preboil_sg").jqxNumberInput('decimal')),
                        brew_preboil_ph: parseFloat($("#brew_preboil_ph").jqxNumberInput('decimal')),
                        brew_preboil_efficiency: parseFloat($("#brew_preboil_efficiency").jqxNumberInput('decimal')),
                        brew_aboil_volume: parseFloat($("#brew_aboil_volume").jqxNumberInput('decimal')),
                        brew_aboil_sg: parseFloat($("#brew_aboil_sg").jqxNumberInput('decimal')),
                        brew_aboil_ph: parseFloat($("#brew_aboil_ph").jqxNumberInput('decimal')),
                        brew_aboil_efficiency: parseFloat($("#brew_aboil_efficiency").jqxNumberInput('decimal')),
                        brew_cooling_method: $("#brew_cooling_method").val(),
                        brew_cooling_time: parseFloat($("#brew_cooling_time").jqxNumberInput('decimal')),
                        brew_cooling_to: parseFloat($("#brew_cooling_to").jqxNumberInput('decimal')),
                        brew_whirlpool9: parseFloat($("#brew_whirlpool9").jqxNumberInput('decimal')),
                        brew_whirlpool7: parseFloat($("#brew_whirlpool7").jqxNumberInput('decimal')),
                        brew_whirlpool6: parseFloat($("#brew_whirlpool6").jqxNumberInput('decimal')),
                        brew_whirlpool2: parseFloat($("#brew_whirlpool2").jqxNumberInput('decimal')),
                        brew_fermenter_volume: parseFloat($("#brew_fermenter_volume").jqxNumberInput('decimal')),
                        brew_fermenter_extrawater: parseFloat($("#brew_fermenter_extrawater").jqxNumberInput('decimal')),
                        brew_fermenter_tcloss: parseFloat($("#brew_fermenter_tcloss").jqxNumberInput('decimal')),
                        brew_aeration_time: parseFloat($("#brew_aeration_time").jqxNumberInput('decimal')),
                        brew_aeration_speed: parseFloat($("#brew_aeration_speed").jqxNumberInput('decimal')),
                        brew_aeration_type: $("#brew_aeration_type").val(),
                        brew_fermenter_sg: parseFloat($("#brew_fermenter_sg").jqxNumberInput('decimal')),
                        brew_fermenter_ibu: parseFloat($("#brew_fermenter_ibu").jqxNumberInput('decimal')),
                        brew_fermenter_color: parseFloat($("#brew_fermenter_color").jqxNumberInput('decimal')),
                        brew_date_end: $("#brew_date_end").val(),
                        og: dataRecord.og,
                        fg: parseFloat($("#fg").jqxNumberInput('decimal')),
                        primary_start_temp: parseFloat($("#primary_start_temp").jqxNumberInput('decimal')),
                        primary_max_temp: parseFloat($("#primary_max_temp").jqxNumberInput('decimal')),
                        primary_end_temp: parseFloat($("#primary_end_temp").jqxNumberInput('decimal')),
                        primary_end_sg: parseFloat($("#primary_end_sg").jqxNumberInput('decimal')),
                        primary_end_date: $("#primary_end_date").val(),
                        secondary_temp: parseFloat($("#secondary_temp").jqxNumberInput('decimal')),
                        secondary_end_sg: parseFloat($("#secondary_end_sg").jqxNumberInput('decimal')),
                        secondary_end_date: $("#secondary_end_date").val(),
                        tertiary_temp: parseFloat($("#tertiary_temp").jqxNumberInput('decimal')),
                        package_date: $("#package_date").val(),
                        package_volume: parseFloat($("#package_volume").jqxNumberInput('decimal')),
                        package_infuse_amount: parseFloat($("#package_infuse_amount").jqxNumberInput('decimal')),
                        package_infuse_abv: parseFloat($("#package_infuse_abv").jqxNumberInput('decimal')),
                        package_infuse_notes: $("#package_infuse_notes").val(),
                        package_abv: parseFloat($("#package_abv").jqxNumberInput('decimal')),
                        package_ph: parseFloat($("#package_ph").jqxNumberInput('decimal')),
                        bottle_amount: parseFloat($("#bottle_amount").jqxNumberInput('decimal')),
                        bottle_carbonation: parseFloat($("#bottle_carbonation").jqxNumberInput('decimal')),
                        bottle_priming_water: parseFloat($("#bottle_priming_water").jqxNumberInput('decimal')),
                        bottle_priming_amount: parseFloat($("#bottle_priming_amount").jqxNumberInput('decimal')),
                        bottle_carbonation_temp: parseFloat($("#bottle_carbonation_temp").jqxNumberInput('decimal')),
                        keg_amount: parseFloat($("#keg_amount").jqxNumberInput('decimal')),
                        keg_carbonation: parseFloat($("#keg_carbonation").jqxNumberInput('decimal')),
                        keg_priming_water: parseFloat($("#keg_priming_water").jqxNumberInput('decimal')),
                        keg_priming_amount: parseFloat($("#keg_priming_amount").jqxNumberInput('decimal')),
                        keg_carbonation_temp: parseFloat($("#keg_carbonation_temp").jqxNumberInput('decimal')),
                        keg_forced_carb: dataRecord.keg_forced_carb,
                        keg_pressure: parseFloat($("#keg_pressure").jqxNumberInput('decimal')),
                        taste_notes: $("#taste_notes").val(),
                        taste_rate: parseFloat($("#taste_rate").jqxNumberInput('decimal')),
                        taste_date: $("#taste_date").val(),
                        taste_color: $("#taste_color").val(),
                        taste_transparency: $("#taste_transparency").val(),
                        taste_head: $("#taste_head").val(),
                        taste_aroma: $("#taste_aroma").val(),
                        taste_taste: $("#taste_taste").val(),
                        taste_mouthfeel: $("#taste_mouthfeel").val(),
                        taste_aftertaste: $("#taste_aftertaste").val(),
                        st_name: $('#st_name').val(),
                        st_letter: $('#st_letter').val(),
                        st_guide: $('#st_guide').val(),
                        st_type: dataRecord.st_type,
                        st_category: $('#st_category').val(),
                        st_category_number: parseFloat($("#st_category_number").jqxNumberInput('decimal')),
                        st_og_min: parseFloat($("#st_og_min").jqxNumberInput('decimal')),
                        st_og_max: parseFloat($("#st_og_max").jqxNumberInput('decimal')),
                        st_fg_min: parseFloat($("#st_fg_min").jqxNumberInput('decimal')),
                        st_fg_max: parseFloat($("#st_fg_max").jqxNumberInput('decimal')),
                        st_ibu_min: parseFloat($("#st_ibu_min").jqxNumberInput('decimal')),
                        st_ibu_max: parseFloat($("#st_ibu_max").jqxNumberInput('decimal')),
                        st_color_min: parseFloat($("#st_color_min").jqxNumberInput('decimal')),
                        st_color_max: parseFloat($("#st_color_max").jqxNumberInput('decimal')),
                        st_carb_min: parseFloat($("#st_carb_min").jqxNumberInput('decimal')),
                        st_carb_max: parseFloat($("#st_carb_max").jqxNumberInput('decimal')),
                        st_abv_min: parseFloat($("#st_abv_min").jqxNumberInput('decimal')),
                        st_abv_max: parseFloat($("#st_abv_max").jqxNumberInput('decimal')),
                        type: $("#type").val(),
                        batch_size: parseFloat($("#batch_size").jqxNumberInput('decimal')),
                        boil_size: parseFloat($("#boil_size").jqxNumberInput('decimal')),
                        boil_time: parseFloat($("#boil_time").jqxNumberInput('decimal')),
                        efficiency: parseFloat($("#efficiency").jqxNumberInput('decimal')),
                        est_og: parseFloat($("#est_og").jqxNumberInput('decimal')),
                        est_fg: parseFloat($("#est_fg").jqxNumberInput('decimal')),
                        est_abv: parseFloat($("#est_abv").jqxNumberInput('decimal')),
                        est_color: parseFloat($("#est_color").jqxNumberInput('decimal')),
                        color_method: $("#color_method").val(),
                        est_ibu: parseFloat($("#est_ibu").jqxNumberInput('decimal')),
                        ibu_method: $("#ibu_method").val(),
                        est_carb: parseFloat($("#est_carb").jqxNumberInput('decimal')),
                        mash_name: $("#mash_name").val(),
                        mash_ph: parseFloat($("#mash_ph").jqxNumberInput('decimal')),
                        sparge_temp: parseFloat($("#sparge_temp").jqxNumberInput('decimal')),
                        sparge_ph: parseFloat($("#sparge_ph").jqxNumberInput('decimal')),
                        sparge_volume: parseFloat($("#sparge_volume").jqxNumberInput('decimal')),
                        sparge_source: $("#sparge_source").val(),
                        sparge_acid_type: $("#sparge_acid_type").val(),
                        sparge_acid_perc: parseFloat($("#sparge_acid_perc").jqxNumberInput('decimal')),
                        sparge_acid_amount: dataRecord.sparge_acid_amount,
                        calc_acid: dataRecord.calc_acid,
                        w1_name: $("#w1_name").val(),
                        w1_amount: parseFloat($("#w1_amount").jqxNumberInput('decimal')),
                        w1_calcium: parseFloat($("#w1_calcium").jqxNumberInput('decimal')),
                        w1_sulfate: parseFloat($("#w1_sulfate").jqxNumberInput('decimal')),
                        w1_chloride: parseFloat($("#w1_chloride").jqxNumberInput('decimal')),
                        w1_sodium: parseFloat($("#w1_sodium").jqxNumberInput('decimal')),
                        w1_magnesium: parseFloat($("#w1_magnesium").jqxNumberInput('decimal')),
                        w1_total_alkalinity: parseFloat($("#w1_total_alkalinity").jqxNumberInput('decimal')),
                        w1_ph: parseFloat($("#w1_ph").jqxNumberInput('decimal')),
                        w1_cost: dataRecord.w1_cost,
                        w2_name: $("#w2_name").val(),
                        w2_amount: parseFloat($("#w2_amount").jqxNumberInput('decimal')),
                        w2_calcium: parseFloat($("#w2_calcium").jqxNumberInput('decimal')),
                        w2_sulfate: parseFloat($("#w2_sulfate").jqxNumberInput('decimal')),
                        w2_chloride: parseFloat($("#w2_chloride").jqxNumberInput('decimal')),
                        w2_sodium: parseFloat($("#w2_sodium").jqxNumberInput('decimal')),
                        w2_magnesium: parseFloat($("#w2_magnesium").jqxNumberInput('decimal')),
                        w2_total_alkalinity: parseFloat($("#w2_total_alkalinity").jqxNumberInput('decimal')),
                        w2_ph: parseFloat($("#w2_ph").jqxNumberInput('decimal')),
                        w2_cost: dataRecord.w2_cost,
                        wg_amount: parseFloat($("#wg_amount").jqxNumberInput('decimal')),
                        wg_calcium: parseFloat($("#wg_calcium").jqxNumberInput('decimal')),
                        wg_sulfate: parseFloat($("#wg_sulfate").jqxNumberInput('decimal')),
                        wg_chloride: parseFloat($("#wg_chloride").jqxNumberInput('decimal')),
                        wg_sodium: parseFloat($("#wg_sodium").jqxNumberInput('decimal')),
                        wg_magnesium: parseFloat($("#wg_magnesium").jqxNumberInput('decimal')),
                        wg_total_alkalinity: parseFloat($("#wg_total_alkalinity").jqxNumberInput('decimal')),
                        wg_ph: parseFloat($("#wg_ph").jqxNumberInput('decimal')),
                        wb_calcium: parseFloat($("#wb_calcium").jqxNumberInput('decimal')),
                        wb_sulfate: parseFloat($("#wb_sulfate").jqxNumberInput('decimal')),
                        wb_chloride: parseFloat($("#wb_chloride").jqxNumberInput('decimal')),
                        wb_sodium: parseFloat($("#wb_sodium").jqxNumberInput('decimal')),
                        wb_magnesium: parseFloat($("#wb_magnesium").jqxNumberInput('decimal')),
                        wb_total_alkalinity: parseFloat($("#wb_total_alkalinity").jqxNumberInput('decimal')),
                        wb_ph: parseFloat($("#wb_ph").jqxNumberInput('decimal')),
                        wa_acid_name: $("#wa_acid_name").val(),
                        wa_acid_perc: parseFloat($("#wa_acid_perc").jqxNumberInput('decimal')),
                        wa_base_name: $("#wa_base_name").val(),
                        starter_enable: dataRecord.starter_enable,
                        starter_type: $("#starter_type").val(),
                        starter_sg: parseFloat($("#starter_sg").jqxNumberInput('decimal')),
                        starter_viability: parseFloat($("#starter_viability").jqxNumberInput('decimal')),
                        prop1_type: $("#prop1_type").val(),
                        prop1_volume: parseFloat($("#prop1_volume").jqxNumberInput('decimal')),
                        prop2_type: $("#prop2_type").val(),
                        prop2_volume: parseFloat($("#prop2_volume").jqxNumberInput('decimal')),
                        prop3_type: $("#prop3_type").val(),
                        prop3_volume: parseFloat($("#prop3_volume").jqxNumberInput('decimal')),
                        prop4_type: $("#prop4_type").val(),
                        prop4_volume: parseFloat($("#prop4_volume").jqxNumberInput('decimal')),
                        fermentables: $('#fermentableGrid').jqxGrid('getrows'),
                        hops: $('#hopGrid').jqxGrid('getrows'),
                        miscs: $('#miscGrid').jqxGrid('getrows'),
                        yeasts: $('#yeastGrid').jqxGrid('getrows'),
                        mashs: $('#mashGrid').jqxGrid('getrows')
                },
                data = "update=true&" + $.param(row);
                $.ajax({
                        dataType: 'json',
                        url: url,
                        cache: false,
                        data: data,
                        async: false,
                        type: "POST",
                        success: function (data, status, xhr) {
                                console.log("saveRecord() success");
                        },
                        error: function(jqXHR, textStatus, errorThrown) {
                                console.log("saveRecord() error");
                        }
                });
        };

	// initialize the input fields.
	// Tab 1, Algemeen
	$("#name").jqxTooltip({ content: 'De naam voor dit product.' });
	$("#name").jqxInput({ theme: theme, width: 640, height: 23 });
	$("#code").jqxTooltip({ content: 'Product code nummer.' });
	$("#code").jqxInput({ theme: theme, width: 100, height: 23 });
	$("#birth").jqxTooltip({ content: 'De ontwerp datum van dit product.' });
	$("#birth").jqxInput({ theme: theme, width: 120, height: 23 });
	$("#stage").jqxTooltip({ content: 'De productie fase van dit product.' });
	$("#stage").jqxInput({ theme: theme, width: 100, height: 23 });
	$("#locked").jqxCheckBox({ theme: theme, width: 120, height: 23, disabled : true });
	$('#locked').on('checked', function (event) {
		if (dataRecord.stage >= 10) {
			dataRecord.locked = 1;
			dataRecord.stage = 11;
			calcStage();
		}
	});
	$('#locked').on('unchecked', function (event) {
		if (dataRecord.stage >= 10) {
			dataRecord.locked = 0;
			dataRecord.stage = 10;
			calcStage();
		}
	});
	$("#notes").jqxTooltip({ content: 'De uitgebreide opmerkingen over dit product.' });
	$("#notes").jqxInput({ theme: theme, width: 960, height: 100 });
	$("#type").jqxTooltip({ content: 'Het brouw type van dit recept.' });
	$("#type").jqxDropDownList({
		theme: theme,
		source: RecipeTypeAdapter,
		valueMember: 'id',
		displayMember: 'nl',
		width: 180,
		height: 23,
		autoDropDownHeight: true
	});
	$("#efficiency").jqxTooltip({ content: 'Het rendement van maischen en koken.' });
	$("#efficiency").jqxNumberInput( Perc1dec );
	$("#batch_size").jqxTooltip({ content: 'Het volume van het gekoelde wort na het koken.' });
	$("#batch_size").jqxNumberInput( Spin1dec );
	$("#batch_size").jqxNumberInput({ min: 4 });
	$("#boil_time").jqxTooltip({ content: 'De kooktijd in minuten.' });
	$("#boil_time").jqxNumberInput( PosInt );
	$("#boil_time").jqxNumberInput({ min: 4, max: 360 });
	$("#boil_size").jqxTooltip({ content: 'Het volume van het wort voor het koken.' });
	$("#boil_size").jqxNumberInput({ inputMode: 'simple', theme: theme, width: 90, height: 23, decimalDigits: 2, readOnly: true });

	$("#st_guide").jqxTooltip({ content: 'De bierstijl gids voor dit recept.'});
	$("#st_guide").jqxInput({ theme: theme, width: 250, height: 23 });
	$("#st_name").jqxTooltip({ content: 'De bierstijl naam voor dit recept.'});
	$("#st_name").jqxInput({ theme: theme, width: 250, height: 23 });
	$("#st_letter").jqxTooltip({ content: 'De bierstijl letter voor dit recept.'});
	$("#st_letter").jqxInput({ theme: theme, width: 90, height: 23 });
	$("#st_type").jqxTooltip({ content: 'Het bierstijl type.'});
	$("#st_type").jqxInput({ theme: theme, width: 250, height: 23 });
	$("#st_category").jqxTooltip({ content: 'De Amerikaanse bierstijl categorie.'});
	$("#st_category").jqxInput({ theme: theme, width: 250, height: 23 });
	$("#st_category_number").jqxTooltip({ content: 'De Amerikaanse bierstijl categorie sub nummer.'});
	$("#st_category_number").jqxNumberInput(Smal0dec);

	$("#est_og").jqxTooltip({ content: 'Het begin SG wat je wilt bereiken. De moutstort wordt automatisch herberekend.' });
	$("#est_og").jqxNumberInput( SGopts );
	$("#st_og_min").jqxTooltip({ content: 'Het minimum begin SG voor deze bierstijl.'});
	$("#st_og_min").jqxNumberInput({ inputMode: 'simple', theme: theme, width: 50, height: 23, decimalDigits: 3, readOnly: true });
	$("#st_og_max").jqxTooltip({ content: 'Het maximum begin SG voor deze bierstijl.'});
	$("#st_og_max").jqxNumberInput({ inputMode: 'simple', theme: theme, width: 50, height: 23, decimalDigits: 3, readOnly: true });

	$("#est_fg").jqxTooltip({ content: 'Het verwachte eind SG. Dit wordt automatisch berekend.' });
	$("#est_fg").jqxNumberInput( Show3dec );
	$("#st_fg_min").jqxTooltip({ content: 'Het minimum eind SG voor deze bierstijl.'});
	$("#st_fg_min").jqxNumberInput({ inputMode: 'simple', theme: theme, width: 50, height: 23, decimalDigits: 3, readOnly: true });
	$("#st_fg_max").jqxTooltip({ content: 'Het maximum eind SG voor deze bierstijl.'});
	$("#st_fg_max").jqxNumberInput({ inputMode: 'simple', theme: theme, width: 50, height: 23, decimalDigits: 3, readOnly: true });

	$("#est_abv").jqxTooltip({ content: 'Alcohol volume %. Dit wordt automatisch berekend.' });
	$("#est_abv").jqxNumberInput(Smal1dec);
	$("#st_abv_min").jqxTooltip({ content: 'Het minimum alcohol volume % voor deze bierstijl.'});
	$("#st_abv_min").jqxNumberInput(Smal1dec);
	$("#st_abv_max").jqxTooltip({ content: 'Het maximum alcohol volume % voor deze bierstijl.'});
	$("#st_abv_max").jqxNumberInput(Smal1dec);

	$("#est_color").jqxTooltip({ content: 'De kleur in EBC. Dit wordt automatisch berekend.' });
	$("#est_color").jqxNumberInput( Show0dec );
	$("#st_color_min").jqxTooltip({ content: 'De minimum kleur voor deze bierstijl.'});
	$("#st_color_min").jqxNumberInput(Smal0dec);
	$("#st_color_max").jqxTooltip({ content: 'De maximum kleur voor deze bierstijl.'});
	$("#st_color_max").jqxNumberInput(Smal0dec);
	$("#color_method").jqxDropDownList({
		theme: theme,
		source: ColorMethodAdapter,
		valueMember: 'id',
		displayMember: 'nl',
		width: 180,
		height: 23,
		autoDropDownHeight: true
	});
	$("#est_ibu").jqxTooltip({ content: 'De bitterheid in IBU. Dit wordt automatisch berekend.' });
	$("#est_ibu").jqxNumberInput( Show0dec );
	$("#st_ibu_min").jqxTooltip({ content: 'De minimum bitterheid voor deze bierstijl.'});
	$("#st_ibu_min").jqxNumberInput(Smal0dec);
	$("#st_ibu_max").jqxTooltip({ content: 'De maximum bitterheid voor deze bierstijl.'});
	$("#st_ibu_max").jqxNumberInput(Smal0dec);
	$("#ibu_method").jqxDropDownList({
		theme: theme,
		source: IBUmethodAdapter,
		valueMember: 'id',
		displayMember: 'nl',
		width: 180,
		height: 23,
		autoDropDownHeight: true,
		dropDownVerticalAlignment: 'top'
	});
	$("#kcal").jqxTooltip({ content: 'Energie-inhoud in kcal/liter.' });
	$("#kcal").jqxNumberInput( Smal0dec );
	$("#est_carb").jqxTooltip({ content: 'Koolzuur volume. Dit wordt automatisch berekend.' });
	$("#est_carb").jqxNumberInput(Smal1dec);
	$("#st_carb_min").jqxTooltip({ content: 'Het minimum koolzuur volume voor deze bierstijl.'});
	$("#st_carb_min").jqxNumberInput(Smal1dec);
	$("#st_carb_max").jqxTooltip({ content: 'Het maximum koolzuur volume voor deze bierstijl.'});
	$("#st_carb_max").jqxNumberInput(Smal1dec);

	// Tab 2, Equipment
	$("#eq_name").jqxTooltip({ content: 'De naam van deze brouw apparatuur.' });
	$("#eq_name").jqxInput({ theme: theme, width: 250, height: 23 });
	$("#eq_boil_size").jqxTooltip({ content: 'Normaal kook volume in liters' });
	$("#eq_boil_size").jqxNumberInput( Show1dec );
	$("#eq_batch_size").jqxTooltip({ content: 'Berekende batch grootte in liters aan het eind van de kook.' });
	$("#eq_batch_size").jqxNumberInput( Show1dec );
	$("#eq_tun_volume").jqxTooltip({ content: 'Maisch ketel volume.' });
	$("#eq_tun_volume").jqxNumberInput( Show1dec );
	$("#eq_top_up_water").jqxTooltip({ content: 'Extra water in het gistvat.' });
	$("#eq_top_up_water").jqxNumberInput( Show1dec );
	$("#eq_trub_chiller_loss").jqxTooltip({ content: 'Standaard verlies bij het overbrengen naar het gistvat.' });
	$("#eq_trub_chiller_loss").jqxNumberInput( Show1dec );
	$("#eq_evap_rate").jqxTooltip({ content: 'Verdamping in liters per uur.' });
	$("#eq_evap_rate").jqxNumberInput( Show2dec );
	$("#eq_boil_time").jqxTooltip({ content: 'Normale kooktijd in minuten.' });
	$("#eq_boil_time").jqxNumberInput( Show0dec );
	$("#eq_top_up_kettle").jqxTooltip({ content: 'Extra water toevoegen tijdens de kook.' });
	$("#eq_top_up_kettle").jqxNumberInput( Show1dec );
	$("#eq_hop_utilization").jqxTooltip({ content: '100% voor kleine installaties, hoger voor grote brouwerijen.' });
	$("#eq_hop_utilization").jqxNumberInput( Show0dec );
	$("#eq_notes").jqxTooltip({ content: 'Opmerkingen over deze apparatuur.' });
	$("#eq_notes").jqxInput({ theme: theme, width: 960, height: 200 });
	$("#eq_lauter_volume").jqxTooltip({ content: 'Filterkuip volume.' });
	$("#eq_lauter_volume").jqxNumberInput( Show1dec );
	$("#eq_lauter_deadspace").jqxTooltip({ content: 'Filterkuip verlies in liters.' });
	$("#eq_lauter_deadspace").jqxNumberInput( Show1dec );
	$("#eq_kettle_volume").jqxTooltip({ content: 'Kook ketel volume in liters.' });
	$("#eq_kettle_volume").jqxNumberInput( Show1dec );
	$("#eq_mash_volume").jqxTooltip({ content: 'Maisch water voor de eerste stap.' });
	$("#eq_mash_volume").jqxNumberInput( Show1dec );
	$("#eq_mash_max").jqxTooltip({ content: 'De maximale moutstort in Kg.' });
	$("#eq_mash_max").jqxNumberInput( Show1dec );
	$("#eq_efficiency").jqxTooltip({ content: 'Gemiddeld brouwzaal rendement.' });
	$("#eq_efficiency").jqxNumberInput( Show1dec );

	// Tab 3, Fermentables
	$("#est_color2").jqxTooltip({ content: 'De kleur in EBC. Dit wordt automatisch berekend.' });
	$("#est_color2").jqxNumberInput( Show0dec );
	$("#est_og2").jqxTooltip({ content: 'Het geschatte begin SG van dit product.' });
	$("#est_og2").jqxNumberInput( Show3dec );
	$("#mash_kg").jqxTooltip({ content: 'Het gewicht van alle mouten in de maisch.' });
	$("#mash_kg").jqxNumberInput( Show3dec );
	$("#perc_malts").jqxProgressBar({
		width: 300,
		height: 23,
		theme: theme,
		showText: true,
		max: 120,
		animationDuration: 0,
		colorRanges: [
			{ stop:  90, color: '#008C00' },
			{ stop: 100, color: '#EB7331' },
			{ stop: 120, color: '#FF0000' }
		],
		renderText: function (text) {
			return (Math.round(parseInt(text) * 1.2)) + '%';
    		}
	});
	$("#perc_sugars").jqxProgressBar({
		width: 300,
		height: 23,
		theme: theme,
		showText: true,
		max: 50,
		animationDuration: 0,
		colorRanges: [
			{ stop: 20, color: '#008C00' },
			{ stop: 50, color: '#FF0000' }
		],
		renderText: function (text) {
			return (Math.round(parseInt(text) * 5) / 10) + '%';
		}
	});
	$("#perc_cara").jqxProgressBar({
		width: 300,
		height: 23,
		theme: theme,
		showText: true,
		max: 50,
		animationDuration: 0,
		colorRanges: [
			{ stop: 25, color: '#008C00' },
			{ stop: 50, color: '#FF0000' }
		],
		renderText: function (text) {
			return (Math.round(parseInt(text) * 5) / 10) + '%';
		}
	});
	$("#ferm_lintner").jqxProgressBar({
		width: 300,
		height: 23,
		theme: theme,
		showText: true,
		max: 200,
		animationDuration: 0,
		colorRanges: [
			{ stop:  30, color: '#FF0000' },
			{ stop:  40, color: '#EB7331' },
			{ stop: 200, color: '#008C00' }
		],
		renderText: function (text) {
			return (parseInt(text) * 2) + ' lintner';
		}
	});
	$("#popupFermentable").jqxWindow({
		width: 800,
		height: 300,
		position: { x: 230, y: 100 },
		resizable: false,
		theme: theme,
		isModal: true,
		autoOpen: false,
		cancelButton: $("#FermentableReady"),
		modalOpacity: 0.40
	});
	$("#FermentableReady").jqxButton({ template: "success", width: '90px', theme: theme });
	$("#FermentableReady").click(function () {
		var row, rowID = $("#fermentableGrid").jqxGrid('getrowid', fermentableRow);
		console.log("FermentableReady row:"+fermentableRow+" ID:"+rowID);
		row = {
			f_name: fermentableData.f_name,
			f_origin: fermentableData.f_origin,
			f_supplier: fermentableData.f_supplier,
			f_amount: fermentableData.f_amount,
			f_cost: fermentableData.f_cost,
			f_type: fermentableData.f_type,
			f_yield: fermentableData.f_yield,
			f_color: fermentableData.f_color,
			f_coarse_fine_diff: fermentableData.f_coarse_fine_diff,
			f_moisture: fermentableData.f_moisture,
			f_diastatic_power: fermentableData.f_diastatic_power,
			f_protein: fermentableData.f_protein,
			f_max_in_batch: fermentableData.f_max_in_batch,
			f_graintype: fermentableData.f_graintype,
			f_added: fermentableData.f_added,
			f_dissolved_protein: fermentableData.f_dissolved_protein,
			f_recommend_mash: fermentableData.f_recommend_mash,
			f_add_after_boil: fermentableData.f_add_after_boil,
			f_adjust_to_total_100: fermentableData.f_adjust_to_total_100,
			f_percentage: fermentableData.f_percentage,
			f_di_ph: fermentableData.f_di_ph,
			f_acid_to_ph_57: fermentableData.f_acid_to_ph_57,
			f_inventory: fermentableData.f_inventory,
			f_avail: fermentableData.f_avail
		};
		$("#fermentableGrid").jqxGrid('updaterow', rowID, row);
		calcPercentages();
		calcFermentables();
		calcIBUs();
		calcMash();
		// Waters: yes there is impact.
	});
	$("#wf_name").jqxInput({ theme: theme, width: 320, height: 23 });
	$("#wf_instock").jqxCheckBox({ theme: theme, height: 23 });
	$("#wf_instock").on('change', function (event) {
		fermentableinstock = event.args.checked;
		fermentablelist.dataBind();
	});
	$("#wf_select").jqxDropDownList({
		placeHolder: "Kies mout:",
		theme: theme,
		source: fermentablelist,
		displayMember: "name",
		width: 150,
		height: 23,
		dropDownWidth: 500,
		dropDownHeight: 500,
		renderer: function (index, label, value) {
			var datarecord = fermentablelist.records[index];
			return datarecord.supplier+ " / " + datarecord.name + " (" + datarecord.color + " EBC)";
		}
	});
	$("#wf_select").on('select', function (event) {
		if (event.args) {
			var datarecord, index = event.args.index;
			datarecord = fermentablelist.records[index];
			$("#wf_name").val(datarecord.name);
			fermentableData.f_name = datarecord.name;
			fermentableData.f_origin = datarecord.origin;
			fermentableData.f_supplier = datarecord.supplier;
			fermentableData.f_type = datarecord.type;
			fermentableData.f_cost = datarecord.cost;
			fermentableData.f_yield = datarecord.yield;
			fermentableData.f_color = datarecord.color;
			fermentableData.f_coarse_fine_diff = datarecord.coarse_fine_diff;
			fermentableData.f_moisture = datarecord.moisture;
			fermentableData.f_diastatic_power = datarecord.diastatic_power;
			fermentableData.f_protein = datarecord.protein;
			fermentableData.f_max_in_batch = datarecord.max_in_batch;
			fermentableData.f_graintype = datarecord.graintype;
			fermentableData.f_dissolved_protein = datarecord.dissolved_protein;
			fermentableData.f_recommend_mash = datarecord.recommend_mash;
			fermentableData.f_add_after_boil = datarecord.add_after_boil;
			fermentableData.f_di_ph = datarecord.di_ph;
			fermentableData.f_acid_to_ph_57 = datarecord.acid_to_ph_57;
			fermentableData.f_inventory = datarecord.inventory;
		}
	});
	$("#wf_amount").jqxNumberInput( Spin3dec );
	$('#wf_amount').on('change', function (event) {
		console.log("amount changed: "+event.args.value);
		$("#fermentableGrid").jqxGrid('setcellvalue', fermentableRow, 'f_amount', event.args.value);
		fermentableData.f_amount = event.args.value;
		if (! to_100) {
			calcPercentages();
			calcFermentables();
			calcIBUs();
			calcMash();
		};
	});
	$("#wf_percentage").jqxNumberInput( Perc1dec );
	$("#wf_percentage").on('change', function (event) {
		var newvalue, rowscount, rowdata, diff, tw, damount, namount, nw, newperc,
		oldvalue = Math.round(fermentableData.f_percentage * 10) / 10.0;
		newvalue = event.args.value;
		console.log("percentage changed: "+newvalue+" old: "+oldvalue);
		fermentableData.f_percent = newvalue;
		rowscount = $("#fermentableGrid").jqxGrid('getdatainformation').rowscount;
		if ((oldvalue != newvalue) && (rowscount > 1)) {
			rowdata = $("#fermentableGrid").jqxGrid('getrowdata', fermentableRow);
			if (rowdata.f_adjust_to_total_100) {
				$("#wf_percentage").val(oldvalue);
			} else {
				diff = newvalue - oldvalue;
				tw = 0;     // total weight
				for (i = 0; i < rowscount; i++) {
					rowdata = $("#fermentableGrid").jqxGrid('getrowdata', i);
					if (rowdata.f_added < 4)
						tw += Math.round(rowdata.f_amount * 1000) / 1000;
				}
				tw = Math.round(tw * 1000) / 1000;
				if (to_100) {
					// Adjust this row and the 100% row.
					damount = Math.round(tw * diff *10) / 1000;
					rowdata = $("#fermentableGrid").jqxGrid('getrowdata', fermentableRow);
					namount = Math.round((rowdata.f_amount + damount) * 1000) / 1000;
					$("#fermentableGrid").jqxGrid('setcellvalue', fermentableRow, 'f_amount', namount);
					$("#wf_amount").val(namount);
					$("#fermentableGrid").jqxGrid('setcellvalue', fermentableRow, 'f_percentage', rowdata.f_percentage + diff);
					for (i = 0; i < rowscount; i++) {
						rowdata = $("#fermentableGrid").jqxGrid('getrowdata', i);
						if (rowdata.f_adjust_to_total_100) {
							namount = rowdata.f_amount - damount;
							$("#fermentableGrid").jqxGrid('setcellvalue', i, 'f_percentage', rowdata.f_percentage - diff);
							$("#fermentableGrid").jqxGrid('setcellvalue', i, 'f_amount', namount);
						}
					}
					calcFermentables();
					calcIBUs();
					calcMash();
				} else {
					// Adjust all the rows.
					nw = tw * diff / 100;
					for (i = 0; i < rowscount; i++) {
						rowdata = $("#fermentableGrid").jqxGrid('getrowdata', i);
						if (rowdata.f_added < 4) {
							if (i == fermentableRow) {
								namount = Math.round((rowdata.f_amount + nw) * 1000) / 1000;
								$("#fermentableGrid").jqxGrid('setcellvalue', i, 'f_amount', namount);
		//                                      	$("#wf_amount").val(namount); // Will crash the script.
								$("#fermentableGrid").jqxGrid('setcellvalue', i, 'f_percentage', newvalue);
							} else {
								namount = Math.round((rowdata.f_amount - (nw / (rowscount - 1))) * 1000) / 1000;
								newperc = Math.round((namount / tw) * 1000) / 10.0;
								$("#fermentableGrid").jqxGrid('setcellvalue', i, 'f_amount', namount);
								$("#fermentableGrid").jqxGrid('setcellvalue', i, 'f_percentage', newperc);
							}
						} else {
							$("#fermentableGrid").jqxGrid('setcellvalue', i, 'f_percentage', 0);
						}
					}
					calcFermentables();
					calcIBUs();
					calcMash();
				}
			}
		}
	});
	$("#wf_max_in_batch").jqxNumberInput( Show1dec );
	$("#wf_adjust_to_total_100").jqxCheckBox({ theme: theme, width: 120, height: 23 });
	$("#wf_adjust_to_total_100").on('checked', function (event) {
		if (fermentableData.f_adjust_to_total_100 == 0) {
			if (to_100) {
				// Reset other flag first.
				var i, rowscount = $("#fermentableGrid").jqxGrid('getdatainformation').rowscount;
				for (i = 0; i < rowscount; i++) {
					if (i != fermentableRow) {
						$("#fermentableGrid").jqxGrid('setcellvalue', i, 'f_adjust_to_total_100', 0);
					}
				}
			}
			$("#fermentableGrid").jqxGrid('setcellvalue', fermentableRow, 'f_adjust_to_total_100', 1);
			calcFermentables();
		}
	});
	$("#wf_adjust_to_total_100").on('unchecked', function (event) {
		if (fermentableData.f_adjust_to_total_100 != 0) {
			$("#fermentableGrid").jqxGrid('setcellvalue', fermentableRow, 'f_adjust_to_total_100', 0);
			calcFermentables();
		}
	});
	$("#wf_added").jqxDropDownList({
		theme: theme,
		source: AddedAdapter,
		valueMember: 'id',
		displayMember: 'nl',
		width: 180,
		height: 23,
		autoDropDownHeight: true,
		dropDownVerticalAlignment: 'top'
	});
	$("#wf_added").on('select', function (event) {
		if (event.args) {
			var index = event.args.index;
			$("#fermentableGrid").jqxGrid('setcellvalue', fermentableRow, 'f_added', index);
			calcFermentables();
			calcIBUs();
			calcMash();
		}
	});

	// Tab 4, Hops
	$("#est_ibu2").jqxTooltip({ content: 'De bitterheid in IBU. Dit wordt automatisch berekend.' });
	$("#est_ibu2").jqxNumberInput(Smal0dec);
	$("#hop_flavour").jqxProgressBar({
		width: 300,
		height: 23,
		theme: theme,
		showText: true,
		animationDuration: 0,
		colorRanges: [
			{ stop:  20, color: '#004D00' },
			{ stop:  40, color: '#008C00' },
			{ stop:  60, color: '#00BF00' },
			{ stop:  80, color: '#00FF00' },
			{ stop: 100, color: '#80FF80' }
		],
                renderText: function (text) {
                        var val = parseInt(text);
                        if (val < 20)
                                return 'Weinig';
                        else if (val < 40)
                                return 'Matig';
                        else if (val < 60)
                                return 'Redelijk';
                        else if (val < 80)
                                return 'Veel';
                        else
                                return 'Zeer veel';
                }
	});
	$("#hop_aroma").jqxProgressBar({
		width: 300, height: 23, theme: theme, showText: true,
		animationDuration: 0,
		colorRanges: [
			{ stop:  20, color: '#004D00' },
		        { stop:  40, color: '#008C00' },
			{ stop:  60, color: '#00BF00' },
			{ stop:  80, color: '#00FF00' },
			{ stop: 100, color: '#80FF80' }
		],
		renderText: function (text) {
			var val = parseInt(text);
			if (val < 20)
				return 'Weinig';
			else if (val < 40)
				return 'Matig';
			else if (val < 60)
				return 'Redelijk';
			else if (val < 80)
				return 'Veel';
			else
				return 'Zeer veel';
		}
	});
	$("#popupHop").jqxWindow({
		width: 800,
		height: 300,
		position: { x: 230, y: 100 },
		resizable: false,
		theme: theme,
		isModal: true,
		autoOpen: false,
		cancelButton: $("#HopReady"),
		modalOpacity: 0.40
	});
	$("#HopReady").jqxButton({ template: "success", width: '90px', theme: theme });
	$("#HopReady").click(function () {
		var row, rowID = $("#hopGrid").jqxGrid('getrowid', hopRow);
		row = {
			h_name: $("#wh_name").val(),
			h_origin: hopData.h_origin,
			h_amount: parseFloat($("#wh_amount").jqxNumberInput('decimal')) / 1000,
			h_cost: hopData.h_cost,
			h_type: hopData.h_type,
			h_form: hopData.h_form,
			h_useat: $("#wh_useat").val(),
			h_time: hopData.h_time,
			h_alpha: hopData.h_alpha,
			h_beta: hopData.h_beta,
			h_hsi: hopData.h_hsi,
			h_humulene: hopData.h_humulene,
			h_caryophyllene: hopData.h_caryophyllene,
			h_cohumulone: hopData.h_cohumulone,
			h_myrcene: hopData.h_myrcene,
			h_total_oil: hopData.h_total_oil,
			h_inventory: hopData.h_inventory,
			h_avail: hopData.h_avail
		};
		$("#hopGrid").jqxGrid('updaterow', rowID, row);
		calcIBUs();
	});
	$("#wh_name").jqxInput({ theme: theme, width: 320, height: 23 });
	$("#wh_instock").jqxCheckBox({ theme: theme, height: 23 });
	$("#wh_instock").on('change', function (event) {
		hopinstock = event.args.checked;
		hoplist.dataBind();
	});
	$("#wh_select").jqxDropDownList({
		placeHolder: "Kies hop:",
		theme: theme,
		source: hoplist,
		displayMember: "name",
		width: 150,
		height: 23,
		dropDownWidth: 500,
		dropDownHeight: 500,
		renderer: function (index, label, value) {
			var datarecord = hoplist.records[index];
			return datarecord.origin+ " - " + datarecord.name + " / " + HopFormData[datarecord.form].nl + " (" + datarecord.alpha + " % &alpha;)";
		}
	});
	$("#wh_select").on('select', function (event) {
		if (event.args) {
			var datarecord, index = event.args.index;
			datarecord = hoplist.records[index];
			$("#wh_name").val(datarecord.name);
			hopData.h_name = datarecord.name;
			hopData.h_origin = datarecord.origin;
			hopData.h_cost = datarecord.cost;
			hopData.h_type = datarecord.type;
			hopData.h_form = datarecord.form;
			hopData.h_alpha = datarecord.alpha;
			hopData.h_beta = datarecord.beta;
			hopData.h_hsi = datarecord.hsi;
			hopData.h_humulene = datarecord.humulene;
			hopData.h_caryophyllene = datarecord.caryophyllene;
			hopData.h_cohumulone = datarecord.cohumulone;
			hopData.h_myrcene = datarecord.myrcene;
			hopData.h_total_oil = datarecord.total_oil;
			hopData.h_inventory = datarecord.inventory;
		}
	});
	$("#wh_amount").jqxNumberInput( Spin1dec );
	$('#wh_amount').on('change', function (event) {
		console.log("amount changed: "+event.args.value+" time:"+hopData.h_time+" alpha:"+hopData.h_alpha);
		var ibu, amount = parseFloat(event.args.value) / 1000;
		ibu = toIBU(hopData.h_useat, hopData.h_form, preboil_sg,
			parseFloat($("#batch_size").jqxNumberInput('decimal')),
			amount, parseFloat(hopData.h_time),
			parseFloat(hopData.h_alpha), $("#ibu_method").val()
		);
		hopData.h_amount = amount;
		$("#wh_ibu").val(ibu);
	});
	$("#wh_ibu").jqxNumberInput( Show1dec );
	$("#wh_time").jqxNumberInput( PosInt );
	$("#wh_time").on('change', function (event) {
		var ibu, newtime = parseFloat(event.args.value);
		// Check limits and correct
		if (hopData.h_useat == 2) {     // Boil
			if (newtime > parseFloat($("#boil_time").jqxNumberInput('decimal'))) {
				newtime = parseFloat($("#boil_time").jqxNumberInput('decimal'));
				$("#wh_time").val(newtime);
			}
			hopData.h_time = newtime;
		} else if (hopData.h_useat == 4) {      // Whirlpool
			if (newtime > 120) {
				newtime = 120;
				$("#wh_time").val(newtime);
			}
			hopData.h_time = newtime;
		} else if (hopData.h_useat == 5) {      // Dry hop
			if (newtime > 21) {
				newtime = 21;
				$("#wh_time").val(newtime);
			}
			hopData.h_time = newtime * 1440;
		}
		ibu = toIBU(hopData.h_useat, hopData.h_form, preboil_sg, parseFloat($("#batch_size").jqxNumberInput('decimal')),
				parseFloat(hopData.h_amount), parseFloat(hopData.h_time), parseFloat(hopData.h_alpha), $("#ibu_method").val());
		// console.log("time changed: "+newtime+" final:"+hopData.h_time+" ibu:"+ibu);
		$("#wh_ibu").val(ibu);
	});
	$("#wh_useat").jqxDropDownList({
		theme: theme,
		source: HopUseAdapter,
		valueMember: 'id',
		displayMember: 'nl',
		width: 180,
		height: 23,
		autoDropDownHeight: true,
		dropDownVerticalAlignment: 'top'
	});
	$("#wh_useat").on('select', function (event) {
		if (event.args) {
			var index = event.args.index;
			hopData.h_useat = index;
			if ((index == 0) || (index == 1)) {     // Mashhop or First wort hop
				hopData.h_time = parseFloat(dataRecord.boil_time);
				$("#wh_time").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
				$("#wh_time").val(hopData.h_time);
			} else if (index == 3) {        // Aroma
				hopData.h_time = 0;
				$("#wh_time").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
				$("#wh_time").val(0);
			} else {        // Boil, Whirlpool or Dry hop
				$("#wh_time").jqxNumberInput({ spinButtons: true, readOnly: false, width: 110 });
			}
			if (index == 5) // Dry hop
				$("#wh_pmpt_time").html("Tijd in dagen");
			else
				$("#wh_pmpt_time").html("Tijd in minuten");
		}
	});

	// Tab 5, Miscs
	$("#popupMisc").jqxWindow({
		width: 800,
		height: 275,
		position: { x: 230, y: 100 },
		resizable: false,
		theme: theme,
		isModal: true,
		autoOpen: false,
		cancelButton: $("#MiscReady"),
		modalOpacity: 0.40
	});
	$("#MiscReady").jqxButton({ template: "success", width: '90px', theme: theme });
	$("#MiscReady").click(function () {
		var row, rowID = $("#miscGrid").jqxGrid('getrowid', miscRow);
		console.log("MiscReady row:"+miscRow+" ID:"+rowID);
		row = {
			m_name: miscData.m_name,
			m_amount: miscData.m_amount,
			m_cost: miscData.m_cost,
			m_type: miscData.m_type,
			m_use_use: miscData.m_use_use,
			m_time: miscData.m_time,
			m_amount_is_weight: miscData.m_amount_is_weight,
			m_inventory: miscData.m_inventory,
			m_avail:  miscData.m_avail
		};
		$("#miscGrid").jqxGrid('updaterow', rowID, row);
		calcMiscs();
	});
	$("#wm_name").jqxInput({ theme: theme, width: 320, height: 23 });
	$("#wm_instock").jqxCheckBox({ theme: theme, height: 23 });
	$("#wm_instock").on('change', function (event) {
		miscinstock = event.args.checked;
		misclist.dataBind();
	});
	$("#wm_select").jqxDropDownList({
		placeHolder: "Kies ingredi&euml;nt:",
		theme: theme,
		source: misclist,
		displayMember: "name",
		width: 150,
		height: 23,
		dropDownWidth: 500,
		dropDownHeight: 500
	});
	$("#wm_select").on('select', function (event) {
		if (event.args) {
			var datarecord, index = event.args.index;
			datarecord = misclist.records[index];
			$("#wm_name").val(datarecord.name);
			miscData.m_name = datarecord.name;
			miscData.m_cost = datarecord.cost;
			miscData.m_type = datarecord.type;
			miscData.m_use_use = datarecord.use_use;
			miscData.m_amount_is_weight = datarecord.amount_is_weight;
			miscData.m_inventory = datarecord.inventory;
		}
	});
	$("#wm_amount").jqxNumberInput( Spin2dec );
	$('#wm_amount').on('change', function (event) {
		console.log("amount changed: "+event.args.value);
		miscData.m_amount = parseFloat(event.args.value) / 1000;
	});
	$("#wm_time").jqxNumberInput( PosInt );
	$("#wm_time").on('change', function (event) {
		var newtime = parseFloat(event.args.value);

		if (miscData.m_use_use == 2) {   // Boil
			if (newtime > parseFloat($("#boil_time").jqxNumberInput('decimal'))) {
				newtime = parseFloat($("#boil_time").jqxNumberInput('decimal'));
				$("#wm_time").val(newtime);
			}
			miscData.m_time = newtime;
		} else if ((miscData.m_use_use == 3) || (miscData.m_use_use == 4)) {      // Primary or Secondary
			if (newtime > 21) {
				newtime = 21;
				$("#wm_time").val(newtime);
			}
			miscData.m_time = newtime * 1440;
		}
	});
	$("#wm_use_use").jqxDropDownList({
		theme: theme,
		source: MiscUseAdapter,
		valueMember: 'id',
		displayMember: 'nl',
		width: 180,
		height: 23,
		autoDropDownHeight: true,
		dropDownVerticalAlignment: 'top'
	});
	$("#wm_use_use").on('select', function (event) {
		if (event.args) {
			var index = event.args.index;
			miscData.m_use_use = index;
			if ((index == 2) || (index == 3) || (index == 4)) {     // Boil, Primary or Secondary
				$("#wm_time").jqxNumberInput({ spinButtons: true, readOnly: false, width: 110 });
			} else {
				$("#wm_time").jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 });
				$("#wm_time").val(0);
				miscData.m_time = 0;
			}
		}
	});

	// Tab 6, Yeasts
	$("#est_fg2").jqxTooltip({ content: 'Het verwachte eind SG. Dit wordt automatisch berekend.' });
	$("#est_fg2").jqxNumberInput( Show3dec );
	$("#est_abv2").jqxTooltip({ content: 'Alcohol volume %. Dit wordt automatisch berekend.' });
	$("#est_abv2").jqxNumberInput(Smal1dec);
	$("#yeast_cells").jqxNumberInput( Show1dec );
	$("#need_cells").jqxNumberInput( Show1dec );
	$("#plato_cells").jqxNumberInput( Show2dec );
	$("#popupYeast").jqxWindow({
		width: 800,
		height: 300,
		position: { x: 230, y: 100 },
		resizable: false,
		theme: theme,
		isModal: true,
		autoOpen: false,
		cancelButton: $("#YeastReady"),
		modalOpacity: 0.40
	});
	$("#YeastReady").jqxButton({ template: "success", width: '90px', theme: theme });
	$("#YeastReady").click(function () {
		var row, rowID = $("#yeastGrid").jqxGrid('getrowid', yeastRow);
		console.log("YeastReady row:"+yeastRow+" ID:"+rowID);
		row = {
			y_name: yeastData.y_name,
			y_laboratory: yeastData.y_laboratory,
			y_product_id: yeastData.y_product_id,
			y_amount: yeastData.y_amount,
			y_cost: yeastData.y_cost,
			y_type: yeastData.y_type,
			y_form: yeastData.y_form,
			y_flocculation: yeastData.y_flocculation,
			y_min_temperature: yeastData.y_min_temperature,
			y_max_temperature: yeastData.y_max_temperature,
			y_attenuation: yeastData.y_attenuation,
			y_use: yeastData.y_use,
			y_cells: yeastData.y_cells,
			y_tolerance: yeastData.y_tolerance,
			y_inventory: yeastData.y_inventory,
			y_avail: yeastData.y_avail
		};
		$("#yeastGrid").jqxGrid('updaterow', rowID, row);
		calcFermentables();
		calcYeast();
	});
	$("#wy_name").jqxInput({ theme: theme, width: 320, height: 23 });
	$("#wy_laboratory").jqxInput({ theme: theme, width: 320, height: 23 });
	$("#wy_product_id").jqxInput({ theme: theme, width: 320, height: 23 });
	$("#wy_instock").jqxCheckBox({ theme: theme, height: 23 });
	$("#wy_instock").on('change', function (event) {
		yeastinstock = event.args.checked;
		yeastlist.dataBind();
	});
	$("#wy_select").jqxDropDownList({
		placeHolder: "Kies gist:",
		theme: theme,
		source: yeastlist,
		displayMember: "name",
		width: 150,
		height: 23,
		dropDownWidth: 500,
		dropDownHeight: 500,
		renderer: function (index, label, value) {
			var datarecord = yeastlist.records[index];
			return datarecord.laboratory+" "+datarecord.product_id+" "+datarecord.name;
		}
	});
	$("#wy_select").on('select', function (event) {
		if (event.args) {
			var datarecord, index = event.args.index;
			datarecord = yeastlist.records[index];
			$("#wy_name").val(datarecord.name);
			$("#wy_laboratory").val(datarecord.laboratory);
			$("#wy_product_id").val(datarecord.product_id);
			yeastData.y_name = datarecord.name;
			yeastData.y_cost = datarecord.cost;
			yeastData.y_type = datarecord.type;
			yeastData.y_form = datarecord.form;
			yeastData.y_laboratory = datarecord.laboratory;
			yeastData.y_product_id = datarecord.product_id;
			yeastData.y_min_temperature = datarecord.min_temperature;
			yeastData.y_max_temperature = datarecord.max_temperature;
			yeastData.y_flocculation = datarecord.flocculation;
			yeastData.y_attenuation = datarecord.attenuation;
			yeastData.y_cells = datarecord.cells;
			yeastData.y_inventory = datarecord.inventory;
			if (yeastData.y_form == 0) {
				$("#wy_pmpt_amount").html("Pak(ken):");
			} else if (yeastData.y_form == 1) {
				$("#wy_pmpt_amount").html("Gewicht gram:");
			} else {
				$("#wy_pmpt_amount").html("Volume ml:");
			}
			calcFermentables();
			calcYeast();
		}
	});
	$("#wy_amount").jqxNumberInput( Spin1dec );
	$('#wy_amount').on('change', function (event) {
		var amount = parseFloat(event.args.value);
		if (yeastData.y_form != 0)        // not Liquid
			amount = parseFloat(event.args.value) / 1000;
		yeastData.y_amount = amount;
		calcFermentables();
		calcYeast();
	});
	$("#wy_use").jqxDropDownList({
		theme: theme,
		source: YeastUseAdapter,
		valueMember: 'id',
		displayMember: 'nl',
		width: 180,
		height: 23,
		autoDropDownHeight: true,
		dropDownVerticalAlignment: 'top'
	});
	$("#wy_use").on('select', function (event) {
		if (event.args) {
			var index = event.args.index;
			yeastData.y_use = index;
			calcFermentables();
			calcYeast();
		}
	});
	for (i = 1; i < 5; i++) {
		$("#prop"+i+"_type").jqxDropDownList({
			theme: theme,
			source: StarterTypeAdapter,
			valueMember: 'id',
			displayMember: 'nl',
			width: 120,
			height: 23,
			autoDropDownHeight: true
		});
		$("#prop"+i+"_type").hide();
		$("#prop"+i+"_volume").jqxNumberInput( Spin3dec );
		$("#prop"+i+"_volume").hide();
		$("#prop"+i+"_irate").jqxNumberInput( Show1dec );
		$("#prop"+i+"_irate").hide();
		$("#prop"+i+"_ncells").jqxNumberInput( Show1dec );
		$("#prop"+i+"_ncells").hide();
		$("#prop"+i+"_tcells").jqxNumberInput( Show1dec );
		$("#prop"+i+"_tcells").hide();
		$("#prop"+i+"_growf").jqxNumberInput( Show2dec );
		$("#prop"+i+"_growf").hide();
	}
	$("#starter_enable").jqxCheckBox({ theme: theme, height: 23 });
	$("#starter_type").jqxDropDownList({
		theme: theme,
		source: StarterTypeAdapter,
		valueMember: 'id',
		displayMember: 'nl',
		width: 120,
		height: 23,
		autoDropDownHeight: true
	});
	$("#starter_sg").jqxNumberInput( SGopts );
	$("#starter_viability").jqxNumberInput( Perc0 );
	$("#starter_try").jqxButton({ template: "primary", width: '100px', height: 23, theme: theme });

	// Tab 7, Mashing
	$("#mash_name").jqxTooltip({ content: 'De omschrijving van dit maisch profiel.' });
	$("#mash_name").jqxInput({ theme: theme, width: 320, height: 23 });
	$("#mash_select").jqxDropDownList({
		placeHolder: "Kies schema:",
		theme: theme,
		source: mashlist,
		displayMember: "name",
		width: 250,
		height: 23,
		dropDownWidth: 500,
		dropDownHeight: 500,
		dropDownHorizontalAlignment: 'right'
	});
	$("#mash_select").on('select', function (event) {
		if (event.args) {
			var data, datarecord, rowIDs, rows, i, row = {}, index = event.args.index;
			// First delete all current steps
			rowIDs = new Array();
			rows = $("#mashGrid").jqxGrid('getdisplayrows');
			for (i = 0; i < rows.length; i++) {
				row = rows[i];
				rowIDs.push(row.uid);
			}
			$("#mashGrid").jqxGrid('deleterow', rowIDs);
			// Then add the new steps
			datarecord = mashlist.records[index];
			$("#mash_name").val(datarecord.name);
			for (i = 0; i < datarecord.steps.length; i++) {
				data = datarecord.steps[i];
				row["step_name"] = data.step_name;
				row["step_type"] = data.step_type;
				// For now, but this must be smarter.
				if (mash_infuse == 0 && dataRecord.w1_amount > 0)
					mash_infuse = dataRecord.w1_amount;
				if (i == 0)
					row["step_infuse_amount"] = mash_infuse;
				else
					row["step_infuse_amount"] = 0;
				if (mashkg > 0)
					row['step_thickness'] = parseFloat(mash_infuse / mashkg);
				else
					row['step_thickness'] = 0;
				row["step_temp"] = data.step_temp;
				row["end_temp"] = data.end_temp;
				row["step_time"] = data.step_time;
				row["ramp_time"] = data.ramp_time;
				$("#mashGrid").jqxGrid('addrow', null, row);
			}
		}
	});
	$("#popupMash").jqxWindow({
		width: 800,
		height: 350,
		position: { x: 230, y: 100 },
		resizable: false,
		theme: theme,
		isModal: true,
		autoOpen: false,
		cancelButton: $("#MashReady"),
		modalOpacity: 0.40
	});
	$("#MashReady").jqxButton({ template: "success", width: '90px', theme: theme });
	$("#MashReady").click(function () {
		calcMash();
	});
	$("#wstep_name").jqxInput({ theme: theme, width: 320, height: 23 });
	$("#wstep_name").on('change', function (event) {
		var rowdata = $("#mashGrid").jqxGrid('getrowdata', mashRow);
                rowdata.step_name = event.args.value;
	});
	$("#wstep_type").jqxDropDownList({
		theme: theme,
		source: MashStepTypeAdapter,
		valueMember: 'id',
		displayMember: 'nl',
		width: 180,
		height: 23,
		autoDropDownHeight: true
	});
	$("#wstep_type").on('select', function (event) {
		if (event.args) {
			var rowdata, i, rows, row, index = event.args.index;
			rowdata = $("#mashGrid").jqxGrid('getrowdata', mashRow);
			rowdata.step_type = index;
			if (index == 0) {
				$("#wstep_infuse_amount").show();
				$("#wstep_pmpt").show();
			} else {
				rowdata.step_infuse_amount = 0;
				$("#wstep_infuse_amount").hide();
				$("#wstep_pmpt").hide();
			}
			mash_infuse = 0;
			rows = $('#mashGrid').jqxGrid('getrows');
			for (i = 0; i < rows.length; i++) {
				row = rows[i];
				if (row.step_type == 0) // Infusion
					mash_infuse += parseFloat(row.step_infuse_amount);
			}
		}
	});
	$("#wstep_temp").jqxNumberInput( Spin1dec );
	$('#wstep_temp').on('change', function (event) {
		var rowdata = $("#mashGrid").jqxGrid('getrowdata', mashRow);
		rowdata.step_temp = parseFloat(event.args.value);
	});
	$("#wend_temp").jqxNumberInput( Spin1dec );
	$('#wend_temp').on('change', function (event) {
		var rowdata = $("#mashGrid").jqxGrid('getrowdata', mashRow);
		rowdata.end_temp = parseFloat(event.args.value);
	});
	$("#wstep_time").jqxNumberInput( PosInt );
	$('#wstep_time').on('change', function (event) {
		var rowdata = $("#mashGrid").jqxGrid('getrowdata', mashRow);
		rowdata.step_time = parseFloat(event.args.value);
	});
	$("#wramp_time").jqxNumberInput( PosInt );
	$('#wramp_time').on('change', function (event) {
		var rowdata = $("#mashGrid").jqxGrid('getrowdata', mashRow);
		rowdata.ramp_time = parseFloat(event.args.value);
	});
	$("#wstep_infuse_amount").jqxNumberInput( Spin1dec );
	$('#wstep_infuse_amount').on('change', function (event) {
		var row, i, rows, rowdata = $("#mashGrid").jqxGrid('getrowdata', mashRow);
		rowdata.step_infuse_amount = parseFloat(event.args.value);
		mash_infuse = 0;
		rows = $('#mashGrid').jqxGrid('getrows');
		for (i = 0; i < rows.length; i++) {
			row = rows[i];
			if (row.step_type == 0) // Infusion
				mash_infuse += parseFloat(row.step_infuse_amount);
		}
		if (dataRecord.w2_amount == 0) {
			dataRecord.w1_amount = mash_infuse;
			$("#w1_amount").val(mash_infuse);
		} else {
			dataRecord.w1_amount = (dataRecord.w1_amount / (dataRecord.w1_amount + dataRecord.w2_amount)) * mash_infuse;
			dataRecord.w2_amount = (dataRecord.w2_amount / (dataRecord.w1_amount + dataRecord.w2_amount)) * mash_infuse;
			$("#w1_amount").val(dataRecord.w1_amount);
			$("#w2_amount").val(dataRecord.w2_amount);
		}
		$('#wg_amount').val(mash_infuse);
	});

	// Tab 8, Water
	$("#tgt_bu").jqxNumberInput( Show2wat );
	$("#tgt_cl_so4").jqxNumberInput( Show1wat );
	$("#got_cl_so4").jqxNumberInput( Show1wat );

	// Water source 1
	$("#w1_name").jqxDropDownList({
		placeHolder: "Kies hoofd water:",
		theme: theme,
		source: waterlist,
		displayMember: "name",
		width: 250,
		height: 27,
		dropDownWidth: 400,
		dropDownHeight: 400
	});
	$("#w1_name").on('select', function (event) {
		if (event.args) {
			var datarecord, index = event.args.index;
			datarecord = waterlist.records[index];
			dataRecord.w1_name = datarecord.name;
			$("#w1_calcium").val(datarecord.calcium);
			dataRecord.w1_calcium = datarecord.calcium;
			$("#w1_sulfate").val(datarecord.sulfate);
			dataRecord.w1_sulfate = datarecord.sulfate;
			$("#w1_chloride").val(datarecord.chloride);
			dataRecord.w1_chloride = datarecord.chloride;
			$("#w1_sodium").val(datarecord.sodium);
			dataRecord.w1_sodium = datarecord.sodium;
			$("#w1_magnesium").val(datarecord.magnesium);
			dataRecord.w1_magnesium = datarecord.magnesium;
			$("#w1_total_alkalinity").val(datarecord.total_alkalinity);
			dataRecord.w1_total_alkalinity = datarecord.total_alkalinity;
			$("#w1_ph").val(datarecord.ph);
			dataRecord.w1_ph = datarecord.ph;
			$("#w1_cost").val(datarecord.cost);
			dataRecord.w1_cost = datarecord.cost;
			calcWater();
		}
	});
	$("#w1_amount").jqxNumberInput( Show1wat );
	$("#w1_calcium").jqxNumberInput( Show1wat );
	$("#w1_magnesium").jqxNumberInput( Show1wat );
	$("#w1_sodium").jqxNumberInput( Show1wat );
	$("#w1_total_alkalinity").jqxNumberInput( Show1wat );
	$("#w1_chloride").jqxNumberInput( Show1wat );
	$("#w1_sulfate").jqxNumberInput( Show1wat );
	$("#w1_ph").jqxNumberInput( Show1wat );
	// Water source 2
	$("#w2_name").jqxDropDownList({
		placeHolder: "Kies meng water:",
		theme: theme,
		source: waterlist,
		displayMember: "name",
		width: 250,
		height: 27,
		dropDownWidth: 400,
		dropDownHeight: 400
	});
	$("#w2_name").on('select', function (event) {
		if (event.args) {
			var datarecord, index = event.args.index;
			datarecord = waterlist.records[index];
			dataRecord.w2_name = datarecord.name;
			$("#w2_calcium").val(datarecord.calcium);
			dataRecord.w2_calcium = datarecord.calcium;
			$("#w2_sulfate").val(datarecord.sulfate);
			dataRecord.w2_sulfate = datarecord.sulfate;
			$("#w2_chloride").val(datarecord.chloride);
			dataRecord.w2_chloride = datarecord.chloride;
			$("#w2_sodium").val(datarecord.sodium);
			dataRecord.w2_sodium = datarecord.sodium;
			$("#w2_magnesium").val(datarecord.magnesium);
			dataRecord.w2_magnesium = datarecord.magnesium;
			$("#w2_total_alkalinity").val(datarecord.total_alkalinity);
			dataRecord.w2_total_alkalinity = datarecord.total_alkalinity;
			$("#w2_ph").val(datarecord.ph);
			dataRecord.w2_ph = datarecord.ph;
			$("#w2_cost").val(datarecord.cost);
			dataRecord.w2_cost = datarecord.cost;
			$("#w2_amount").jqxNumberInput({ max: 100000, readOnly: false }); // Set high max to enable the spinbuttons.
			calcWater();
		}
	});
	$("#w2_amount").jqxTooltip({ content: 'De verdeling van het hoofd en meng water. Het totale maisch water volume blijft gelijk.'});
	$("#w2_amount").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 94, height: 23, min: 0, max: 0, decimalDigits: 1, spinButtons: true, spinButtonsStep: 0.5, readOnly: true });
	$("#w2_calcium").jqxNumberInput( Show1wat );
	$("#w2_magnesium").jqxNumberInput( Show1wat );
	$("#w2_sodium").jqxNumberInput( Show1wat );
	$("#w2_total_alkalinity").jqxNumberInput( Show1wat );
	$("#w2_chloride").jqxNumberInput( Show1wat );
	$("#w2_sulfate").jqxNumberInput( Show1wat );
	$("#w2_ph").jqxNumberInput( Show1wat );
	// Water mixed
	$("#wg_amount").jqxNumberInput( Show1wat );
	$("#wg_calcium").jqxNumberInput( Show1wat );
	$("#wg_magnesium").jqxNumberInput( Show1wat );
	$("#wg_sodium").jqxNumberInput( Show1wat );
	$("#wg_total_alkalinity").jqxNumberInput( Show1wat );
	$("#wg_chloride").jqxNumberInput( Show1wat );
	$("#wg_sulfate").jqxNumberInput( Show1wat );
	$("#wg_ph").jqxNumberInput( Show1wat );
	// Water treated
	$("#wb_calcium").jqxTooltip({ content: 'De ideale hoeveelheid Calcium is tussen 40 en 150.'});
	$("#wb_calcium").jqxNumberInput( Show1wat );
	$("#wb_magnesium").jqxTooltip({ content: 'De ideale hoeveelheid Magnesium is lager dan 30.'});
	$("#wb_magnesium").jqxNumberInput( Show1wat );
	$("#wb_sodium").jqxTooltip({ content: 'De ideale hoeveelheid Natrium is lager dan 150.'});
	$("#wb_sodium").jqxNumberInput( Show1wat );
	$("#wb_total_alkalinity").jqxNumberInput( Show1wat );
	$("#wb_chloride").jqxTooltip({ content: 'De ideale hoeveelheid Chloride is tussen 50 en 100.'});
	$("#wb_chloride").jqxNumberInput( Show1wat );
	$("#wb_sulfate").jqxTooltip({ content: 'De ideale hoeveelheid Sulfaat is tussen 50 en 350.'});
	$("#wb_sulfate").jqxNumberInput( Show1wat );
	$("#wb_ph").jqxNumberInput( Show1wat );
	// Water target profile
	$("#pr_name").jqxDropDownList({
		placeHolder: "Kies doel profiel:",
		theme: theme,
		source: waterprofiles,
		displayMember: "name",
		width: 250,
		height: 27,
		dropDownWidth: 400,
		dropDownHeight: 300
	});
	$("#pr_name").on('select', function (event) {
		if (event.args) {
			var datarecord, index = event.args.index;
			datarecord = waterprofiles.records[index];
			$("#pr_calcium").val(datarecord.calcium);
			$("#pr_sulfate").val(datarecord.sulfate);
			$("#pr_chloride").val(datarecord.chloride);
			$("#pr_sodium").val(datarecord.sodium);
			$("#pr_magnesium").val(datarecord.magnesium);
			$("#pr_total_alkalinity").val(datarecord.total_alkalinity);
		}
	});
	$("#pr_calcium").jqxNumberInput( Show1wat );
	$("#pr_magnesium").jqxNumberInput( Show1wat );
	$("#pr_sodium").jqxNumberInput( Show1wat );
	$("#pr_total_alkalinity").jqxNumberInput( Show1wat );
	$("#pr_chloride").jqxNumberInput( Show1wat );
	$("#pr_sulfate").jqxNumberInput( Show1wat );

	// Water agents
	$("#wa_cacl2").jqxTooltip({ content: 'Voor het maken van een ander waterprofiel. Voegt calcium en chloride toe. Voor het verbeteren van zoetere bieren.' });
	$("#wa_cacl2").jqxNumberInput( Spin1dec );
	$("#wa_caso4").jqxTooltip({ content: 'Gips. Voor het maken van een ander waterprofiel. Voegt calcium en sulfaat toe. Voor het verbeteren van bittere bieren.' });
	$("#wa_caso4").jqxNumberInput( Spin1dec );
	$("#wa_mgso4").jqxTooltip({ content: 'Epsom zout. Voor het maken van een ander waterprofiel. Voegt magnesium en sulfaat toe. Gebruik spaarzaam!' });
	$("#wa_mgso4").jqxNumberInput( Spin1dec );
	$("#wa_nacl").jqxTooltip({ content: 'Keukenzout. Voor het maken van een ander waterprofiel. Voegt natrium en chloride toe. Voor het accentueren van zoetheid. Bij hoge dosering wordt het bier ziltig.' });
	$("#wa_nacl").jqxNumberInput( Spin1dec );
	$("#mash_ph").jqxTooltip({ content: 'Maisch pH tussen 5.2 en 5.6. Gebruik 5.2 voor lichte en 5.5 voor donkere bieren.'});
	$("#mash_ph").jqxNumberInput( SpinpH );
	$("#calc_acid").jqxCheckBox({ theme: theme, width: 120, height: 23 });
	$("#wa_base_name").jqxDropDownList({
		theme: theme,
		source: BaseTypeAdapter,
		valueMember: 'id',
		displayMember: 'nl',
		width: 170,
		height: 23,
		autoDropDownHeight: true
	});
	$("#wa_base").jqxNumberInput( Spin2dec );
	$("#wa_base").jqxNumberInput({ symbol: ' gr', symbolPosition: 'right' });
	$("#wa_acid_name").jqxDropDownList({
		theme: theme,
		source: AcidTypeAdapter,
		valueMember: 'id',
		displayMember: 'nl',
		width: 170,
		height: 23,
		autoDropDownHeight: true
	})
	$("#wa_acid").jqxNumberInput( Spin2dec );
	$("#wa_acid").jqxNumberInput({ symbol: ' ml', symbolPosition: 'right' });
	$("#wa_acid_perc").jqxNumberInput( Perc0 );
	$("#wa_acid_perc").jqxNumberInput({ width: 70, symbol: '%', symbolPosition: 'right' });
	// Sparge water
	$("#sparge_temp").jqxNumberInput( Spin1dec );
	$("#sparge_volume").jqxNumberInput( Spin1dec );
	$("#sparge_ph").jqxNumberInput( SpinpH );
	$("#sparge_source").jqxDropDownList({
		theme: theme,
		source: SpargeSourceAdapter,
		valueMember: 'id',
		displayMember: 'nl',
		width: 110,
		height: 23,
		autoDropDownHeight: true
	});
	$("#sparge_acid_amount").jqxNumberInput( Spin2dec );
	$("#sparge_acid_amount").jqxNumberInput({ spinButtons: false, readOnly: true, symbol: ' ml', symbolPosition: 'right' });
	$("#sparge_acid_type").jqxDropDownList({
		theme: theme,
		source: AcidTypeAdapter,
		valueMember: 'id',
		displayMember: 'nl',
		width: 110,
		height: 23,
		autoDropDownHeight: true
	});
	$("#sparge_acid_perc").jqxNumberInput( Perc0 );
	$("#sparge_acid_perc").jqxNumberInput({ symbol: '%', symbolPosition: 'right' });

	// Tab 9, Brewday
	$("#brew_date_start").jqxTooltip({ content: 'Brouw datum en tijd. Voor planning laat de tijd op 00:00:00 staan.' });
	$("#brew_date_start").jqxDateTimeInput( DateTimeopts );
	$('#brew_date_start').on('close', function (event) { calcStage(); });
	$("#brew_date_end").jqxTooltip({ content: 'End datum en tijd van de brouw. Leeg laten als er nog niet gebrouwen is.' });
	$("#brew_date_end").jqxDateTimeInput( DateTimeopts );
	$('#brew_date_end').on('close', function (event) { calcStage(); });
	$("#brew_mash_ph").jqxTooltip({ content: 'De gemeten pH tijdens het maischen eventueel na correctie.' });
	$("#brew_mash_ph").jqxNumberInput( SpinpH );
	$("#est_mash_ph").jqxTooltip({ content: 'De gewenste pH tijdens het maischen.' });
	$("#est_mash_ph").jqxNumberInput( Show1wat );
	$("#brew_preboil_ph").jqxTooltip({ content: 'De gemeten pH in de kookketel na het spoelen en voor de kook.' });
	$("#brew_preboil_ph").jqxNumberInput( SpinpH );
	// est_preboil_ph
	$("#brew_aboil_ph").jqxTooltip({ content: 'De gemeten pH na het koken.' });
	$("#brew_aboil_ph").jqxNumberInput( SpinpH );
	// est_aboil_ph
	$("#brew_mash_sg").jqxTooltip({ content: 'Het bereikte SG na het maischen.' });
	$("#brew_mash_sg").jqxNumberInput( SGopts );
	$("#brew_mash_sg").on('valueChanged', function () { calcMashEfficiency(); });
	$("#est_mash_sg").jqxTooltip({ content: 'Het berekende verwachte SG na het maischen.' });
	$("#est_mash_sg").jqxNumberInput( Show3wat );
	$("#brew_preboil_sg").jqxTooltip({ content: 'Het gemeten SG in de kookketel na het spoelen en voor het koken.' });
	$("#brew_preboil_sg").jqxNumberInput( SGopts );
	$("#brew_preboil_sg").on('valueChanged', function (event) {
		dataRecord.brew_preboil_sg = event.args.value;
		calcEfficiencyBeforeBoil();
	});
	$("#est_pre_sg").jqxTooltip({ content: 'Het berekende SG in de kookketel na het spoelen en voor het koken.' });
	$("#est_pre_sg").jqxNumberInput( Show3wat );
	$("#brew_aboil_sg").jqxTooltip({ content: 'Het gemeten SG in de kookketel na het koken.' });
	$("#brew_aboil_sg").jqxNumberInput( SGopts );
	$("#brew_aboil_sg").on('valueChanged', function (event) {
		dataRecord.brew_aboil_sg = event.args.value;
		calcEfficiencyAfterBoil();
		calcFermentables();
		calcIBUs();
	});
	$("#est_og3").jqxTooltip({ content: 'Het gewenste SG in de kookketel na het koken.' });
	$("#est_og3").jqxNumberInput( Show3wat );
	$("#brew_mash_efficiency").jqxTooltip({ content: 'Het behaalde maisch rendement.' });
	$("#brew_mash_efficiency").jqxNumberInput( Show1dec );
	$("#brew_preboil_volume").jqxTooltip({ content: 'Het gemeten volume van het wort voor het koken.' });
	$("#brew_preboil_volume").jqxNumberInput( Spin1dec );
	$("#brew_preboil_volume").on('valueChanged', function (event) {
		dataRecord.brew_preboil_volume = event.args.value;
		calcEfficiencyBeforeBoil();
	});
	$("#est_pre_vol").jqxTooltip({ content: 'Het berekende volume van het wort voor het koken.' });
	$("#est_pre_vol").jqxNumberInput( Show1wat );
	$("#brew_aboil_volume").jqxTooltip({ content: 'Het gemeten volume van het wort na het koken.' });
	$("#brew_aboil_volume").jqxNumberInput( Spin1dec );
	$("#brew_aboil_volume").on('valueChanged', function (event) {
		dataRecord.brew_aboil_volume = event.args.value;
		calcEfficiencyAfterBoil();
		calcFermentables();
		calcIBUs();
	});
	$("#est_a_vol").jqxTooltip({ content: 'Het gewenste volume na het koken.' });
	$("#est_a_vol").jqxNumberInput( Show1wat );
	$("#brew_preboil_efficiency").jqxTooltip({ content: 'Het berekende rendement voor het koken.' });
	$("#brew_preboil_efficiency").jqxNumberInput( Show1dec );
	$("#brew_aboil_efficiency").jqxTooltip({ content: 'Het bereikte rendement na het koken.' });
	$("#brew_aboil_efficiency").jqxNumberInput( Show1dec );
	$("#brew_sparge_temperature").jqxTooltip({ content: 'De spoelwater temperatuur, in te stellen in de Water tab.' });
	$("#brew_sparge_temperature").jqxNumberInput( Show1dec );
	$("#brew_sparge_volume").jqxTooltip({ content: 'Het spoelwater voorraad volume, in te stellen in de Water tab.' });
	$("#brew_sparge_volume").jqxNumberInput( Show1dec );
	$("#brew_sparge_est").jqxNumberInput( Show1dec );
	$("#brew_whirlpool9").jqxNumberInput( PosInt );
	$("#brew_whirlpool9").jqxNumberInput({ max: 120 });
	$("#brew_cooling_to").jqxNumberInput( Spin1dec );
	$("#brew_sparge_ph").jqxNumberInput( SpinpH );
	$("#brew_whirlpool7").jqxNumberInput( PosInt );
	$("#brew_whirlpool7").jqxNumberInput({ max: 120 });
	$("#brew_cooling_method").jqxDropDownList({
		theme: theme,
		source: CoolingTypeAdapter,
		valueMember: 'id',
		displayMember: 'nl',
		width: 180,
		height: 23,
		autoDropDownHeight: true
	});
	$("#brew_whirlpool6").jqxNumberInput( PosInt );
	$("#brew_whirlpool6").jqxNumberInput({ max: 120 });
	$("#brew_cooling_time").jqxNumberInput( PosInt );
	$("#brew_cooling_time").jqxNumberInput({ max: 1440 });
	$("#brew_whirlpool2").jqxNumberInput( PosInt );
	$("#brew_whirlpool2").jqxNumberInput({ max: 120 });
	$("#brew_aeration_type").jqxDropDownList({
		theme: theme,
		source: AerationTypeAdapter,
		valueMember: 'id',
		displayMember: 'nl',
		width: 180,
		height: 23,
		autoDropDownHeight: true
	});
	$("#brew_aeration_time").jqxNumberInput( PosInt );
	$("#brew_aeration_time").jqxNumberInput({ max: 1440 });
	$("#brew_aeration_speed").jqxNumberInput( PosInt );
	$("#brew_aeration_speed").jqxNumberInput({ max: 1440 });
	$("#brew_fermenter_volume").jqxNumberInput( Show1dec );
	$("#brew_fermenter_extrawater").jqxNumberInput( Spin1dec );
	$("#brew_fermenter_sg").jqxNumberInput( Show3dec );
	$("#brew_fermenter_tcloss").jqxNumberInput( Spin1dec );
	$("#brew_fermenter_ibu").jqxNumberInput( Show0dec );
	$("#brew_fermenter_color").jqxNumberInput( Show0dec );
	$("#BLog").jqxButton({ template: "info", width: '150px', theme: theme });
	$("#BLog").click(function () {
		// Open log in a new tab.
		window.open("log_brew.php?code=" + dataRecord.code + "&name=" + dataRecord.name);
	});

	// Tab 10, Fermentation
	// Note, fermentation temps changes must do calcCarbonation()
	$("#brew_fermenter_sg2").jqxTooltip({ content: 'Het behaalde SG in het gistvat, overgenomen van de brouwdag.' });
	$("#brew_fermenter_sg2").jqxNumberInput( Show3dec );
	$("#primary_start_temp").jqxTooltip({ content: 'De begintemperatuur van de hoofdvergisting.' });
	$("#primary_start_temp").jqxNumberInput( YeastT );
	$("#primary_max_temp").jqxTooltip({ content: 'De hoogst bereikte piek temperatuur tijdens de hoofgvergisting.' });
	$("#primary_max_temp").jqxNumberInput( YeastT );
	$("#primary_end_temp").jqxTooltip({ content: 'De eind temperatuur van de hoofdvergisting.' });
	$("#primary_end_temp").jqxNumberInput( YeastT );
	$("#primary_end_sg").jqxTooltip({ content: 'Het gemeten SG aan het eind van de hoofdvergisting.' });
	$("#primary_end_sg").jqxNumberInput( SGopts );
	$("#primary_end_brix").jqxTooltip({ content: 'Hulpfinctie: de afgelezen &deg;Brix RI waarde met een refractometer.' });
	$("#primary_end_brix").jqxNumberInput( Spin1dec );
	$("#primary_svg").jqxTooltip({ content: 'De schijnbare vergisting graad behaald na de hoofdgisting.' });
	$("#primary_svg").jqxNumberInput( Show1dec );
	$("#primary_end_date").jqxTooltip({ content: 'De eind datum van de hoofdvergisting en eventueel overhevelen.' });
	$("#primary_end_date").jqxDateTimeInput( Dateopts );
	$('#primary_end_date').on('close', function (event) { calcStage(); });
	$("#secondary_temp").jqxNumberInput( YeastT );
	$("#secondary_end_sg").jqxTooltip({ content: 'Het gemeten SG aan het eind van de navergisting.' });
        $("#secondary_end_sg").jqxNumberInput( SGopts );
        $("#secondary_end_brix").jqxTooltip({ content: 'Hulpfinctie: de afgelezen &deg;Brix RI waarde met een refractometer.' });
        $("#secondary_end_brix").jqxNumberInput( Spin1dec );
        $("#secondary_svg").jqxTooltip({ content: 'De schijnbare vergisting graad behaald na de nagisting.' });
        $("#secondary_svg").jqxNumberInput( Show1dec );
	$("#secondary_end_date").jqxTooltip({ content: 'De eind datum van de navergisting en het begin van het lageren.' });
	$("#secondary_end_date").jqxDateTimeInput( Dateopts );
	$('#secondary_end_date').on('close', function (event) { calcStage(); });
	$("#tertiary_temp").jqxNumberInput( YeastT );
	$("#fg").jqxNumberInput( Spin3dec );
	$("#est_fg3").jqxTooltip({ content: 'Het verwachte eind SG. Dit wordt automatisch berekend.' });
	$("#est_fg3").jqxNumberInput( Show3dec );
	$("#final_brix").jqxTooltip({ content: 'Hulpfinctie: de afgelezen &deg;Brix RI waarde met een refractometer.' });
	$("#final_brix").jqxNumberInput( Spin1dec );
	$("#final_abv").jqxNumberInput( Show2dec );
	$("#final_svg").jqxNumberInput( Show1dec );
	$("#FLog").jqxButton({ template: "info", width: '150px', theme: theme });
	$("#FLog").click(function () {
		// Open log in a new tab.
		var url="log_fermentation.php?code=" + dataRecord.code + "&name=" + dataRecord.name;
		window.open(url);
	});

	// Tab 11, Packaging
	// TODO: high gravity packaging, extra water and recalc abv, color and ibu.
	$("#package_date").jqxTooltip({ content: 'De verpakkings datum van dit bier.' });
	$("#package_date").jqxDateTimeInput( Dateopts );
	$('#package_date').on('close', function (event) { calcStage(); });
	$('#package_volume').jqxTooltip({ content: 'Het beschikbare volume om te bottelen of op fust te zetten.' });
	$('#package_volume').jqxNumberInput( Spin1dec );
	$('#package_infuse_amount').jqxTooltip({ content: 'De hoeveelheid water of drank extra toe te voegen.' });
	$('#package_infuse_amount').jqxNumberInput( Spin3dec );
	$('#package_infuse_abv').jqxTooltip({ content: 'De hoeveelheid alcohol in de drank, of 0.0 als het water is.' });
	$('#package_infuse_abv').jqxNumberInput( Spin1dec );
	$('#package_infuse_notes').jqxTooltip({ content: 'Omschrijving van de extra toevoeging.' });
	$('#package_infuse_notes').jqxInput({ theme: theme, width: 640, height: 23 });
	$('#package_abv').jqxTooltip({ content: 'De uiteindelijke hoeveelheid alcohol volume %.' });
	$('#package_abv').jqxNumberInput( Show2dec );
	$('#package_ph').jqxTooltip({ content: 'De gemeten pH vlak voor het verpakken.' });
        $('#package_ph').jqxNumberInput( SpinpH );
	$("#st_carb_min2").jqxTooltip({ content: 'Het minimum aanbevolen koolzuur volume voor deze bierstijl.'});
	$("#st_carb_min2").jqxNumberInput(Smal1dec);
	$("#st_carb_max2").jqxTooltip({ content: 'Het maximum aamnevolen koolzuur volume voor deze bierstijl.'});
	$("#st_carb_max2").jqxNumberInput(Smal1dec);
	$("#bottle_amount").jqxTooltip({ content: 'De totale hoeveelheid te bottelen bier.' });
	$("#bottle_amount").jqxNumberInput( Spin1dec );
	$("#keg_amount").jqxTooltip({ content: 'De totale hoeveelheid op fust te zetten bier.' });
	$("#keg_amount").jqxNumberInput( Spin1dec );
	$("#bottle_carbonation").jqxTooltip({ content: 'Het gewenste CO2 volume in de flessen.' });
	$("#bottle_carbonation").jqxNumberInput( Spin2dec );
	$("#bottle_carbonation").jqxNumberInput({ max: 5 });
	$("#keg_carbonation").jqxTooltip({ content: 'Het gewenste CO2 volume door de suiker in de fusten.' });
	$("#keg_carbonation").jqxNumberInput( Spin2dec );
	$("#keg_carbonation").jqxNumberInput({ max: 5 });
	$("#bottle_priming_sugar").jqxDropDownList({
		placeHolder: "Kies suiker:",
		theme: theme,
		source: fermentablesugars,
		displayMember: 'name',
		width: 200,
		height: 23,
		dropDownWidth: 300,
		dropDownHeight: 400
	});
	$("#bottle_priming_sugar").on('select', function (event) {
		if (event.args) {
			var rowID, index, editrow = -1, datarecord, rows, i, row = {};
			index = event.args.index;
			datarecord = fermentablesugars.records[index];
			rows = $('#fermentableGrid').jqxGrid('getrows');
			for (i = 0; i < rows.length; i++) {
				if (rows[i].f_added == 4) {
					editrow = i;
				}
			}
			row["f_name"] = datarecord.name;
                        row["f_origin"] = datarecord.origin;
                        row["f_supplier"] = datarecord.supplier;
                        row["f_amount"] = parseFloat($("#bottle_priming_total").jqxNumberInput('decimal')) / 1000;
                        row["f_cost"] = datarecord.cost;
                        row["f_type"] = datarecord.type;
                        row["f_yield"] = datarecord.yield;
                        row["f_color"] = datarecord.color;
                        row["f_coarse_fine_diff"] = datarecord.coarse_fine_diff;
                        row["f_moisture"] = datarecord.moisture;
                        row["f_diastatic_power"] = datarecord.diastatic_power;
                        row["f_protein"] = datarecord.protein;
                        row["f_max_in_batch"] = datarecord.max_in_batch;
                        row["f_graintype"] = datarecord.graintype;
			row["f_added"] = 4;
			row["f_dissolved_protein"] = datarecord.dissolved_protein;
                        row["f_recommend_mash"] = datarecord.recommend_mash;
                        row["f_add_after_boil"] = 1;
                        row["f_adjust_to_total_100"] = 0;
                        row["f_percentage"] = 0;
                        row["f_di_ph"] = datarecord.di_ph;
                        row["f_acid_to_ph_57"] = datarecord.acid_to_ph_57;
                        row["f_inventory"] = datarecord.inventory;
			if (editrow >= 0) {
				rowID = $('#fermentableGrid').jqxGrid('getrowid', editrow);
				$('#fermentableGrid').jqxGrid('updaterow', rowID, row);
			} else {
                        	$("#fermentableGrid").jqxGrid('addrow', null, row);
			}
			calcCarbonation();
		}
	});
	$("#keg_priming_sugar").jqxDropDownList({
		placeHolder: "Kies suiker:",
		theme: theme,
		source: fermentablesugars,
		displayMember: 'name',
		width: 200,
		height: 23,
		dropDownWidth: 300,
                dropDownHeight: 400
	});
	$("#keg_priming_sugar").on('select', function (event) {
                if (event.args) {
			var rowID, index, editrow = -1, datarecord, rows, i, row = {};
                        index = event.args.index;
                        datarecord = fermentablesugars.records[index];
                        rows = $('#fermentableGrid').jqxGrid('getrows');
                        for (i = 0; i < rows.length; i++) {
                                if (rows[i].f_added == 5) {
                                        editrow = i;
                                }
                        }
                        row["f_name"] = datarecord.name;
                        row["f_origin"] = datarecord.origin;
                        row["f_supplier"] = datarecord.supplier;
                        row["f_amount"] = parseFloat($("#keg_priming_total").jqxNumberInput('decimal')) / 1000;
                        row["f_cost"] = datarecord.cost;
                        row["f_type"] = datarecord.type;
                        row["f_yield"] = datarecord.yield;
                        row["f_color"] = datarecord.color;
                        row["f_coarse_fine_diff"] = datarecord.coarse_fine_diff;
                        row["f_moisture"] = datarecord.moisture;
                        row["f_diastatic_power"] = datarecord.diastatic_power;
                        row["f_protein"] = datarecord.protein;
                        row["f_max_in_batch"] = datarecord.max_in_batch;
                        row["f_graintype"] = datarecord.graintype;
                        row["f_added"] = 5;
                        row["f_dissolved_protein"] = datarecord.dissolved_protein;
                        row["f_recommend_mash"] = datarecord.recommend_mash;
                        row["f_add_after_boil"] = 1;
                        row["f_adjust_to_total_100"] = 0;
                        row["f_percentage"] = 0;
                        row["f_di_ph"] = datarecord.di_ph;
                        row["f_acid_to_ph_57"] = datarecord.acid_to_ph_57;
                        row["f_inventory"] = datarecord.inventory;
                        if (editrow >= 0) {
                                rowID = $('#fermentableGrid').jqxGrid('getrowid', editrow);
                                $('#fermentableGrid').jqxGrid('updaterow', rowID, row);
                        } else {
                                $("#fermentableGrid").jqxGrid('addrow', null, row);
                        }
			calcCarbonation();
                }
        });
	$("#bottle_priming_amount").jqxNumberInput( Show1dec );
	$("#bottle_priming_water").jqxTooltip({ content: 'De hoeveelheid water om de suiker op te lossen.' });
	$("#bottle_priming_water").jqxNumberInput( Spin3dec );
	$("#keg_priming_amount").jqxNumberInput( Show1dec );
	$("#keg_priming_water").jqxTooltip({ content: 'De hoeveelheid water om de suiker op te lossen.' });
	$("#keg_priming_water").jqxNumberInput( Spin3dec );
	$("#bottle_priming_total").jqxNumberInput( Show1dec );
	$("#bottle_pressure").jqxTooltip({ content: 'De maximaal te verwachten druk tijdens het hergisten.' });
	$("#bottle_pressure").jqxNumberInput( Show1dec );
	$("#keg_priming_total").jqxNumberInput( Show1dec );
	$("#keg_forced_carb").jqxCheckBox({ theme: theme, width: 120, height: 23 });
	$("#keg_pressure").jqxNumberInput( Show1dec );
	$("#bottle_abv").jqxNumberInput( Show2dec );
	$("#keg_abv").jqxNumberInput( Show2dec );
	$("#bottle_carbonation_temp").jqxNumberInput( YeastT );
	$("#keg_carbonation_temp").jqxNumberInput( YeastT );

	// Tab 12, Tasting
	$("#taste_date").jqxTooltip({ content: 'De proef datum van dit bier.' });
        $("#taste_date").jqxDateTimeInput( Dateopts );
	$('#taste_date').on('close', function (event) { calcStage(); });
	$("#taste_rate").jqxTooltip({ content: 'Het cijfer voor dit bier van 1 tot 10.' });
	$("#taste_rate").jqxNumberInput( Spin1dec );
	$("#taste_rate").jqxNumberInput({ max: 10 });
	$("#taste_color").jqxTooltip({ content: 'De kleur van het bier.' });
	$("#taste_color").jqxInput({ theme: theme, width: 320, height: 23 });
	$("#taste_transparency").jqxTooltip({ content: 'De helderheid van het bier.' });
	$("#taste_transparency").jqxInput({ theme: theme, width: 320, height: 23 });
	$("#taste_head").jqxTooltip({ content: 'Het schuim op het bier.' });
	$("#taste_head").jqxInput({ theme: theme, width: 320, height: 23 });
	$("#taste_aroma").jqxTooltip({ content: 'Het aroma van het bier.' });
	$("#taste_aroma").jqxInput({ theme: theme, width: 960, height: 23 });
	$("#taste_taste").jqxTooltip({ content: 'De smaak van het bier.' });
	$("#taste_taste").jqxInput({ theme: theme, width: 960, height: 23 });
	$("#taste_aftertaste").jqxTooltip({ content: 'De nasmaak van het bier.' });
	$("#taste_aftertaste").jqxInput({ theme: theme, width: 960, height: 23 });
	$("#taste_mouthfeel").jqxTooltip({ content: 'Het mondgevoelvan het bier.' });
	$("#taste_mouthfeel").jqxInput({ theme: theme, width: 960, height: 23 });
	$("#taste_notes").jqxTooltip({ content: 'Het oordeel en opmerkingen over dit bier.' });
	$("#taste_notes").jqxInput({ theme: theme, width: 960, height: 100 });

	$('#jqxTabs').jqxTabs({
		theme: theme,
		width: 1280,
		height: 660,
		autoHeight: false,
		position: 'top'
	});

	// Buttons below
	$("#Export").jqxButton({ template: "info", width: '80px', theme: theme });
	$("#Export").bind('click', function () {
		saveRecord();
		var url="prod_export.php?record=" + my_record + "&return=" + my_return + "&select=" + my_select +
			"&code=" + dataRecord.code + "&name=" + dataRecord.name;
		window.location.href = url;
	});

	$("#Delete").jqxButton({ template: "danger", width: '80px', theme: theme });
	$("#Delete").bind('click', function () {
		// Open a popup to confirm this action.
		$('#eventWindow').jqxWindow('open');
		$("#delOk").click(function () {
			var data = "delete=true&" + $.param({ uuid: dataRecord.uuid });
			$.ajax({
				dataType: 'json',
				url: url,
				cache: false,
				data: data,
				type: "POST",
				success: function (data, status, xhr) {
					// delete command is executed.
					window.location.href = my_return;
				},
				error: function (jqXHR, textStatus, errorThrown) {
				}
			});
		});
	});

	$("#Cancel").jqxButton({ template: "primary", width: '80px', theme: theme });
	$("#Cancel").bind('click', function () {
		window.location.href = my_return;
	});

	$("#Save").jqxButton({ template: "success", width: '80px', theme: theme });
	$("#Save").bind('click', function () {
		saveRecord();
		window.location.href = my_return;
	});	
	createDelElements();
});

mercurial