Renamed scripts rec_edit.* to rec_view.*. Removed the add recipe button from the recipe tree selecctor.

Fri, 05 Aug 2022 10:53:56 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Fri, 05 Aug 2022 10:53:56 +0200
changeset 815
5714ea86187d
parent 814
de4a74899969
child 816
d76f623d487c

Renamed scripts rec_edit.* to rec_view.*. Removed the add recipe button from the recipe tree selecctor.

www/Makefile file | annotate | diff | comparison | revisions
www/js/rec_edit.js file | annotate | diff | comparison | revisions
www/js/rec_main.js file | annotate | diff | comparison | revisions
www/js/rec_view.js file | annotate | diff | comparison | revisions
www/rec_edit.php file | annotate | diff | comparison | revisions
www/rec_view.php file | annotate | diff | comparison | revisions
--- a/www/Makefile	Fri Aug 05 10:44:59 2022 +0200
+++ b/www/Makefile	Fri Aug 05 10:53:56 2022 +0200
@@ -13,7 +13,7 @@
 		  prod_beerxml.php prod_checklist.php prod_divide.php prod_duplicate.php \
 		  prod_edit.php prod_export.php prod_forum.php \
 		  prod_impbrew.php prod_inprod.php prod_new.php prod_print.php prod_torecipe.php \
