www/js/prod_edit.js

changeset 469
3d532097860d
parent 464
fbd2a7cecaaa
child 470
94a69f6b0f35
--- a/www/js/prod_edit.js	Fri Sep 06 14:11:56 2019 +0200
+++ b/www/js/prod_edit.js	Fri Sep 06 22:59:59 2019 +0200
@@ -46,2876 +46,63 @@
 
 $(document).ready(function () {
 
-	var	to_100 = false;		// Fermentables adjust to 100%
-	var     preboil_sg = 0;
-	var	aboil_sg = 0;
-	var	est_mash_sg = 0;
-	var     psugar = 0;		// Percentage real sugars
-	var     pcara = 0;		// Percentage cara/crystal malts
-	var     svg = 77;               // Default attenuation
-        var     mashkg = 0;             // Malt in mash weight
-	var	pitchrate = 0.75;	// Yeast pitch rate default
-	var	initcells = 0;		// Initial yeast cell count
-
-	var	ok_fermentables = 1;	// Fermentables are in stock
-	var	ok_hops = 1;		// Hops are in stock
-	var	ok_miscs = 1;		// Miscs are in stock
-	var	ok_yeasts = 1;		// Yeasts are in stock
-	var	ok_waters = 1;		// Waters are in stock
-
-        var     hop_flavour = 0;
-        var     hop_aroma = 0;
-        var     mash_infuse = 0;
-        var     last_base = '';
-        var     last_acid = '';
-
-        var     MMCa = 40.048;
-        var     MMMg = 24.305;
-        var     MMNa = 22.98976928;
-        var     MMCl = 35.453;
-        var     MMSO4 = 96.0626;
-        var     MMHCO3 = 61.01684;
-        var     MMCaSO4 = 172.171;
-        var     MMCaCl2 = 147.015;
-        var     MMCaCO3 = 100.087;
-        var     MMMgSO4 = 246.475;
-        var     MMNaHCO3 = 84.007;
-        var     MMNa2CO3 = 105.996;
-        var     MMNaCl = 58.443;
-        var     MMCaOH2 = 74.06268;
-
-	var     fermentableRow = 0;
-	var     fermentableData = {};
-	var	fermentableInit = 1;
-	var     hopRow = 0;
-	var     hopData = {};
-	var     miscRow = 0;
-	var     miscData = {};
-	var     yeastRow = 0;
-	var     yeastData = {};
-	var     mashRow = 0;
-	var     mashData = {};
-
-	/*
-	 * 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});
-
-	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 rowscount = $("#fermentableGrid").jqxGrid('getdatainformation').rowscount;
-		if (rowscount > 1) {
-			var tw = 0;
-			for (i = 0; i < rowscount; i++) {
-				var rowdata = $("#fermentableGrid").jqxGrid('getrowdata', i);
-				if (rowdata.f_added < 4)
-					tw += Math.round(rowdata.f_amount * 1000) / 1000;
-			};
-			tw = Math.round(tw * 1000) / 1000;
-
-			for (i = 0; i < rowscount; i++) {
-				var rowdata = $("#fermentableGrid").jqxGrid('getrowdata', i);
-				if (rowdata.f_added < 4) {
-					var percentage = Math.round(rowdata.f_amount / tw * 1000) / 10.0;
-					$("#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
-		var sugarsm = 0;	// fermentable sugars in mash
-		psugar = 0;
-		pcara = 0;
-		mashkg = 0;
-		ok_fermentables = 1;	// All is in stock.
-		ok_yeasts = 1;
-		var vol = 0;		// Volume sugars after boil
-		var addedS = 0;		// Added sugars after boil
-		var addedmass = 0;	// Added mass after boil
-		var mvol = 0;		// mash volume
-		var colort = 0;		// Colors srm * vol totals
-		var colorh = 0;		// Colors ebc * vol * kt
-		var colorn = 0;		// Colors ebc * pt * pct
-		var my_100 = false;
-		var mashtime = 0;	// Total mash time
-		var mashtemp = 0;	// Average mash temperature
-		var bv = 0.925; 	// Bierverlies rendement
-        	var sr = 0.95;  	// Mash en spoel rendement
-		var lintner = 0;	// Total recipe lintner
-
-		if ((rows = $('#mashGrid').jqxGrid('getrows'))){
-			for(var i=0;i<rows.length;i++){
-				var row=rows[i];
-				if(row.step_type==0) // Infusion
-					mvol+=parseFloat(row.step_infuse_amount);
-				if(row.step_temp<=75){ // Ignore mashout
-					var 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.
-		}
-
-		var s = 0;
-                for (var i = 0; i < rows.length; i++) {
-                        var 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;
-			var 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
-				var 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) {
-			var v = s / sugardensity + mvol;
-			s = 1000 * s / (v * 10); //deg. Plato
-			est_mash_sg = Math.round(plato_to_sg(s) * 10000) / 10000;
-			$('#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);
-		var 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.
-		var 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.
-		var 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
-		var ogx = dataRecord.brew_aboil_sg;
-		if (ogx < 1.002)
-			ogx = aboil_sg;
-		var top = dataRecord.brew_fermenter_extrawater;
-
-		if (dataRecord.brew_fermenter_volume > 0) {
-			var 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) {
-				var pt = 100 * sug / (dataRecord.brew_fermenter_volume * ogx + addedmass + top);
-				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 + top) * colorh);
-				} else {
-					var cw = colort / (aboil_volume + top) * 8.34436;
-					dataRecord.brew_fermenter_color = kw_to_ebc(dataRecord.color_method, cw);
-				}
-				$("#brew_fermenter_color").val(dataRecord.brew_fermenter_color);
-				var 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) {
-			var color = Math.round(((sg_to_plato(dataRecord.est_og) / 8.6) * colorn) + (dataRecord.boil_time / 60));
-                } else if (dataRecord.color_method == 3) {	// Hans Halberstadt
-			var color = Math.round((4.46 * bv * sr) /  parseFloat(dataRecord.batch_size) * colorh);
-		} else {
-			var cw = colort / parseFloat(dataRecord.batch_size) * 8.34436;
-			var color = kw_to_ebc(dataRecord.color_method, cw);
-		}
-		dataRecord.est_color = color;
-                $('#est_color').val(color);
-                $('#est_color2').val(color);
-                var 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;
-		var rows = $('#yeastGrid').jqxGrid('getrows');
-		for (var i = 0; i < rows.length; i++) {
-			var 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);
-		var 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)
-		var alc = 1881.22 * fig * (org - fig) / (1.775 - org);
-		var sug = 3550 * fig * (0.1808 * org + 0.8192 * fig - 1.0004);
-		$("#kcal").val(Math.round((alc + sug) / (12 * 0.0295735296)));
-	};
-
-	function calcMash() {
-
-		if (!(rows = $('#mashGrid').jqxGrid('getrows')))
-			return;
-		if (mashkg == 0)
-			return;
-
-		var infused = 0;
-		for (var i = 0; i < rows.length; i++) {
-			var 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 efficiency = parseFloat($("#efficiency").jqxNumberInput('decimal'));
-		var sug = sg_to_plato(OG) * parseFloat($("#batch_size").jqxNumberInput('decimal')) * OG / 100;      //total amount of sugars in kg
-		var tot = 0;
-		var rowscount = $("#fermentableGrid").jqxGrid('getdatainformation').rowscount;
-
-		for (var i = 0; i < rowscount; i++) {
-			var row = $("#fermentableGrid").jqxGrid('getrowdata', i);
-			if (row.f_added < 4) {
-				var 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;
-			}
-		}
-		var totmass = 0;
-		if (tot)
-			totmass = Math.round((sug / tot) * 1000) / 1000;
-
-		if (totmass) {
-			for (i = 0; i < rowscount; i++) {
-				var row = $("#fermentableGrid").jqxGrid('getrowdata', i);
-				if (row.f_added < 4) {
-					var amount = Math.round(row.f_percentage * 10 * totmass) / 1000;
-					$("#fermentableGrid").jqxGrid('setcellvalue', i, "f_amount", amount);
-				}
-			}
-		}
-	};
-
-	function getNeededYeastCells() {
-
-		var 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;
-		var plato = sg_to_plato(sg);
-
-		var volume = dataRecord.brew_fermenter_volume;
-		if (volume <= 0)
-			volume = dataRecord.batch_size - dataRecord.eq_trub_chiller_loss;
-
-		var result = pitchrate * volume * plato;
-		return result;
-	}
-
-	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;
-		var ferm_ibus = 0;
-		var rows = {};
-		hop_aroma = hop_flavour = 0;
-		if (!(rows = $('#hopGrid').jqxGrid('getrows'))) {
-			return;
-		}
-		ok_hops = 1;
-		for (var i = 0; i < rows.length; i++) {
-			var 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
-		var prate = start/svol * 1000;
-		var irate = Math.round(prate * 10) / 10;
-		var egrams = (dataRecord.starter_sg - 1) * svol * gperpoint;
-		var grate = getGrowthRate(stype, start, egrams);
-		var ncells = Math.round(egrams * grate * 10) / 10;
-		var totcells = parseFloat(ncells) + start;
-		console.log("svol:"+svol+" start:"+start+" irate:"+irate+" egrams:"+egrams+" grate:"+grate+" ncells:"+ncells);
-		return {
-			svol: svol,
-			irate: irate,
-			prate: Math.round(prate * 10)/10,
-			ncells: ncells,
-			totcells: totcells,
-			growf: Math.round(ncells/start*100)/100
-		};
-	}
-
-	/*
-	 * 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 ];
-		var mvols  = uvols.length;
-		var svol = 0;
-		var lasti = 0;
-		var result = {};
-
-		/*
-		 * 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 (var 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 (var 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 (var 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 (var 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 (var 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 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;
-		var plato = sg_to_plato(sg);
-
-                var 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.
-		}
-		var rowscount = $("#yeastGrid").jqxGrid('getdatainformation').rowscount;
-		if (rowscount == 0)
-			return;	// no yeast in recipe
-
-		for (var i = 0; i < rowscount; i++) {
-			var 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
-				}
-			}
-		}
-		var needed = pitchrate * volume * plato;
-		console.log("calcYeast() pitchrate:"+pitchrate+" start:"+initcells+" needed:"+needed+" volume:"+volume);
-		$("#need_cells").val(needed);
-                var use_cells = initcells;
-
-		if (dataRecord.starter_enable) {
-			calcSteps(dataRecord.starter_type, initcells, needed);
-
-			for (var 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 rowscount = $("#hopGrid").jqxGrid('getdatainformation').rowscount;
-		if (rowscount == 0)
-			return;
-
-		for (var i = 0; i < rowscount; i++) {
-			var row = $("#hopGrid").jqxGrid('getrowdata', i);
-			var amount = row.h_amount * factor;
-			$("#hopGrid").jqxGrid('setcellvalue', i, "h_amount", amount);
-		}
-	};
-
-	function calcMiscs() {
-
-		ok_miscs = 1;
-		var rowscount = $("#miscGrid").jqxGrid('getdatainformation').rowscount;
-
-		if (rowscount == 0)
-                        return;
-
-                for (var i = 0; i < rowscount; i++) {
-                        var 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 rowscount = $("#miscGrid").jqxGrid('getdatainformation').rowscount;
-		if (rowscount == 0)
-			return;
-
-		for (var i = 0; i < rowscount; i++) {
-			var row = $("#miscGrid").jqxGrid('getrowdata', i);
-			var 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 rowscount = $("#yeastGrid").jqxGrid('getdatainformation').rowscount;
-		if (rowscount == 0)
-			return;
-
-		for (var i = 0; i < rowscount; i++) {
-			var row = $("#yeastGrid").jqxGrid('getrowdata', i);
-			if (row.y_form == 1) { // Only adjust dry yeast
-				var amount = row.y_amount * factor;
-				$("#yeastGrid").jqxGrid('setcellvalue', i, "y_amount", amount);
-			}
-		}
-
-		calcYeast();
-	};
-
-	function adjustWaters(factor) {
-
-		console.log("adjustWaters("+factor+")");
-
-		var rowscount = $("#mashGrid").jqxGrid('getdatainformation').rowscount;
-		if (rowscount == 0)
-			return;
-
-		mash_infuse = 0;
-		for (var i = 0; i < rowscount; i++) {
-			var row = $("#mashGrid").jqxGrid('getrowdata', i);
-			if (row.step_type == 0) { // Infusion
-				var amount = Math.round(row.step_infuse_amount * factor * 10) / 10;
-				$("#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() {
-		if (parseFloat($("#brew_mash_sg").jqxNumberInput('decimal')) < 1.002)
-			return;
-		var c = sg_to_plato(est_mash_sg);
-		var 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;
-		var	rows = {};
-		if (!(rows = $('#fermentableGrid').jqxGrid('getrows'))) {
-			return;	// grid not yet loaded.
-		}
-		for (var i = 0; i < rows.length; i++) {
-			var row = rows[i];
-			if (row.f_added == 0) { // Mash
-				m += row.f_amount * (row.f_yield / 100) * (1 - row.f_moisture / 100);
-			}
-		}
-		var tot = sg_to_plato(dataRecord.brew_preboil_sg) * (dataRecord.brew_preboil_volume / 1.04) * dataRecord.brew_preboil_sg * 10 / 1000;
-		var result = 0;
-		if (m > 0)
-			result = Math.round((tot / m * 100) * 10) / 10;
-		if (result < 0)
-			result = 0;
-		$("#brew_preboil_efficiency").val(result);
-	}
-
-	function calcEfficiencyAfterBoil() {
-		var	m = 0;	// Sugars added at mash
-		var	b = 0;	// Sugars added at boil
-		var	rows = {};
-		if (!(rows = $('#fermentableGrid').jqxGrid('getrows'))) {
-			return; // grid not yet loaded.
-		}
-		for (var i = 0; i < rows.length; i++) {
-			var 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);
-			}
-		}
-		var 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.
-		var result = 0;
-		if (m > 0)
-			result = Math.round((tot / m * 100) * 10) / 10;
-		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 rows = $('#miscGrid').jqxGrid('getrows');
-		if (amount == 0) {
-			for (var i = 0; i < rows.length; i++) {
-				var row = rows[i];
-				if (row.m_name == name) {
-					var id = $("#miscGrid").jqxGrid('getrowid', i);
-					$("#miscGrid").jqxGrid('deleterow', id);
-				}
-			}
-		} else {
-			var found = false;
-			for (var i = 0; i < rows.length; i++) {
-				var row = rows[i];
-				if (row.m_name == name) {
-					found = true;
-					$("#miscGrid").jqxGrid('setcellvalue', i, 'm_amount', amount / 1000);
-					break;
-				}
-			}
-			if (! found) {
-				var miscs = new $.jqx.dataAdapter(miscInvSource, {
-					loadComplete: function () {
-						var records = miscs.records;
-						for (var i = 0; i < records.length; i++) {
-							var record = records[i];
-							if (record.name == name) {
-								var row = {};
-								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);
-	}
-
-	var Ka1 = 0.0000004445;
-	var Ka2 = 0.0000000000468;
-
-	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);
-		var Cw = Charge(parseFloat($("#wg_ph").jqxNumberInput('decimal')));
-		var Cz = Charge(pHZ);
-		var DeltaCNaught = -C43+Cw;
-		var CT = parseFloat($("#wg_total_alkalinity").jqxNumberInput('decimal')) / 50 / DeltaCNaught;
-		var 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 Calc = parseFloat($("#wg_calcium").jqxNumberInput('decimal')) / (MMCa / 2);
-		var Magn = parseFloat($("#wg_magnesium").jqxNumberInput('decimal')) / (MMMg / 2);
-		var Z = ZAlkalinity(pHZ);
-		return Z - (Calc / 3.5 + Magn / 7);
-	}
-
-	function ProtonDeficit(pHZ) {
-
-		var Result = ZRA(pHZ) * parseFloat($("#wg_amount").jqxNumberInput('decimal'));
-		// proton deficit for the grist
-		var rows = $('#fermentableGrid').jqxGrid('getrows');
-		for (var i = 0; i < rows.length; i++) {
-			var row = rows[i];
-			if (row.f_added == 0 && row.f_graintype != 6) {	// Added == Mash && graintype != No Malt
-				// Check if acid is required
-				var 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.
-					var 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;
-		var pH = 5.4;
-		var deltapH = 0.001;
-		var deltapd = 0.1;
-		var 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;
-		var calcium = 0;
-		var magnesium = 0;
-		var sodium = 0;
-		var total_alkalinity = 0;
-		var bicarbonate = 0;
-		var chloride = 0;
-		var sulfate = 0;
-		var ph = 0;
-		var RA = 0;
-		var frac = 0;
-		var TpH = 0;
-		var protonDeficit = 0;
-
-		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);
-		var wg_calcium = calcium;
-		$('#wg_calcium').val(Math.round(calcium * 10) / 10);
-		//var wg_magnesium = magnesium;
-		$('#wg_magnesium').val(Math.round(magnesium * 10) / 10);
-		var wg_sodium = sodium;
-		$('#wg_sodium').val(Math.round(sodium * 10) / 10);
-		var wg_total_alkalinity = total_alkalinity;
-		$('#wg_total_alkalinity').val(Math.round(total_alkalinity * 10) / 10);
-		var wg_chloride = chloride;
-		$('#wg_chloride').val(Math.round(chloride * 10) / 10);
-		var 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(Math.round(ph * 10) / 10);
-		$('#wb_ph').val(Math.round(MashpH() * 10) / 10);
-		$('#est_mash_ph').val(Math.round(MashpH() * 10) / 10);
-		bicarbonate = total_alkalinity * 1.22;
-		var 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;
-
-		var AT = dataRecord.wa_acid_name;
-		var BT = dataRecord.wa_base_name;
-
-		var result = GetAcidSpecs(AT);
-		var pK1 = result.pK1;
-		var pK2 = result.pK2;
-		var pK3 = result.pK3;
-		var MolWt = result.MolWt;
-		var AcidSG = result.AcidSG;
-		var 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(Math.round(Acid * 100) / 100);
-				setWaterAgent(AcidTypeData[AT].nl, Math.round(Acid * 100) / 100);
-
-				bicarbonate = bicarbonate - protonDeficit * frac / liters;
-				total_alkalinity = bicarbonate * 50 / 61;
-			} else if (protonDeficit < 0) { //Add base
-				$("#wa_acid").val(0);
-				setWaterAgent(last_acid, 0);
-				var r1d = Math.pow(10, (TpH - 6.38));
-				var r2d = Math.pow(10, (TpH - 10.38));
-				var f1d = 1 / (1 + r1d + r1d * r2d);
-				var f2d = f1d * r1d;
-				var f3d = f2d * r2d;
-				switch (BT) {
-					case 0:  RA = -protonDeficit / (f1d - f3d); // Sodiumbicarbonate, mmol totaal
-						RA = RA * MMNaHCO3/1000; //gram
-						$("#wa_base").val(Math.round(RA * 100) / 100);
-						setWaterAgent('NaHCO3', Math.round(RA * 100) / 100);
-						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(Math.round(RA * 100) / 100);
-						setWaterAgent('Na2CO3', Math.round(RA * 100) / 100);
-						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(Math.round(RA * 100) / 100);
-						setWaterAgent('CaCO3', Math.round(RA * 100) / 100);
-						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(Math.round(RA * 100) / 100);
-						setWaterAgent('Ca(OH)2', Math.round(RA * 100) / 100);
-						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(Math.round(ph * 10) / 10);
-			$('#est_mash_ph').val(Math.round(ph * 10) / 10);
-		} 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;
-
-				var deltapH = 0.001;
-				var deltapd = 0.1;
-				var pd = ProtonDeficit(pHa);
-				var 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(Math.round(ph * 10) / 10);
-				$('#est_mash_ph').val(Math.round(ph * 10) / 10);
-			}
-		}
-
-		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(Math.round(GetBUGU() * 100) / 100);
-		// 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(Math.round(GetOptClSO4ratio() * 10) / 10);
-		if (sulfate > 0)
-			RA = chloride / sulfate;
-		else
-			RA = 10;
-		$('#got_cl_so4').val(Math.round(RA * 10) / 10);
-		var piCLSO4_low = 0.8 * GetOptClSO4ratio();
-		var piCLSO4_high = 1.2 * GetOptClSO4ratio();
-		var Res = 'normaal';
-		if (RA < piCLSO4_low)
-			Res = 'laag';
-		else if (RA > piCLSO4_high)
-			Res = 'hoog';
-		setRangeIndicator('cl_so4', Res);
-
-		$('#wb_calcium').val(Math.round(calcium * 10) / 10);
-		$('#wb_magnesium').val(Math.round(magnesium * 10) / 10);
-		$('#wb_sodium').val(Math.round(sodium * 10) / 10);
-		$('#wb_sulfate').val(Math.round(sulfate * 10) / 10);
-		$('#wb_chloride').val(Math.round(chloride * 10) / 10);
-		$('#wb_total_alkalinity').val(Math.round(total_alkalinity * 10) / 10);
-
-		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() {
-
-		// Code from BrewBuddy/Brouwhulp, who got it from http://www.brewery.org/brewery/library/Acidi0,00fWaterAJD0497.html
-		var TargetpH = dataRecord.sparge_ph;
-		var Source_pH = dataRecord.w1_ph;
-		var 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
-		var r1 = Math.pow(10, Source_pH - 6.38);
-		var r2 = Math.pow(10, Source_pH - 10.373);
-		var d = 1 + r1 + r1*r2;
-		var f1 = 1/d;
-		//var f2 = r1/d;
-		var f3 = r1 * r2 / d;
-
-		//Step 2. Compute the mole fractions at pH = 4.3 (the pH which defines alkalinity)
-		var r143 = Math.pow(10, 4.3 - 6.38);
-		var r243 = Math.pow(10, 4.3 - 10.373);
-		var d43 = 1 + r143 + r143*r243;
-		var f143 = 1/d43;
-		//var f243 = r143 / d43;
-		var f343 = r143 * r243 / d43;
-
-		//Step 3. Convert the water alkalinity to milliequivalents/L
-		var alkalinity = Source_alkalinity / 50;
-		
-		//Step 4. Solve
-		var 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
-		var r1g = Math.pow(10, TargetpH - 6.38);
-		var r2g = Math.pow(10, TargetpH - 10.373);
-		var dg = 1 + r1g + r1g*r2g;
-		var f1g = 1/dg;
-		//var f2g = r1g / dg;
-		var f3g = r1g * r2g / dg;
-
-		//Step 6. Use these to compute the milliequivalents acid required per liter (mEq/L)
-		var 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.
-		var AT = dataRecord.sparge_acid_type;
-		var result = GetAcidSpecs(AT);
-		var pK1 = result.pK1;
-		var pK2 = result.pK2;
-		var pK3 = result.pK3;
-		var MolWt = result.MolWt;
-		var AcidSG = result.AcidSG;
-		var AcidPrc = result.AcidPrc;
-		var 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
-		var 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 = Math.round(Acid * 100) / 100;
-		dataRecord.sparge_acid_amount = Acid / 1000;
-		$("#sparge_acid_amount").val(Acid);
-	}
-
-	function calcFermentation(){
-
-		if (dataRecord.brew_fermenter_sg<1.020)
-			return;
-
-//	var obrix = sg_to_brix(dataRecord.brew_fermenter_sg);
-		if ((dataRecord.primary_end_sg>0.990)&&(dataRecord.primary_end_sg<dataRecord.brew_fermenter_sg)){
-			var 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)){
-				var 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)){
-					var final_svg=Round(100*(dataRecord.brew_fermenter_sg-dataRecord.fg)/(dataRecord.brew_fermenter_sg-1),1);
-					$("#final_svg").val(final_svg);
-					var 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 V = CO2 - ResCO2(CO2, T1);
-		if (V < 0)
-			return 0;
-		var 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=dataRecord.secondary_temp;
-		if(TSec<1)
-			TSec=dataRecord.primary_end_temp;
-		if(TSec<1)
-			TSec=18;
-
-		if(dataRecord.fg==0.000)
-			var ABV=abvol(dataRecord.brew_fermenter_sg,parseFloat($("#est_fg").jqxNumberInput('decimal')));
-		else
-			var ABV=abvol(dataRecord.brew_fermenter_sg,dataRecord.fg);
-
-		/* Calculate new volume and alcohol. */
-		var bvol=dataRecord.package_volume-(ABV*dataRecord.package_volume)/100;
-		var balc=dataRecord.package_volume-bvol;
-		var mvol=dataRecord.package_infuse_amount-(dataRecord.package_infuse_abv*dataRecord.package_infuse_amount)/100;
-		var malc=dataRecord.package_infuse_amount-mvol;
-		var talc=balc+malc;
-		var 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 (var i=0;i<rows.length;i++){
-			var row=rows[i];
-			if(row.f_added==4){
-				var 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);
-		var pabv=ABV+dataRecord.bottle_priming_amount*0.47/7.907;
-		var pvol=dataRecord.bottle_amount-(pabv*dataRecord.bottle_amount)/100;
-		var talc=dataRecord.bottle_amount-pvol;
-		var tvol=pvol+dataRecord.bottle_priming_water;
-		var 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
-		var 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(var i=0;i<rows.length;i++){
-				var row=rows[i];
-				if(row.f_added==5){
-					var 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);
-			var pabv=ABV+dataRecord.keg_priming_amount*0.47/7.907;
-			var pvol=dataRecord.keg_amount-(pabv*dataRecord.keg_amount)/100;
-			var talc=dataRecord.keg_amount-pvol;
-			var tvol=pvol+dataRecord.keg_priming_water;
-			var 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;
-		/* parseFloat$("#brew_date_start").val()) returns the year if it is a valid mysql style date. */
-		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) {
-			var d = new Date();
-			var 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
-			var timeDifference = date1_unixtime - date2_unixtime;
-			var 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 new_boil = parseFloat(event.args.value) + dataRecord.boil_size - dataRecord.batch_size;
-			var factor = parseFloat(event.args.value) / dataRecord.batch_size;
-			dataRecord.boil_size = new_boil;
-			$("#boil_size").val(Math.round(new_boil * 100) / 100);
-			$("#est_pre_vol").val(Math.round(new_boil * 1.04 * 100) / 100);
-			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 old_evap = parseFloat(dataRecord.boil_size) - parseFloat(dataRecord.batch_size);
-			var new_evap = old_evap * (parseFloat(event.args.value) / dataRecord.boil_time);
-			var new_boil = parseFloat(dataRecord.batch_size) + new_evap;
-			//var factor = new_boil / dataRecord.boil_size;
-			dataRecord.boil_time = parseFloat(event.args.value);
-			dataRecord.boil_size = new_boil;
-			$("#est_pre_vol").val(Math.round(new_boil * 1.04 * 100) / 100);
-			$("#boil_size").val(Math.round(new_boil * 100) / 100);
-			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 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);
-			}
-			var tnew = dataRecord.package_volume + dataRecord.package_infuse_amount;
-			var 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 told = dataRecord.package_volume + dataRecord.package_infuse_amount;
-                        dataRecord.package_infuse_amount = parseFloat(event.args.value);
-			var tnew = dataRecord.package_volume + dataRecord.package_infuse_amount;
-                        var 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 vnew = parseFloat(event.args.value);
-			var 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 vnew = parseFloat(event.args.value);
-			var 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) {
-			if(dataRecord.brew_fermenter_sg>=1.020){
-				OBrix=sg_to_brix(dataRecord.brew_fermenter_sg);
-				FBrix=parseFloat(event.args.value);
-var 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) {
-                        if(dataRecord.brew_fermenter_sg>=1.020){
-                                OBrix=sg_to_brix(dataRecord.brew_fermenter_sg);
-                                FBrix=parseFloat(event.args.value);
-var 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){
-			if(dataRecord.brew_fermenter_sg>=1.020){
-				OBrix=sg_to_brix(dataRecord.brew_fermenter_sg);
-				FBrix=parseFloat(event.args.value);
-var 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);
-// Ook brouwhulp SGFerm() maar is niet in gebruik.
-//var FG=((1.001843-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))+(1.313454)*0.001);
-				//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 index = event.args.index;
-			var 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 index = event.args.index;
-			var datarecord = equipmentlist.records[index];
-			var 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 fermentablerow = $('#fermentableGrid').jqxGrid('getrows');
-		var hoprow = $('#hopGrid').jqxGrid('getrows');
-		var miscrow = $('#miscGrid').jqxGrid('getrows');
-		var yeastrow = $('#yeastGrid').jqxGrid('getrows');
-		var mashrow = $('#mashGrid').jqxGrid('getrows');
-		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: fermentablerow,
-			hops: hoprow,
-			miscs: miscrow,
-			yeasts: yeastrow,
-			mashs: mashrow
-		};
-		var 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");
-			}
-		});
-	};
-
-	var dataRecord = {};
-	var url = "includes/db_product.php";
+    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
-	var source = {
+	source = {
 		datatype: "json",
 		cache: false,
 		datafields: [
@@ -3125,9 +312,9 @@
 		],
 		id: 'record',
 		url: url + '?record=' + my_record
-	};
+	},
 	// Load data and select one record.