-		  rec_edit.php rec_main.php \
+		  rec_view.php rec_main.php \
 		  upl_fermentables.php upl_hops.php upl_miscs.php upl_styles.php upl_yeasts.php version.php
 SUB		= version.php.in images/* css/* jqwidgets/* jqwidgets/styles/* \
 		  jqwidgets/styles/images/* jqwidgets/globalization/* js/* \
--- a/www/js/rec_edit.js	Fri Aug 05 10:44:59 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2055 +0,0 @@
-/*****************************************************************************
- * Copyright (C) 2018-2022
- *
- * Michiel Broek <mbroek at mbse dot eu>
- *
- * This file is part of BMS
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * BrewCloud is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with ThermFerm; see the file COPYING.  If not, write to the Free
- * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *****************************************************************************/
-
- var psugar = 0,     // Percentage real sugars
- pcara = 0,          // Percentage cara/crystal malts
- svg = 77,           // Default attenuation
- mashkg = 0,         // Malt in mash weight
- mash_infuse = 0,
- dataRecord = {},    // Main recipe record
- hop_flavour = 0,
- hop_aroma = 0,
- preboil_sg = 0,
- last_base = '',
- last_acid = '',
- Ka1 = 0.0000004445,
- Ka2 = 0.0000000000468,
- error_count = 0,
- MMCa = 40.048,
- MMMg = 24.305,
- MMNa = 22.98976928,
- MMCl = 35.453,
- MMSO4 = 96.0626,
- MMCO3 = 60.01684,
- MMHCO3 = 61.01684,
- MMCaSO4 = 172.171,
- MMCaCl2 = 147.015,
- MMCaCO3 = 100.087,
- MMMgCl2 = 95.211,      /* Since 27-06-2021 */
- MMMgSO4 = 246.475,
- MMNaHCO3 = 84.007,
- MMNa2CO3 = 105.996,
- MMNaCl = 58.443,
- MMCaOH2 = 74.06268,
- SpecificHeatWater = 1.0,
- SpecificHeatMalt = 0.399, //cal/g.°C
- SlakingHeat = 10.318, //cal/g.°C
- eq_tun_weight = 2.0, // 2 Kg pot
- eq_tun_specific_heat = 0.110, // Stainless Steel
- data_loaded = 0;
-
-function hopFlavourContribution(bt, vol, use, amount) {
- var result;
-
- if (use == 4 || use == 5) // Whirlpool or Dry-hop
-  return 0;
- 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 (use == 4) { // Whirlpool
-   if (bt > 30)
-    bt = 30; // Max 30 minutes
-   result = 0.62 * bt / 30;
- } 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;
- }
- return (result * amount * 1000) / vol;
-}
-
-
-function calcFermentables() {
- console.log('calcFermentables()');
- var i, row, rows, org, s = 0, d, x,
- sug, alc, cw, color, scolor, fig,
- 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
- /* Init global variables */
- psugar = 0;
- pcara = 0;
- mashkg = 0;
-
- 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
-    mashtime += row.step_time;
-    mashtemp += row.step_time * row.step_temp;
-   }
-  }
-  mashtemp = mashtemp / mashtime;
- }
-
- 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 += 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 == 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;
-  }
-  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.
-  }
- }
- $('#ferm_lintner').val(Math.round(parseFloat(lintner / mashkg)));
- to_100 = my_100;
-
- // 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 before boil
- preboil_sg = estimate_sg(sugarsm, parseFloat(dataRecord.boil_size));
-
- // 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.boil_size / 3) * 100;
- $('#perc_malts').jqxProgressBar('val', pmalts);
- $('#perc_sugars').jqxProgressBar('val', psugar);
- $('#perc_cara').jqxProgressBar('val', pcara);
-
- // Calculate estimated svg.
- svg = 0; // default.
- 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.
-  }
-  // TODO: brett in secondary ??
- }
- 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);
- 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 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 infusionVol(step_infused, step_mashkg, infuse_temp, step_temp, last_temp) {
- var a = last_temp * (eq_tun_weight * eq_tun_specific_heat + step_infused * SpecificHeatWater + step_mashkg * SpecificHeatMalt);
- var b = step_temp * (eq_tun_weight * eq_tun_specific_heat + step_infused * SpecificHeatWater + step_mashkg * SpecificHeatMalt);
- var vol = Round(((b - a) / ((infuse_temp - step_temp) * SpecificHeatWater)), 2);
- console.log('infusionVol(' + step_infused + ', ' + step_mashkg + ', ' + infuse_temp + ', ' + step_temp + ', ' + last_temp + '): ' + vol);
- return vol;
-}
-
-
-function decoctionVol(step_volume, step_temp, prev_temp) {
- var a = (eq_tun_weight * eq_tun_specific_heat + step_volume * SpecificHeatWater) * (step_temp - prev_temp);
- var b = SpecificHeatWater * (99 - step_temp);
- var vol = 0;
- if (b > 0)
-  vol = Round(a / b, 6);
- console.log('decoctionVol(' + step_volume + ', ' + step_temp + ', ' + prev_temp + '): ' + vol);
- return vol;
-}
-
-
-function calcMash() {
- var infused = 0, vol, i, j, n, a, b, row, rows, temp;
- var lasttemp = 18.0;
- var graintemp = 18.0;
- var tuntemp = 18.0;
-
- if ((rows = $('#mashGrid').jqxGrid('getrows')) && (mashkg > 0)) {
-  console.log('calcMash()');
-  for (i = 0; i < rows.length; i++) {
-   row = $('#mashGrid').jqxGrid('getrowdata', i);
-   if (row.step_type == 0) { // Infusion
-    if (i == 0) {
-      // First mash step, temperature from the mashtun and malt.
-      n = 20; // tun is preheated.
-      tuntemp = row.step_temp;
-      for (j = 0; j < n; j++) {
-       a = mashkg * graintemp * SpecificHeatMalt + eq_tun_weight * tuntemp * eq_tun_specific_heat;
-       b = row.step_temp * (eq_tun_weight * eq_tun_specific_heat + row.step_infuse_amount * SpecificHeatWater + mashkg * SpecificHeatMalt) - SlakingHeat * mashkg;
-       if (row.step_infuse_amount > 0) {
-        temp = (b - a) / (row.step_infuse_amount * SpecificHeatWater);
-       } else {
-        temp = 99;
-       }
-       tuntemp += (temp - tuntemp) / 2;
-       row.step_infuse_temp = Round(temp, 6);
-      }
-      console.log('init infuse temp: ' + row.step_infuse_temp);
-    } else {
-      // Calculate amount of infusion water.
-      row.step_infuse_amount = infusionVol(infused, mashkg, row.step_infuse_temp, row.step_temp, lasttemp);
-      //console.log('vol: ' + row.step_infuse_amount + ' temp: ' + row.step_infuse_temp);
-    }
-    infused += row.step_infuse_amount;
-   } else if (row.step_type == 1) { // Temperature
-     if (i > 0)
-      row.step_infuse_amount = 0;
-     row.step_infuse_temp = 0;
-   } else if (row.step_type == 2) { // Decoction
-     row.step_infuse_amount = decoctionVol(infused, row.step_temp, lasttemp);
-     row.step_infuse_temp = 99;
-   }
-    row.step_volume = infused;
-    //console.log(i + ' type: ' + row.step_type + ' volume: ' + row.step_infuse_amount + ' temp: ' + row.step_infuse_temp);
-    lasttemp = row.step_temp;
-    mashtime += row.step_time + row.ramp_time;
-    row.step_wg_ratio = Round(infused / mashkg, 6);
-    $('#mashGrid').jqxGrid('updaterow', i, row);
-  }
- }
-}
-
-
-function GetBUGU() {
- var gu = (dataRecord.est_og - 1) * 1000;
- if (gu > 0)
-  return dataRecord.est_ibu / gu;
- else
-  return 0.5;
-}
-
-
-function GetOptSO4Clratio() {
- var BUGU = GetBUGU();
- return (-1.2 * BUGU + 1.4);
-}
-
-
-
-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 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 BufferCapacity(di_ph, acid_to_ph_57, ebc, graintype) {
- C1 = 0;
- if ((di_ph != 5.7) && ((acid_to_ph_57 < - 0.1) || (acid_to_ph_57 > 0.1))) {
-  C1 = acid_to_ph_57 / (di_ph - 5.7);
- } else {
-  // If the acid_to_ph_5.7 is unknown from the maltster, guess the required acid.
-  switch (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;
-  }
- }
- return C1;
-}
-
-
-function ProtonDeficit(pHZ) {
- var C1, i, rows, row, Result = ZRA(pHZ) * parseFloat($('#wg_amount').jqxNumberInput('decimal'));
- // proton deficit for the grist
- if ((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
-    C1 = BufferCapacity(row.f_di_ph, row.f_acid_to_ph_57, row.f_color, row.f_graintype);
-    x = C1 * (pHZ - row.f_di_ph);   // AcidRequired(ZpH)
-    Result += x * row.f_amount;
-   }
-  }
- } else {
-  error_count++;
-  if (error_count < 5)
-   console.log('ProtonDeficit(' + pHZ + ') invalid grist, return ' + Result);
- }
- 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);
- }
- pH = Round(pH, 6);
- //console.log('MashpH() n: ' + n + ' pH: ' + pH);
- return pH;
-}
-
-
-
-
-$(document).ready(function() {
-
- var to_100 = false, // Fermentables adjust to 100%
-
- fermentableRow = 0,
- fermentableData = {},
- hopRow = 0,
- hopData = {},
- miscRow = 0,
- miscData = {},
- yeastRow = 0,
- yeastData = {},
- mashRow = 0,
- mashData = {},
-
- url = 'includes/db_recipes.php',
- // prepare the data
- source = {
-  datatype: 'json',
-  cache: false,
-  datafields: [
-   { name: 'record', type: 'number' },
-   { name: 'uuid', type: 'string' },
-   { name: 'locked', type: 'int' },
-   { name: 'st_name', type: 'string' },
-   { name: 'st_letter', type: 'string' },
-   { name: 'st_guide', type: 'string' },
-   { name: 'st_type', type: 'int' },
-   { name: 'st_category', type: 'string' },
-   { name: 'st_category_number', type: 'int' },
-   { name: 'st_og_min', type: 'float' },
-   { name: 'st_og_max', type: 'float' },
-   { name: 'st_fg_min', type: 'float' },
-   { name: 'st_fg_max', type: 'float' },
-   { name: 'st_ibu_min', type: 'float' },
-   { name: 'st_ibu_max', type: 'float' },
-   { name: 'st_color_min', type: 'float' },
-   { name: 'st_color_max', type: 'float' },
-   { name: 'st_carb_min', type: 'float' },
-   { name: 'st_carb_max', type: 'float' },
-   { name: 'st_abv_min', type: 'float' },
-   { name: 'st_abv_max', type: 'float' },
-   { name: 'name', type: 'string' },
-   { name: 'notes', type: 'string' },
-   { name: 'type', type: 'int' },
-   { name: 'batch_size', type: 'float' },
-   { name: 'boil_size', type: 'float' },
-   { name: 'boil_time', type: 'float' },
-   { name: 'efficiency', type: 'float' },
-   { name: 'est_og', type: 'float' },
-   { name: 'est_fg', type: 'float' },
-   { name: 'est_abv', type: 'float' },
-   { name: 'est_color', type: 'float' },
-   { name: 'color_method', type: 'int' },
-   { name: 'est_ibu', type: 'float' },
-   { name: 'ibu_method', type: 'int' },
-   { name: 'est_carb', type: 'float' },
-   { name: 'sparge_temp', type: 'float' },
-   { name: 'sparge_ph', type: 'float' },
-   { name: 'sparge_volume', type: 'float' },
-   { name: 'sparge_source', type: 'int' },
-   { name: 'sparge_acid_type', type: 'int' },
-   { name: 'sparge_acid_perc', type: 'float' },
-   { name: 'sparge_acid_amount', type: 'float' },
-   { name: 'mash_ph', type: 'float' },
-   { name: 'mash_name', type: 'string' },
-   { name: 'calc_acid', type: 'int' },
-   { name: 'w1_name', type: 'string' },
-   { name: 'w1_amount', type: 'float' },
-   { name: 'w1_calcium', type: 'float' },
-   { name: 'w1_sulfate', type: 'float' },
-   { name: 'w1_chloride', type: 'float' },
-   { name: 'w1_sodium', type: 'float' },
-   { name: 'w1_magnesium', type: 'float' },
-   { name: 'w1_total_alkalinity', type: 'float' },
-   { name: 'w1_ph', type: 'float' },
-   { name: 'w1_cost', type: 'float' },
-   { name: 'w2_name', type: 'string' },
-   { name: 'w2_amount', type: 'float' },
-   { name: 'w2_calcium', type: 'float' },
-   { name: 'w2_sulfate', type: 'float' },
-   { name: 'w2_chloride', type: 'float' },
-   { name: 'w2_sodium', type: 'float' },
-   { name: 'w2_magnesium', type: 'float' },
-   { name: 'w2_total_alkalinity', type: 'float' },
-   { name: 'w2_ph', type: 'float' },
-   { name: 'w2_cost', type: 'float' },
-   { name: 'wg_amount', type: 'float' },
-   { name: 'wg_calcium', type: 'float' },
-   { name: 'wg_sulfate', type: 'float' },
-   { name: 'wg_chloride', type: 'float' },
-   { name: 'wg_sodium', type: 'float' },
-   { name: 'wg_magnesium', type: 'float' },
-   { name: 'wg_total_alkalinity', type: 'float' },
-   { name: 'wg_ph', type: 'float' },
-   { name: 'wb_calcium', type: 'float' },
-   { name: 'wb_sulfate', type: 'float' },
-   { name: 'wb_chloride', type: 'float' },
-   { name: 'wb_sodium', type: 'float' },
-   { name: 'wb_magnesium', type: 'float' },
-   { name: 'wb_total_alkalinity', type: 'float' },
-   { name: 'wb_ph', type: 'float' },
-   { name: 'wa_acid_name', type: 'int' },
-   { name: 'wa_acid_perc', type: 'int' },
-   { name: 'wa_base_name', type: 'int' },
-   { name: 'fermentables', type: 'string' },
-   { name: 'hops', type: 'string' },
-   { name: 'miscs', type: 'string' },
-   { name: 'yeasts', type: 'string' },
-   { name: 'mashs', type: 'string' }
-  ],
-  id: 'record',
-  url: url + '?record=' + my_record
- },
- // Load data and select one record.
- dataAdapter = new $.jqx.dataAdapter(source, {
-  loadComplete: function() {
-   var records = dataAdapter.records;
-   dataRecord = records[0];
-   // Hidden record uuid
-   $('#name').val(dataRecord.name);
-   $('#notes').val(dataRecord.notes);
-   // Hidden record locked
-   $('#st_name').val(dataRecord.st_name);
-   $('#st_letter').val(dataRecord.st_letter);
-   $('#st_guide').val(dataRecord.st_guide);
-   $('#st_category').val(dataRecord.st_category);
-   $('#st_category_number').val(dataRecord.st_category_number);
-   $('#st_type').val(StyleTypeData[dataRecord.st_type].nl);
-   $('#type').val(RecipeTypeData[dataRecord.type].nl);
-   $('#batch_size').val(dataRecord.batch_size);
-   $('#boil_size').val(dataRecord.boil_size);
-   $('#boil_time').val(dataRecord.boil_time);
-   $('#efficiency').val(dataRecord.efficiency);
-   $('#est_og').val(dataRecord.est_og);
-   $('#est_og2').val(dataRecord.est_og);
-   $('#st_og_min').val(dataRecord.st_og_min);
-   $('#st_og_max').val(dataRecord.st_og_max);
-   $('#est_fg').val(dataRecord.est_fg);
-   $('#est_fg2').val(dataRecord.est_fg);
-   $('#st_fg_min').val(dataRecord.st_fg_min);
-   $('#st_fg_max').val(dataRecord.st_fg_max);
-   $('#est_fg').val(dataRecord.est_fg);
-   $('#est_fg2').val(dataRecord.est_fg);
-   $('#st_fg_min').val(dataRecord.st_fg_min);
-   $('#st_fg_max').val(dataRecord.st_fg_max);
-   $('#est_color').val(dataRecord.est_color);
-   $('#est_color2').val(dataRecord.est_color);
-   $('#est_abv').val(dataRecord.est_abv);
-   $('#est_abv2').val(dataRecord.est_abv);
-   $('#st_abv_min').val(dataRecord.st_abv_min);
-   $('#st_abv_max').val(dataRecord.st_abv_max);
-   $('#st_color_min').val(dataRecord.st_color_min);
-   $('#st_color_max').val(dataRecord.st_color_max);
-   $('#color_method').val(ColorMethodData[dataRecord.color_method].nl);
-   $('#est_ibu').val(dataRecord.est_ibu);
-   $('#est_ibu2').val(dataRecord.est_ibu);
-   $('#st_ibu_min').val(dataRecord.st_ibu_min);
-   $('#st_ibu_max').val(dataRecord.st_ibu_max);
-   $('#ibu_method').val(IBUmethodData[dataRecord.ibu_method].nl);
-   $('#est_carb').val(dataRecord.est_carb);
-   $('#st_carb_min').val(dataRecord.st_carb_min);
-   $('#st_carb_max').val(dataRecord.st_carb_max);
-   $('#mash_name').val(dataRecord.mash_name);
-   $('#mash_ph').val(dataRecord.mash_ph);
-   // Hidden record sparge_temp
-   $('#sparge_ph').val(dataRecord.sparge_ph);
-   $('#sw_amount').val(dataRecord.sparge_volume);
-   // Hidden record sparge_source
-   $('#sparge_acid_type').val(AcidTypeData[dataRecord.sparge_acid_type].nl);
-   $('#sparge_acid_perc').val(dataRecord.sparge_acid_perc);
-   $('#sparge_acid_amount').val(dataRecord.sparge_acid_amount * 1000);
-   $('#calc_acid').val(dataRecord.calc_acid);
-   $('#w1_name').val(dataRecord.w1_name);
-   $('#w1_amount').val(dataRecord.w1_amount);
-   $('#w1_calcium').val(dataRecord.w1_calcium);
-   $('#w1_sulfate').val(dataRecord.w1_sulfate);
-   $('#w1_chloride').val(dataRecord.w1_chloride);
-   $('#w1_sodium').val(dataRecord.w1_sodium);
-   $('#w1_magnesium').val(dataRecord.w1_magnesium);
-   $('#w1_total_alkalinity').val(dataRecord.w1_total_alkalinity);
-   $('#w1_ph').val(dataRecord.w1_ph);
-   $('#w1_bicarbonate').val(Bicarbonate(dataRecord.w1_total_alkalinity, dataRecord.w1_ph));
-   $('#w1_cost').val(dataRecord.w1_cost);
-   $('#w2_name').val(dataRecord.w2_name);
-   $('#w2_amount').val(dataRecord.w2_amount);
-   $('#w2_calcium').val(dataRecord.w2_calcium);
-   $('#w2_sulfate').val(dataRecord.w2_sulfate);
-   $('#w2_chloride').val(dataRecord.w2_chloride);
-   $('#w2_sodium').val(dataRecord.w2_sodium);
-   $('#w2_magnesium').val(dataRecord.w2_magnesium);
-   $('#w2_total_alkalinity').val(dataRecord.w2_total_alkalinity);
-   $('#w2_ph').val(dataRecord.w2_ph);
-   $('#w2_bicarbonate').val(Bicarbonate(dataRecord.w2_total_alkalinity, dataRecord.w2_ph));
-   $('#w2_cost').val(dataRecord.w2_cost);
-   $('#wg_amount').val(dataRecord.wg_amount);
-   $('#wg_calcium').val(dataRecord.wg_calcium);
-   $('#wg_sulfate').val(dataRecord.wg_sulfate);
-   $('#wg_chloride').val(dataRecord.wg_chloride);
-   $('#wg_sodium').val(dataRecord.wg_sodium);
-   $('#wg_magnesium').val(dataRecord.wg_magnesium);
-   $('#wg_total_alkalinity').val(dataRecord.wg_total_alkalinity);
-   $('#wg_ph').val(dataRecord.wg_ph);
-   $('#wb_calcium').val(dataRecord.wb_calcium);
-   $('#wb_sulfate').val(dataRecord.wb_sulfate);
-   $('#wb_chloride').val(dataRecord.wb_chloride);
-   $('#wb_sodium').val(dataRecord.wb_sodium);
-   $('#wb_magnesium').val(dataRecord.wb_magnesium);
-   $('#wb_total_alkalinity').val(dataRecord.wb_total_alkalinity);
-   $('#wb_ph').val(dataRecord.wb_ph);
-   $('#wa_acid_name').val(AcidTypeData[dataRecord.wa_acid_name].nl);
-   $('#wa_acid_perc').val(dataRecord.wa_acid_perc);
-   editFermentable(dataRecord);
-   editHop(dataRecord);
-   editMisc(dataRecord);
-   editYeast(dataRecord);
-   editMash(dataRecord);
-   $('#jqxTabs').jqxTabs('next');
-   data_loaded = 1;
-  },
-  loadError: function(jqXHR, status, error) {},
-  beforeLoadComplete: function(records) { $('#jqxLoader').jqxLoader('open'); }
- }),
-
- // Inline fermentables editor
- editFermentable = function(data) {
-  var fermentableSource = {
-   localdata: data.fermentables,
-   datafields: [
-    { name: 'f_name', type: 'string' },
-    { name: 'f_origin', type: 'string' },
-    { name: 'f_supplier', type: 'string' },
-    { name: 'f_amount', type: 'float' },
-    { name: 'f_cost', type: 'float' },
-    { name: 'f_type', type: 'int' },
-    { name: 'f_yield', type: 'float' },
-    { name: 'f_color', type: 'float' },
-    { name: 'f_coarse_fine_diff', type: 'float' },
-    { name: 'f_moisture', type: 'float' },
-    { name: 'f_diastatic_power', type: 'float' },
-    { name: 'f_protein', type: 'float' },
-    { name: 'f_max_in_batch', type: 'float' },
-    { name: 'f_graintype', type: 'int' },
-    { name: 'f_added', type: 'int' },
-    { name: 'f_dissolved_protein', type: 'float' },
-    { name: 'f_recommend_mash', type: 'int' },
-    { name: 'f_add_after_boil', type: 'int' },
-    { name: 'f_adjust_to_total_100', type: 'int' },
-    { name: 'f_percentage', type: 'float' },
-    { name: 'f_di_ph', type: 'float' },
-    { name: 'f_acid_to_ph_57', type: 'float' },
-    { name: 'f_inventory', type: 'float' },
-    { name: 'f_avail', type: 'int' }
-   ],
-  },
-  fermentableAdapter = new $.jqx.dataAdapter(fermentableSource);
-
-  $('#fermentableGrid').jqxGrid({
-   width: 1240,
-   height: 470,
-   source: fermentableAdapter,
-   theme: theme,
-   editable: false,
-   ready: function() {
-    calcFermentables();
-    $('#jqxTabs').jqxTabs('next');
-   },
-   columns: [
-    { text: 'Vergistbaar ingredi&euml;nt', datafield: 'f_name' },
-    { text: 'Leverancier', datafield: 'f_supplier', width: 180 },
-    { text: 'Kleur', datafield: 'f_color', width: 90, align: 'right',
-     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
-      return '<span style="margin: 4px; margin-top: 6px; float: right;">' + dataAdapter.formatNumber(value, 'f0') + ' EBC</span>';
-     }
-    },
-    { text: 'Type', width: 100, datafield: 'f_type',
-     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
-      return '<span style="margin: 3px; margin-top: 6px; float: left;">' + FermentableTypeData[value].nl + '</span>';
-     }
-    },
-    { text: 'Moment', width: 110, datafield: 'f_added',
-     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
-      return '<span style="margin: 3px; margin-top: 6px; float: left;">' + AddedData[value].nl + '</span>';
-     }
-    },
-    { text: 'Maxinbatch', datafield: 'f_max_in_batch', hidden: true },
-    { text: 'Opbrengst', editable: false, datafield: 'f_yield', width: 90, align: 'right', cellsalign: 'right', cellsformat: 'p1' },
-    { text: 'Gewicht Kg', datafield: 'f_amount', width: 120, align: 'right', cellsalign: 'right', cellsformat: 'f3' },
-    { text: 'Procent', datafield: 'f_percentage', width: 90, align: 'right',
-     cellsrenderer: function(row, columnfield, value, defaulthtml, columnproperties, rowdata) {
-      var color = '#ffffff';
-      if (value > rowdata.f_max_in_batch)
-       color = '#ff4040';
-      return '<span style="margin: 4px; margin-top: 6px; float: right; color: ' +
-             color + ';">' + fermentableAdapter.formatNumber(value, 'p1') + '</span>';
-     }
-    },
-    { text: '100%', align: 'center', datafield: 'f_adjust_to_total_100', columntype: 'checkbox', width: 70 }
-   ]
-  });
- };
-
- // Inline hops editor
- var editHop = function(data) {
-  var hopSource = {
-   localdata: data.hops,
-   datafields: [
-    { name: 'h_name', type: 'string' },
-    { name: 'h_origin', type: 'string' },
-    { name: 'h_amount', type: 'float' },
-    { name: 'h_cost', type: 'float' },
-    { name: 'h_type', type: 'int' },
-    { name: 'h_form', type: 'int' },
-    { name: 'h_useat', type: 'int' },
-    { name: 'h_time', type: 'float' },
-    { name: 'h_alpha', type: 'float' },
-    { name: 'h_beta', type: 'float' },
-    { name: 'h_hsi', type: 'float' },
-    { name: 'h_humulene', type: 'float' },
-    { name: 'h_caryophyllene', type: 'float' },
-    { name: 'h_cohumulone', type: 'float' },
-    { name: 'h_myrcene', type: 'float' },
-    { name: 'h_total_oil', type: 'float' },
-    { name: 'h_inventory', type: 'float' },
-    { name: 'h_avail', type: 'int' }
-   ],
-  },
-  hopAdapter = new $.jqx.dataAdapter(hopSource);
-
-  $('#hopGrid').jqxGrid({
-   width: 1240,
-   height: 560,
-   source: hopAdapter,
-   theme: theme,
-   editable: false,
-   ready: function() { $('#jqxTabs').jqxTabs('next'); },
-   columns: [
-    { text: 'Hop', datafield: 'h_name' },
-    { text: 'Origin', width: 180, datafield: 'h_origin' },
-    { text: 'Type', width: 90, datafield: 'h_type',
-     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
-      return '<span style="margin: 4px; margin-top: 6px; float: left;">' + HopTypeData[value].nl + '</span>';
-     }
-    },
-    { text: 'Vorm', width: 110, datafield: 'h_form',
-     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
-      return '<span style="margin: 4px; margin-top: 6px; float: left;">' + HopFormData[value].nl + '</span>';
-     }
-    },
-    { text: 'Alpha', datafield: 'h_alpha', width: 80, align: 'right', cellsalign: 'right', cellsformat: 'p1' },
-    { text: 'Gebruik', width: 110, datafield: 'h_useat',
-     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
-      return '<span style="margin: 4px; margin-top: 6px; float: left;">' + HopUseData[value].nl + '</span>';
-     }
-    },
-    { text: 'Tijdsduur', datafield: 'h_time', width: 90, align: 'right',
-     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
-      var duration = '';
-      if ((rowdata.h_useat == 2) || (rowdata.h_useat == 4))   // Boil, Whirlpool
-       duration = dataAdapter.formatNumber(value, 'f0') + ' min.';
-      else if (rowdata.h_useat == 5)       // Dry hop
-       duration = dataAdapter.formatNumber(value / 1440, 'f0') + ' dagen';
-      return '<span style="margin: 4px; margin-top: 6px; float: right;">' + duration + '</span>';
-     }
-    },
-    { text: 'IBU', datafield: 'ibu', width: 80, align: 'right',
-     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
-      var ibu = toIBU(rowdata.h_useat, rowdata.h_form, preboil_sg, parseFloat(dataRecord.batch_size),
-                      parseFloat(rowdata.h_amount), parseFloat(rowdata.h_time),
-                      parseFloat(rowdata.h_alpha), dataRecord.ibu_method, 0, parseFloat(rowdata.h_time), 0);
-      return '<span style="margin: 4px; margin-top: 6px; float: right;">' + dataAdapter.formatNumber(ibu, 'f1') + '</span>';
-     }
-    },
-    { text: 'Gewicht', datafield: 'h_amount', width: 110, align: 'right',
-     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
-      var amount = dataAdapter.formatNumber(value, 'f1') + ' kg';
-      if (value < 1)
-       amount = dataAdapter.formatNumber(value * 1000, 'f1') + ' gr';
-      return '<span style="margin: 4px; margin-top: 6px; float: right;">' + amount + '</span>';
-     }
-    }
-   ]
-  });
- };
-
- // Inline miscs editor
- var editMisc = function(data) {
-  var miscSource = {
-   localdata: data.miscs,
-   datafields: [
-    { name: 'm_name', type: 'string' },
-    { name: 'm_amount', type: 'float' },
-    { name: 'm_cost', type: 'float' },
-    { name: 'm_type', type: 'int' },
-    { name: 'm_use_use', type: 'int' },
-    { name: 'm_time', type: 'float' },
-    { name: 'm_amount_is_weight', type: 'int' },
-    { name: 'm_inventory', type: 'float' },
-    { name: 'm_avail', type: 'int' }
-   ],
-  },
-  miscAdapter = new $.jqx.dataAdapter(miscSource, {
-   beforeLoadComplete: function(records) {
-    var i, row, data = new Array();
-    for (i = 0; i < records.length; i++) {
-     row = records[i];
-     data.push(row);
-     // Initial set water agent values.
-     if (row.m_use_use == 1) {	// Mash
-      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 'MgCl2':
-        $('#wa_mgcl2').val(row.m_amount * 1000);
-        break;
-       case 'NaHCO3':
-        $('#wa_nahco3').val(row.m_amount * 1000);
-        break;
-       case 'CaCO3':
-        $('#wa_caco3').val(row.m_amount * 1000);
-        break;
-       case 'Melkzuur':
-        $('#wa_acid_name').val(AcidTypeData[0].nl);
-        $('#wa_acid').val(row.m_amount * 1000);
-        $('#wa_acid_perc').val(AcidTypeData[0].AcidPrc);
-        last_acid = 'Melkzuur';
-        break;
-       case 'Zoutzuur':
-        $('#wa_acid_name').val(AcidTypeData[1].nl);
-        $('#wa_acid').val(row.m_amount * 1000);
-        $('#wa_acid_perc').val(AcidTypeData[1].AcidPrc);
-        last_acid = 'Zoutzuur';
-        break;
-       case 'Fosforzuur':
-        $('#wa_acid_name').val(AcidTypeData[2].nl);
-        $('#wa_acid').val(row.m_amount * 1000);
-        $('#wa_acid_perc').val(AcidTypeData[2].AcidPrc);
-        last_acid = 'Fosforzuur';
-        break;
-       case 'Zwavelzuur':
-        $('#wa_acid_name').val(AcidTypeData[3].nl);
-        $('#wa_acid').val(row.m_amount * 1000);
-        $('#wa_acid_perc').val(AcidTypeData[3].AcidPrc);
-        last_acid = 'Zwavelzuur';
-        break;
-      }
-     }
-     if (row.m_use_use == 6) {	// Sparge
-      switch (row.m_name) {
-       case 'CaCl2':
-        $('#ss_cacl2').val(row.m_amount * 1000);
-        break;
-       case 'CaSO4':
-        $('#ss_caso4').val(row.m_amount * 1000);
-        break;
-       case 'MgSO4':
-        $('#ss_mgso4').val(row.m_amount * 1000);
-        break;
-       case 'NaCl':
-        $('#ss_nacl').val(row.m_amount * 1000);
-        break;
-       case 'MgCl2':
-        $('#ss_mgcl2').val(row.m_amount * 1000);
-        break;
-       case 'Melkzuur':
-//       $('#wa_acid_name').val(0);
-//       $('#wa_acid').val(row.m_amount * 1000);
-//       $('#wa_acid_perc').val(AcidTypeData[0].AcidPrc); // TODO: this ignores changed percentages.
-//       last_acid = 'Melkzuur';
-        break;
-       case 'Zoutzuur':
- //      $('#wa_acid_name').val(1);
-//       $('#wa_acid').val(row.m_amount * 1000);
-//       $('#wa_acid_perc').val(AcidTypeData[1].AcidPrc);
-//       last_acid = 'Zoutzuur';
-        break;
-       case 'Fosforzuur':
-//       $('#wa_acid_name').val(2);
-//       $('#wa_acid').val(row.m_amount * 1000);
-//       $('#wa_acid_perc').val(AcidTypeData[2].AcidPrc);
-//       last_acid = 'Fosforzuur';
-        break;
-       case 'Zwavelzuur':
-//       $('#wa_acid_name').val(3);
-//       $('#wa_acid').val(row.m_amount * 1000);
-//       $('#wa_acid_perc').val(AcidTypeData[3].AcidPrc);
-//       last_acid = 'Zwavelzuur';
-        break;
-      }
-     }
-    }
-    return data;
-   },
-   loadError: function(jqXHR, status, error) {}
-  });
-  $('#miscGrid').jqxGrid({
-   width: 1240,
-   height: 575,
-   source: miscAdapter,
-   theme: theme,
-   editable: false,
-   ready: function() {
-    $('#jqxTabs').jqxTabs('next');
-   },
-   columns: [
-    { text: 'Ingredient', datafield: 'm_name' },
-    { text: 'Type', width: 140, datafield: 'm_type',
-     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
-      return '<span style="margin: 3px; margin-top: 6px; float: left;">' + MiscTypeData[value].nl + '</span>';
-     }
-    },
-    { text: 'Gebruik', width: 140, datafield: 'm_use_use',
-     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
-      return '<span style="margin: 3px; margin-top: 6px; float: left;">' + MiscUseData[value].nl + '</span>';
-     }
-    },
-    { text: 'Tijd', datafield: 'm_time', width: 140, align: 'right',
-     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
-      var duration = '';
-      if (rowdata.m_use_use == 2)     // Boil
-       duration = dataAdapter.formatNumber(value, 'f0') + ' minuten';
-      else if ((rowdata.m_use_use == 3) || (rowdata.m_use_use == 4))  // Primary or Secondary
-       duration = dataAdapter.formatNumber(value / 1440, 'f0') + ' dagen';
-      return '<span style="margin: 4px; margin-top: 6px; float: right;">' + duration + '</span>';
-     }
-    },
-    { text: 'Hoeveel', datafield: 'm_amount', width: 110, align: 'right',
-     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
-      var vstr = rowdata.m_amount_is_weight ? 'gr' : 'ml';
-      return '<span style="margin: 4px; margin-top: 6px; float: right;">' +
-             dataAdapter.formatNumber(value * 1000, 'f2') + ' ' + vstr + '</span>';
-     }
-    }
-   ]
-  });
- };
-
- // Inline yeasts editor
- var editYeast = function(data) {
-  var yeastSource = {
-   localdata: data.yeasts,
-   datafields: [
-    { name: 'y_name', type: 'string' },
-    { name: 'y_laboratory', type: 'string' },
-    { name: 'y_product_id', type: 'string' },
-    { name: 'y_amount', type: 'float' },
-    { name: 'y_cost', type: 'float' },
-    { name: 'y_type', type: 'int' },
-    { name: 'y_form', type: 'int' },
-    { name: 'y_flocculation', type: 'int' },
-    { name: 'y_min_temperature', type: 'float' },
-    { name: 'y_max_temperature', type: 'float' },
-    { name: 'y_attenuation', type: 'float' },
-    { name: 'y_use', type: 'int' },
-    { name: 'y_cells', type: 'float' },
-    { name: 'y_tolerance', type: 'float' },
-    { name: 'y_inventory', type: 'float' },
-    { name: 'y_sta1', type: 'int' },
-    { name: 'y_bacteria', type: 'int' },
-    { name: 'y_harvest_top', type: 'int' },
-    { name: 'y_harvest_time', type: 'int' },
-    { name: 'y_pitch_temperature', type: 'float' },
-    { name: 'y_pofpos', type: 'int' },
-    { name: 'y_zymocide', type: 'int' },
-    { name: 'y_gr_hl_lo', type: 'int' },
-    { name: 'y_sg_lo', type: 'float' },
-    { name: 'y_gr_hl_hi', type: 'int' },
-    { name: 'y_sg_hi', type: 'float' },
-    { name: 'y_avail', type: 'int' }
-   ],
-  },
-  yeastAdapter = new $.jqx.dataAdapter(yeastSource);
-
-  $('#yeastGrid').jqxGrid({
-   width: 1240,
-   height: 350,
-   source: yeastAdapter,
-   theme: theme,
-   editable: false,
-   ready: function() {
-    calcFermentables();
-    $('#jqxTabs').jqxTabs('next');
-   },
-   columns: [
-    { text: 'Gist', datafield: 'y_name' },
-    { text: 'Laboratorium', width: 150, datafield: 'y_laboratory' },
-    { text: 'Code', width: 90, datafield: 'y_product_id' },
-    { text: 'Soort', width: 100, datafield: 'y_form',
-     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
-      return '<span style="margin: 4px; margin-top: 6px; float: left;">' + YeastFormData[value].nl + '</span>';
-     }
-    },
-    { text: 'Min. &deg;C', width: 70, align: 'right', cellsalign: 'right', datafield: 'y_min_temperature' },
-    { text: 'Max. &deg;C', width: 70, align: 'right', cellsalign: 'right', datafield: 'y_max_temperature' },
-    { text: 'Tol. %', width: 60, align: 'right', cellsalign: 'right', datafield: 'y_tolerance',
-     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
-      var amount = '', color = '#ffffff';
-      if (value > 0) {
-       amount = dataAdapter.formatNumber(value, 'f1');
-       if (dataRecord.est_abv > value)
-        color = '#ff4040';
-      }
-      return '<span style="margin: 4px; margin-top: 6px; float: right; color: ' + color + ';">' + amount + '</span>';
-     }
-    },
-    { text: 'Attn. %', width: 70, align: 'right', cellsalign: 'right', datafield: 'y_attenuation', cellsformat: 'f1' },
-    { text: 'Voor', width: 120, datafield: 'y_use',
-     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
-      return '<span style="margin: 4px; margin-top: 6px; float: left;">' + YeastUseData[value].nl + '</span>';
-     }
-    },
-    { text: 'Hoeveel', datafield: 'y_amount', width: 90, align: 'right',
-     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
-      var amount = dataAdapter.formatNumber(value * 1000, 'f0') + ' ml';
-      if (rowdata.y_form == 0)        // Liquid
-       amount = dataAdapter.formatNumber(value, 'f0') + ' pk';
-      else if (rowdata.y_form == 1)   // Dry
-       amount = dataAdapter.formatNumber(value * 1000, 'f1') + ' gr';
-      return '<span style="margin: 4px; margin-top: 6px; float: right;">' + amount + '</span>';
-     }
-    }
-   ]
-  });
- };
-
- // inline mash editor
- var editMash = function(data) {
-  var mashSource = {
-   localdata: data.mashs,
-   datafields: [
-    { name: 'step_name', type: 'string' },
-    { name: 'step_type', type: 'int' },
-    { name: 'step_volume', type: 'float' },
-    { name: 'step_infuse_amount', type: 'float' },
-    { name: 'step_infuse_temp', type: 'float' },
-    { name: 'step_temp', type: 'float' },
-    { name: 'step_time', type: 'float' },
-    { name: 'step_wg_ratio', type: 'float' },
-    { name: 'ramp_time', type: 'float' },
-    { name: 'end_temp', type: 'float' }
-   ],
-  },
-  mashAdapter = new $.jqx.dataAdapter(mashSource, {
-   beforeLoadComplete: function(records) {
-    mash_infuse = 0;
-    var row, i, 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_wg_ratio = 0; // Init this field.
-     data.push(row);
-    }
-   },
-  });
-  $('#mashGrid').jqxGrid({
-   width: 1240,
-   height: 400,
-   source: mashAdapter,
-   theme: theme,
-   editable: false,
-   ready: function() {
-    calcFermentables();
-    calcInit();
-    calcMash();
-    $('#jqxLoader').jqxLoader('close');
-    $('#jqxTabs').jqxTabs('first');
-   },
-   columns: [
-    { text: 'Stap naam', datafield: 'step_name' },
-    { text: 'Stap type', datafield: 'step_type', width: 175,
-     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
-      return '<div style="margin: 4px;">' + MashStepTypeData[value].nl + '</div>';
-     }
-    },
-    { text: 'Start &deg;C', datafield: 'step_temp', width: 90, align: 'right', cellsalign: 'right', cellsformat: 'f1' },
-    { text: 'Eind &deg;C', datafield: 'end_temp', width: 90, align: 'right', cellsalign: 'right', cellsformat: 'f1' },
-    { text: 'Rust min.', datafield: 'step_time', width: 90, align: 'right', cellsalign: 'right' },
-    { text: 'Stap min.', datafield: 'ramp_time', width: 90, align: 'right', cellsalign: 'right' },
-    { text: 'Inf/dec L.', datafield: 'step_infuse_amount', width: 90, align: 'right',
-      cellsrenderer: function(row, columnfield, value, defaulthtml, columnproperties, rowdata) {
-       if (rowdata.step_type == 1)
-        return '<span></span>';
-       return '<span style="margin: 4px; margin-top: 6px; float: right;">' + dataAdapter.formatNumber(value, 'f1') + '</span>';
-      }
-    },
-    { text: 'Inf/dec &deg;C', datafield: 'step_infuse_temp', width: 90, align: 'right',
-      cellsrenderer: function(row, columnfield, value, defaulthtml, columnproperties, rowdata) {
-       if (rowdata.step_type == 1)
-        return '<span></span>';
-       return '<span style="margin: 4px; margin-top: 6px; float: right;">' + dataAdapter.formatNumber(value, 'f2') + '</span>';
-      }
-    },
-    { text: 'L/Kg.', datafield: 'step_wg_ratio', width: 90, align: 'right',
-      cellsrenderer: function(row, columnfield, value, defaulthtml, columnproperties, rowdata) {
-       var color = '#ffffff';
-       if (value < 2.0 || value > 6.0)
-        color = '#ff4040';
-       return '<span style="margin: 4px; margin-top: 6px; float: right; color: ' + color + ';">' + dataAdapter.formatNumber(value, 'f2') + '</span>';
-      }
-    }
-   ]
-  });
- };
-
-
- /*
-  * 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 recept ...',
-  theme: theme
- });
-
- function setWaterAgent(name, amount) {
-
-  var record, records, miscs, i, id, row, found = false, 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() {
-      records = miscs.records;
-      for (i = 0; i < records.length; i++) {
-       record = records[i];
-       if (record.name == name) {
-        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;
-   }
-  }
- }
-
-
- // Procedure TFrmWaterAdjustment.CalcWater2;
- function calcWater() {
-
-  if (! data_loaded) {
-   console.log('calcWater(): failsave');
-   return;
-  }
-
-  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,
-  r1d, r2d, f1d, f2d, f3d,
-  deltapH, deltapd, pd, n,
-  Res;
-
-  if (dataRecord.w1_name == '') {
-   return;
-  }
-
-  $('#w1_hardness').val(Hardness(dataRecord.w1_calcium, dataRecord.w1_magnesium));
-  $('#w1_ra').val(ResidualAlkalinity(dataRecord.w1_total_alkalinity, dataRecord.w1_calcium, dataRecord.w1_magnesium));
-
-  // 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);
-   $('#w2_hardness').val(Hardness(dataRecord.w2_calcium, dataRecord.w2_magnesium));
-   $('#w2_ra').val(ResidualAlkalinity(dataRecord.w2_total_alkalinity, dataRecord.w2_calcium, dataRecord.w2_magnesium));
-  } 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;
-  }
-  var bicarbonate = Bicarbonate(total_alkalinity, ph);
-
-  /* Save mixed water ions for later */
-  var wg_calcium = calcium;
-  var wg_sodium = sodium;
-  var wg_total_alkalinity = total_alkalinity;
-  var wg_chloride = chloride;
-  var wg_sulfate = sulfate;
-  var wg_bicarbonate = bicarbonate;
-
-  dataRecord.wg_amount = liters;
-  dataRecord.wg_ph = ph;
-
-  $('#wg_amount').val(liters);
-  $('#wg_calcium').val(Round(calcium, 1));
-  $('#wg_magnesium').val(Round(magnesium, 1));
-  $('#wg_sodium').val(Round(sodium, 1));
-  $('#wg_bicarbonate').val(Round(bicarbonate, 1));
-  $('#wg_total_alkalinity').val(Round(total_alkalinity, 1));
-  $('#wg_chloride').val(Round(chloride, 1));
-  $('#wg_sulfate').val(Round(sulfate, 1));
-  $('#wg_ph').val(Round(ph, 2));
-  $('#wg_hardness').val(Round(Hardness(calcium, magnesium), 1));
-  $('#wg_ra').val(Round(ResidualAlkalinity(total_alkalinity, calcium, magnesium), 1));
-
-  var mash_ph = Round(MashpH(), 3);
-  console.log('Distilled water mash pH: ' + mash_ph);
-
-  /* Calculate Salt additions */
-  if (liters > 0) {
-   calcium += (parseFloat($('#wa_cacl2').jqxNumberInput('decimal')) * MMCa / MMCaCl2 * 1000 +
-    parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMCa / MMCaSO4 * 1000 +
-    parseFloat($('#wa_caco3').jqxNumberInput('decimal')) * MMCa / MMCaCO3 * 1000) / liters;
-   magnesium += (parseFloat($('#wa_mgso4').jqxNumberInput('decimal')) * MMMg / MMMgSO4 * 1000 +
-    parseFloat($('#wa_mgcl2').jqxNumberInput('decimal')) * MMMg / MMMgCl2 * 1000) / liters;
-   sodium += (parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMNa / MMNaCl * 1000 +
-    parseFloat($('#wa_nahco3').jqxNumberInput('decimal')) * MMNa / MMNaHCO3 * 1000) / liters;
-   sulfate += (parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMSO4 / MMCaSO4 * 1000 +
-    parseFloat($('#wa_mgso4').jqxNumberInput('decimal')) * MMSO4 / MMMgSO4 * 1000) / liters;
-   chloride += (2 * parseFloat($('#wa_cacl2').jqxNumberInput('decimal')) * MMCl / MMCaCl2 * 1000 +
-    parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMCl / MMNaCl * 1000 +
-    parseFloat($('#wa_mgcl2').jqxNumberInput('decimal')) * MMCl / MMMgCl2 * 1000) / liters;
-   bicarbonate += (parseFloat($('#wa_nahco3').jqxNumberInput('decimal')) * MMHCO3 / MMNaHCO3 * 1000 +
-    parseFloat($('#wa_caco3').jqxNumberInput('decimal')) / 3 * MMHCO3 / MMCaCO3 * 1000) / liters;
-  }
-
-  if (dataRecord.wa_acid_name < 0 || dataRecord,wa_acid_name >= AcidTypeData.length) {
-   $('#wa_acid_name').val(0);
-   dataRecord.wa_acid_name = 0;
-   dataRecord.wa_acid_perc = AcidTypeData[0].AcidPrc;
-   $('#wa_acid_perc').val(AcidTypeData[0].AcidPrc);
-  }
-  if (last_acid == '')
-   last_acid = AcidTypeData[dataRecord.wa_acid_name].nl;
-
-  if (parseFloat(dataRecord.wa_acid_perc) == 0) {
-   dataRecord.wa_acid_perc = AcidTypeData[AT].AcidPrc;
-   $('#wa_acid_perc').val(AcidTypeData[AT].AcidPrc);
-  }
-
-  AT = dataRecord.wa_acid_name;
-
-  /* Note that the next calculations do not correct the pH change by the added salts.
-     This pH change is at most 0.1 pH and is a minor difference in Acid amount. */
-
-  if (dataRecord.calc_acid) {
-   $('.c_mashph').show();
-   /* Auto calculate pH */
-   TpH = parseFloat(dataRecord.mash_ph);
-   protonDeficit = ProtonDeficit(TpH);
-   console.log('calc_acid tgt: ' + TpH + ' protonDeficit: ' + protonDeficit);
-   if (protonDeficit > 0) { // Add acid
-    frac = CalcFrac(TpH, AcidTypeData[AT].pK1, AcidTypeData[AT].pK2, AcidTypeData[AT].pK3);
-    Acid = protonDeficit / frac;
-    Acid *= AcidTypeData[AT].MolWt; // mg
-    Acidmg = Acid;
-    var RealSG = Round(((AcidTypeData[AT].AcidSG - 1000) * (parseFloat(dataRecord.wa_acid_perc) / 100)) + 1000, 2);
-    Acid /= RealSG;
-    Acid /= AcidTypeData[AT].AcidPrc / 100;
-    Acid = Round(Acid, 2);
-    console.log('Mash auto Acid final ml: ' + Acid);
-    $('#wa_acid').val(Acid);
-    setWaterAgent(AcidTypeData[AT].nl, Acid);
-
-    bicarbonate = bicarbonate - protonDeficit * frac / liters;
-    total_alkalinity = bicarbonate * 50 / 61;
-   }
-   ph = TpH;
-   dataRecord.wb_ph = ph;
-   $('#wb_ph').val(Round(ph, 2));
-   $('#est_mash_ph').val(Round(ph, 2));
-  } else { // Manual
-   /* Manual calculate pH */
-   $('.c_mashph').hide();
-   console.log('calc_acid no');
-   pHa = Round(ph, 3); // Adjusted water pH
-   // Then calculate the new pH with added acids and malts
-   console.log('Mash pH: ' + pHa);
-   Acid  = AcidTypeData[AT].AcidSG * (parseFloat(dataRecord.wa_acid_perc) / 100); // ml
-   Acid *= parseFloat($('#wa_acid').jqxNumberInput('decimal'));
-   Acid /= AcidTypeData[AT].MolWt;  // mg
-   Acidmg = Acid;
-
-   //find the pH where the protondeficit = protondeficit by the acid
-   frac = CalcFrac(pHa, AcidTypeData[AT].pK1, AcidTypeData[AT].pK2, AcidTypeData[AT].pK3);
-   protonDeficit = Round(Acid * frac, 3);
-   //console.log('protonDeficit Acid: ' + protonDeficit + ' frac: ' + frac + ' pH: ' + pHa);
-
-   deltapH = 0.001;
-   deltapd = 0.1;
-   pd = Round(ProtonDeficit(pHa), 6);
-   n = 0;
-   while (((pd < (protonDeficit - deltapd)) || (pd > (protonDeficit + deltapd))) && (n < 4000)) {
-     n++;
-     if (pd < (protonDeficit - deltapd))
-      pHa -= deltapH;
-     else if (pd > (protonDeficit + deltapd))
-      pHa += deltapH;
-     frac = CalcFrac(pHa, AcidTypeData[AT].pK1, AcidTypeData[AT].pK2, AcidTypeData[AT].pK3);
-     protonDeficit = Acid * frac;
-     pd = ProtonDeficit(pHa);
-   }
-   //console.log('n: ' + n + ' pd: ' + pd + ' protonDeficit: ' + protonDeficit + ' frac: ' + frac + ' pHa: ' + pHa);
-   bicarbonate = wg_bicarbonate - protonDeficit * frac / liters;
-   total_alkalinity = RA * 50 / 61;
-   ph = pHa;
-   $('#wb_ph').val(Round(ph, 2));
-   $('#est_mash_ph').val(Round(ph, 2));
-  }
-
-  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;
-  }
-
-  var BUGU = GetBUGU();
-  $('#tgt_bu').val(Round(BUGU, 2));
-  // From brouwhulp.
-  if (BUGU < 0.32)
-   $('#wr_bu').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Zeer moutig en zoet</span>");
-  else if (BUGU < 0.43)
-   $('#wr_bu').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Moutig, zoet</span>");
-  else if (BUGU < 0.52)
-   $('#wr_bu').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Evenwichtig</span>");
-  else if (BUGU < 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>");
-
-  // Sulfate to Chloride ratio (Palmer).
-  var OptSO4Clratio = GetOptSO4Clratio();
-  $('#tgt_so4_cl').val(Round(OptSO4Clratio, 1));
-  if (OptSO4Clratio < 0.4)
-   $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Te moutig</span>");
-  else if (OptSO4Clratio < 0.6)
-   $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Zeer moutig</span>");
-  else if (OptSO4Clratio < 0.8)
-   $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Moutig</span>");
-  else if (OptSO4Clratio < 1.5)
-   $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Gebalanceerd</span>");
-  else if (OptSO4Clratio < 2.0)
-   $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Licht bitter</span>");
-  else if (OptSO4Clratio < 4.0)
-   $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Bitter</span>");
-  else if (OptSO4Clratio < 9.0)
-   $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Zeer bitter</span>");
-  else
-   $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Te bitter</span>");
-  if (chloride > 0)
-   RA = sulfate / chloride;
-  else
-   RA = 10;
-  $('#got_so4_cl').val(Round(RA, 1));
-  Res = 'normaal';
-  if (RA < (0.8 * OptSO4Clratio))
-   Res = 'laag';
-  else if (RA > (1.2 * OptSO4Clratio))
-   Res = 'hoog';
-  setRangeIndicator('so4_cl', 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_bicarbonate').val(Round(bicarbonate, 1));
-  $('#wb_total_alkalinity').val(Round(total_alkalinity, 1));
-  $('#wb_hardness').val(Hardness(calcium, magnesium));
-  $('#wb_ra').val(ResidualAlkalinity(total_alkalinity, calcium, magnesium));
-
-  if (calcium < 40) {
-   setRangeIndicator('calcium', 'laag');
-  } else if (calcium > 150) {
-   setRangeIndicator('calcium', 'hoog');
-  } else {
-   setRangeIndicator('calcium', 'normaal');
-  }
-  if (magnesium < 5) {
-   setRangeIndicator('magnesium', 'laag');
-  } else if (magnesium > 40) {
-   setRangeIndicator('magnesium', 'hoog');
-  } else {
-   setRangeIndicator('magnesium', 'normaal');
-  }
-  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 <= 150) {
-   setRangeIndicator('chloride', 'normaal');
-  } else {
-   setRangeIndicator('chloride', 'hoog');
-  }
-  if (sulfate <= 50) {
-   setRangeIndicator('sulfate', 'laag');
-  } else if (sulfate <= 400) {
-   setRangeIndicator('sulfate', 'normaal');
-  } else {
-   setRangeIndicator('sulfate', 'hoog');
-  }
-  // (cloride + sulfate) > 500 is too high
-  if ((chloride + sulfate) > 500) {
-   setRangeIndicator('chloride', 'hoog');
-   setRangeIndicator('sulfate', 'hoog');
-  }
-  if (ph < 5.2) {
-   setRangeIndicator('ph', 'laag');
-  } else if (ph > 5.6) {
-   setRangeIndicator('ph', 'hoog');
-  } else {
-   setRangeIndicator('ph', 'normaal');
-  }
-  if (bicarbonate > 250) {
-   setRangeIndicator('bicarbonate', 'hoog');
-  } else {
-   setRangeIndicator('bicarbonate', 'normaal');
-  }
-  calcSparge();
- }
-
-
- function calcSparge() {
-
-  /* Based on the work of ajDeLange. */
-  var ws_calcium, ws_magnesium, ws_total_alkalinity, ws_sodium, ws_chloride;
-  var ws_sulfate, ws_ph, ws_hardness, ws_ra;
-  var TargetpH = dataRecord.sparge_ph;
-  var Source_pH = 7.0;
-
-  // Select watersource or fallback to the first source.
-  if ((dataRecord.sparge_source == 1) && (dataRecord.w2_ph > 0.0)) { // Source 2
-    ws_calcium = dataRecord.w2_calcium;
-    ws_magnesium = dataRecord.w2_magnesium;
-    ws_total_alkalinity = dataRecord.w2_total_alkalinity;
-    ws_sodium = dataRecord.w2_sodium;
-    ws_chloride = dataRecord.w2_chloride;
-    ws_sulfate = dataRecord.w2_sulfate;
-    Source_pH = dataRecord.w2_ph;
-    $('#w2_button').jqxRadioButton({ checked: true });
-  } else if ((dataRecord.sparge_source == 2) && (dataRecord.w2_ph > 0.0)) { // Mixed
-    ws_calcium = dataRecord.wg_calcium;
-    ws_magnesium = dataRecord.wg_magnesium;
-    ws_total_alkalinity = dataRecord.wg_total_alkalinity;
-    ws_sodium = dataRecord.wg_sodium;
-    ws_chloride = dataRecord.wg_chloride;
-    ws_sulfate = dataRecord.wg_sulfate;
-    Source_pH = dataRecord.wg_ph;
-    $('#wg_button').jqxRadioButton({ checked: true });
-  } else {
-    ws_calcium = dataRecord.w1_calcium;
-    ws_magnesium = dataRecord.w1_magnesium;
-    ws_total_alkalinity = dataRecord.w1_total_alkalinity;
-    ws_sodium = dataRecord.w1_sodium;
-    ws_chloride = dataRecord.w1_chloride;
-    ws_sulfate = dataRecord.w1_sulfate;
-    Source_pH = dataRecord.w1_ph;
-    $('#w1_button').jqxRadioButton({ checked: true });
-  }
-
-  if (dataRecord.sparge_volume > 0) {
-   ws_calcium += (parseFloat($('#ss_cacl2').jqxNumberInput('decimal')) * MMCa / MMCaCl2 * 1000 +
-    parseFloat($('#ss_caso4').jqxNumberInput('decimal')) * MMCa / MMCaSO4 * 1000) / dataRecord.sparge_volume;
-   ws_magnesium += (parseFloat($('#ss_mgso4').jqxNumberInput('decimal')) * MMMg / MMMgSO4 * 1000 +
-    parseFloat($('#ss_mgcl2').jqxNumberInput('decimal')) * MMMg / MMMgCl2 * 1000) / dataRecord.sparge_volume;
-   ws_sodium += (parseFloat($('#ss_nacl').jqxNumberInput('decimal')) * MMNa / MMNaCl * 1000) / dataRecord.sparge_volume;
-   ws_sulfate += (parseFloat($('#ss_caso4').jqxNumberInput('decimal')) * MMSO4 / MMCaSO4 * 1000 +
-    parseFloat($('#ss_mgso4').jqxNumberInput('decimal')) * MMSO4 / MMMgSO4 * 1000) / dataRecord.sparge_volume;
-   ws_chloride += (2 * parseFloat($('#ss_cacl2').jqxNumberInput('decimal')) * MMCl / MMCaCl2 * 1000 +
-    parseFloat($('#ss_nacl').jqxNumberInput('decimal')) * MMCl / MMNaCl * 1000 +
-    parseFloat($('#ss_mgcl2').jqxNumberInput('decimal')) * MMCl / MMMgCl2 * 1000) / dataRecord.sparge_volume;
-  }
-
-  /* Show the spargewate with salt additions */
-  $('#sw_calcium').val(Round(ws_calcium, 1));
-  $('#sw_magnesium').val(Round(ws_magnesium, 1));
-  $('#sw_sodium').val(Round(ws_sodium, 1));
-  $('#sw_sulfate').val(Round(ws_sulfate, 1));
-  $('#sw_chloride').val(Round(ws_chloride, 1));
-  $('#sw_bicarbonate').val(Round(Bicarbonate(ws_total_alkalinity, Source_pH), 1));
-  $('#sw_total_alkalinity').val(Round(ws_total_alkalinity, 1));
-  $('#sw_ph').val(dataRecord.sparge_ph);
-  $('#sw_hardness').val(Hardness(ws_calcium, ws_magnesium));
-  $('#sw_ra').val(ResidualAlkalinity(ws_total_alkalinity, ws_calcium, ws_magnesium));
-
-  AT = dataRecord.sparge_acid_type;
-  if (AT < 0 || AT >= AcidTypeData.length) {
-   AT = 0;
-   dataRecord.sparge_acid_type = 0;
-   $('#sparge_acid_type').val(AcidTypeData[0].nl);
-   dataRecord.sparge_acid_perc = AcidTypeData[0].AcidPrc;
-   $('#sparge_acid_perc').val(dataRecord.sparge_acid_perc);
-  }
-
-  /*
-   * Auto calculate the required acid
-   */
-  if (dataRecord.calc_acid) {
-   // 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.35);
-   var r2 = Math.pow(10, Source_pH - 10.33);
-   var d = 1 + r1 + r1 * r2;
-   var f1 = 1 / 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.35);
-   var r243 = Math.pow(10, 4.3 - 10.33);
-   var d43 = 1 + r143 + r143 * r243;
-   var f143 = 1 / d43;
-   var f343 = r143 * r243 / d43;
-
-   //Step 4. Solve
-   var Ct = ws_total_alkalinity / 50 / ((f143 - f1) + (f3 - f343));
-
-   //Step 5. Compute mole fractions at desired pH
-   var r1g = Math.pow(10, TargetpH - 6.35);
-   var r2g = Math.pow(10, TargetpH - 10.33);
-   var dg = 1 + r1g + r1g * r2g;
-   var f1g = 1 / 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.
-
-   //Step 8. Get the acid data.
-   var fract = CalcFrac(TargetpH, AcidTypeData[AT].pK1, AcidTypeData[AT].pK2, AcidTypeData[AT].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 *= AcidTypeData[AT].MolWt; //mg
-
-   //Step 11. Divide by Specific Gravity and Percentage to get the final ml.
-   var RealSG = Round(((AcidTypeData[AT].AcidSG - 1000) * (dataRecord.sparge_acid_perc / 100)) + 1000, 2);
-   Acid = Acid / RealSG;           //ml
-   Acid *= dataRecord.sparge_volume; //ml acid total at 100%
-   Acid /= AcidTypeData[AT].AcidPrc / 100;     //ml acid at supplied strength
-   Acid = Round(Acid, 2);
-   dataRecord.sparge_acid_amount = Acid / 1000;
-   $('#sparge_acid_amount').val(Acid);
-  }
-
-  // Finally calculate the estimate preboil pH
-  var ph = -Math.log10(((Math.pow(10, -dataRecord.wb_ph) * dataRecord.wg_amount) + (Math.pow(10, -dataRecord.sparge_ph) * dataRecord.sparge_volume)) /
-	  (dataRecord.wg_amount + dataRecord.sparge_volume));
-  $('#preboil_ph').val(ph);
- }
-
- function calcInit() {
-  console.log('calc.init()');
-
-  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();
-
- };
-
- function saveRecord(goback) {
-  window.location.href = my_return;
- };
-
- dataAdapter.dataBind();
-
- // initialize the input fields.
- // Tab 1, Algemeen
- $('#name').jqxTooltip({ content: 'De naam voor dit recept.' });
- $('#name').jqxInput({ theme: theme, width: 640, height: 23 });
- $('#notes').jqxTooltip({ content: 'De uitgebreide opmerkingen over dit recept.' });
- $('#notes').jqxInput({ theme: theme, width: 960, height: 200 });
- $('#type').jqxTooltip({ content: 'Het brouw type van dit recept.' });
- $('#type').jqxInput({ theme: theme, width: 180, height: 23 });
- $('#efficiency').jqxTooltip({ content: 'Het rendement van maischen en koken.' });
- $('#efficiency').jqxNumberInput(Show1dec);
- $('#batch_size').jqxTooltip({ content: 'Het volume van het gekoelde wort na het koken.' });
- $('#batch_size').jqxNumberInput(Show1dec);
- $('#batch_size').jqxNumberInput({ min: 4 });
- $('#boil_size').jqxTooltip({ content: 'Het volume van het wort voor het koken.' });
- $('#boil_size').jqxNumberInput({ inputMode: 'simple', theme: theme, width: 90, height: 23, decimalDigits: 2, readOnly: true });
- $('#boil_time').jqxTooltip({ content: 'De kooktijd in minuten.' });
- $('#boil_time').jqxNumberInput(Show0dec);
- $('#boil_time').jqxNumberInput({ min: 4, max: 360 });
-
- $('#st_name').jqxTooltip({ content: 'De bierstijl naam voor dit recept.'});
- $('#st_name').jqxInput({ theme: theme, width: 250, height: 23 });
- $('#st_letter').jqxTooltip({ content: 'De bierstijl letter voor dit recept.'});
- $('#st_letter').jqxInput({ theme: theme, width: 90, height: 23 });
- $('#st_guide').jqxTooltip({ content: 'De bierstijl gids voor dit recept.'});
- $('#st_guide').jqxInput({ theme: theme, width: 250, height: 23 });
- $('#st_category').jqxTooltip({ content: 'De Amerikaanse bierstijl categorie.'});
- $('#st_category').jqxInput({ theme: theme, width: 250, height: 23 });
- $('#st_category_number').jqxTooltip({ content: 'De Amerikaanse bierstijl categorie sub nummer.'});
- $('#st_category_number').jqxNumberInput(Smal0dec);
- $('#st_type').jqxTooltip({ content: 'Het bierstijl type.'});
- $('#st_type').jqxInput({ theme: theme, width: 250, height: 23 });
-
- $('#est_og').jqxTooltip({ content: 'Het begin SG wat je wilt bereiken. De moutstort wordt automatisch herberekend.' });
- $('#est_og').jqxNumberInput(Show3dec);
- $('#st_og_min').jqxTooltip({ content: 'Het minimum begin SG voor deze bierstijl.'});
- $('#st_og_min').jqxNumberInput({ inputMode: 'simple', theme: theme, width: 50, height: 23, decimalDigits: 3, readOnly: true });
- $('#st_og_max').jqxTooltip({ content: 'Het maximum begin SG voor deze bierstijl.'});
- $('#st_og_max').jqxNumberInput({ inputMode: 'simple', theme: theme, width: 50, height: 23, decimalDigits: 3, readOnly: true });
-
- $('#est_fg').jqxTooltip({ content: 'Het eind SG. Dit wordt automatisch berekend.' });
- $('#est_fg').jqxNumberInput(Show3dec);
- $('#st_fg_min').jqxTooltip({ content: 'Het minimum eind SG voor deze bierstijl.'});
- $('#st_fg_min').jqxNumberInput({ inputMode: 'simple', theme: theme, width: 50, height: 23, decimalDigits: 3, readOnly: true });
- $('#st_fg_max').jqxTooltip({ content: 'Het maximum eind SG voor deze bierstijl.'});
- $('#st_fg_max').jqxNumberInput({ inputMode: 'simple', theme: theme, width: 50, height: 23, decimalDigits: 3, readOnly: true });
-
- $('#est_abv').jqxTooltip({ content: 'Alcohol volume %. Dit wordt automatisch berekend.' });
- $('#est_abv').jqxNumberInput(Smal1dec);
- $('#st_abv_min').jqxTooltip({ content: 'Het minimum alcohol volume % voor deze bierstijl.'});
- $('#st_abv_min').jqxNumberInput(Smal1dec);
- $('#st_abv_max').jqxTooltip({ content: 'Het maximum alcohol volume % voor deze bierstijl.'});
- $('#st_abv_max').jqxNumberInput(Smal1dec);
-
- $('#est_color').jqxTooltip({ content: 'De kleur in EBC. Dit wordt automatisch berekend.' });
- $('#est_color').jqxNumberInput(Show0dec);
- $('#st_color_min').jqxTooltip({ content: 'De minimum kleur voor deze bierstijl.'});
- $('#st_color_min').jqxNumberInput(Smal0dec);
- $('#st_color_max').jqxTooltip({ content: 'De maximum kleur voor deze bierstijl.'});
- $('#st_color_max').jqxNumberInput(Smal0dec);
- $('#color_method').jqxInput({ theme: theme, width: 180, height: 23 }); 
- $('#est_ibu').jqxTooltip({ content: 'De bitterheid in IBU. Dit wordt automatisch berekend.' });
- $('#est_ibu').jqxNumberInput(Show0dec);
- $('#st_ibu_min').jqxTooltip({ content: 'De minimum bitterheid voor deze bierstijl.'});
- $('#st_ibu_min').jqxNumberInput(Smal0dec);
- $('#st_ibu_max').jqxTooltip({ content: 'De maximum bitterheid voor deze bierstijl.'});
- $('#st_ibu_max').jqxNumberInput(Smal0dec);
-
- $('#ibu_method').jqxInput({ theme: theme, width: 180, height: 23 });
- $('#kcal').jqxTooltip({ content: 'Energie-inhoud in kcal/liter.' });
- $('#kcal').jqxNumberInput(Smal0dec);
- $('#est_carb').jqxTooltip({ content: 'Koolzuur volume. Dit wordt automatisch berekend.' });
- $('#est_carb').jqxNumberInput(Smal1dec);
- $('#st_carb_min').jqxTooltip({ content: 'Het minimum koolzuur volume voor deze bierstijl.'});
- $('#st_carb_min').jqxNumberInput(Smal1dec);
- $('#st_carb_max').jqxTooltip({ content: 'Het maximum koolzuur volume voor deze bierstijl.'});
- $('#st_carb_max').jqxNumberInput(Smal1dec);
-
- // Tab 2, Vergistbaar
- $('#est_color2').jqxTooltip({ content: 'De kleur in EBC. Dit wordt automatisch berekend.' });
- $('#est_color2').jqxNumberInput(Show0dec);
- $('#est_og2').jqxTooltip({ content: 'Het begin SG wat je wilt bereiken. De moutstort wordt automatisch herberekend.' });
- $('#est_og2').jqxNumberInput(Show3dec);
- $('#perc_malts').jqxProgressBar({
-  width: 300,
-  height: 23,
-  theme: theme,
-  showText: true,
-  max: 120,
-  animationDuration: 0,
-  colorRanges: [
-   { stop: 90, color: '#008C00' },
-   { stop: 100, color: '#EB7331' },
-   { stop: 120, color: '#FF0000' }
-  ],
-  renderText: function(text) {
-   return (Math.round(parseInt(text) * 1.2)) + '%';
-  }
- });
- $('#perc_sugars').jqxProgressBar({
-  width: 300,
-  height: 23,
-  theme: theme,
-  showText: true,
-  max: 50,
-  animationDuration: 0,
-  colorRanges: [
-   { stop: 20, color: '#008C00' },
-   { stop: 50, color: '#FF0000' }
-  ],
-  renderText: function(text) {
-   return (Math.round(parseInt(text) * 5) / 10) + '%';
-  }
- });
- $('#perc_cara').jqxProgressBar({
-  width: 300,
-  height: 23,
-  theme: theme,
-  showText: true,
-  max: 50,
-  animationDuration: 0,
-  colorRanges: [
-   { stop: 25, color: '#008C00' },
-   { stop: 50, color: '#FF0000' }
-  ],
-  renderText: function(text) {
-   return (Math.round(parseInt(text) * 5) / 10) + '%';
-  }
- });
- $('#ferm_lintner').jqxProgressBar({
-  width: 300,
-  height: 23,
-  theme: theme,
-  showText: true,
-  max: 200,
-  animationDuration: 0,
-  colorRanges: [
-   { stop: 30, color: '#FF0000' },
-   { stop: 40, color: '#EB7331' },
-   { stop: 200, color: '#008C00' }
-  ],
-  renderText: function(text) {
-   return (parseInt(text) * 2) + ' lintner';
-  }
- });
-
- // Tab 3, Hoppen
- $('#est_ibu2').jqxTooltip({ content: 'De bitterheid in IBU. Dit wordt automatisch berekend.' });
- $('#est_ibu2').jqxNumberInput(Smal0dec);
- $('#hop_flavour').jqxProgressBar({
-  width: 300,
-  height: 23,
-  theme: theme,
-  showText: true,
-  animationDuration: 0,
-  colorRanges: [
-   { stop: 20, color: '#004D00' },
-   { stop: 40, color: '#008C00' },
-   { stop: 60, color: '#00BF00' },
-   { stop: 80, color: '#00FF00' },
-   { stop: 100, color: '#80FF80' }
-  ],
-  renderText: function(text) {
-   var val = parseInt(text);
-   if (val < 20)
-    return 'Weinig';
-   else if (val < 40)
-    return 'Matig';
-   else if (val < 60)
-    return 'Redelijk';
-   else if (val < 80)
-    return 'Veel';
-   else
-    return 'Zeer veel';
-  }
- });
- $('#hop_aroma').jqxProgressBar({
-  width: 300,
-  height: 23,
-  theme: theme,
-  showText: true,
-  animationDuration: 0,
-  colorRanges: [
-   { stop: 20, color: '#004D00' },
-   { stop: 40, color: '#008C00' },
-   { stop: 60, color: '#00BF00' },
-   { stop: 80, color: '#00FF00' },
-   { stop: 100, color: '#80FF80' }
-  ],
-  renderText: function(text) {
-   var val = parseInt(text);
-   if (val < 20)
-    return 'Weinig';
-   else if (val < 40)
-    return 'Matig';
-   else if (val < 60)
-    return 'Redelijk';
-   else if (val < 80)
-    return 'Veel';
-   else
-    return 'Zeer veel';
-  }
- });
-
- // Tab 4, Diversen
-
- // Tab 5, Gist
- $('#est_fg2').jqxTooltip({ content: 'Het eind SG. Dit wordt automatisch berekend.' });
- $('#est_fg2').jqxNumberInput(Show3dec);
- $('#est_abv2').jqxTooltip({ content: 'Alcohol volume %. Dit wordt automatisch berekend.' });
- $('#est_abv2').jqxNumberInput(Smal1dec);
-
- // Tab 6, Maischen
- $('#mash_name').jqxInput({ theme: theme, width: 320, height: 23 });
-
- // Tab 7, Water
- $('#tgt_bu').jqxNumberInput(Show2wat);
- $('#tgt_so4_cl,#got_so4_cl').jqxNumberInput(Show1wat);
- $('#preboil_ph').jqxNumberInput(Show2wat);
-
- // Water source 1
- $('#w1_name').jqxInput({ theme: theme, width: 200, height: 23 });
- $('#w1_button').jqxRadioButton({ theme: theme, width: 50, height: 23, disabled: true });
- $('#w1_amount').jqxNumberInput(Show1wat);
- $('#w1_calcium').jqxNumberInput(Show1wat);
- $('#w1_magnesium').jqxNumberInput(Show1wat);
- $('#w1_sodium').jqxNumberInput(Show1wat);
- $('#w1_bicarbonate').jqxNumberInput(Show1wat);
- $('#w1_total_alkalinity').jqxNumberInput(Show1wat);
- $('#w1_chloride').jqxNumberInput(Show1wat);
- $('#w1_sulfate').jqxNumberInput(Show1wat);
- $('#w1_ph').jqxNumberInput(Show2wat);
- $('#w1_hardness').jqxNumberInput(Show1wat);
- $('#w1_ra').jqxNumberInput(Show1wat);
- // Water source 2
- $('#w2_name').jqxInput({ theme: theme, width: 200, height: 23 });
- $('#w2_button').jqxRadioButton({ theme: theme, width: 50, height: 23, disabled: true });
- $('#w2_amount').jqxNumberInput(Show1wat);
- $('#w2_calcium').jqxNumberInput(Show1wat);
- $('#w2_magnesium').jqxNumberInput(Show1wat);
- $('#w2_sodium').jqxNumberInput(Show1wat);
- $('#w2_bicarbonate').jqxNumberInput(Show1wat);
- $('#w2_total_alkalinity').jqxNumberInput(Show1wat);
- $('#w2_chloride').jqxNumberInput(Show1wat);
- $('#w2_sulfate').jqxNumberInput(Show1wat);
- $('#w2_ph').jqxNumberInput(Show2wat);
- $('#w2_hardness').jqxNumberInput(Show1wat);
- $('#w2_ra').jqxNumberInput(Show1wat);
- // Water mixed
- $('#wg_button').jqxRadioButton({ theme: theme, width: 50, height: 23, disabled: true });
- $('#wg_amount').jqxNumberInput(Show1wat);
- $('#wg_calcium').jqxNumberInput(Show1wat);
- $('#wg_magnesium').jqxNumberInput(Show1wat);
- $('#wg_sodium').jqxNumberInput(Show1wat);
- $('#wg_bicarbonate').jqxNumberInput(Show1wat);
- $('#wg_total_alkalinity').jqxNumberInput(Show1wat);
- $('#wg_chloride').jqxNumberInput(Show1wat);
- $('#wg_sulfate').jqxNumberInput(Show1wat);
- $('#wg_ph').jqxNumberInput(Show2wat);
- $('#wg_hardness').jqxNumberInput(Show1wat);
- $('#wg_ra').jqxNumberInput(Show1wat);
- // Water treated
- $('#wb_calcium').jqxTooltip({ content: 'De ideale hoeveelheid Calcium is tussen 40 en 150.'});
- $('#wb_calcium').jqxNumberInput(Show1wat);
- $('#wb_magnesium').jqxTooltip({ content: 'De ideale hoeveelheid Magnesium is tussen 5 en 40.'});
- $('#wb_magnesium').jqxNumberInput(Show1wat);
- $('#wb_sodium').jqxTooltip({ content: 'De ideale hoeveelheid Natrium is lager dan 150.'});
- $('#wb_sodium').jqxNumberInput(Show1wat);
- $('#wb_chloride').jqxTooltip({ content: 'De ideale hoeveelheid Chloride is tussen 50 en 150. Samen met Sulfaat minder dan 500.'});
- $('#wb_chloride').jqxNumberInput(Show1wat);
- $('#wb_sulfate').jqxTooltip({ content: 'De ideale hoeveelheid Sulfaat is tussen 50 en 400. Samen met Sulfaat minder dan 500.'});
- $('#wb_sulfate').jqxNumberInput(Show1wat);
- $('#wb_bicarbonate').jqxTooltip({ content: '0 tot 50 lichte bieren, 50 tot 150 amber bieren, 150 tot 250 donkere bieren.'});
- $('#wb_bicarbonate').jqxNumberInput(Show1wat);
- $('#wb_total_alkalinity').jqxNumberInput(Show1wat);
- $('#wb_ph').jqxNumberInput(Show2wat);
- $('#wb_hardness').jqxNumberInput(Show1wat);
- $('#wb_ra').jqxNumberInput(Show1wat);
- // Sparge water
- $('#sw_amount').jqxNumberInput(Show1wat);
- $('#sw_calcium').jqxNumberInput(Show1wat);
- $('#sw_magnesium').jqxNumberInput(Show1wat);
- $('#sw_sodium').jqxNumberInput(Show1wat);
- $('#sw_bicarbonate').jqxNumberInput(Show1wat);
- $('#sw_total_alkalinity').jqxNumberInput(Show1wat);
- $('#sw_chloride').jqxNumberInput(Show1wat);
- $('#sw_sulfate').jqxNumberInput(Show1wat);
- $('#sw_ph').jqxNumberInput(Show2wat);
- $('#sw_hardness').jqxNumberInput(Show1wat);
- $('#sw_ra').jqxNumberInput(Show1wat);
-
- // Water agents
- $('#wa_cacl2').jqxTooltip({ content: 'Voor het maken van een ander waterprofiel. Voegt calcium en chloride toe. Voor het verbeteren van zoetere bieren.'});
- $('#wa_cacl2').jqxNumberInput(Show2wat);
- $('#ss_cacl2').jqxNumberInput(Show2wat);
-
- $('#wa_caso4').jqxTooltip({
-  content: 'Gips. Voor het maken van een ander waterprofiel. Voegt calcium en sulfaat toe. Voor het verbeteren van bittere bieren.'
- });
- $('#wa_caso4').jqxNumberInput(Show2wat);
- $('#ss_caso4').jqxNumberInput(Show2wat);
-
- $('#wa_mgso4').jqxTooltip({ content: 'Epsom zout. Voor het maken van een ander waterprofiel. Voegt magnesium en sulfaat toe. Gebruik spaarzaam!'});
- $('#wa_mgso4').jqxNumberInput(Show2wat);
- $('#ss_mgso4').jqxNumberInput(Show2wat);
-
- $('#wa_nacl').jqxTooltip({
-  content: 'Keukenzout. Voor het maken van een ander waterprofiel. Voegt natrium en chloride toe. ' +
-  'Voor het accentueren van zoetheid. Bij hoge dosering wordt het bier ziltig.'
- });
- $('#wa_nacl').jqxNumberInput(Show2wat);
- $('#ss_nacl').jqxNumberInput(Show2wat);
-
- $('#wa_mgcl2').jqxTooltip({ content: 'Magnesiumchloride'});
- $('#wa_mgcl2').jqxNumberInput(Show2wat);
- $('#ss_mgcl2').jqxNumberInput(Show2wat);
-
- $('#wa_nahco3').jqxTooltip({ content: 'Baksoda'});
- $('#wa_caco3').jqxTooltip({ content: 'Kalk'});
- $('#wa_nahco3,#wa_caco3').jqxNumberInput(Show2wat);
-
- $('#mash_ph').jqxTooltip({ content: 'Maisch pH tussen 5.2 en 5.6. Gebruik 5.2 voor lichte en 5.5 voor donkere bieren.'});
- $('#mash_ph').jqxNumberInput(Show2dec);
-
- $('#calc_acid').jqxCheckBox({ theme: theme, width: 120, height: 23, disabled: true });
-
- $('#wa_acid_name').jqxInput({ theme: theme, width: 130, height: 23 });
- $('#wa_acid').jqxNumberInput(Show2dec);
- $('#wa_acid').jqxNumberInput({ symbol: ' ml', symbolPosition: 'right' });
- $('#wa_acid_perc').jqxNumberInput(Show0dec);
- $('#wa_acid_perc').jqxNumberInput({ symbol: '%', symbolPosition: 'right' });
-
- // Sparge water
- $('#sparge_ph').jqxNumberInput(Show2dec);
- $('#sparge_acid_amount').jqxNumberInput(Show2dec);
- $('#sparge_acid_amount').jqxNumberInput({ symbol: ' ml', symbolPosition: 'right' });
- $('#sparge_acid_type').jqxInput({ theme: theme, width: 130, height: 23 });
- $('#sparge_acid_perc').jqxNumberInput(Show0dec);
- $('#sparge_acid_perc').jqxNumberInput({ symbol: '%', symbolPosition: 'right' });
-
- // Tabs inside the popup window.
- $('#jqxTabs').jqxTabs({
-  theme: theme,
-  width: 1280,
-  height: 660,
-  autoHeight: false,
-  position: 'top'
- });
-
- // Button below
- $('#Terug').jqxButton({ template: 'primary', width: '80px', theme: theme });
- $('#Terug').bind('click', function() {
-  window.location.href = my_return;
- });
-
-});
-
--- a/www/js/rec_main.js	Fri Aug 05 10:44:59 2022 +0200
+++ b/www/js/rec_main.js	Fri Aug 05 10:53:56 2022 +0200
@@ -48,19 +48,6 @@
   source: dataAdapter,
   groupable: true,
   theme: theme,
-  showstatusbar: true,
-  renderstatusbar: function(statusbar) {
-   var addButton, container = $("<div style='overflow: hidden; position: relative; margin: 5px;'></div>");
-   addButton = $('<div style="float: right; margin-right: 15px;"><img style="position: relative; margin-top: 2px;" ' +
-     'src="images/add.png"/><span style="margin-left: 4px; position: relative; top: -3px;">Add</span></div>');
-   container.append(addButton);
-   statusbar.append(container);
-   addButton.jqxButton({ theme: theme, width: 100, height: 20 });
-   // add new recipe.
-   addButton.click(function(event) {
-    window.location.href = 'rec_new.php?return=rec_main.php';
-   });
-  },
   filterable: true,
   filtermode: 'excel',
   columns: [
@@ -76,7 +63,7 @@
     return 'Bekijk';
     }, buttonclick: function(row) {
      var datarecord = dataAdapter.records[row];
-     window.location.href = 'rec_edit.php?record=' + datarecord.record + '&return=rec_main.php';
+     window.location.href = 'rec_view.php?record=' + datarecord.record + '&return=rec_main.php';
     }
    }
   ],
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/www/js/rec_view.js	Fri Aug 05 10:53:56 2022 +0200
@@ -0,0 +1,2055 @@
+/*****************************************************************************
+ * Copyright (C) 2018-2022
+ *
+ * Michiel Broek <mbroek at mbse dot eu>
+ *
+ * This file is part of BMS
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * BrewCloud is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with ThermFerm; see the file COPYING.  If not, write to the Free
+ * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *****************************************************************************/
+
+ var psugar = 0,     // Percentage real sugars
+ pcara = 0,          // Percentage cara/crystal malts
+ svg = 77,           // Default attenuation
+ mashkg = 0,         // Malt in mash weight
+ mash_infuse = 0,
+ dataRecord = {},    // Main recipe record
+ hop_flavour = 0,
+ hop_aroma = 0,
+ preboil_sg = 0,
+ last_base = '',
+ last_acid = '',
+ Ka1 = 0.0000004445,
+ Ka2 = 0.0000000000468,
+ error_count = 0,
+ MMCa = 40.048,
+ MMMg = 24.305,
+ MMNa = 22.98976928,
+ MMCl = 35.453,
+ MMSO4 = 96.0626,
+ MMCO3 = 60.01684,
+ MMHCO3 = 61.01684,
+ MMCaSO4 = 172.171,
+ MMCaCl2 = 147.015,
+ MMCaCO3 = 100.087,
+ MMMgCl2 = 95.211,      /* Since 27-06-2021 */
+ MMMgSO4 = 246.475,
+ MMNaHCO3 = 84.007,
+ MMNa2CO3 = 105.996,
+ MMNaCl = 58.443,
+ MMCaOH2 = 74.06268,
+ SpecificHeatWater = 1.0,
+ SpecificHeatMalt = 0.399, //cal/g.°C
+ SlakingHeat = 10.318, //cal/g.°C
+ eq_tun_weight = 2.0, // 2 Kg pot
+ eq_tun_specific_heat = 0.110, // Stainless Steel
+ data_loaded = 0;
+
+function hopFlavourContribution(bt, vol, use, amount) {
+ var result;
+
+ if (use == 4 || use == 5) // Whirlpool or Dry-hop
+  return 0;
+ 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 (use == 4) { // Whirlpool
+   if (bt > 30)
+    bt = 30; // Max 30 minutes
+   result = 0.62 * bt / 30;
+ } 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;
+ }
+ return (result * amount * 1000) / vol;
+}
+
+
+function calcFermentables() {
+ console.log('calcFermentables()');
+ var i, row, rows, org, s = 0, d, x,
+ sug, alc, cw, color, scolor, fig,
+ 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
+ /* Init global variables */
+ psugar = 0;
+ pcara = 0;
+ mashkg = 0;
+
+ 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
+    mashtime += row.step_time;
+    mashtemp += row.step_time * row.step_temp;
+   }
+  }
+  mashtemp = mashtemp / mashtime;
+ }
+
+ 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 += 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 == 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;
+  }
+  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.
+  }
+ }
+ $('#ferm_lintner').val(Math.round(parseFloat(lintner / mashkg)));
+ to_100 = my_100;
+
+ // 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 before boil
+ preboil_sg = estimate_sg(sugarsm, parseFloat(dataRecord.boil_size));
+
+ // 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.boil_size / 3) * 100;
+ $('#perc_malts').jqxProgressBar('val', pmalts);
+ $('#perc_sugars').jqxProgressBar('val', psugar);
+ $('#perc_cara').jqxProgressBar('val', pcara);
+
+ // Calculate estimated svg.
+ svg = 0; // default.
+ 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.
+  }
+  // TODO: brett in secondary ??
+ }
+ 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);
+ 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 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 infusionVol(step_infused, step_mashkg, infuse_temp, step_temp, last_temp) {
+ var a = last_temp * (eq_tun_weight * eq_tun_specific_heat + step_infused * SpecificHeatWater + step_mashkg * SpecificHeatMalt);
+ var b = step_temp * (eq_tun_weight * eq_tun_specific_heat + step_infused * SpecificHeatWater + step_mashkg * SpecificHeatMalt);
+ var vol = Round(((b - a) / ((infuse_temp - step_temp) * SpecificHeatWater)), 2);
+ console.log('infusionVol(' + step_infused + ', ' + step_mashkg + ', ' + infuse_temp + ', ' + step_temp + ', ' + last_temp + '): ' + vol);
+ return vol;
+}
+
+
+function decoctionVol(step_volume, step_temp, prev_temp) {
+ var a = (eq_tun_weight * eq_tun_specific_heat + step_volume * SpecificHeatWater) * (step_temp - prev_temp);
+ var b = SpecificHeatWater * (99 - step_temp);
+ var vol = 0;
+ if (b > 0)
+  vol = Round(a / b, 6);
+ console.log('decoctionVol(' + step_volume + ', ' + step_temp + ', ' + prev_temp + '): ' + vol);
+ return vol;
+}
+
+
+function calcMash() {
+ var infused = 0, vol, i, j, n, a, b, row, rows, temp;
+ var lasttemp = 18.0;
+ var graintemp = 18.0;
+ var tuntemp = 18.0;
+
+ if ((rows = $('#mashGrid').jqxGrid('getrows')) && (mashkg > 0)) {
+  console.log('calcMash()');
+  for (i = 0; i < rows.length; i++) {
+   row = $('#mashGrid').jqxGrid('getrowdata', i);
+   if (row.step_type == 0) { // Infusion
+    if (i == 0) {
+      // First mash step, temperature from the mashtun and malt.
+      n = 20; // tun is preheated.
+      tuntemp = row.step_temp;
+      for (j = 0; j < n; j++) {
+       a = mashkg * graintemp * SpecificHeatMalt + eq_tun_weight * tuntemp * eq_tun_specific_heat;
+       b = row.step_temp * (eq_tun_weight * eq_tun_specific_heat + row.step_infuse_amount * SpecificHeatWater + mashkg * SpecificHeatMalt) - SlakingHeat * mashkg;
+       if (row.step_infuse_amount > 0) {
+        temp = (b - a) / (row.step_infuse_amount * SpecificHeatWater);
+       } else {
+        temp = 99;
+       }
+       tuntemp += (temp - tuntemp) / 2;
+       row.step_infuse_temp = Round(temp, 6);
+      }
+      console.log('init infuse temp: ' + row.step_infuse_temp);
+    } else {
+      // Calculate amount of infusion water.
+      row.step_infuse_amount = infusionVol(infused, mashkg, row.step_infuse_temp, row.step_temp, lasttemp);
+      //console.log('vol: ' + row.step_infuse_amount + ' temp: ' + row.step_infuse_temp);
+    }
+    infused += row.step_infuse_amount;
+   } else if (row.step_type == 1) { // Temperature
+     if (i > 0)
+      row.step_infuse_amount = 0;
+     row.step_infuse_temp = 0;
+   } else if (row.step_type == 2) { // Decoction
+     row.step_infuse_amount = decoctionVol(infused, row.step_temp, lasttemp);
+     row.step_infuse_temp = 99;
+   }
+    row.step_volume = infused;
+    //console.log(i + ' type: ' + row.step_type + ' volume: ' + row.step_infuse_amount + ' temp: ' + row.step_infuse_temp);
+    lasttemp = row.step_temp;
+    mashtime += row.step_time + row.ramp_time;
+    row.step_wg_ratio = Round(infused / mashkg, 6);
+    $('#mashGrid').jqxGrid('updaterow', i, row);
+  }
+ }
+}
+
+
+function GetBUGU() {
+ var gu = (dataRecord.est_og - 1) * 1000;
+ if (gu > 0)
+  return dataRecord.est_ibu / gu;
+ else
+  return 0.5;
+}
+
+
+function GetOptSO4Clratio() {
+ var BUGU = GetBUGU();
+ return (-1.2 * BUGU + 1.4);
+}
+
+
+
+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 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 BufferCapacity(di_ph, acid_to_ph_57, ebc, graintype) {
+ C1 = 0;
+ if ((di_ph != 5.7) && ((acid_to_ph_57 < - 0.1) || (acid_to_ph_57 > 0.1))) {
+  C1 = acid_to_ph_57 / (di_ph - 5.7);
+ } else {
+  // If the acid_to_ph_5.7 is unknown from the maltster, guess the required acid.
+  switch (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;
+  }
+ }
+ return C1;
+}
+
+
+function ProtonDeficit(pHZ) {
+ var C1, i, rows, row, Result = ZRA(pHZ) * parseFloat($('#wg_amount').jqxNumberInput('decimal'));
+ // proton deficit for the grist
+ if ((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
+    C1 = BufferCapacity(row.f_di_ph, row.f_acid_to_ph_57, row.f_color, row.f_graintype);
+    x = C1 * (pHZ - row.f_di_ph);   // AcidRequired(ZpH)
+    Result += x * row.f_amount;
+   }
+  }
+ } else {
+  error_count++;
+  if (error_count < 5)
+   console.log('ProtonDeficit(' + pHZ + ') invalid grist, return ' + Result);
+ }
+ 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);
+ }
+ pH = Round(pH, 6);
+ //console.log('MashpH() n: ' + n + ' pH: ' + pH);
+ return pH;
+}
+
+
+
+
+$(document).ready(function() {
+
+ var to_100 = false, // Fermentables adjust to 100%
+
+ fermentableRow = 0,
+ fermentableData = {},
+ hopRow = 0,
+ hopData = {},
+ miscRow = 0,
+ miscData = {},
+ yeastRow = 0,
+ yeastData = {},
+ mashRow = 0,
+ mashData = {},
+
+ url = 'includes/db_recipes.php',
+ // prepare the data
+ source = {
+  datatype: 'json',
+  cache: false,
+  datafields: [
+   { name: 'record', type: 'number' },
+   { name: 'uuid', type: 'string' },
+   { name: 'locked', type: 'int' },
+   { name: 'st_name', type: 'string' },
+   { name: 'st_letter', type: 'string' },
+   { name: 'st_guide', type: 'string' },
+   { name: 'st_type', type: 'int' },
+   { name: 'st_category', type: 'string' },
+   { name: 'st_category_number', type: 'int' },
+   { name: 'st_og_min', type: 'float' },
+   { name: 'st_og_max', type: 'float' },
+   { name: 'st_fg_min', type: 'float' },
+   { name: 'st_fg_max', type: 'float' },
+   { name: 'st_ibu_min', type: 'float' },
+   { name: 'st_ibu_max', type: 'float' },
+   { name: 'st_color_min', type: 'float' },
+   { name: 'st_color_max', type: 'float' },
+   { name: 'st_carb_min', type: 'float' },
+   { name: 'st_carb_max', type: 'float' },
+   { name: 'st_abv_min', type: 'float' },
+   { name: 'st_abv_max', type: 'float' },
+   { name: 'name', type: 'string' },
+   { name: 'notes', type: 'string' },
+   { name: 'type', type: 'int' },
+   { name: 'batch_size', type: 'float' },
+   { name: 'boil_size', type: 'float' },
+   { name: 'boil_time', type: 'float' },
+   { name: 'efficiency', type: 'float' },
+   { name: 'est_og', type: 'float' },
+   { name: 'est_fg', type: 'float' },
+   { name: 'est_abv', type: 'float' },
+   { name: 'est_color', type: 'float' },
+   { name: 'color_method', type: 'int' },
+   { name: 'est_ibu', type: 'float' },
+   { name: 'ibu_method', type: 'int' },
+   { name: 'est_carb', type: 'float' },
+   { name: 'sparge_temp', type: 'float' },
+   { name: 'sparge_ph', type: 'float' },
+   { name: 'sparge_volume', type: 'float' },
+   { name: 'sparge_source', type: 'int' },
+   { name: 'sparge_acid_type', type: 'int' },
+   { name: 'sparge_acid_perc', type: 'float' },
+   { name: 'sparge_acid_amount', type: 'float' },
+   { name: 'mash_ph', type: 'float' },
+   { name: 'mash_name', type: 'string' },
+   { name: 'calc_acid', type: 'int' },
+   { name: 'w1_name', type: 'string' },
+   { name: 'w1_amount', type: 'float' },
+   { name: 'w1_calcium', type: 'float' },
+   { name: 'w1_sulfate', type: 'float' },
+   { name: 'w1_chloride', type: 'float' },
+   { name: 'w1_sodium', type: 'float' },
+   { name: 'w1_magnesium', type: 'float' },
+   { name: 'w1_total_alkalinity', type: 'float' },
+   { name: 'w1_ph', type: 'float' },
+   { name: 'w1_cost', type: 'float' },
+   { name: 'w2_name', type: 'string' },
+   { name: 'w2_amount', type: 'float' },
+   { name: 'w2_calcium', type: 'float' },
+   { name: 'w2_sulfate', type: 'float' },
+   { name: 'w2_chloride', type: 'float' },
+   { name: 'w2_sodium', type: 'float' },
+   { name: 'w2_magnesium', type: 'float' },
+   { name: 'w2_total_alkalinity', type: 'float' },
+   { name: 'w2_ph', type: 'float' },
+   { name: 'w2_cost', type: 'float' },
+   { name: 'wg_amount', type: 'float' },
+   { name: 'wg_calcium', type: 'float' },
+   { name: 'wg_sulfate', type: 'float' },
+   { name: 'wg_chloride', type: 'float' },
+   { name: 'wg_sodium', type: 'float' },
+   { name: 'wg_magnesium', type: 'float' },
+   { name: 'wg_total_alkalinity', type: 'float' },
+   { name: 'wg_ph', type: 'float' },
+   { name: 'wb_calcium', type: 'float' },
+   { name: 'wb_sulfate', type: 'float' },
+   { name: 'wb_chloride', type: 'float' },
+   { name: 'wb_sodium', type: 'float' },
+   { name: 'wb_magnesium', type: 'float' },
+   { name: 'wb_total_alkalinity', type: 'float' },
+   { name: 'wb_ph', type: 'float' },
+   { name: 'wa_acid_name', type: 'int' },
+   { name: 'wa_acid_perc', type: 'int' },
+   { name: 'wa_base_name', type: 'int' },
+   { name: 'fermentables', type: 'string' },
+   { name: 'hops', type: 'string' },
+   { name: 'miscs', type: 'string' },
+   { name: 'yeasts', type: 'string' },
+   { name: 'mashs', type: 'string' }
+  ],
+  id: 'record',
+  url: url + '?record=' + my_record
+ },
+ // Load data and select one record.
+ dataAdapter = new $.jqx.dataAdapter(source, {
+  loadComplete: function() {
+   var records = dataAdapter.records;
+   dataRecord = records[0];
+   // Hidden record uuid
+   $('#name').val(dataRecord.name);
+   $('#notes').val(dataRecord.notes);
+   // Hidden record locked
+   $('#st_name').val(dataRecord.st_name);
+   $('#st_letter').val(dataRecord.st_letter);
+   $('#st_guide').val(dataRecord.st_guide);
+   $('#st_category').val(dataRecord.st_category);
+   $('#st_category_number').val(dataRecord.st_category_number);
+   $('#st_type').val(StyleTypeData[dataRecord.st_type].nl);
+   $('#type').val(RecipeTypeData[dataRecord.type].nl);
+   $('#batch_size').val(dataRecord.batch_size);
+   $('#boil_size').val(dataRecord.boil_size);
+   $('#boil_time').val(dataRecord.boil_time);
+   $('#efficiency').val(dataRecord.efficiency);
+   $('#est_og').val(dataRecord.est_og);
+   $('#est_og2').val(dataRecord.est_og);
+   $('#st_og_min').val(dataRecord.st_og_min);
+   $('#st_og_max').val(dataRecord.st_og_max);
+   $('#est_fg').val(dataRecord.est_fg);
+   $('#est_fg2').val(dataRecord.est_fg);
+   $('#st_fg_min').val(dataRecord.st_fg_min);
+   $('#st_fg_max').val(dataRecord.st_fg_max);
+   $('#est_fg').val(dataRecord.est_fg);
+   $('#est_fg2').val(dataRecord.est_fg);
+   $('#st_fg_min').val(dataRecord.st_fg_min);
+   $('#st_fg_max').val(dataRecord.st_fg_max);
+   $('#est_color').val(dataRecord.est_color);
+   $('#est_color2').val(dataRecord.est_color);
+   $('#est_abv').val(dataRecord.est_abv);
+   $('#est_abv2').val(dataRecord.est_abv);
+   $('#st_abv_min').val(dataRecord.st_abv_min);
+   $('#st_abv_max').val(dataRecord.st_abv_max);
+   $('#st_color_min').val(dataRecord.st_color_min);
+   $('#st_color_max').val(dataRecord.st_color_max);
+   $('#color_method').val(ColorMethodData[dataRecord.color_method].nl);
+   $('#est_ibu').val(dataRecord.est_ibu);
+   $('#est_ibu2').val(dataRecord.est_ibu);
+   $('#st_ibu_min').val(dataRecord.st_ibu_min);
+   $('#st_ibu_max').val(dataRecord.st_ibu_max);
+   $('#ibu_method').val(IBUmethodData[dataRecord.ibu_method].nl);
+   $('#est_carb').val(dataRecord.est_carb);
+   $('#st_carb_min').val(dataRecord.st_carb_min);
+   $('#st_carb_max').val(dataRecord.st_carb_max);
+   $('#mash_name').val(dataRecord.mash_name);
+   $('#mash_ph').val(dataRecord.mash_ph);
+   // Hidden record sparge_temp
+   $('#sparge_ph').val(dataRecord.sparge_ph);
+   $('#sw_amount').val(dataRecord.sparge_volume);
+   // Hidden record sparge_source
+   $('#sparge_acid_type').val(AcidTypeData[dataRecord.sparge_acid_type].nl);
+   $('#sparge_acid_perc').val(dataRecord.sparge_acid_perc);
+   $('#sparge_acid_amount').val(dataRecord.sparge_acid_amount * 1000);
+   $('#calc_acid').val(dataRecord.calc_acid);
+   $('#w1_name').val(dataRecord.w1_name);
+   $('#w1_amount').val(dataRecord.w1_amount);
+   $('#w1_calcium').val(dataRecord.w1_calcium);
+   $('#w1_sulfate').val(dataRecord.w1_sulfate);
+   $('#w1_chloride').val(dataRecord.w1_chloride);
+   $('#w1_sodium').val(dataRecord.w1_sodium);
+   $('#w1_magnesium').val(dataRecord.w1_magnesium);
+   $('#w1_total_alkalinity').val(dataRecord.w1_total_alkalinity);
+   $('#w1_ph').val(dataRecord.w1_ph);
+   $('#w1_bicarbonate').val(Bicarbonate(dataRecord.w1_total_alkalinity, dataRecord.w1_ph));
+   $('#w1_cost').val(dataRecord.w1_cost);
+   $('#w2_name').val(dataRecord.w2_name);
+   $('#w2_amount').val(dataRecord.w2_amount);
+   $('#w2_calcium').val(dataRecord.w2_calcium);
+   $('#w2_sulfate').val(dataRecord.w2_sulfate);
+   $('#w2_chloride').val(dataRecord.w2_chloride);
+   $('#w2_sodium').val(dataRecord.w2_sodium);
+   $('#w2_magnesium').val(dataRecord.w2_magnesium);
+   $('#w2_total_alkalinity').val(dataRecord.w2_total_alkalinity);
+   $('#w2_ph').val(dataRecord.w2_ph);
+   $('#w2_bicarbonate').val(Bicarbonate(dataRecord.w2_total_alkalinity, dataRecord.w2_ph));
+   $('#w2_cost').val(dataRecord.w2_cost);
+   $('#wg_amount').val(dataRecord.wg_amount);
+   $('#wg_calcium').val(dataRecord.wg_calcium);
+   $('#wg_sulfate').val(dataRecord.wg_sulfate);
+   $('#wg_chloride').val(dataRecord.wg_chloride);
+   $('#wg_sodium').val(dataRecord.wg_sodium);
+   $('#wg_magnesium').val(dataRecord.wg_magnesium);
+   $('#wg_total_alkalinity').val(dataRecord.wg_total_alkalinity);
+   $('#wg_ph').val(dataRecord.wg_ph);
+   $('#wb_calcium').val(dataRecord.wb_calcium);
+   $('#wb_sulfate').val(dataRecord.wb_sulfate);
+   $('#wb_chloride').val(dataRecord.wb_chloride);
+   $('#wb_sodium').val(dataRecord.wb_sodium);
+   $('#wb_magnesium').val(dataRecord.wb_magnesium);
+   $('#wb_total_alkalinity').val(dataRecord.wb_total_alkalinity);
+   $('#wb_ph').val(dataRecord.wb_ph);
+   $('#wa_acid_name').val(AcidTypeData[dataRecord.wa_acid_name].nl);
+   $('#wa_acid_perc').val(dataRecord.wa_acid_perc);
+   editFermentable(dataRecord);
+   editHop(dataRecord);
+   editMisc(dataRecord);
+   editYeast(dataRecord);
+   editMash(dataRecord);
+   $('#jqxTabs').jqxTabs('next');
+   data_loaded = 1;
+  },
+  loadError: function(jqXHR, status, error) {},
+  beforeLoadComplete: function(records) { $('#jqxLoader').jqxLoader('open'); }
+ }),
+
+ // Inline fermentables editor
+ editFermentable = function(data) {
+  var fermentableSource = {
+   localdata: data.fermentables,
+   datafields: [
+    { name: 'f_name', type: 'string' },
+    { name: 'f_origin', type: 'string' },
+    { name: 'f_supplier', type: 'string' },
+    { name: 'f_amount', type: 'float' },
+    { name: 'f_cost', type: 'float' },
+    { name: 'f_type', type: 'int' },
+    { name: 'f_yield', type: 'float' },
+    { name: 'f_color', type: 'float' },
+    { name: 'f_coarse_fine_diff', type: 'float' },
+    { name: 'f_moisture', type: 'float' },
+    { name: 'f_diastatic_power', type: 'float' },
+    { name: 'f_protein', type: 'float' },
+    { name: 'f_max_in_batch', type: 'float' },
+    { name: 'f_graintype', type: 'int' },
+    { name: 'f_added', type: 'int' },
+    { name: 'f_dissolved_protein', type: 'float' },
+    { name: 'f_recommend_mash', type: 'int' },
+    { name: 'f_add_after_boil', type: 'int' },
+    { name: 'f_adjust_to_total_100', type: 'int' },
+    { name: 'f_percentage', type: 'float' },
+    { name: 'f_di_ph', type: 'float' },
+    { name: 'f_acid_to_ph_57', type: 'float' },
+    { name: 'f_inventory', type: 'float' },
+    { name: 'f_avail', type: 'int' }
+   ],
+  },
+  fermentableAdapter = new $.jqx.dataAdapter(fermentableSource);
+
+  $('#fermentableGrid').jqxGrid({
+   width: 1240,
+   height: 470,
+   source: fermentableAdapter,
+   theme: theme,
+   editable: false,
+   ready: function() {
+    calcFermentables();
+    $('#jqxTabs').jqxTabs('next');
+   },
+   columns: [
+    { text: 'Vergistbaar ingredi&euml;nt', datafield: 'f_name' },
+    { text: 'Leverancier', datafield: 'f_supplier', width: 180 },
+    { text: 'Kleur', datafield: 'f_color', width: 90, align: 'right',
+     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
+      return '<span style="margin: 4px; margin-top: 6px; float: right;">' + dataAdapter.formatNumber(value, 'f0') + ' EBC</span>';
+     }
+    },
+    { text: 'Type', width: 100, datafield: 'f_type',
+     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
+      return '<span style="margin: 3px; margin-top: 6px; float: left;">' + FermentableTypeData[value].nl + '</span>';
+     }
+    },
+    { text: 'Moment', width: 110, datafield: 'f_added',
+     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
+      return '<span style="margin: 3px; margin-top: 6px; float: left;">' + AddedData[value].nl + '</span>';
+     }
+    },
+    { text: 'Maxinbatch', datafield: 'f_max_in_batch', hidden: true },
+    { text: 'Opbrengst', editable: false, datafield: 'f_yield', width: 90, align: 'right', cellsalign: 'right', cellsformat: 'p1' },
+    { text: 'Gewicht Kg', datafield: 'f_amount', width: 120, align: 'right', cellsalign: 'right', cellsformat: 'f3' },
+    { text: 'Procent', datafield: 'f_percentage', width: 90, align: 'right',
+     cellsrenderer: function(row, columnfield, value, defaulthtml, columnproperties, rowdata) {
+      var color = '#ffffff';
+      if (value > rowdata.f_max_in_batch)
+       color = '#ff4040';
+      return '<span style="margin: 4px; margin-top: 6px; float: right; color: ' +
+             color + ';">' + fermentableAdapter.formatNumber(value, 'p1') + '</span>';
+     }
+    },
+    { text: '100%', align: 'center', datafield: 'f_adjust_to_total_100', columntype: 'checkbox', width: 70 }
+   ]
+  });
+ };
+
+ // Inline hops editor
+ var editHop = function(data) {
+  var hopSource = {
+   localdata: data.hops,
+   datafields: [
+    { name: 'h_name', type: 'string' },
+    { name: 'h_origin', type: 'string' },
+    { name: 'h_amount', type: 'float' },
+    { name: 'h_cost', type: 'float' },
+    { name: 'h_type', type: 'int' },
+    { name: 'h_form', type: 'int' },
+    { name: 'h_useat', type: 'int' },
+    { name: 'h_time', type: 'float' },
+    { name: 'h_alpha', type: 'float' },
+    { name: 'h_beta', type: 'float' },
+    { name: 'h_hsi', type: 'float' },
+    { name: 'h_humulene', type: 'float' },
+    { name: 'h_caryophyllene', type: 'float' },
+    { name: 'h_cohumulone', type: 'float' },
+    { name: 'h_myrcene', type: 'float' },
+    { name: 'h_total_oil', type: 'float' },
+    { name: 'h_inventory', type: 'float' },
+    { name: 'h_avail', type: 'int' }
+   ],
+  },
+  hopAdapter = new $.jqx.dataAdapter(hopSource);
+
+  $('#hopGrid').jqxGrid({
+   width: 1240,
+   height: 560,
+   source: hopAdapter,
+   theme: theme,
+   editable: false,
+   ready: function() { $('#jqxTabs').jqxTabs('next'); },
+   columns: [
+    { text: 'Hop', datafield: 'h_name' },
+    { text: 'Origin', width: 180, datafield: 'h_origin' },
+    { text: 'Type', width: 90, datafield: 'h_type',
+     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
+      return '<span style="margin: 4px; margin-top: 6px; float: left;">' + HopTypeData[value].nl + '</span>';
+     }
+    },
+    { text: 'Vorm', width: 110, datafield: 'h_form',
+     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
+      return '<span style="margin: 4px; margin-top: 6px; float: left;">' + HopFormData[value].nl + '</span>';
+     }
+    },
+    { text: 'Alpha', datafield: 'h_alpha', width: 80, align: 'right', cellsalign: 'right', cellsformat: 'p1' },
+    { text: 'Gebruik', width: 110, datafield: 'h_useat',
+     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
+      return '<span style="margin: 4px; margin-top: 6px; float: left;">' + HopUseData[value].nl + '</span>';
+     }
+    },
+    { text: 'Tijdsduur', datafield: 'h_time', width: 90, align: 'right',
+     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
+      var duration = '';
+      if ((rowdata.h_useat == 2) || (rowdata.h_useat == 4))   // Boil, Whirlpool
+       duration = dataAdapter.formatNumber(value, 'f0') + ' min.';
+      else if (rowdata.h_useat == 5)       // Dry hop
+       duration = dataAdapter.formatNumber(value / 1440, 'f0') + ' dagen';
+      return '<span style="margin: 4px; margin-top: 6px; float: right;">' + duration + '</span>';
+     }
+    },
+    { text: 'IBU', datafield: 'ibu', width: 80, align: 'right',
+     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
+      var ibu = toIBU(rowdata.h_useat, rowdata.h_form, preboil_sg, parseFloat(dataRecord.batch_size),
+                      parseFloat(rowdata.h_amount), parseFloat(rowdata.h_time),
+                      parseFloat(rowdata.h_alpha), dataRecord.ibu_method, 0, parseFloat(rowdata.h_time), 0);
+      return '<span style="margin: 4px; margin-top: 6px; float: right;">' + dataAdapter.formatNumber(ibu, 'f1') + '</span>';
+     }
+    },
+    { text: 'Gewicht', datafield: 'h_amount', width: 110, align: 'right',
+     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
+      var amount = dataAdapter.formatNumber(value, 'f1') + ' kg';
+      if (value < 1)
+       amount = dataAdapter.formatNumber(value * 1000, 'f1') + ' gr';
+      return '<span style="margin: 4px; margin-top: 6px; float: right;">' + amount + '</span>';
+     }
+    }
+   ]
+  });
+ };
+
+ // Inline miscs editor
+ var editMisc = function(data) {
+  var miscSource = {
+   localdata: data.miscs,
+   datafields: [
+    { name: 'm_name', type: 'string' },
+    { name: 'm_amount', type: 'float' },
+    { name: 'm_cost', type: 'float' },
+    { name: 'm_type', type: 'int' },
+    { name: 'm_use_use', type: 'int' },
+    { name: 'm_time', type: 'float' },
+    { name: 'm_amount_is_weight', type: 'int' },
+    { name: 'm_inventory', type: 'float' },
+    { name: 'm_avail', type: 'int' }
+   ],
+  },
+  miscAdapter = new $.jqx.dataAdapter(miscSource, {
+   beforeLoadComplete: function(records) {
+    var i, row, data = new Array();
+    for (i = 0; i < records.length; i++) {
+     row = records[i];
+     data.push(row);
+     // Initial set water agent values.
+     if (row.m_use_use == 1) {	// Mash
+      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 'MgCl2':
+        $('#wa_mgcl2').val(row.m_amount * 1000);
+        break;
+       case 'NaHCO3':
+        $('#wa_nahco3').val(row.m_amount * 1000);
+        break;
+       case 'CaCO3':
+        $('#wa_caco3').val(row.m_amount * 1000);
+        break;
+       case 'Melkzuur':
+        $('#wa_acid_name').val(AcidTypeData[0].nl);
+        $('#wa_acid').val(row.m_amount * 1000);
+        $('#wa_acid_perc').val(AcidTypeData[0].AcidPrc);
+        last_acid = 'Melkzuur';
+        break;
+       case 'Zoutzuur':
+        $('#wa_acid_name').val(AcidTypeData[1].nl);
+        $('#wa_acid').val(row.m_amount * 1000);
+        $('#wa_acid_perc').val(AcidTypeData[1].AcidPrc);
+        last_acid = 'Zoutzuur';
+        break;
+       case 'Fosforzuur':
+        $('#wa_acid_name').val(AcidTypeData[2].nl);
+        $('#wa_acid').val(row.m_amount * 1000);
+        $('#wa_acid_perc').val(AcidTypeData[2].AcidPrc);
+        last_acid = 'Fosforzuur';
+        break;
+       case 'Zwavelzuur':
+        $('#wa_acid_name').val(AcidTypeData[3].nl);
+        $('#wa_acid').val(row.m_amount * 1000);
+        $('#wa_acid_perc').val(AcidTypeData[3].AcidPrc);
+        last_acid = 'Zwavelzuur';
+        break;
+      }
+     }
+     if (row.m_use_use == 6) {	// Sparge
+      switch (row.m_name) {
+       case 'CaCl2':
+        $('#ss_cacl2').val(row.m_amount * 1000);
+        break;
+       case 'CaSO4':
+        $('#ss_caso4').val(row.m_amount * 1000);
+        break;
+       case 'MgSO4':
+        $('#ss_mgso4').val(row.m_amount * 1000);
+        break;
+       case 'NaCl':
+        $('#ss_nacl').val(row.m_amount * 1000);
+        break;
+       case 'MgCl2':
+        $('#ss_mgcl2').val(row.m_amount * 1000);
+        break;
+       case 'Melkzuur':
+//       $('#wa_acid_name').val(0);
+//       $('#wa_acid').val(row.m_amount * 1000);
+//       $('#wa_acid_perc').val(AcidTypeData[0].AcidPrc); // TODO: this ignores changed percentages.
+//       last_acid = 'Melkzuur';
+        break;
+       case 'Zoutzuur':
+ //      $('#wa_acid_name').val(1);
+//       $('#wa_acid').val(row.m_amount * 1000);
+//       $('#wa_acid_perc').val(AcidTypeData[1].AcidPrc);
+//       last_acid = 'Zoutzuur';
+        break;
+       case 'Fosforzuur':
+//       $('#wa_acid_name').val(2);
+//       $('#wa_acid').val(row.m_amount * 1000);
+//       $('#wa_acid_perc').val(AcidTypeData[2].AcidPrc);
+//       last_acid = 'Fosforzuur';
+        break;
+       case 'Zwavelzuur':
+//       $('#wa_acid_name').val(3);
+//       $('#wa_acid').val(row.m_amount * 1000);
+//       $('#wa_acid_perc').val(AcidTypeData[3].AcidPrc);
+//       last_acid = 'Zwavelzuur';
+        break;
+      }
+     }
+    }
+    return data;
+   },
+   loadError: function(jqXHR, status, error) {}
+  });
+  $('#miscGrid').jqxGrid({
+   width: 1240,
+   height: 575,
+   source: miscAdapter,
+   theme: theme,
+   editable: false,
+   ready: function() {
+    $('#jqxTabs').jqxTabs('next');
+   },
+   columns: [
+    { text: 'Ingredient', datafield: 'm_name' },
+    { text: 'Type', width: 140, datafield: 'm_type',
+     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
+      return '<span style="margin: 3px; margin-top: 6px; float: left;">' + MiscTypeData[value].nl + '</span>';
+     }
+    },
+    { text: 'Gebruik', width: 140, datafield: 'm_use_use',
+     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
+      return '<span style="margin: 3px; margin-top: 6px; float: left;">' + MiscUseData[value].nl + '</span>';
+     }
+    },
+    { text: 'Tijd', datafield: 'm_time', width: 140, align: 'right',
+     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
+      var duration = '';
+      if (rowdata.m_use_use == 2)     // Boil
+       duration = dataAdapter.formatNumber(value, 'f0') + ' minuten';
+      else if ((rowdata.m_use_use == 3) || (rowdata.m_use_use == 4))  // Primary or Secondary
+       duration = dataAdapter.formatNumber(value / 1440, 'f0') + ' dagen';
+      return '<span style="margin: 4px; margin-top: 6px; float: right;">' + duration + '</span>';
+     }
+    },
+    { text: 'Hoeveel', datafield: 'm_amount', width: 110, align: 'right',
+     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
+      var vstr = rowdata.m_amount_is_weight ? 'gr' : 'ml';
+      return '<span style="margin: 4px; margin-top: 6px; float: right;">' +
+             dataAdapter.formatNumber(value * 1000, 'f2') + ' ' + vstr + '</span>';
+     }
+    }
+   ]
+  });
+ };
+
+ // Inline yeasts editor
+ var editYeast = function(data) {
+  var yeastSource = {
+   localdata: data.yeasts,
+   datafields: [
+    { name: 'y_name', type: 'string' },
+    { name: 'y_laboratory', type: 'string' },
+    { name: 'y_product_id', type: 'string' },
+    { name: 'y_amount', type: 'float' },
+    { name: 'y_cost', type: 'float' },
+    { name: 'y_type', type: 'int' },
+    { name: 'y_form', type: 'int' },
+    { name: 'y_flocculation', type: 'int' },
+    { name: 'y_min_temperature', type: 'float' },
+    { name: 'y_max_temperature', type: 'float' },
+    { name: 'y_attenuation', type: 'float' },
+    { name: 'y_use', type: 'int' },
+    { name: 'y_cells', type: 'float' },
+    { name: 'y_tolerance', type: 'float' },
+    { name: 'y_inventory', type: 'float' },
+    { name: 'y_sta1', type: 'int' },
+    { name: 'y_bacteria', type: 'int' },
+    { name: 'y_harvest_top', type: 'int' },
+    { name: 'y_harvest_time', type: 'int' },
+    { name: 'y_pitch_temperature', type: 'float' },
+    { name: 'y_pofpos', type: 'int' },
+    { name: 'y_zymocide', type: 'int' },
+    { name: 'y_gr_hl_lo', type: 'int' },
+    { name: 'y_sg_lo', type: 'float' },
+    { name: 'y_gr_hl_hi', type: 'int' },
+    { name: 'y_sg_hi', type: 'float' },
+    { name: 'y_avail', type: 'int' }
+   ],
+  },
+  yeastAdapter = new $.jqx.dataAdapter(yeastSource);
+
+  $('#yeastGrid').jqxGrid({
+   width: 1240,
+   height: 350,
+   source: yeastAdapter,
+   theme: theme,
+   editable: false,
+   ready: function() {
+    calcFermentables();
+    $('#jqxTabs').jqxTabs('next');
+   },
+   columns: [
+    { text: 'Gist', datafield: 'y_name' },
+    { text: 'Laboratorium', width: 150, datafield: 'y_laboratory' },
+    { text: 'Code', width: 90, datafield: 'y_product_id' },
+    { text: 'Soort', width: 100, datafield: 'y_form',
+     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
+      return '<span style="margin: 4px; margin-top: 6px; float: left;">' + YeastFormData[value].nl + '</span>';
+     }
+    },
+    { text: 'Min. &deg;C', width: 70, align: 'right', cellsalign: 'right', datafield: 'y_min_temperature' },
+    { text: 'Max. &deg;C', width: 70, align: 'right', cellsalign: 'right', datafield: 'y_max_temperature' },
+    { text: 'Tol. %', width: 60, align: 'right', cellsalign: 'right', datafield: 'y_tolerance',
+     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
+      var amount = '', color = '#ffffff';
+      if (value > 0) {
+       amount = dataAdapter.formatNumber(value, 'f1');
+       if (dataRecord.est_abv > value)
+        color = '#ff4040';
+      }
+      return '<span style="margin: 4px; margin-top: 6px; float: right; color: ' + color + ';">' + amount + '</span>';
+     }
+    },
+    { text: 'Attn. %', width: 70, align: 'right', cellsalign: 'right', datafield: 'y_attenuation', cellsformat: 'f1' },
+    { text: 'Voor', width: 120, datafield: 'y_use',
+     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
+      return '<span style="margin: 4px; margin-top: 6px; float: left;">' + YeastUseData[value].nl + '</span>';
+     }
+    },
+    { text: 'Hoeveel', datafield: 'y_amount', width: 90, align: 'right',
+     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
+      var amount = dataAdapter.formatNumber(value * 1000, 'f0') + ' ml';
+      if (rowdata.y_form == 0)        // Liquid
+       amount = dataAdapter.formatNumber(value, 'f0') + ' pk';
+      else if (rowdata.y_form == 1)   // Dry
+       amount = dataAdapter.formatNumber(value * 1000, 'f1') + ' gr';
+      return '<span style="margin: 4px; margin-top: 6px; float: right;">' + amount + '</span>';
+     }
+    }
+   ]
+  });
+ };
+
+ // inline mash editor
+ var editMash = function(data) {
+  var mashSource = {
+   localdata: data.mashs,
+   datafields: [
+    { name: 'step_name', type: 'string' },
+    { name: 'step_type', type: 'int' },
+    { name: 'step_volume', type: 'float' },
+    { name: 'step_infuse_amount', type: 'float' },
+    { name: 'step_infuse_temp', type: 'float' },
+    { name: 'step_temp', type: 'float' },
+    { name: 'step_time', type: 'float' },
+    { name: 'step_wg_ratio', type: 'float' },
+    { name: 'ramp_time', type: 'float' },
+    { name: 'end_temp', type: 'float' }
+   ],
+  },
+  mashAdapter = new $.jqx.dataAdapter(mashSource, {
+   beforeLoadComplete: function(records) {
+    mash_infuse = 0;
+    var row, i, 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_wg_ratio = 0; // Init this field.
+     data.push(row);
+    }
+   },
+  });
+  $('#mashGrid').jqxGrid({
+   width: 1240,
+   height: 400,
+   source: mashAdapter,
+   theme: theme,
+   editable: false,
+   ready: function() {
+    calcFermentables();
+    calcInit();
+    calcMash();
+    $('#jqxLoader').jqxLoader('close');
+    $('#jqxTabs').jqxTabs('first');
+   },
+   columns: [
+    { text: 'Stap naam', datafield: 'step_name' },
+    { text: 'Stap type', datafield: 'step_type', width: 175,
+     cellsrenderer: function(index, datafield, value, defaultvalue, column, rowdata) {
+      return '<div style="margin: 4px;">' + MashStepTypeData[value].nl + '</div>';
+     }
+    },
+    { text: 'Start &deg;C', datafield: 'step_temp', width: 90, align: 'right', cellsalign: 'right', cellsformat: 'f1' },
+    { text: 'Eind &deg;C', datafield: 'end_temp', width: 90, align: 'right', cellsalign: 'right', cellsformat: 'f1' },
+    { text: 'Rust min.', datafield: 'step_time', width: 90, align: 'right', cellsalign: 'right' },
+    { text: 'Stap min.', datafield: 'ramp_time', width: 90, align: 'right', cellsalign: 'right' },
+    { text: 'Inf/dec L.', datafield: 'step_infuse_amount', width: 90, align: 'right',
+      cellsrenderer: function(row, columnfield, value, defaulthtml, columnproperties, rowdata) {
+       if (rowdata.step_type == 1)
+        return '<span></span>';
+       return '<span style="margin: 4px; margin-top: 6px; float: right;">' + dataAdapter.formatNumber(value, 'f1') + '</span>';
+      }
+    },
+    { text: 'Inf/dec &deg;C', datafield: 'step_infuse_temp', width: 90, align: 'right',
+      cellsrenderer: function(row, columnfield, value, defaulthtml, columnproperties, rowdata) {
+       if (rowdata.step_type == 1)
+        return '<span></span>';
+       return '<span style="margin: 4px; margin-top: 6px; float: right;">' + dataAdapter.formatNumber(value, 'f2') + '</span>';
+      }
+    },
+    { text: 'L/Kg.', datafield: 'step_wg_ratio', width: 90, align: 'right',
+      cellsrenderer: function(row, columnfield, value, defaulthtml, columnproperties, rowdata) {
+       var color = '#ffffff';
+       if (value < 2.0 || value > 6.0)
+        color = '#ff4040';
+       return '<span style="margin: 4px; margin-top: 6px; float: right; color: ' + color + ';">' + dataAdapter.formatNumber(value, 'f2') + '</span>';
+      }
+    }
+   ]
+  });
+ };
+
+
+ /*
+  * 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 recept ...',
+  theme: theme
+ });
+
+ function setWaterAgent(name, amount) {
+
+  var record, records, miscs, i, id, row, found = false, 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() {
+      records = miscs.records;
+      for (i = 0; i < records.length; i++) {
+       record = records[i];
+       if (record.name == name) {
+        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;
+   }
+  }
+ }
+
+
+ // Procedure TFrmWaterAdjustment.CalcWater2;
+ function calcWater() {
+
+  if (! data_loaded) {
+   console.log('calcWater(): failsave');
+   return;
+  }
+
+  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,
+  r1d, r2d, f1d, f2d, f3d,
+  deltapH, deltapd, pd, n,
+  Res;
+
+  if (dataRecord.w1_name == '') {
+   return;
+  }
+
+  $('#w1_hardness').val(Hardness(dataRecord.w1_calcium, dataRecord.w1_magnesium));
+  $('#w1_ra').val(ResidualAlkalinity(dataRecord.w1_total_alkalinity, dataRecord.w1_calcium, dataRecord.w1_magnesium));
+
+  // 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);
+   $('#w2_hardness').val(Hardness(dataRecord.w2_calcium, dataRecord.w2_magnesium));
+   $('#w2_ra').val(ResidualAlkalinity(dataRecord.w2_total_alkalinity, dataRecord.w2_calcium, dataRecord.w2_magnesium));
+  } 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;
+  }
+  var bicarbonate = Bicarbonate(total_alkalinity, ph);
+
+  /* Save mixed water ions for later */
+  var wg_calcium = calcium;
+  var wg_sodium = sodium;
+  var wg_total_alkalinity = total_alkalinity;
+  var wg_chloride = chloride;
+  var wg_sulfate = sulfate;
+  var wg_bicarbonate = bicarbonate;
+
+  dataRecord.wg_amount = liters;
+  dataRecord.wg_ph = ph;
+
+  $('#wg_amount').val(liters);
+  $('#wg_calcium').val(Round(calcium, 1));
+  $('#wg_magnesium').val(Round(magnesium, 1));
+  $('#wg_sodium').val(Round(sodium, 1));
+  $('#wg_bicarbonate').val(Round(bicarbonate, 1));
+  $('#wg_total_alkalinity').val(Round(total_alkalinity, 1));
+  $('#wg_chloride').val(Round(chloride, 1));
+  $('#wg_sulfate').val(Round(sulfate, 1));
+  $('#wg_ph').val(Round(ph, 2));
+  $('#wg_hardness').val(Round(Hardness(calcium, magnesium), 1));
+  $('#wg_ra').val(Round(ResidualAlkalinity(total_alkalinity, calcium, magnesium), 1));
+
+  var mash_ph = Round(MashpH(), 3);
+  console.log('Distilled water mash pH: ' + mash_ph);
+
+  /* Calculate Salt additions */
+  if (liters > 0) {
+   calcium += (parseFloat($('#wa_cacl2').jqxNumberInput('decimal')) * MMCa / MMCaCl2 * 1000 +
+    parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMCa / MMCaSO4 * 1000 +
+    parseFloat($('#wa_caco3').jqxNumberInput('decimal')) * MMCa / MMCaCO3 * 1000) / liters;
+   magnesium += (parseFloat($('#wa_mgso4').jqxNumberInput('decimal')) * MMMg / MMMgSO4 * 1000 +
+    parseFloat($('#wa_mgcl2').jqxNumberInput('decimal')) * MMMg / MMMgCl2 * 1000) / liters;
+   sodium += (parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMNa / MMNaCl * 1000 +
+    parseFloat($('#wa_nahco3').jqxNumberInput('decimal')) * MMNa / MMNaHCO3 * 1000) / liters;
+   sulfate += (parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMSO4 / MMCaSO4 * 1000 +
+    parseFloat($('#wa_mgso4').jqxNumberInput('decimal')) * MMSO4 / MMMgSO4 * 1000) / liters;
+   chloride += (2 * parseFloat($('#wa_cacl2').jqxNumberInput('decimal')) * MMCl / MMCaCl2 * 1000 +
+    parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMCl / MMNaCl * 1000 +
+    parseFloat($('#wa_mgcl2').jqxNumberInput('decimal')) * MMCl / MMMgCl2 * 1000) / liters;
+   bicarbonate += (parseFloat($('#wa_nahco3').jqxNumberInput('decimal')) * MMHCO3 / MMNaHCO3 * 1000 +
+    parseFloat($('#wa_caco3').jqxNumberInput('decimal')) / 3 * MMHCO3 / MMCaCO3 * 1000) / liters;
+  }
+
+  if (dataRecord.wa_acid_name < 0 || dataRecord,wa_acid_name >= AcidTypeData.length) {
+   $('#wa_acid_name').val(0);
+   dataRecord.wa_acid_name = 0;
+   dataRecord.wa_acid_perc = AcidTypeData[0].AcidPrc;
+   $('#wa_acid_perc').val(AcidTypeData[0].AcidPrc);
+  }
+  if (last_acid == '')
+   last_acid = AcidTypeData[dataRecord.wa_acid_name].nl;
+
+  if (parseFloat(dataRecord.wa_acid_perc) == 0) {
+   dataRecord.wa_acid_perc = AcidTypeData[AT].AcidPrc;
+   $('#wa_acid_perc').val(AcidTypeData[AT].AcidPrc);
+  }
+
+  AT = dataRecord.wa_acid_name;
+
+  /* Note that the next calculations do not correct the pH change by the added salts.
+     This pH change is at most 0.1 pH and is a minor difference in Acid amount. */
+
+  if (dataRecord.calc_acid) {
+   $('.c_mashph').show();
+   /* Auto calculate pH */
+   TpH = parseFloat(dataRecord.mash_ph);
+   protonDeficit = ProtonDeficit(TpH);
+   console.log('calc_acid tgt: ' + TpH + ' protonDeficit: ' + protonDeficit);
+   if (protonDeficit > 0) { // Add acid
+    frac = CalcFrac(TpH, AcidTypeData[AT].pK1, AcidTypeData[AT].pK2, AcidTypeData[AT].pK3);
+    Acid = protonDeficit / frac;
+    Acid *= AcidTypeData[AT].MolWt; // mg
+    Acidmg = Acid;
+    var RealSG = Round(((AcidTypeData[AT].AcidSG - 1000) * (parseFloat(dataRecord.wa_acid_perc) / 100)) + 1000, 2);
+    Acid /= RealSG;
+    Acid /= AcidTypeData[AT].AcidPrc / 100;
+    Acid = Round(Acid, 2);
+    console.log('Mash auto Acid final ml: ' + Acid);
+    $('#wa_acid').val(Acid);
+    setWaterAgent(AcidTypeData[AT].nl, Acid);
+
+    bicarbonate = bicarbonate - protonDeficit * frac / liters;
+    total_alkalinity = bicarbonate * 50 / 61;
+   }
+   ph = TpH;
+   dataRecord.wb_ph = ph;
+   $('#wb_ph').val(Round(ph, 2));
+   $('#est_mash_ph').val(Round(ph, 2));
+  } else { // Manual
+   /* Manual calculate pH */
+   $('.c_mashph').hide();
+   console.log('calc_acid no');
+   pHa = Round(ph, 3); // Adjusted water pH
+   // Then calculate the new pH with added acids and malts
+   console.log('Mash pH: ' + pHa);
+   Acid  = AcidTypeData[AT].AcidSG * (parseFloat(dataRecord.wa_acid_perc) / 100); // ml
+   Acid *= parseFloat($('#wa_acid').jqxNumberInput('decimal'));
+   Acid /= AcidTypeData[AT].MolWt;  // mg
+   Acidmg = Acid;
+
+   //find the pH where the protondeficit = protondeficit by the acid
+   frac = CalcFrac(pHa, AcidTypeData[AT].pK1, AcidTypeData[AT].pK2, AcidTypeData[AT].pK3);
+   protonDeficit = Round(Acid * frac, 3);
+   //console.log('protonDeficit Acid: ' + protonDeficit + ' frac: ' + frac + ' pH: ' + pHa);
+
+   deltapH = 0.001;
+   deltapd = 0.1;
+   pd = Round(ProtonDeficit(pHa), 6);
+   n = 0;
+   while (((pd < (protonDeficit - deltapd)) || (pd > (protonDeficit + deltapd))) && (n < 4000)) {
+     n++;
+     if (pd < (protonDeficit - deltapd))
+      pHa -= deltapH;
+     else if (pd > (protonDeficit + deltapd))
+      pHa += deltapH;
+     frac = CalcFrac(pHa, AcidTypeData[AT].pK1, AcidTypeData[AT].pK2, AcidTypeData[AT].pK3);
+     protonDeficit = Acid * frac;
+     pd = ProtonDeficit(pHa);
+   }
+   //console.log('n: ' + n + ' pd: ' + pd + ' protonDeficit: ' + protonDeficit + ' frac: ' + frac + ' pHa: ' + pHa);
+   bicarbonate = wg_bicarbonate - protonDeficit * frac / liters;
+   total_alkalinity = RA * 50 / 61;
+   ph = pHa;
+   $('#wb_ph').val(Round(ph, 2));
+   $('#est_mash_ph').val(Round(ph, 2));
+  }
+
+  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;
+  }
+
+  var BUGU = GetBUGU();
+  $('#tgt_bu').val(Round(BUGU, 2));
+  // From brouwhulp.
+  if (BUGU < 0.32)
+   $('#wr_bu').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Zeer moutig en zoet</span>");
+  else if (BUGU < 0.43)
+   $('#wr_bu').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Moutig, zoet</span>");
+  else if (BUGU < 0.52)
+   $('#wr_bu').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Evenwichtig</span>");
+  else if (BUGU < 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>");
+
+  // Sulfate to Chloride ratio (Palmer).
+  var OptSO4Clratio = GetOptSO4Clratio();
+  $('#tgt_so4_cl').val(Round(OptSO4Clratio, 1));
+  if (OptSO4Clratio < 0.4)
+   $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Te moutig</span>");
+  else if (OptSO4Clratio < 0.6)
+   $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Zeer moutig</span>");
+  else if (OptSO4Clratio < 0.8)
+   $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Moutig</span>");
+  else if (OptSO4Clratio < 1.5)
+   $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Gebalanceerd</span>");
+  else if (OptSO4Clratio < 2.0)
+   $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Licht bitter</span>");
+  else if (OptSO4Clratio < 4.0)
+   $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Bitter</span>");
+  else if (OptSO4Clratio < 9.0)
+   $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Zeer bitter</span>");
+  else
+   $('#wrt_so4_cl').html("<span style='vertical-align: top; font-size: 14px; font-style: italic;'>Te bitter</span>");
+  if (chloride > 0)
+   RA = sulfate / chloride;
+  else
+   RA = 10;
+  $('#got_so4_cl').val(Round(RA, 1));
+  Res = 'normaal';
+  if (RA < (0.8 * OptSO4Clratio))
+   Res = 'laag';
+  else if (RA > (1.2 * OptSO4Clratio))
+   Res = 'hoog';
+  setRangeIndicator('so4_cl', 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_bicarbonate').val(Round(bicarbonate, 1));
+  $('#wb_total_alkalinity').val(Round(total_alkalinity, 1));
+  $('#wb_hardness').val(Hardness(calcium, magnesium));
+  $('#wb_ra').val(ResidualAlkalinity(total_alkalinity, calcium, magnesium));
+
+  if (calcium < 40) {
+   setRangeIndicator('calcium', 'laag');
+  } else if (calcium > 150) {
+   setRangeIndicator('calcium', 'hoog');
+  } else {
+   setRangeIndicator('calcium', 'normaal');
+  }
+  if (magnesium < 5) {
+   setRangeIndicator('magnesium', 'laag');
+  } else if (magnesium > 40) {
+   setRangeIndicator('magnesium', 'hoog');
+  } else {
+   setRangeIndicator('magnesium', 'normaal');
+  }
+  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 <= 150) {
+   setRangeIndicator('chloride', 'normaal');
+  } else {
+   setRangeIndicator('chloride', 'hoog');
+  }
+  if (sulfate <= 50) {
+   setRangeIndicator('sulfate', 'laag');
+  } else if (sulfate <= 400) {
+   setRangeIndicator('sulfate', 'normaal');
+  } else {
+   setRangeIndicator('sulfate', 'hoog');
+  }
+  // (cloride + sulfate) > 500 is too high
+  if ((chloride + sulfate) > 500) {
+   setRangeIndicator('chloride', 'hoog');
+   setRangeIndicator('sulfate', 'hoog');
+  }
+  if (ph < 5.2) {
+   setRangeIndicator('ph', 'laag');
+  } else if (ph > 5.6) {
+   setRangeIndicator('ph', 'hoog');
+  } else {
+   setRangeIndicator('ph', 'normaal');
+  }
+  if (bicarbonate > 250) {
+   setRangeIndicator('bicarbonate', 'hoog');
+  } else {
+   setRangeIndicator('bicarbonate', 'normaal');
+  }
+  calcSparge();
+ }
+
+
+ function calcSparge() {
+
+  /* Based on the work of ajDeLange. */
+  var ws_calcium, ws_magnesium, ws_total_alkalinity, ws_sodium, ws_chloride;
+  var ws_sulfate, ws_ph, ws_hardness, ws_ra;
+  var TargetpH = dataRecord.sparge_ph;
+  var Source_pH = 7.0;
+
+  // Select watersource or fallback to the first source.
+  if ((dataRecord.sparge_source == 1) && (dataRecord.w2_ph > 0.0)) { // Source 2
+    ws_calcium = dataRecord.w2_calcium;
+    ws_magnesium = dataRecord.w2_magnesium;
+    ws_total_alkalinity = dataRecord.w2_total_alkalinity;
+    ws_sodium = dataRecord.w2_sodium;
+    ws_chloride = dataRecord.w2_chloride;
+    ws_sulfate = dataRecord.w2_sulfate;
+    Source_pH = dataRecord.w2_ph;
+    $('#w2_button').jqxRadioButton({ checked: true });
+  } else if ((dataRecord.sparge_source == 2) && (dataRecord.w2_ph > 0.0)) { // Mixed
+    ws_calcium = dataRecord.wg_calcium;
+    ws_magnesium = dataRecord.wg_magnesium;
+    ws_total_alkalinity = dataRecord.wg_total_alkalinity;
+    ws_sodium = dataRecord.wg_sodium;
+    ws_chloride = dataRecord.wg_chloride;
+    ws_sulfate = dataRecord.wg_sulfate;
+    Source_pH = dataRecord.wg_ph;
+    $('#wg_button').jqxRadioButton({ checked: true });
+  } else {
+    ws_calcium = dataRecord.w1_calcium;
+    ws_magnesium = dataRecord.w1_magnesium;
+    ws_total_alkalinity = dataRecord.w1_total_alkalinity;
+    ws_sodium = dataRecord.w1_sodium;
+    ws_chloride = dataRecord.w1_chloride;
+    ws_sulfate = dataRecord.w1_sulfate;
+    Source_pH = dataRecord.w1_ph;
+    $('#w1_button').jqxRadioButton({ checked: true });
+  }
+
+  if (dataRecord.sparge_volume > 0) {
+   ws_calcium += (parseFloat($('#ss_cacl2').jqxNumberInput('decimal')) * MMCa / MMCaCl2 * 1000 +
+    parseFloat($('#ss_caso4').jqxNumberInput('decimal')) * MMCa / MMCaSO4 * 1000) / dataRecord.sparge_volume;
+   ws_magnesium += (parseFloat($('#ss_mgso4').jqxNumberInput('decimal')) * MMMg / MMMgSO4 * 1000 +
+    parseFloat($('#ss_mgcl2').jqxNumberInput('decimal')) * MMMg / MMMgCl2 * 1000) / dataRecord.sparge_volume;
+   ws_sodium += (parseFloat($('#ss_nacl').jqxNumberInput('decimal')) * MMNa / MMNaCl * 1000) / dataRecord.sparge_volume;
+   ws_sulfate += (parseFloat($('#ss_caso4').jqxNumberInput('decimal')) * MMSO4 / MMCaSO4 * 1000 +
+    parseFloat($('#ss_mgso4').jqxNumberInput('decimal')) * MMSO4 / MMMgSO4 * 1000) / dataRecord.sparge_volume;
+   ws_chloride += (2 * parseFloat($('#ss_cacl2').jqxNumberInput('decimal')) * MMCl / MMCaCl2 * 1000 +
+    parseFloat($('#ss_nacl').jqxNumberInput('decimal')) * MMCl / MMNaCl * 1000 +
+    parseFloat($('#ss_mgcl2').jqxNumberInput('decimal')) * MMCl / MMMgCl2 * 1000) / dataRecord.sparge_volume;
+  }
+
+  /* Show the spargewate with salt additions */
+  $('#sw_calcium').val(Round(ws_calcium, 1));
+  $('#sw_magnesium').val(Round(ws_magnesium, 1));
+  $('#sw_sodium').val(Round(ws_sodium, 1));
+  $('#sw_sulfate').val(Round(ws_sulfate, 1));
+  $('#sw_chloride').val(Round(ws_chloride, 1));
+  $('#sw_bicarbonate').val(Round(Bicarbonate(ws_total_alkalinity, Source_pH), 1));
+  $('#sw_total_alkalinity').val(Round(ws_total_alkalinity, 1));
+  $('#sw_ph').val(dataRecord.sparge_ph);
+  $('#sw_hardness').val(Hardness(ws_calcium, ws_magnesium));
+  $('#sw_ra').val(ResidualAlkalinity(ws_total_alkalinity, ws_calcium, ws_magnesium));
+
+  AT = dataRecord.sparge_acid_type;
+  if (AT < 0 || AT >= AcidTypeData.length) {
+   AT = 0;
+   dataRecord.sparge_acid_type = 0;
+   $('#sparge_acid_type').val(AcidTypeData[0].nl);
+   dataRecord.sparge_acid_perc = AcidTypeData[0].AcidPrc;
+   $('#sparge_acid_perc').val(dataRecord.sparge_acid_perc);
+  }
+
+  /*
+   * Auto calculate the required acid
+   */
+  if (dataRecord.calc_acid) {
+   // 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.35);
+   var r2 = Math.pow(10, Source_pH - 10.33);
+   var d = 1 + r1 + r1 * r2;
+   var f1 = 1 / 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.35);
+   var r243 = Math.pow(10, 4.3 - 10.33);
+   var d43 = 1 + r143 + r143 * r243;
+   var f143 = 1 / d43;
+   var f343 = r143 * r243 / d43;
+
+   //Step 4. Solve
+   var Ct = ws_total_alkalinity / 50 / ((f143 - f1) + (f3 - f343));
+
+   //Step 5. Compute mole fractions at desired pH
+   var r1g = Math.pow(10, TargetpH - 6.35);
+   var r2g = Math.pow(10, TargetpH - 10.33);
+   var dg = 1 + r1g + r1g * r2g;
+   var f1g = 1 / 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.
+
+   //Step 8. Get the acid data.
+   var fract = CalcFrac(TargetpH, AcidTypeData[AT].pK1, AcidTypeData[AT].pK2, AcidTypeData[AT].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 *= AcidTypeData[AT].MolWt; //mg
+
+   //Step 11. Divide by Specific Gravity and Percentage to get the final ml.
+   var RealSG = Round(((AcidTypeData[AT].AcidSG - 1000) * (dataRecord.sparge_acid_perc / 100)) + 1000, 2);
+   Acid = Acid / RealSG;           //ml
+   Acid *= dataRecord.sparge_volume; //ml acid total at 100%
+   Acid /= AcidTypeData[AT].AcidPrc / 100;     //ml acid at supplied strength
+   Acid = Round(Acid, 2);
+   dataRecord.sparge_acid_amount = Acid / 1000;
+   $('#sparge_acid_amount').val(Acid);
+  }
+
+  // Finally calculate the estimate preboil pH
+  var ph = -Math.log10(((Math.pow(10, -dataRecord.wb_ph) * dataRecord.wg_amount) + (Math.pow(10, -dataRecord.sparge_ph) * dataRecord.sparge_volume)) /
+	  (dataRecord.wg_amount + dataRecord.sparge_volume));
+  $('#preboil_ph').val(ph);
+ }
+
+ function calcInit() {
+  console.log('calc.init()');
+
+  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();
+
+ };
+
+ function saveRecord(goback) {
+  window.location.href = my_return;
+ };
+
+ dataAdapter.dataBind();
+
+ // initialize the input fields.
+ // Tab 1, Algemeen
+ $('#name').jqxTooltip({ content: 'De naam voor dit recept.' });
+ $('#name').jqxInput({ theme: theme, width: 640, height: 23 });
+ $('#notes').jqxTooltip({ content: 'De uitgebreide opmerkingen over dit recept.' });
+ $('#notes').jqxInput({ theme: theme, width: 960, height: 200 });
+ $('#type').jqxTooltip({ content: 'Het brouw type van dit recept.' });
+ $('#type').jqxInput({ theme: theme, width: 180, height: 23 });
+ $('#efficiency').jqxTooltip({ content: 'Het rendement van maischen en koken.' });
+ $('#efficiency').jqxNumberInput(Show1dec);
+ $('#batch_size').jqxTooltip({ content: 'Het volume van het gekoelde wort na het koken.' });
+ $('#batch_size').jqxNumberInput(Show1dec);
+ $('#batch_size').jqxNumberInput({ min: 4 });
+ $('#boil_size').jqxTooltip({ content: 'Het volume van het wort voor het koken.' });
+ $('#boil_size').jqxNumberInput({ inputMode: 'simple', theme: theme, width: 90, height: 23, decimalDigits: 2, readOnly: true });
+ $('#boil_time').jqxTooltip({ content: 'De kooktijd in minuten.' });
+ $('#boil_time').jqxNumberInput(Show0dec);
+ $('#boil_time').jqxNumberInput({ min: 4, max: 360 });
+
+ $('#st_name').jqxTooltip({ content: 'De bierstijl naam voor dit recept.'});
+ $('#st_name').jqxInput({ theme: theme, width: 250, height: 23 });
+ $('#st_letter').jqxTooltip({ content: 'De bierstijl letter voor dit recept.'});
+ $('#st_letter').jqxInput({ theme: theme, width: 90, height: 23 });
+ $('#st_guide').jqxTooltip({ content: 'De bierstijl gids voor dit recept.'});
+ $('#st_guide').jqxInput({ theme: theme, width: 250, height: 23 });
+ $('#st_category').jqxTooltip({ content: 'De Amerikaanse bierstijl categorie.'});
+ $('#st_category').jqxInput({ theme: theme, width: 250, height: 23 });
+ $('#st_category_number').jqxTooltip({ content: 'De Amerikaanse bierstijl categorie sub nummer.'});
+ $('#st_category_number').jqxNumberInput(Smal0dec);
+ $('#st_type').jqxTooltip({ content: 'Het bierstijl type.'});
+ $('#st_type').jqxInput({ theme: theme, width: 250, height: 23 });
+
+ $('#est_og').jqxTooltip({ content: 'Het begin SG wat je wilt bereiken. De moutstort wordt automatisch herberekend.' });
+ $('#est_og').jqxNumberInput(Show3dec);
+ $('#st_og_min').jqxTooltip({ content: 'Het minimum begin SG voor deze bierstijl.'});
+ $('#st_og_min').jqxNumberInput({ inputMode: 'simple', theme: theme, width: 50, height: 23, decimalDigits: 3, readOnly: true });
+ $('#st_og_max').jqxTooltip({ content: 'Het maximum begin SG voor deze bierstijl.'});
+ $('#st_og_max').jqxNumberInput({ inputMode: 'simple', theme: theme, width: 50, height: 23, decimalDigits: 3, readOnly: true });
+
+ $('#est_fg').jqxTooltip({ content: 'Het eind SG. Dit wordt automatisch berekend.' });
+ $('#est_fg').jqxNumberInput(Show3dec);
+ $('#st_fg_min').jqxTooltip({ content: 'Het minimum eind SG voor deze bierstijl.'});
+ $('#st_fg_min').jqxNumberInput({ inputMode: 'simple', theme: theme, width: 50, height: 23, decimalDigits: 3, readOnly: true });
+ $('#st_fg_max').jqxTooltip({ content: 'Het maximum eind SG voor deze bierstijl.'});
+ $('#st_fg_max').jqxNumberInput({ inputMode: 'simple', theme: theme, width: 50, height: 23, decimalDigits: 3, readOnly: true });
+
+ $('#est_abv').jqxTooltip({ content: 'Alcohol volume %. Dit wordt automatisch berekend.' });
+ $('#est_abv').jqxNumberInput(Smal1dec);
+ $('#st_abv_min').jqxTooltip({ content: 'Het minimum alcohol volume % voor deze bierstijl.'});
+ $('#st_abv_min').jqxNumberInput(Smal1dec);
+ $('#st_abv_max').jqxTooltip({ content: 'Het maximum alcohol volume % voor deze bierstijl.'});
+ $('#st_abv_max').jqxNumberInput(Smal1dec);
+
+ $('#est_color').jqxTooltip({ content: 'De kleur in EBC. Dit wordt automatisch berekend.' });
+ $('#est_color').jqxNumberInput(Show0dec);
+ $('#st_color_min').jqxTooltip({ content: 'De minimum kleur voor deze bierstijl.'});
+ $('#st_color_min').jqxNumberInput(Smal0dec);
+ $('#st_color_max').jqxTooltip({ content: 'De maximum kleur voor deze bierstijl.'});
+ $('#st_color_max').jqxNumberInput(Smal0dec);
+ $('#color_method').jqxInput({ theme: theme, width: 180, height: 23 }); 
+ $('#est_ibu').jqxTooltip({ content: 'De bitterheid in IBU. Dit wordt automatisch berekend.' });
+ $('#est_ibu').jqxNumberInput(Show0dec);
+ $('#st_ibu_min').jqxTooltip({ content: 'De minimum bitterheid voor deze bierstijl.'});
+ $('#st_ibu_min').jqxNumberInput(Smal0dec);
+ $('#st_ibu_max').jqxTooltip({ content: 'De maximum bitterheid voor deze bierstijl.'});
+ $('#st_ibu_max').jqxNumberInput(Smal0dec);
+
+ $('#ibu_method').jqxInput({ theme: theme, width: 180, height: 23 });
+ $('#kcal').jqxTooltip({ content: 'Energie-inhoud in kcal/liter.' });
+ $('#kcal').jqxNumberInput(Smal0dec);
+ $('#est_carb').jqxTooltip({ content: 'Koolzuur volume. Dit wordt automatisch berekend.' });
+ $('#est_carb').jqxNumberInput(Smal1dec);
+ $('#st_carb_min').jqxTooltip({ content: 'Het minimum koolzuur volume voor deze bierstijl.'});
+ $('#st_carb_min').jqxNumberInput(Smal1dec);
+ $('#st_carb_max').jqxTooltip({ content: 'Het maximum koolzuur volume voor deze bierstijl.'});
+ $('#st_carb_max').jqxNumberInput(Smal1dec);
+
+ // Tab 2, Vergistbaar
+ $('#est_color2').jqxTooltip({ content: 'De kleur in EBC. Dit wordt automatisch berekend.' });
+ $('#est_color2').jqxNumberInput(Show0dec);
+ $('#est_og2').jqxTooltip({ content: 'Het begin SG wat je wilt bereiken. De moutstort wordt automatisch herberekend.' });
+ $('#est_og2').jqxNumberInput(Show3dec);
+ $('#perc_malts').jqxProgressBar({
+  width: 300,
+  height: 23,
+  theme: theme,
+  showText: true,
+  max: 120,
+  animationDuration: 0,
+  colorRanges: [
+   { stop: 90, color: '#008C00' },
+   { stop: 100, color: '#EB7331' },
+   { stop: 120, color: '#FF0000' }
+  ],
+  renderText: function(text) {
+   return (Math.round(parseInt(text) * 1.2)) + '%';
+  }
+ });
+ $('#perc_sugars').jqxProgressBar({
+  width: 300,
+  height: 23,
+  theme: theme,
+  showText: true,
+  max: 50,
+  animationDuration: 0,
+  colorRanges: [
+   { stop: 20, color: '#008C00' },
+   { stop: 50, color: '#FF0000' }
+  ],
+  renderText: function(text) {
+   return (Math.round(parseInt(text) * 5) / 10) + '%';
+  }
+ });
+ $('#perc_cara').jqxProgressBar({
+  width: 300,
+  height: 23,
+  theme: theme,
+  showText: true,
+  max: 50,
+  animationDuration: 0,
+  colorRanges: [
+   { stop: 25, color: '#008C00' },
+   { stop: 50, color: '#FF0000' }
+  ],
+  renderText: function(text) {
+   return (Math.round(parseInt(text) * 5) / 10) + '%';
+  }
+ });
+ $('#ferm_lintner').jqxProgressBar({
+  width: 300,
+  height: 23,
+  theme: theme,
+  showText: true,
+  max: 200,
+  animationDuration: 0,
+  colorRanges: [
+   { stop: 30, color: '#FF0000' },
+   { stop: 40, color: '#EB7331' },
+   { stop: 200, color: '#008C00' }
+  ],
+  renderText: function(text) {
+   return (parseInt(text) * 2) + ' lintner';
+  }
+ });
+
+ // Tab 3, Hoppen
+ $('#est_ibu2').jqxTooltip({ content: 'De bitterheid in IBU. Dit wordt automatisch berekend.' });
+ $('#est_ibu2').jqxNumberInput(Smal0dec);
+ $('#hop_flavour').jqxProgressBar({
+  width: 300,
+  height: 23,
+  theme: theme,
+  showText: true,
+  animationDuration: 0,
+  colorRanges: [
+   { stop: 20, color: '#004D00' },
+   { stop: 40, color: '#008C00' },
+   { stop: 60, color: '#00BF00' },
+   { stop: 80, color: '#00FF00' },
+   { stop: 100, color: '#80FF80' }
+  ],
+  renderText: function(text) {
+   var val = parseInt(text);
+   if (val < 20)
+    return 'Weinig';
+   else if (val < 40)
+    return 'Matig';
+   else if (val < 60)
+    return 'Redelijk';
+   else if (val < 80)
+    return 'Veel';
+   else
+    return 'Zeer veel';
+  }
+ });
+ $('#hop_aroma').jqxProgressBar({
+  width: 300,
+  height: 23,
+  theme: theme,
+  showText: true,
+  animationDuration: 0,
+  colorRanges: [
+   { stop: 20, color: '#004D00' },
+   { stop: 40, color: '#008C00' },
+   { stop: 60, color: '#00BF00' },
+   { stop: 80, color: '#00FF00' },
+   { stop: 100, color: '#80FF80' }
+  ],
+  renderText: function(text) {
+   var val = parseInt(text);
+   if (val < 20)
+    return 'Weinig';
+   else if (val < 40)
+    return 'Matig';
+   else if (val < 60)
+    return 'Redelijk';
+   else if (val < 80)
+    return 'Veel';
+   else
+    return 'Zeer veel';
+  }
+ });
+
+ // Tab 4, Diversen
+
+ // Tab 5, Gist
+ $('#est_fg2').jqxTooltip({ content: 'Het eind SG. Dit wordt automatisch berekend.' });
+ $('#est_fg2').jqxNumberInput(Show3dec);
+ $('#est_abv2').jqxTooltip({ content: 'Alcohol volume %. Dit wordt automatisch berekend.' });
+ $('#est_abv2').jqxNumberInput(Smal1dec);
+
+ // Tab 6, Maischen
+ $('#mash_name').jqxInput({ theme: theme, width: 320, height: 23 });
+
+ // Tab 7, Water
+ $('#tgt_bu').jqxNumberInput(Show2wat);
+ $('#tgt_so4_cl,#got_so4_cl').jqxNumberInput(Show1wat);
+ $('#preboil_ph').jqxNumberInput(Show2wat);
+
+ // Water source 1
+ $('#w1_name').jqxInput({ theme: theme, width: 200, height: 23 });
+ $('#w1_button').jqxRadioButton({ theme: theme, width: 50, height: 23, disabled: true });
+ $('#w1_amount').jqxNumberInput(Show1wat);
+ $('#w1_calcium').jqxNumberInput(Show1wat);
+ $('#w1_magnesium').jqxNumberInput(Show1wat);
+ $('#w1_sodium').jqxNumberInput(Show1wat);
+ $('#w1_bicarbonate').jqxNumberInput(Show1wat);
+ $('#w1_total_alkalinity').jqxNumberInput(Show1wat);
+ $('#w1_chloride').jqxNumberInput(Show1wat);
+ $('#w1_sulfate').jqxNumberInput(Show1wat);
+ $('#w1_ph').jqxNumberInput(Show2wat);
+ $('#w1_hardness').jqxNumberInput(Show1wat);
+ $('#w1_ra').jqxNumberInput(Show1wat);
+ // Water source 2
+ $('#w2_name').jqxInput({ theme: theme, width: 200, height: 23 });
+ $('#w2_button').jqxRadioButton({ theme: theme, width: 50, height: 23, disabled: true });
+ $('#w2_amount').jqxNumberInput(Show1wat);
+ $('#w2_calcium').jqxNumberInput(Show1wat);
+ $('#w2_magnesium').jqxNumberInput(Show1wat);
+ $('#w2_sodium').jqxNumberInput(Show1wat);
+ $('#w2_bicarbonate').jqxNumberInput(Show1wat);
+ $('#w2_total_alkalinity').jqxNumberInput(Show1wat);
+ $('#w2_chloride').jqxNumberInput(Show1wat);
+ $('#w2_sulfate').jqxNumberInput(Show1wat);
+ $('#w2_ph').jqxNumberInput(Show2wat);
+ $('#w2_hardness').jqxNumberInput(Show1wat);
+ $('#w2_ra').jqxNumberInput(Show1wat);
+ // Water mixed
+ $('#wg_button').jqxRadioButton({ theme: theme, width: 50, height: 23, disabled: true });
+ $('#wg_amount').jqxNumberInput(Show1wat);
+ $('#wg_calcium').jqxNumberInput(Show1wat);
+ $('#wg_magnesium').jqxNumberInput(Show1wat);
+ $('#wg_sodium').jqxNumberInput(Show1wat);
+ $('#wg_bicarbonate').jqxNumberInput(Show1wat);
+ $('#wg_total_alkalinity').jqxNumberInput(Show1wat);
+ $('#wg_chloride').jqxNumberInput(Show1wat);
+ $('#wg_sulfate').jqxNumberInput(Show1wat);
+ $('#wg_ph').jqxNumberInput(Show2wat);
+ $('#wg_hardness').jqxNumberInput(Show1wat);
+ $('#wg_ra').jqxNumberInput(Show1wat);
+ // Water treated
+ $('#wb_calcium').jqxTooltip({ content: 'De ideale hoeveelheid Calcium is tussen 40 en 150.'});
+ $('#wb_calcium').jqxNumberInput(Show1wat);
+ $('#wb_magnesium').jqxTooltip({ content: 'De ideale hoeveelheid Magnesium is tussen 5 en 40.'});
+ $('#wb_magnesium').jqxNumberInput(Show1wat);
+ $('#wb_sodium').jqxTooltip({ content: 'De ideale hoeveelheid Natrium is lager dan 150.'});
+ $('#wb_sodium').jqxNumberInput(Show1wat);
+ $('#wb_chloride').jqxTooltip({ content: 'De ideale hoeveelheid Chloride is tussen 50 en 150. Samen met Sulfaat minder dan 500.'});
+ $('#wb_chloride').jqxNumberInput(Show1wat);
+ $('#wb_sulfate').jqxTooltip({ content: 'De ideale hoeveelheid Sulfaat is tussen 50 en 400. Samen met Sulfaat minder dan 500.'});
+ $('#wb_sulfate').jqxNumberInput(Show1wat);
+ $('#wb_bicarbonate').jqxTooltip({ content: '0 tot 50 lichte bieren, 50 tot 150 amber bieren, 150 tot 250 donkere bieren.'});
+ $('#wb_bicarbonate').jqxNumberInput(Show1wat);
+ $('#wb_total_alkalinity').jqxNumberInput(Show1wat);
+ $('#wb_ph').jqxNumberInput(Show2wat);
+ $('#wb_hardness').jqxNumberInput(Show1wat);
+ $('#wb_ra').jqxNumberInput(Show1wat);
+ // Sparge water
+ $('#sw_amount').jqxNumberInput(Show1wat);
+ $('#sw_calcium').jqxNumberInput(Show1wat);
+ $('#sw_magnesium').jqxNumberInput(Show1wat);
+ $('#sw_sodium').jqxNumberInput(Show1wat);
+ $('#sw_bicarbonate').jqxNumberInput(Show1wat);
+ $('#sw_total_alkalinity').jqxNumberInput(Show1wat);
+ $('#sw_chloride').jqxNumberInput(Show1wat);
+ $('#sw_sulfate').jqxNumberInput(Show1wat);
+ $('#sw_ph').jqxNumberInput(Show2wat);
+ $('#sw_hardness').jqxNumberInput(Show1wat);
+ $('#sw_ra').jqxNumberInput(Show1wat);
+
+ // Water agents
+ $('#wa_cacl2').jqxTooltip({ content: 'Voor het maken van een ander waterprofiel. Voegt calcium en chloride toe. Voor het verbeteren van zoetere bieren.'});
+ $('#wa_cacl2').jqxNumberInput(Show2wat);
+ $('#ss_cacl2').jqxNumberInput(Show2wat);
+
+ $('#wa_caso4').jqxTooltip({
+  content: 'Gips. Voor het maken van een ander waterprofiel. Voegt calcium en sulfaat toe. Voor het verbeteren van bittere bieren.'
+ });
+ $('#wa_caso4').jqxNumberInput(Show2wat);
+ $('#ss_caso4').jqxNumberInput(Show2wat);
+
+ $('#wa_mgso4').jqxTooltip({ content: 'Epsom zout. Voor het maken van een ander waterprofiel. Voegt magnesium en sulfaat toe. Gebruik spaarzaam!'});
+ $('#wa_mgso4').jqxNumberInput(Show2wat);
+ $('#ss_mgso4').jqxNumberInput(Show2wat);
+
+ $('#wa_nacl').jqxTooltip({
+  content: 'Keukenzout. Voor het maken van een ander waterprofiel. Voegt natrium en chloride toe. ' +
+  'Voor het accentueren van zoetheid. Bij hoge dosering wordt het bier ziltig.'
+ });
+ $('#wa_nacl').jqxNumberInput(Show2wat);
+ $('#ss_nacl').jqxNumberInput(Show2wat);
+
+ $('#wa_mgcl2').jqxTooltip({ content: 'Magnesiumchloride'});
+ $('#wa_mgcl2').jqxNumberInput(Show2wat);
+ $('#ss_mgcl2').jqxNumberInput(Show2wat);
+
+ $('#wa_nahco3').jqxTooltip({ content: 'Baksoda'});
+ $('#wa_caco3').jqxTooltip({ content: 'Kalk'});
+ $('#wa_nahco3,#wa_caco3').jqxNumberInput(Show2wat);
+
+ $('#mash_ph').jqxTooltip({ content: 'Maisch pH tussen 5.2 en 5.6. Gebruik 5.2 voor lichte en 5.5 voor donkere bieren.'});
+ $('#mash_ph').jqxNumberInput(Show2dec);
+
+ $('#calc_acid').jqxCheckBox({ theme: theme, width: 120, height: 23, disabled: true });
+
+ $('#wa_acid_name').jqxInput({ theme: theme, width: 130, height: 23 });
+ $('#wa_acid').jqxNumberInput(Show2dec);
+ $('#wa_acid').jqxNumberInput({ symbol: ' ml', symbolPosition: 'right' });
+ $('#wa_acid_perc').jqxNumberInput(Show0dec);
+ $('#wa_acid_perc').jqxNumberInput({ symbol: '%', symbolPosition: 'right' });
+
+ // Sparge water
+ $('#sparge_ph').jqxNumberInput(Show2dec);
+ $('#sparge_acid_amount').jqxNumberInput(Show2dec);
+ $('#sparge_acid_amount').jqxNumberInput({ symbol: ' ml', symbolPosition: 'right' });
+ $('#sparge_acid_type').jqxInput({ theme: theme, width: 130, height: 23 });
+ $('#sparge_acid_perc').jqxNumberInput(Show0dec);
+ $('#sparge_acid_perc').jqxNumberInput({ symbol: '%', symbolPosition: 'right' });
+
+ // Tabs inside the popup window.
+ $('#jqxTabs').jqxTabs({
+  theme: theme,
+  width: 1280,
+  height: 660,
+  autoHeight: false,
+  position: 'top'
+ });
+
+ // Button below
+ $('#Terug').jqxButton({ template: 'primary', width: '80px', theme: theme });
+ $('#Terug').bind('click', function() {
+  window.location.href = my_return;
+ });
+
+});
+
--- a/www/rec_edit.php	Fri Aug 05 10:44:59 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,386 +0,0 @@
-<?php
-require_once($_SERVER['DOCUMENT_ROOT'].'/includes/global.inc.php');
-page_header('Recept wijzigen', 'rec_edit');
-// met POST commando's record ophalen.
-?>
-
-   <!-- Editor tabs. -->
-   <div id="jqxTabs">
-     <ul>
-      <li>Algemeen</li>
-      <li>Vergistbaar</li>
-      <li>Hoppen</li>
-      <li>Diversen</li>
-      <li>Gist</li>
-      <li>Maischen</li>
-      <li>Water</li>
-     </ul>
-
-     <div> <!-- tab algemeen -->
-      <div style="overflow: hidden;">
-       <table style="width: 100%;">
-        <tr>
-         <td style="vertical-align: top; float: right; padding: 3px;">Recept naam:</td>
-	 <td align="left" colspan="5" style="vertical-align: top; padding: 3px;"><input id="name" /></td>
-        </tr>
-        <tr>
-         <td style="vertical-align: top; float: right; padding: 3px;">Opmerkingen:</td>
-         <td colspan="5" style="padding: 3px;"><textarea id="notes"></textarea></td>
-	</tr>
-        <tr>
-	 <td style="vertical-align: top; float: right; padding: 3px;">Brouw type:</td>
-	 <td align="left" style="vertical-align: top; padding: 3px;"><input readonly="1" id="type" /></td>
-         <td style="vertical-align: top; float: right; padding: 3px;">Brouwzaal rendement:</td>
-         <td colspan="3" style="padding: 3px;"><div id="efficiency"></div></td>
-        </tr>
-        <tr>
-         <td style="vertical-align: top; float: right; padding: 3px;">Brouw volume L:</td>
-         <td style="padding: 3px;"><div id="batch_size"></div></td>
-         <td style="vertical-align: top; float: right; padding: 3px;">Kooktijd minuten:</td>
-	 <td style="padding: 3px;"><div id="boil_time"></div></td>
-         <td style="vertical-align: top; float: right; padding: 3px;">Kook volume L:</td>
-         <td style="padding: 3px;"><div id="boil_size"></div></td>
-	</tr>
-        <tr>
-         <td colspan="6"><hr></td>
-        </tr>
-	<tr>
-         <td></td>
-	 <th>Bierstijl gegevens</th>
-         <td align="left" colspan="4"></td>
-        </tr>
-        <tr>
-         <td style="vertical-align: top; float: right; padding: 3px;">Stijlgids:</td>
-         <td align="left" style="vertical-align: top; padding: 3px;"><input readonly="1" id="st_guide" /></td>
-         <td style="vertical-align: top; float: right; padding: 3px;">Bier stijl:</td>
-         <td align="left" style="vertical-align: top; padding: 3px;"><input readonly="1" id="st_name" /></td>
-         <td style="vertical-align: top; float: right; padding: 3px;">Bier groep:</td>
-         <td align="left" style="vertical-align: top; padding: 3px;"><input readonly="1" id="st_letter" /></td>
-        </tr>
-        <tr>
-         <td style="vertical-align: top; float: right; padding: 3px;">Stijl type:</td>
-         <td align="left" style="vertical-align: top; padding: 3px;"><input readonly="1"  id="st_type" /></td>
-         <td style="vertical-align: top; float: right; padding: 3px;">Categorie:</td>
-         <td align="left" style="vertical-align: top; padding: 3px;"><input readonly="1" id="st_category" /></td>
-         <td style="vertical-align: top; float: right; padding: 3px;">Categorie nr:</td>
-         <td style="padding: 3px;"><div id="st_category_number"></div></td>
-        </tr>
-	<tr>
-         <td style="vertical-align: top; float: right; padding: 3px;">Verwacht start SG:</td>
-         <td style="padding: 3px;"><div style="float: left;" id="est_og"></div><div style="float: left; margin-left: 15px;" id="st_og_min"></div><div style="float: left; margin-left: 5px;" id="st_og_max"></div></td>
-         <td style="vertical-align: top; float: right; padding: 3px;">Verwacht eind SG:</td>
-	 <td style="padding: 3px;"><div style="float: left;" id="est_fg"></div><div style="float: left; margin-left: 15px;" id="st_fg_min"></div><div style="float: left; margin-left: 5px;" id="st_fg_max"></div></td>
-         <td style="vertical-align: top; float: right; padding: 3px;">Alcohol vol.%:</td>
-         <td style="padding: 3px;"><div style="float: left;" id="est_abv"></div><div style="float: left; margin-left: 15px;" id="st_abv_min"></div><div style="float: left; margin-left: 5px;" id="st_abv_max"></div></td>
-	</tr>
-        <tr>
-         <td style="vertical-align: top; float: right; padding: 3px;">Kleur EBC:</td>
-         <td style="padding: 3px;"><div style="float: left;" id="est_color"></div><div style="float: left; margin-left: 15px;" id="st_color_min"></div><div style="float: left; margin-left: 5px;" id="st_color_max"></div><div id="bcolor" class='ebccolor'> </div></td>
-         <td style="vertical-align: top; float: right; padding: 3px;">Kleur methode:</td>
-	 <td align="left" style="vertical-align: top; padding: 3px;"><input readonly="1" id="color_method" /></td>
-         <td style="vertical-align: top; float: right; padding: 3px;">Koolzuur vol:</td>
-         <td style="padding: 3px;"><div style="float: left;" id="est_carb"></div><div style="float: left; margin-left: 15px;" id="st_carb_min"></div><div style="float: left; margin-left: 5px;" id="st_carb_max"></div></td>
-	</tr>
-        <tr>
-         <td style="vertical-align: top; float: right; padding: 3px;">Bitterheid IBU:</td>
-         <td style="padding: 3px;"><div style="float: left;" id="est_ibu"></div><div style="float: left; margin-left: 15px;" id="st_ibu_min"></div><div style="float: left; margin-left: 5px;" id="st_ibu_max"></div></td>
-         <td style="vertical-align: top; float: right; padding: 3px;">Bitterheid methode:</td>
-         <td align="left" style="vertical-align: top; padding: 3px;"><input readonly="1" id="ibu_method" /></td>
-         <td style="vertical-align: top; float: right; padding: 3px;">Energie-inhoud kcal/l:</td>
-         <td style="padding: 3px;"><div style="float: left;" id="kcal"></div></div></td>
-        </tr>
-       </table>
-       <div style="float: right; margin-top: 30px; margin-bottom: 10px;">
-        <input style="margin-right: 600px;" type="button" id="Terug"   value="Terug" />
-       </div>
-      </div>
-     </div> <!-- tab algemeen -->
-
-     <div> <!-- tab vergistbaar -->
-      <div style="overflow: hidden;">
-       <table style="width: 100%;">
-        <tr>
-         <td style="vertical-align: top; float: right; padding: 3px;">Kleur:</td>
-         <td style="padding: 3px;"><div style="float: left;" id="est_color2"></div><div id="bcolor2" class='ebccolor'> </div></td>
-         <td style="vertical-align: top; float: right; padding: 3px;">Percentage moutstort:</td>
-         <td style="padding: 3px;"><div style="float: left;" id="perc_malts"></div></td>
-	</tr>
-        <tr>
-         <td style="vertical-align: top; float: right; padding: 3px;">Begin SG:</td>
-         <td style="padding: 3px;"><div style="float: left;" id="est_og2"></div></td>
-         <td style="vertical-align: top; float: right; padding: 3px;">Percentage suiker:</td>
-         <td style="padding: 3px;"><div style="float: left;" id="perc_sugars"></div></td>
-        </tr>
-	<tr>
-         <td colspan="2"></td>
-         <td style="vertical-align: top; float: right; padding: 3px;">Percentage cara:</td>
-         <td style="padding: 3px;"><div style="float: left;" id="perc_cara"></div></td>
-        </tr>
-        <tr>
-         <td colspan="2"> </td>
-         <td style="vertical-align: top; float: right; padding: 3px;">Lintner totaal:</td>
-         <td style="padding: 3px;"><div style="float: left;" id="ferm_lintner"></div></td>
-        </tr>
-        <tr>
-         <td align="center" colspan="4"><div id="fermentableGrid"></div></td>
-        </tr>
-       </table>
-      </div>
-     </div> <!-- tab vergistbaar -->
-
-     <div> <!-- tab hoppen -->
-      <div style="overflow: hidden;">
-       <table style="width: 100%;">
-        <tr> 
-	 <td style="vertical-align: top; float: right; padding: 3px;">Bitterheid IBU:</td>
-	 <td style="padding: 3px;"><div id="est_ibu2"></div></td>
-         <td style="vertical-align: top; float: right; padding: 3px;">Smaak bijdrage:</td>
-         <td style="padding: 3px;"><div id="hop_flavour"></div></td>
-         <td style="vertical-align: top; float: right; padding: 3px;">Aroma bijdrage:</td>
-         <td style="padding: 3px;"><div id="hop_aroma"></div></td>
-        </tr>
-        <tr>
-         <td align="center" colspan="6"><div id="hopGrid"></div></td>
-        </tr>
-       </table>
-      </div>
-     </div> <!-- tab hoppen -->
-
-     <div> <!-- tab misc -->
-      <div style="overflow: hidden;">
-       <table style="width: 100%;">
-        <tr><td>&nbsp;</td></tr>
-        <tr><td align="center"><div id="miscGrid"></div></td></tr>
-       </table>
-      </div>
-     </div> <!-- tab misc -->
-
-     <div> <!-- tab gisten -->
-      <div style="overflow: hidden;">
-       <table style="width: 100%;">
-        <tr>
-         <td style="vertical-align: top; float: right; padding: 3px;">Verwacht eind SG:</td>
-         <td style="padding: 3px;"><div id="est_fg2"></div></td>
-         <td style="vertical-align: top; float: right; padding: 3px;">Verwacht ABV %:</td>
-         <td style="padding: 3px;"><div id="est_abv2"></div></td>
-        </tr>
-        <tr><td colspan="4">&nbsp;</td></tr>
-        <tr><td colspan="4" align="center"><div id="yeastGrid"></div></td></tr>
-       </table>
-      </div>
-     </div> <!-- tab gisten -->
-
-     <div> <!-- tab maischen -->
-      <div style="overflow: hidden;">
-       <table style="width: 100%;">
-        <tr>
-         <td style="vertical-align: top; float: right; padding: 3px;">Maischchema:</td>
-	 <td align="left" style="vertical-align: top; padding: 3px;"><input readonly="1" id="mash_name" /></td>
-         <td colspan="2"></td>
-	</tr>
-        <tr><td colspan="4">&nbsp;</td></tr>
-        <tr><td align="center" colspan="4" style="padding: 3px;"><div id="mashGrid"></div></td></tr>
-       </table>
-      </div>
-     </div> <!-- tab maischen -->
-
-     <div> <!-- tab water -->
-      <div style="overflow: hidden;">
-       <table style="width: 100%;">
-        <tr>
-         <td align="center" colspan="9">
-          <div id='water_totals'>
- 	   <table style="width: 100%;">
-            <caption>Water overzicht</caption>
-	    <tr>
-	     <td align="left" style="vertical-align: top; padding: 3px;">Water profiel</td>
-             <td style="width: 50px; padding: 3px;">Spoel</td>
-             <td style="width: 97px; padding: 3px;">Volume</td>
-             <td style="width: 77px; padding: 3px;">Ca</td>
-	     <td style="width: 77px; padding: 3px;">Mg</td>
-             <td style="width: 77px; padding: 3px;">HCO3</td>
-             <td style="width: 77px; padding: 3px;">CaCO3</td>
-             <td style="width: 77px; padding: 3px;">Na</td>
-             <td style="width: 77px; padding: 3px;">Cl</td>
-	     <td style="width: 77px; padding: 3px;">SO4</td>
-	     <td style="width: 77px; padding: 3px;">pH</td>
-	     <td style="width: 77px; padding: 3px;">Hardheid</td>
-             <td style="width: 77px; padding: 3px;">RA</td>
-	    </tr>
-	    <tr>
-	     <td><input readonly="1" id="w1_name" /></td>
-             <td><div style='margin-left: 10px;' id='w1_button'></div></td>
-             <td><div id="w1_amount"></div></td>
-             <td><div id="w1_calcium"></div></td>
-             <td><div id="w1_magnesium"></div></td>
-             <td><div id="w1_bicarbonate"></div></td>
-	     <td><div id="w1_total_alkalinity"></div></td>
-             <td><div id="w1_sodium"></div></td>
-             <td><div id="w1_chloride"></div></td>
-             <td><div id="w1_sulfate"></div></td>
-	     <td><div id="w1_ph"></div></td>
-	     <td><div id="w1_hardness"></div></td>
-             <td><div id="w1_ra"></div></td>
-            </tr>
-	    <tr>
-	     <td><input readonly="1" id="w2_name" /></td>
-             <td><div style='margin-left: 10px;' id='w2_button'></div></td>
-             <td><div id="w2_amount"></div></td>
-             <td><div id="w2_calcium"></div></td>
-             <td><div id="w2_magnesium"></div></td>
-             <td><div id="w2_bicarbonate"></div></td>
-	     <td><div id="w2_total_alkalinity"></div></td>
-             <td><div id="w2_sodium"></div></td>
-             <td><div id="w2_chloride"></div></td>
-             <td><div id="w2_sulfate"></div></td>
-	     <td><div id="w2_ph"></div></td>
-             <td><div id="w2_hardness"></div></td>
-             <td><div id="w2_ra"></div></td>
-            </tr>
-            <tr>
-	     <td style="vertical-align: top; padding: 3px; float: left;">Gemengd water:</td>
-             <td><div style='margin-left: 10px;' id='wg_button'></div></td>
-             <td><div id="wg_amount"></div></td>
-             <td><div id="wg_calcium"></div></td>
-             <td><div id="wg_magnesium"></div></td>
-             <td><div id="wg_bicarbonate"></div></td>
-	     <td><div id="wg_total_alkalinity"></div></td>
-             <td><div id="wg_sodium"></div></td>
-             <td><div id="wg_chloride"></div></td>
-	     <td><div id="wg_sulfate"></div></td>
-	     <td><div id="wg_ph"></div></td>
-             <td><div id="wg_hardness"></div></td>
-             <td><div id="wg_ra"></div></td>
-            </tr>
-            <tr>
-	     <td style="vertical-align: top; padding: 3px; float: left;">Behandeld maisch water:</td>
-             <td></td>
-             <td><div></div></td>
-             <td><div id="wb_calcium"></div></td>
-             <td><div id="wb_magnesium"></div></td>
-             <td><div id="wb_bicarbonate"></div></td>
-             <td><div id="wb_total_alkalinity"></div></td>
-             <td><div id="wb_sodium"></div></td>
-	     <td><div id="wb_chloride"></div></td>
-	     <td><div id="wb_sulfate"></div></td>
-	     <td><div id="wb_ph"></div></td>
-             <td><div id="wb_hardness"></div></td>
-             <td><div id="wb_ra"></div></td>
-	    </tr>
-            <tr>
-	     <td style="vertical-align: top; padding: 3px; float: left;">Resultaat:</td>
-             <td></td>
-	     <td><div></div></td>
-             <td><div id="wr_calcium"></div></td>
-             <td><div id="wr_magnesium"></div></td>
-             <td><div id="wr_bicarbonate"></div></td>
-             <td><div id="wr_total_alkalinity"></div></td>
-             <td><div id="wr_sodium"></div></td>
-	     <td><div id="wr_chloride"></div></td>
-             <td><div id="wr_sulfate"></div></td>
-	     <td><div id="wr_ph"></div></td>
-             <td></td>
-             <td></td>
-            </tr>
-	    <tr>
-	     <td style="vertical-align: top; padding: 3px; float: left;">Behandeld spoelwater:</td>
-             <td></td>
-             <td><div id="sw_amount"></div></td>
-             <td><div id="sw_calcium"></div></td>
-             <td><div id="sw_magnesium"></div></td>
-             <td><div id="sw_bicarbonate"></div></td>
-	     <td><div id="sw_total_alkalinity"></div></td>
-             <td><div id="sw_sodium"></div></td>
-             <td><div id="sw_chloride"></div></td>
-             <td><div id="sw_sulfate"></div></td>
-	     <td><div id="sw_ph"></div></td>
-             <td><div id="sw_hardness"></div></td>
-             <td><div id="sw_ra"></div></td>
-            </tr>
-           </table>
-	  </div>
-         </td>
-	</tr>
-       <tr>
-        <th style="text-align: center;" colspan="3">Brouwzouten</th>
-        <th colspan="3"></th>
-        <th style="text-align: center;" colspan="3">Zuur toevoegingen</th>
-       </tr>
-        <tr>
-         <td style="vertical-align: top; float: right; padding: 3px;">CaCl2 gr:</td>
-	 <td style="padding: 3px;"><div id="wa_cacl2"></div></td>
-         <td style="padding: 3px;"><div id="ss_cacl2"></div></td>
-	 <td style="vertical-align: top; float: right; padding: 3px;">Bitterheidsindex:</td>
-	 <td style="padding: 3px;"><div style="float: left;" id="tgt_bu"></div></td>
-	 <td style="padding: 3px;"><div style="float: left;" id="wr_bu"></div></td>
-         <td style="vertical-align: top; float: right; padding: 3px;">Auto bereken:</td>
-         <td style="padding: 3px;"><div id="calc_acid"></div></td>
-         <td></td>
-        </tr>
-        <tr>
-         <td style="vertical-align: top; float: right; padding: 3px;">CaSO4 gr:</td>
-	 <td style="padding: 3px;"><div id="wa_caso4"></div></td>
-	 <td style="padding: 3px;"><div id="ss_caso4"></div></td>
-         <td style="vertical-align: top; float: right; padding: 3px;">Richtgetal SO4:Cl:</td>
-	 <td style="padding: 3px;"><div style="float: left;" id="tgt_so4_cl"></div></td>
-	 <td style="padding: 3px;"><div style="float: left;" id="wrt_so4_cl"></div></td>
-         <td style="vertical-align: top; float: right; padding: 3px;"><div class='c_mashph'>Gewenst maish pH:</div></td>
-         <td style="padding: 3px;"><div id="mash_ph" class='c_mashph'></div></td>
-         <td></td>
-        </tr>
-        <tr>
-         <td style="vertical-align: top; float: right; padding: 3px;">MgSO4 gr:</td>
-	 <td style="padding: 3px;"><div id="wa_mgso4"></div></td>
-	 <td style="padding: 3px;"><div id="ss_mgso4"></div></td>
-         <td style="vertical-align: top; float: right; padding: 3px;">Huidig SO4:Cl:</td>
-	 <td style="padding: 3px;"><div style="float: left;" id="got_so4_cl"></div></td>
-         <td style="padding: 3px;"><div style="float: left;" id="wr_so4_cl"></div></td>
-         <td style="vertical-align: top; float: right; padding: 3px;">Aanzuren met:</td>
-	 <td style="padding: 3px;"><input readonly="1" id="wa_acid_name" /></td>
-	 <td style="padding: 3px;"><div style="float: left;" id="wa_acid_perc"></div></td>
-	</tr>
-        <tr>
-         <td style="vertical-align: top; float: right; padding: 3px;">NaCl gr:</td>
-	 <td style="padding: 3px;"><div id="wa_nacl"></div></td>
-	 <td style="padding: 3px;"><div style="float: left;" id="ss_nacl"></div></td>
-	 <td style="vertical-align: top; float: right; padding: 3px;">Voor koken pH:</td>
-         <td style="padding: 3px;"><div id="preboil_ph"></div></td>
-	 <td></td>
-	 <td style="vertical-align: top; float: right; padding: 3px;">Zuur hoeveelheid:</td>
-         <td style="padding: 3px;"><div style="float: left;" id="wa_acid"></div></td>
-         <td></td>
-	</tr>
-	<tr>
-         <td style="vertical-align: top; float: right; padding: 3px;">MgCl2 gr:</td>
-	 <td style="padding: 3px;"><div id="wa_mgcl2"></div></td>
-         <td style="padding: 3px;"><div id="ss_mgcl2"></div></td>
-	 <td colspan="3"></td>
-         <td style="vertical-align: top; float: right; padding: 3px;">Gewenst spoel pH:</td>
-         <td style="padding: 3px;"><div id="sparge_ph"></div></td>
-         <td></td>
-        </tr>
-	<tr>
-         <td style="vertical-align: top; float: right; padding: 3px;">NaHCO3 gr:</td>
-	 <td style="padding: 3px;"><div id="wa_nahco3"></div></td>
-	 <td colspan="4"></td>
-         <td style="vertical-align: top; float: right; padding: 3px;">Aanzuren met:</td>
-         <td style="padding: 3px;"><input readonly="1" id="sparge_acid_type" /></td>
-	 <td style="padding: 3px;"><div id="sparge_acid_perc"></div></td>
-        </tr>
-	<tr>
-         <td style="vertical-align: top; float: right; padding: 3px;">CaCO3 gr:</td>
-	 <td style="padding: 3px;"><div id="wa_caco3"></div></td>
-	 <td colspan="4"></td>
-         <td style="vertical-align: top; float: right; padding: 3px;">Zuur hoeveelheid:</td>
-	 <td style="padding: 3px;"><div id="sparge_acid_amount"></div></td>
-         <td></td>
-        </tr>
-       </table>
-      </div>
-     </div> <!-- tab water -->
-
-   </div> <!-- jqxTabs -->
-
-<?php
-page_footer();
-?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/www/rec_view.php	Fri Aug 05 10:53:56 2022 +0200
@@ -0,0 +1,386 @@
+<?php
+require_once($_SERVER['DOCUMENT_ROOT'].'/includes/global.inc.php');
+page_header('Recept wijzigen', 'rec_view');
+// met POST commando's record ophalen.
+?>
+
+   <!-- Editor tabs. -->
+   <div id="jqxTabs">
+     <ul>
+      <li>Algemeen</li>
+      <li>Vergistbaar</li>
+      <li>Hoppen</li>
+      <li>Diversen</li>
+      <li>Gist</li>
+      <li>Maischen</li>
+      <li>Water</li>
+     </ul>
+
+     <div> <!-- tab algemeen -->
+      <div style="overflow: hidden;">
+       <table style="width: 100%;">
+        <tr>
+         <td style="vertical-align: top; float: right; padding: 3px;">Recept naam:</td>
+	 <td align="left" colspan="5" style="vertical-align: top; padding: 3px;"><input id="name" /></td>
+        </tr>
+        <tr>
+         <td style="vertical-align: top; float: right; padding: 3px;">Opmerkingen:</td>
+         <td colspan="5" style="padding: 3px;"><textarea id="notes"></textarea></td>
+	</tr>
+        <tr>
+	 <td style="vertical-align: top; float: right; padding: 3px;">Brouw type:</td>
+	 <td align="left" style="vertical-align: top; padding: 3px;"><input readonly="1" id="type" /></td>
+         <td style="vertical-align: top; float: right; padding: 3px;">Brouwzaal rendement:</td>
+         <td colspan="3" style="padding: 3px;"><div id="efficiency"></div></td>
+        </tr>
+        <tr>
+         <td style="vertical-align: top; float: right; padding: 3px;">Brouw volume L:</td>
+         <td style="padding: 3px;"><div id="batch_size"></div></td>
+         <td style="vertical-align: top; float: right; padding: 3px;">Kooktijd minuten:</td>
+	 <td style="padding: 3px;"><div id="boil_time"></div></td>
+         <td style="vertical-align: top; float: right; padding: 3px;">Kook volume L:</td>
+         <td style="padding: 3px;"><div id="boil_size"></div></td>
+	</tr>
+        <tr>
+         <td colspan="6"><hr></td>
+        </tr>
+	<tr>
+         <td></td>
+	 <th>Bierstijl gegevens</th>
+         <td align="left" colspan="4"></td>
+        </tr>
+        <tr>
+         <td style="vertical-align: top; float: right; padding: 3px;">Stijlgids:</td>
+         <td align="left" style="vertical-align: top; padding: 3px;"><input readonly="1" id="st_guide" /></td>
+         <td style="vertical-align: top; float: right; padding: 3px;">Bier stijl:</td>
+         <td align="left" style="vertical-align: top; padding: 3px;"><input readonly="1" id="st_name" /></td>
+         <td style="vertical-align: top; float: right; padding: 3px;">Bier groep:</td>
+         <td align="left" style="vertical-align: top; padding: 3px;"><input readonly="1" id="st_letter" /></td>
+        </tr>
+        <tr>
+         <td style="vertical-align: top; float: right; padding: 3px;">Stijl type:</td>
+         <td align="left" style="vertical-align: top; padding: 3px;"><input readonly="1"  id="st_type" /></td>
+         <td style="vertical-align: top; float: right; padding: 3px;">Categorie:</td>
+         <td align="left" style="vertical-align: top; padding: 3px;"><input readonly="1" id="st_category" /></td>
+         <td style="vertical-align: top; float: right; padding: 3px;">Categorie nr:</td>
+         <td style="padding: 3px;"><div id="st_category_number"></div></td>
+        </tr>
+	<tr>
+         <td style="vertical-align: top; float: right; padding: 3px;">Verwacht start SG:</td>
+         <td style="padding: 3px;"><div style="float: left;" id="est_og"></div><div style="float: left; margin-left: 15px;" id="st_og_min"></div><div style="float: left; margin-left: 5px;" id="st_og_max"></div></td>
+         <td style="vertical-align: top; float: right; padding: 3px;">Verwacht eind SG:</td>
+	 <td style="padding: 3px;"><div style="float: left;" id="est_fg"></div><div style="float: left; margin-left: 15px;" id="st_fg_min"></div><div style="float: left; margin-left: 5px;" id="st_fg_max"></div></td>
+         <td style="vertical-align: top; float: right; padding: 3px;">Alcohol vol.%:</td>
+         <td style="padding: 3px;"><div style="float: left;" id="est_abv"></div><div style="float: left; margin-left: 15px;" id="st_abv_min"></div><div style="float: left; margin-left: 5px;" id="st_abv_max"></div></td>
+	</tr>
+        <tr>
+         <td style="vertical-align: top; float: right; padding: 3px;">Kleur EBC:</td>
+         <td style="padding: 3px;"><div style="float: left;" id="est_color"></div><div style="float: left; margin-left: 15px;" id="st_color_min"></div><div style="float: left; margin-left: 5px;" id="st_color_max"></div><div id="bcolor" class='ebccolor'> </div></td>
+         <td style="vertical-align: top; float: right; padding: 3px;">Kleur methode:</td>
+	 <td align="left" style="vertical-align: top; padding: 3px;"><input readonly="1" id="color_method" /></td>
+         <td style="vertical-align: top; float: right; padding: 3px;">Koolzuur vol:</td>
+         <td style="padding: 3px;"><div style="float: left;" id="est_carb"></div><div style="float: left; margin-left: 15px;" id="st_carb_min"></div><div style="float: left; margin-left: 5px;" id="st_carb_max"></div></td>
+	</tr>
+        <tr>
+         <td style="vertical-align: top; float: right; padding: 3px;">Bitterheid IBU:</td>
+         <td style="padding: 3px;"><div style="float: left;" id="est_ibu"></div><div style="float: left; margin-left: 15px;" id="st_ibu_min"></div><div style="float: left; margin-left: 5px;" id="st_ibu_max"></div></td>
+         <td style="vertical-align: top; float: right; padding: 3px;">Bitterheid methode:</td>
+         <td align="left" style="vertical-align: top; padding: 3px;"><input readonly="1" id="ibu_method" /></td>
+         <td style="vertical-align: top; float: right; padding: 3px;">Energie-inhoud kcal/l:</td>
+         <td style="padding: 3px;"><div style="float: left;" id="kcal"></div></div></td>
+        </tr>
+       </table>
+       <div style="float: right; margin-top: 30px; margin-bottom: 10px;">
+        <input style="margin-right: 600px;" type="button" id="Terug"   value="Terug" />
+       </div>
+      </div>
+     </div> <!-- tab algemeen -->
+
+     <div> <!-- tab vergistbaar -->
+      <div style="overflow: hidden;">
+       <table style="width: 100%;">
+        <tr>
+         <td style="vertical-align: top; float: right; padding: 3px;">Kleur:</td>
+         <td style="padding: 3px;"><div style="float: left;" id="est_color2"></div><div id="bcolor2" class='ebccolor'> </div></td>
+         <td style="vertical-align: top; float: right; padding: 3px;">Percentage moutstort:</td>
+         <td style="padding: 3px;"><div style="float: left;" id="perc_malts"></div></td>
+	</tr>
+        <tr>
+         <td style="vertical-align: top; float: right; padding: 3px;">Begin SG:</td>
+         <td style="padding: 3px;"><div style="float: left;" id="est_og2"></div></td>
+         <td style="vertical-align: top; float: right; padding: 3px;">Percentage suiker:</td>
+         <td style="padding: 3px;"><div style="float: left;" id="perc_sugars"></div></td>
+        </tr>
+	<tr>
+         <td colspan="2"></td>
+         <td style="vertical-align: top; float: right; padding: 3px;">Percentage cara:</td>
+         <td style="padding: 3px;"><div style="float: left;" id="perc_cara"></div></td>
+        </tr>
+        <tr>
+         <td colspan="2"> </td>
+         <td style="vertical-align: top; float: right; padding: 3px;">Lintner totaal:</td>
+         <td style="padding: 3px;"><div style="float: left;" id="ferm_lintner"></div></td>
+        </tr>
+        <tr>
+         <td align="center" colspan="4"><div id="fermentableGrid"></div></td>
+        </tr>
+       </table>
+      </div>
+     </div> <!-- tab vergistbaar -->
+
+     <div> <!-- tab hoppen -->
+      <div style="overflow: hidden;">
+       <table style="width: 100%;">
+        <tr> 
+	 <td style="vertical-align: top; float: right; padding: 3px;">Bitterheid IBU:</td>
+	 <td style="padding: 3px;"><div id="est_ibu2"></div></td>
+         <td style="vertical-align: top; float: right; padding: 3px;">Smaak bijdrage:</td>
+         <td style="padding: 3px;"><div id="hop_flavour"></div></td>
+         <td style="vertical-align: top; float: right; padding: 3px;">Aroma bijdrage:</td>
+         <td style="padding: 3px;"><div id="hop_aroma"></div></td>
+        </tr>
+        <tr>
+         <td align="center" colspan="6"><div id="hopGrid"></div></td>
+        </tr>
+       </table>
+      </div>
+     </div> <!-- tab hoppen -->
+
+     <div> <!-- tab misc -->
+      <div style="overflow: hidden;">
+       <table style="width: 100%;">
+        <tr><td>&nbsp;</td></tr>
+        <tr><td align="center"><div id="miscGrid"></div></td></tr>
+       </table>
+      </div>
+     </div> <!-- tab misc -->
+
+     <div> <!-- tab gisten -->
+      <div style="overflow: hidden;">
+       <table style="width: 100%;">
+        <tr>
+         <td style="vertical-align: top; float: right; padding: 3px;">Verwacht eind SG:</td>
+         <td style="padding: 3px;"><div id="est_fg2"></div></td>
+         <td style="vertical-align: top; float: right; padding: 3px;">Verwacht ABV %:</td>
+         <td style="padding: 3px;"><div id="est_abv2"></div></td>
+        </tr>
+        <tr><td colspan="4">&nbsp;</td></tr>
+        <tr><td colspan="4" align="center"><div id="yeastGrid"></div></td></tr>
+       </table>
+      </div>
+     </div> <!-- tab gisten -->
+
+     <div> <!-- tab maischen -->
+      <div style="overflow: hidden;">
+       <table style="width: 100%;">
+        <tr>
+         <td style="vertical-align: top; float: right; padding: 3px;">Maischchema:</td>
+	 <td align="left" style="vertical-align: top; padding: 3px;"><input readonly="1" id="mash_name" /></td>
+         <td colspan="2"></td>
+	</tr>
+        <tr><td colspan="4">&nbsp;</td></tr>
+        <tr><td align="center" colspan="4" style="padding: 3px;"><div id="mashGrid"></div></td></tr>
+       </table>
+      </div>
+     </div> <!-- tab maischen -->
+
+     <div> <!-- tab water -->
+      <div style="overflow: hidden;">
+       <table style="width: 100%;">
+        <tr>
+         <td align="center" colspan="9">
+          <div id='water_totals'>
+ 	   <table style="width: 100%;">
+            <caption>Water overzicht</caption>
+	    <tr>
+	     <td align="left" style="vertical-align: top; padding: 3px;">Water profiel</td>
+             <td style="width: 50px; padding: 3px;">Spoel</td>
+             <td style="width: 97px; padding: 3px;">Volume</td>
+             <td style="width: 77px; padding: 3px;">Ca</td>
+	     <td style="width: 77px; padding: 3px;">Mg</td>
+             <td style="width: 77px; padding: 3px;">HCO3</td>
+             <td style="width: 77px; padding: 3px;">CaCO3</td>
+             <td style="width: 77px; padding: 3px;">Na</td>
+             <td style="width: 77px; padding: 3px;">Cl</td>
+	     <td style="width: 77px; padding: 3px;">SO4</td>
+	     <td style="width: 77px; padding: 3px;">pH</td>
+	     <td style="width: 77px; padding: 3px;">Hardheid</td>
+             <td style="width: 77px; padding: 3px;">RA</td>
+	    </tr>
+	    <tr>
+	     <td><input readonly="1" id="w1_name" /></td>
+             <td><div style='margin-left: 10px;' id='w1_button'></div></td>
+             <td><div id="w1_amount"></div></td>
+             <td><div id="w1_calcium"></div></td>
+             <td><div id="w1_magnesium"></div></td>
+             <td><div id="w1_bicarbonate"></div></td>
+	     <td><div id="w1_total_alkalinity"></div></td>
+             <td><div id="w1_sodium"></div></td>
+             <td><div id="w1_chloride"></div></td>
+             <td><div id="w1_sulfate"></div></td>
+	     <td><div id="w1_ph"></div></td>
+	     <td><div id="w1_hardness"></div></td>
+             <td><div id="w1_ra"></div></td>
+            </tr>
+	    <tr>
+	     <td><input readonly="1" id="w2_name" /></td>
+             <td><div style='margin-left: 10px;' id='w2_button'></div></td>
+             <td><div id="w2_amount"></div></td>
+             <td><div id="w2_calcium"></div></td>
+             <td><div id="w2_magnesium"></div></td>
+             <td><div id="w2_bicarbonate"></div></td>
+	     <td><div id="w2_total_alkalinity"></div></td>
+             <td><div id="w2_sodium"></div></td>
+             <td><div id="w2_chloride"></div></td>
+             <td><div id="w2_sulfate"></div></td>
+	     <td><div id="w2_ph"></div></td>
+             <td><div id="w2_hardness"></div></td>
+             <td><div id="w2_ra"></div></td>
+            </tr>
+            <tr>
+	     <td style="vertical-align: top; padding: 3px; float: left;">Gemengd water:</td>
+             <td><div style='margin-left: 10px;' id='wg_button'></div></td>
+             <td><div id="wg_amount"></div></td>
+             <td><div id="wg_calcium"></div></td>
+             <td><div id="wg_magnesium"></div></td>
+             <td><div id="wg_bicarbonate"></div></td>
+	     <td><div id="wg_total_alkalinity"></div></td>
+             <td><div id="wg_sodium"></div></td>
+             <td><div id="wg_chloride"></div></td>
+	     <td><div id="wg_sulfate"></div></td>
+	     <td><div id="wg_ph"></div></td>
+             <td><div id="wg_hardness"></div></td>
+             <td><div id="wg_ra"></div></td>
+            </tr>
+            <tr>
+	     <td style="vertical-align: top; padding: 3px; float: left;">Behandeld maisch water:</td>
+             <td></td>
+             <td><div></div></td>
+             <td><div id="wb_calcium"></div></td>
+             <td><div id="wb_magnesium"></div></td>
+             <td><div id="wb_bicarbonate"></div></td>
+             <td><div id="wb_total_alkalinity"></div></td>
+             <td><div id="wb_sodium"></div></td>
+	     <td><div id="wb_chloride"></div></td>
+	     <td><div id="wb_sulfate"></div></td>
+	     <td><div id="wb_ph"></div></td>
+             <td><div id="wb_hardness"></div></td>
+             <td><div id="wb_ra"></div></td>
+	    </tr>
+            <tr>
+	     <td style="vertical-align: top; padding: 3px; float: left;">Resultaat:</td>
+             <td></td>
+	     <td><div></div></td>
+             <td><div id="wr_calcium"></div></td>
+             <td><div id="wr_magnesium"></div></td>
+             <td><div id="wr_bicarbonate"></div></td>
+             <td><div id="wr_total_alkalinity"></div></td>
+             <td><div id="wr_sodium"></div></td>
+	     <td><div id="wr_chloride"></div></td>
+             <td><div id="wr_sulfate"></div></td>
+	     <td><div id="wr_ph"></div></td>
+             <td></td>
+             <td></td>
+            </tr>
+	    <tr>
+	     <td style="vertical-align: top; padding: 3px; float: left;">Behandeld spoelwater:</td>
+             <td></td>
+             <td><div id="sw_amount"></div></td>
+             <td><div id="sw_calcium"></div></td>
+             <td><div id="sw_magnesium"></div></td>
+             <td><div id="sw_bicarbonate"></div></td>
+	     <td><div id="sw_total_alkalinity"></div></td>
+             <td><div id="sw_sodium"></div></td>
+             <td><div id="sw_chloride"></div></td>
+             <td><div id="sw_sulfate"></div></td>
+	     <td><div id="sw_ph"></div></td>
+             <td><div id="sw_hardness"></div></td>
+             <td><div id="sw_ra"></div></td>
+            </tr>
+           </table>
+	  </div>
+         </td>
+	</tr>
+       <tr>
+        <th style="text-align: center;" colspan="3">Brouwzouten</th>
+        <th colspan="3"></th>
+        <th style="text-align: center;" colspan="3">Zuur toevoegingen</th>
+       </tr>
+        <tr>
+         <td style="vertical-align: top; float: right; padding: 3px;">CaCl2 gr:</td>
+	 <td style="padding: 3px;"><div id="wa_cacl2"></div></td>
+         <td style="padding: 3px;"><div id="ss_cacl2"></div></td>
+	 <td style="vertical-align: top; float: right; padding: 3px;">Bitterheidsindex:</td>
+	 <td style="padding: 3px;"><div style="float: left;" id="tgt_bu"></div></td>
+	 <td style="padding: 3px;"><div style="float: left;" id="wr_bu"></div></td>
+         <td style="vertical-align: top; float: right; padding: 3px;">Auto bereken:</td>
+         <td style="padding: 3px;"><div id="calc_acid"></div></td>
+         <td></td>
+        </tr>
+        <tr>
+         <td style="vertical-align: top; float: right; padding: 3px;">CaSO4 gr:</td>
+	 <td style="padding: 3px;"><div id="wa_caso4"></div></td>
+	 <td style="padding: 3px;"><div id="ss_caso4"></div></td>
+         <td style="vertical-align: top; float: right; padding: 3px;">Richtgetal SO4:Cl:</td>
+	 <td style="padding: 3px;"><div style="float: left;" id="tgt_so4_cl"></div></td>
+	 <td style="padding: 3px;"><div style="float: left;" id="wrt_so4_cl"></div></td>
+         <td style="vertical-align: top; float: right; padding: 3px;"><div class='c_mashph'>Gewenst maish pH:</div></td>
+         <td style="padding: 3px;"><div id="mash_ph" class='c_mashph'></div></td>
+         <td></td>
+        </tr>
+        <tr>
+         <td style="vertical-align: top; float: right; padding: 3px;">MgSO4 gr:</td>
+	 <td style="padding: 3px;"><div id="wa_mgso4"></div></td>
+	 <td style="padding: 3px;"><div id="ss_mgso4"></div></td>
+         <td style="vertical-align: top; float: right; padding: 3px;">Huidig SO4:Cl:</td>
+	 <td style="padding: 3px;"><div style="float: left;" id="got_so4_cl"></div></td>
+         <td style="padding: 3px;"><div style="float: left;" id="wr_so4_cl"></div></td>
+         <td style="vertical-align: top; float: right; padding: 3px;">Aanzuren met:</td>
+	 <td style="padding: 3px;"><input readonly="1" id="wa_acid_name" /></td>
+	 <td style="padding: 3px;"><div style="float: left;" id="wa_acid_perc"></div></td>
+	</tr>
+        <tr>
+         <td style="vertical-align: top; float: right; padding: 3px;">NaCl gr:</td>
+	 <td style="padding: 3px;"><div id="wa_nacl"></div></td>
+	 <td style="padding: 3px;"><div style="float: left;" id="ss_nacl"></div></td>
+	 <td style="vertical-align: top; float: right; padding: 3px;">Voor koken pH:</td>
+         <td style="padding: 3px;"><div id="preboil_ph"></div></td>
+	 <td></td>
+	 <td style="vertical-align: top; float: right; padding: 3px;">Zuur hoeveelheid:</td>
+         <td style="padding: 3px;"><div style="float: left;" id="wa_acid"></div></td>
+         <td></td>
+	</tr>
+	<tr>
+         <td style="vertical-align: top; float: right; padding: 3px;">MgCl2 gr:</td>
+	 <td style="padding: 3px;"><div id="wa_mgcl2"></div></td>
+         <td style="padding: 3px;"><div id="ss_mgcl2"></div></td>
+	 <td colspan="3"></td>
+         <td style="vertical-align: top; float: right; padding: 3px;">Gewenst spoel pH:</td>
+         <td style="padding: 3px;"><div id="sparge_ph"></div></td>
+         <td></td>
+        </tr>
+	<tr>
+         <td style="vertical-align: top; float: right; padding: 3px;">NaHCO3 gr:</td>
+	 <td style="padding: 3px;"><div id="wa_nahco3"></div></td>
+	 <td colspan="4"></td>
+         <td style="vertical-align: top; float: right; padding: 3px;">Aanzuren met:</td>
+         <td style="padding: 3px;"><input readonly="1" id="sparge_acid_type" /></td>
+	 <td style="padding: 3px;"><div id="sparge_acid_perc"></div></td>
+        </tr>
+	<tr>
+         <td style="vertical-align: top; float: right; padding: 3px;">CaCO3 gr:</td>
+	 <td style="padding: 3px;"><div id="wa_caco3"></div></td>
+	 <td colspan="4"></td>
+         <td style="vertical-align: top; float: right; padding: 3px;">Zuur hoeveelheid:</td>
+	 <td style="padding: 3px;"><div id="sparge_acid_amount"></div></td>
+         <td></td>
+        </tr>
+       </table>
+      </div>
+     </div> <!-- tab water -->
+
+   </div> <!-- jqxTabs -->
+
+<?php
+page_footer();
+?>

mercurial