-	var dataAdapter = new $.jqx.dataAdapter(source, {
+	dataAdapter = new $.jqx.dataAdapter(source, {
 		loadComplete: function () {
 			var records = dataAdapter.records;
 			dataRecord = records[0];
@@ -3354,11 +541,10 @@
                 beforeLoadComplete: function (records) {
                         $('#jqxLoader').jqxLoader('open');
                 }
-	});
-	dataAdapter.dataBind();
+	}),
 
         // Inline fermentables editor
-        var editFermentable = function (data) {
+        editFermentable = function (data) {
                 var fermentableSource = {
                         localdata: data.fermentables,
                         datatype: "local",
@@ -3402,8 +588,9 @@
 				//console.log("fermentable updaterow "+rowid);
 				commit(true);
 			}
-                };
-                var fermentableAdapter = new $.jqx.dataAdapter(fermentableSource);
+                },
+                fermentableAdapter = new $.jqx.dataAdapter(fermentableSource);
+
                 $("#fermentableGrid").jqxGrid({
                         width: 1240,
                         height: 470,
@@ -3437,10 +624,9 @@
                                 });
                                 $("#faddrowbutton").on('select', function (event) {
                                         if (event.args) {
-                                                var rowscount = $("#fermentableGrid").jqxGrid('getdatainformation').rowscount;
-                                                var index = event.args.index;
-                                                var datarecord = fermentablelist.records[index];
-                                                var row = {};
+                                                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;
@@ -3489,19 +675,20 @@
                                 // delete selected fermentable.
                                 $("#fdeleterowbutton").jqxButton({ template: "danger", theme: theme, height: 27, width: 150, disabled: (dataRecord.stage > 3) });
                                 $("#fdeleterowbutton").on('click', function () {
-                                        var selectedrowindex = $("#fermentableGrid").jqxGrid('getselectedrowindex');
-                                        var rowscount = $("#fermentableGrid").jqxGrid('getdatainformation').rowscount;
+					var rowscount, id, percent, amount, i, rowdata,
+                                        selectedrowindex = $("#fermentableGrid").jqxGrid('getselectedrowindex');
+                                        rowscount = $("#fermentableGrid").jqxGrid('getdatainformation').rowscount;
                                         if (selectedrowindex >= 0 && selectedrowindex < rowscount) {
-                                                var id = $("#fermentableGrid").jqxGrid('getrowid', selectedrowindex);
-                                                var percent = $('#fermentableGrid').jqxGrid('getcellvalue', id, "f_percentage");
-                                                var amount = $('#fermentableGrid').jqxGrid('getcellvalue', id, "f_amount");
+                                                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 (var i = 0; i < rowscount; i++) {
-                                                                var rowdata = $("#fermentableGrid").jqxGrid('getrowdata', i);
+                                                        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;
@@ -3599,10 +786,10 @@
 				}
                         ]
                 });
-        };
+        },
 
         // Inline hops editor
-        var editHop = function (data) {
+        editHop = function (data) {
                 var hopSource = {
                         localdata: data.hops,
                         datatype: "local",
@@ -3640,8 +827,9 @@
 				console.log("hop updaterow "+rowid);
 				commit(true);
 			}
-                };
-                var hopAdapter = new $.jqx.dataAdapter(hopSource);
+                },
+                hopAdapter = new $.jqx.dataAdapter(hopSource);
+
                 $("#hopGrid").jqxGrid({
                         width: 1240,
                         height: 560,
@@ -3676,9 +864,8 @@
                                 });
                                 $("#haddrowbutton").on('select', function (event) {
                                         if (event.args) {
-                                                var index = event.args.index;
-                                                var datarecord = hoplist.records[index];
-                                                var row = {};
+                                                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;
@@ -3710,10 +897,10 @@
                                 // delete selected hop.
                                 $("#hdeleterowbutton").jqxButton({ template: "danger", theme: theme, height: 27, width: 150, disabled: (dataRecord.stage > 3) });
                                 $("#hdeleterowbutton").on('click', function () {
-                                        var selectedrowindex = $("#hopGrid").jqxGrid('getselectedrowindex');
-                                        var rowscount = $("#hopGrid").jqxGrid('getdatainformation').rowscount;
+                                        var rowscount, id, selectedrowindex = $("#hopGrid").jqxGrid('getselectedrowindex');
+                                        rowscount = $("#hopGrid").jqxGrid('getdatainformation').rowscount;
                                         if (selectedrowindex >= 0 && selectedrowindex < rowscount) {
-                                                var id = $("#hopGrid").jqxGrid('getrowid', selectedrowindex);
+                                                id = $("#hopGrid").jqxGrid('getrowid', selectedrowindex);
                                                 $("#hopGrid").jqxGrid('deleterow', id);
                                         }
 					calcIBUs();
@@ -3775,10 +962,10 @@
 				  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 color = '#ffffff';
+						var amount, color = '#ffffff';
 						if (value < rowdata.h_amount)
 							color = '#ff4040';
-						var amount = dataAdapter.formatNumber(value, "f1") + ' kg';
+						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>';
@@ -3816,10 +1003,10 @@
 				}
                         ]
                 });
-        };
+        },
 
         // Inline miscs editor
-        var editMisc = function (data) {
+        editMisc = function (data) {
                 var miscSource = {
                         localdata: data.miscs,
                         datatype: "local",
@@ -3848,12 +1035,12 @@
 				console.log("misc updaterow "+rowid);
 				commit(true);
 			}
-                };
-                var miscAdapter = new $.jqx.dataAdapter(miscSource, {
+                },
+                miscAdapter = new $.jqx.dataAdapter(miscSource, {
                         beforeLoadComplete: function (records) {
-                                var data = new Array();
-                                for (var i = 0; i < records.length; i++) {
-                                        var row = records[i];
+                                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) {
@@ -3938,9 +1125,8 @@
                                 });
                                 $("#maddrowbutton").on('select', function (event) {
                                         if (event.args) {
-                                                var index = event.args.index;
-                                                var datarecord = misclist.records[index];
-                                                var row = {};
+                                                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;
@@ -3960,11 +1146,11 @@
                                 // delete selected misc.
                                 $("#mdeleterowbutton").jqxButton({ template: "danger", theme: theme, height: 27, width: 150, disabled: (dataRecord.stage > 3) });
                                 $("#mdeleterowbutton").on('click', function () {
-                                        var selectedrowindex = $("#miscGrid").jqxGrid('getselectedrowindex');
-                                        var rowscount = $("#miscGrid").jqxGrid('getdatainformation').rowscount;
-                                        var type = $("#miscGrid").jqxGrid('getcellvalue', selectedrowindex, "m_type");
+                                        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
-                                                var id = $("#miscGrid").jqxGrid('getrowid', selectedrowindex);
+                                                id = $("#miscGrid").jqxGrid('getrowid', selectedrowindex);
                                                 $("#miscGrid").jqxGrid('deleterow', id);
                                         }
                                 });
@@ -4004,15 +1190,16 @@
 				},
 				{ 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
-						var vstr = rowdata.m_amount_is_weight ? "gr":"ml";
-						var color = '#ffffff';
+						vstr = rowdata.m_amount_is_weight ? "gr":"ml";
+						color = '#ffffff';
 						if (value < rowdata.m_amount)
 							color = '#ff4040';
-						var amount = dataAdapter.formatNumber(value * 1000,"f2")+" "+vstr;
+						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>';
@@ -4048,10 +1235,10 @@
 				}
                         ]
                 });
-        };
+        },
 
         // Inline yeasts editor
-        var editYeast = function (data) {
+        editYeast = function (data) {
                 var yeastSource = {
                         localdata: data.yeasts,
                         datatype: "local",
@@ -4087,8 +1274,9 @@
 				console.log("yeast updaterow "+rowid);
 				commit(true);
 			}
-                };
-                var yeastAdapter = new $.jqx.dataAdapter(yeastSource);
+                },
+                yeastAdapter = new $.jqx.dataAdapter(yeastSource);
+
                 $("#yeastGrid").jqxGrid({
                         width: 1240,
                         height: 350,
@@ -4122,9 +1310,8 @@
                                 });
                                 $("#yaddrowbutton").on('select', function (event) {
                                         if (event.args) {
-                                                var index = event.args.index;
-                                                var datarecord = yeastlist.records[index];
-                                                var row = {};
+                                                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;
@@ -4153,10 +1340,10 @@
                                 // delete selected yeast.
                                 $("#ydeleterowbutton").jqxButton({ template: "danger", theme: theme, height: 27, width: 150, disabled: (dataRecord.stage > 3) });
                                 $("#ydeleterowbutton").on('click', function () {
-                                        var selectedrowindex = $("#yeastGrid").jqxGrid('getselectedrowindex');
-                                        var rowscount = $("#yeastGrid").jqxGrid('getdatainformation').rowscount;
+                                        var id, rowscount, selectedrowindex = $("#yeastGrid").jqxGrid('getselectedrowindex');
+                                        rowscount = $("#yeastGrid").jqxGrid('getdatainformation').rowscount;
                                         if (selectedrowindex >= 0 && selectedrowindex < rowscount) {
-                                                var id = $("#yeastGrid").jqxGrid('getrowid', selectedrowindex);
+                                                id = $("#yeastGrid").jqxGrid('getrowid', selectedrowindex);
                                                 $("#yeastGrid").jqxGrid('deleterow', id);
 						calcYeast();
                                         }
@@ -4181,8 +1368,7 @@
                                 { 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 color = '#ffffff';
-					var amount = "";
+					var amount = "", color = '#ffffff';
 					if (value > 0) {
 						amount = dataAdapter.formatNumber(value, "f1");
 						if (dataRecord.est_abv > value)
@@ -4209,14 +1395,15 @@
 				},
 				{ 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
-						var color = '#ffffff';
+						color = '#ffffff';
 						if (value < rowdata.y_amount)
 							color = '#ff4040';
-						var amount = dataAdapter.formatNumber(value*1000, "f0")+" ml";
+						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
@@ -4259,10 +1446,9 @@
 				}
                         ]
                 });
-        };
-
+        },
         // inline mash editor
-        var editMash = function (data) {
+        editMash = function (data) {
                 var mashSource = {
                         localdata: data.mashs,
                         datatype: "local",
@@ -4284,13 +1470,13 @@
                         deleterow: function (rowid, commit) {
                                 commit(true);
                         }
-                };
-                var mashAdapter = new $.jqx.dataAdapter(mashSource, {
+                },
+                mashAdapter = new $.jqx.dataAdapter(mashSource, {
                         beforeLoadComplete: function (records) {
                                 mash_infuse = 0;
-                                var data = new Array();
-                                for (var i = 0; i < records.length; i++) {
-                                        var row = records[i];
+                                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.
@@ -4312,8 +1498,7 @@
                                 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 rowscount = $("#mashGrid").jqxGrid('getdatainformation').rowscount;
-					var row = {};
+					var row = {}, rowscount = $("#mashGrid").jqxGrid('getdatainformation').rowscount;
 					row["step_name"] = "Stap " + (rowscount + 1);
 					if (rowscount > 0) {
 						row["step_type"] = 1;
@@ -4331,10 +1516,10 @@
                                 // delete selected step.
                                 $("#sdeleterowbutton").jqxButton({ template: "danger", theme: theme, height: 27, width: 150, disabled: (dataRecord.stage > 3) });
                                 $("#sdeleterowbutton").on('click', function () {
-                                        var selectedrowindex = $("#mashGrid").jqxGrid('getselectedrowindex');
-                                        var rowscount = $("#mashGrid").jqxGrid('getdatainformation').rowscount;
+                                        var rowscount, id, selectedrowindex = $("#mashGrid").jqxGrid('getselectedrowindex');
+                                        rowscount = $("#mashGrid").jqxGrid('getdatainformation').rowscount;
                                         if (selectedrowindex >= 0 && selectedrowindex < rowscount) {
-                                                var id = $("#mashGrid").jqxGrid('getrowid', selectedrowindex);
+                                                id = $("#mashGrid").jqxGrid('getrowid', selectedrowindex);
 						$("#mashGrid").jqxGrid('deleterow', id);
                                         }
                                 });
@@ -4389,6 +1574,2810 @@
                 });
         };
 
+	/*
+         * 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.' });
@@ -4629,9 +4618,9 @@
 	});
 	$("#FermentableReady").jqxButton({ template: "success", width: '90px', theme: theme });
 	$("#FermentableReady").click(function () {
-		var rowID = $("#fermentableGrid").jqxGrid('getrowid', fermentableRow);
+		var row, rowID = $("#fermentableGrid").jqxGrid('getrowid', fermentableRow);
 		console.log("FermentableReady row:"+fermentableRow+" ID:"+rowID);
-		var row = {
+		row = {
 			f_name: fermentableData.f_name,
 			f_origin: fermentableData.f_origin,
 			f_supplier: fermentableData.f_supplier,
@@ -4686,8 +4675,8 @@
 	});
 	$("#wf_select").on('select', function (event) {
 		if (event.args) {
-			var index = event.args.index;
-			var datarecord = fermentablelist.records[index];
+			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;
@@ -4724,34 +4713,35 @@
 	});
 	$("#wf_percentage").jqxNumberInput( Perc1dec );
 	$("#wf_percentage").on('change', function (event) {
-		var oldvalue = Math.round(fermentableData.f_percentage * 10) / 10.0;
-		var newvalue = event.args.value;
+		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;
-		var rowscount = $("#fermentableGrid").jqxGrid('getdatainformation').rowscount;
+		rowscount = $("#fermentableGrid").jqxGrid('getdatainformation').rowscount;
 		if ((oldvalue != newvalue) && (rowscount > 1)) {
-			var rowdata = $("#fermentableGrid").jqxGrid('getrowdata', fermentableRow);
+			rowdata = $("#fermentableGrid").jqxGrid('getrowdata', fermentableRow);
 			if (rowdata.f_adjust_to_total_100) {
 				$("#wf_percentage").val(oldvalue);
 			} else {
-				var diff = newvalue - oldvalue;
-				var tw = 0;     // total weight
+				diff = newvalue - oldvalue;
+				tw = 0;     // total weight
 				for (i = 0; i < rowscount; i++) {
-					var rowdata = $("#fermentableGrid").jqxGrid('getrowdata', 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.
-					var damount = Math.round(tw * diff *10) / 1000;
-					var rowdata = $("#fermentableGrid").jqxGrid('getrowdata', fermentableRow);
-					var namount = Math.round((rowdata.f_amount + damount) * 1000) / 1000;
+					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++) {
-						var rowdata = $("#fermentableGrid").jqxGrid('getrowdata', 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);
@@ -4763,18 +4753,18 @@
 					calcMash();
 				} else {
 					// Adjust all the rows.
-					var nw = tw * diff / 100;
+					nw = tw * diff / 100;
 					for (i = 0; i < rowscount; i++) {
-						var rowdata = $("#fermentableGrid").jqxGrid('getrowdata', i);
+						rowdata = $("#fermentableGrid").jqxGrid('getrowdata', i);
 						if (rowdata.f_added < 4) {
 							if (i == fermentableRow) {
-								var namount = Math.round((rowdata.f_amount + nw) * 1000) / 1000;
+								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 {
-								var namount = Math.round((rowdata.f_amount - (nw / (rowscount - 1))) * 1000) / 1000;
-								var newperc = Math.round((namount / tw) * 1000) / 10.0;
+								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);
 							}
@@ -4795,8 +4785,8 @@
 		if (fermentableData.f_adjust_to_total_100 == 0) {
 			if (to_100) {
 				// Reset other flag first.
-				var rowscount = $("#fermentableGrid").jqxGrid('getdatainformation').rowscount;
-				for (var i = 0; i < rowscount; i++) {
+				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);
 					}
@@ -4899,9 +4889,8 @@
 	});
 	$("#HopReady").jqxButton({ template: "success", width: '90px', theme: theme });
 	$("#HopReady").click(function () {
-		var rowID = $("#hopGrid").jqxGrid('getrowid', hopRow);
-		console.log("HopReady row:"+hopRow+" ID:"+rowID);
-		var row = {
+		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,
@@ -4946,9 +4935,8 @@
 	});
 	$("#wh_select").on('select', function (event) {
 		if (event.args) {
-			var index = event.args.index;
-			var datarecord = hoplist.records[index];
-			// console.log("select another hop:"+index+" "+datarecord.name);
+			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;
@@ -4969,8 +4957,8 @@
 	$("#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 amount = parseFloat(event.args.value) / 1000;
-		var ibu = toIBU(hopData.h_useat, hopData.h_form, preboil_sg,
+		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()
@@ -4981,7 +4969,7 @@
 	$("#wh_ibu").jqxNumberInput( Show1dec );
 	$("#wh_time").jqxNumberInput( PosInt );
 	$("#wh_time").on('change', function (event) {
-		var newtime = parseFloat(event.args.value);
+		var ibu, newtime = parseFloat(event.args.value);
 		// Check limits and correct
 		if (hopData.h_useat == 2) {     // Boil
 			if (newtime > parseFloat($("#boil_time").jqxNumberInput('decimal'))) {
@@ -5002,7 +4990,7 @@
 			}
 			hopData.h_time = newtime * 1440;
 		}
-		var ibu = toIBU(hopData.h_useat, hopData.h_form, preboil_sg, parseFloat($("#batch_size").jqxNumberInput('decimal')),
+		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);
@@ -5053,9 +5041,9 @@
 	});
 	$("#MiscReady").jqxButton({ template: "success", width: '90px', theme: theme });
 	$("#MiscReady").click(function () {
-		var rowID = $("#miscGrid").jqxGrid('getrowid', miscRow);
+		var row, rowID = $("#miscGrid").jqxGrid('getrowid', miscRow);
 		console.log("MiscReady row:"+miscRow+" ID:"+rowID);
-		var row = {
+		row = {
 			m_name: miscData.m_name,
 			m_amount: miscData.m_amount,
 			m_cost: miscData.m_cost,
@@ -5087,8 +5075,8 @@
 	});
 	$("#wm_select").on('select', function (event) {
 		if (event.args) {
-			var index = event.args.index;
-			var datarecord = misclist.records[index];
+			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;
@@ -5105,7 +5093,6 @@
 	});
 	$("#wm_time").jqxNumberInput( PosInt );
 	$("#wm_time").on('change', function (event) {
-		console.log("time changed: "+event.args.value);
 		var newtime = parseFloat(event.args.value);
 
 		if (miscData.m_use_use == 2) {   // Boil
@@ -5167,9 +5154,9 @@
 	});
 	$("#YeastReady").jqxButton({ template: "success", width: '90px', theme: theme });
 	$("#YeastReady").click(function () {
-		var rowID = $("#yeastGrid").jqxGrid('getrowid', yeastRow);
+		var row, rowID = $("#yeastGrid").jqxGrid('getrowid', yeastRow);
 		console.log("YeastReady row:"+yeastRow+" ID:"+rowID);
-		var row = {
+		row = {
 			y_name: yeastData.y_name,
 			y_laboratory: yeastData.y_laboratory,
 			y_product_id: yeastData.y_product_id,
@@ -5215,8 +5202,8 @@
 	});
 	$("#wy_select").on('select', function (event) {
 		if (event.args) {
-			var index = event.args.index;
-			var datarecord = yeastlist.records[index];
+			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);
@@ -5245,11 +5232,9 @@
 	});
 	$("#wy_amount").jqxNumberInput( Spin1dec );
 	$('#wy_amount').on('change', function (event) {
-		console.log("amount changed: "+event.args.value);
-		if (yeastData.y_form == 0)        // Liquid
-			var amount = parseFloat(event.args.value);
-		else
-			var amount = parseFloat(event.args.value) / 1000;
+		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();
@@ -5272,7 +5257,7 @@
 			calcYeast();
 		}
 	});
-	for (var i = 1; i < 5; i++) {
+	for (i = 1; i < 5; i++) {
 		$("#prop"+i+"_type").jqxDropDownList({
 			theme: theme,
 			source: StarterTypeAdapter,
@@ -5324,21 +5309,20 @@
 	});
 	$("#mash_select").on('select', function (event) {
 		if (event.args) {
-			var index = event.args.index;
+			var data, datarecord, rowIDs, rows, i, row = {}, index = event.args.index;
 			// First delete all current steps
-			var rowIDs = new Array();
-			var rows = $("#mashGrid").jqxGrid('getdisplayrows');
-			for (var i = 0; i < rows.length; i++) {
-				var row = rows[i];
+			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
-			var datarecord = mashlist.records[index];
+			datarecord = mashlist.records[index];
 			$("#mash_name").val(datarecord.name);
 			for (i = 0; i < datarecord.steps.length; i++) {
-				var data = datarecord.steps[i];
-				var row = {};
+				data = datarecord.steps[i];
 				row["step_name"] = data.step_name;
 				row["step_type"] = data.step_type;
 				// For now, but this must be smarter.
@@ -5391,8 +5375,8 @@
 	});
 	$("#wstep_type").on('select', function (event) {
 		if (event.args) {
-			var index = event.args.index;
-			var rowdata = $("#mashGrid").jqxGrid('getrowdata', mashRow);
+			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();
@@ -5403,9 +5387,9 @@
 				$("#wstep_pmpt").hide();
 			}
 			mash_infuse = 0;
-			var rows = $('#mashGrid').jqxGrid('getrows');
-			for (var i = 0; i < rows.length; i++) {
-				var row = rows[i];
+			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);
 			}
@@ -5433,12 +5417,12 @@
 	});
 	$("#wstep_infuse_amount").jqxNumberInput( Spin1dec );
 	$('#wstep_infuse_amount').on('change', function (event) {
-		var rowdata = $("#mashGrid").jqxGrid('getrowdata', mashRow);
+		var row, i, rows, rowdata = $("#mashGrid").jqxGrid('getrowdata', mashRow);
 		rowdata.step_infuse_amount = parseFloat(event.args.value);
 		mash_infuse = 0;
-		var rows = $('#mashGrid').jqxGrid('getrows');
-		for (var i = 0; i < rows.length; i++) {
-			var row = rows[i];
+		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);
 		}
@@ -5472,8 +5456,8 @@
 	});
 	$("#w1_name").on('select', function (event) {
 		if (event.args) {
-			var index = event.args.index;
-			var datarecord = waterlist.records[index];
+			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;
@@ -5515,8 +5499,8 @@
 	});
 	$("#w2_name").on('select', function (event) {
 		if (event.args) {
-			var index = event.args.index;
-			var datarecord = waterlist.records[index];
+			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;
@@ -5582,8 +5566,8 @@
 	});
 	$("#pr_name").on('select', function (event) {
 		if (event.args) {
-			var index = event.args.index;
-			var datarecord = waterprofiles.records[index];
+			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);
@@ -5774,8 +5758,7 @@
 	$("#BLog").jqxButton({ template: "info", width: '150px', theme: theme });
 	$("#BLog").click(function () {
 		// Open log in a new tab.
-		var url="log_brew.php?code=" + dataRecord.code + "&name=" + dataRecord.name;
-		window.open(url);
+		window.open("log_brew.php?code=" + dataRecord.code + "&name=" + dataRecord.name);
 	});
 
 	// Tab 10, Fermentation
@@ -5865,16 +5848,15 @@
 	});
 	$("#bottle_priming_sugar").on('select', function (event) {
 		if (event.args) {
-			var index = event.args.index;
-			var editrow = -1;
-			var datarecord = fermentablesugars.records[index];
-			var rows = $('#fermentableGrid').jqxGrid('getrows');
-			for (var i = 0; i < rows.length; i++) {
+			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;
 				}
 			}
-			var row = {};
 			row["f_name"] = datarecord.name;
                         row["f_origin"] = datarecord.origin;
                         row["f_supplier"] = datarecord.supplier;
@@ -5899,7 +5881,7 @@
                         row["f_acid_to_ph_57"] = datarecord.acid_to_ph_57;
                         row["f_inventory"] = datarecord.inventory;
 			if (editrow >= 0) {
-				var rowID = $('#fermentableGrid').jqxGrid('getrowid', editrow);
+				rowID = $('#fermentableGrid').jqxGrid('getrowid', editrow);
 				$('#fermentableGrid').jqxGrid('updaterow', rowID, row);
 			} else {
                         	$("#fermentableGrid").jqxGrid('addrow', null, row);
@@ -5919,16 +5901,15 @@
 	});
 	$("#keg_priming_sugar").on('select', function (event) {
                 if (event.args) {
-                        var index = event.args.index;
-                        var editrow = -1;
-                        var datarecord = fermentablesugars.records[index];
-                        var rows = $('#fermentableGrid').jqxGrid('getrows');
-                        for (var i = 0; i < rows.length; i++) {
+			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;
                                 }
                         }
-                        var row = {}; 
                         row["f_name"] = datarecord.name;
                         row["f_origin"] = datarecord.origin;
                         row["f_supplier"] = datarecord.supplier;
@@ -5953,7 +5934,7 @@
                         row["f_acid_to_ph_57"] = datarecord.acid_to_ph_57;
                         row["f_inventory"] = datarecord.inventory;
                         if (editrow >= 0) {
-                                var rowID = $('#fermentableGrid').jqxGrid('getrowid', editrow);
+                                rowID = $('#fermentableGrid').jqxGrid('getrowid', editrow);
                                 $('#fermentableGrid').jqxGrid('updaterow', rowID, row);
                         } else {
                                 $("#fermentableGrid").jqxGrid('addrow', null, row);

mercurial