Fermentables database bool to int types. Dropdown lists are using tables with indexes. Dropdown lists display in Dutch. Save and delete in the database now use POST instead of GET. Added the added and dissolved_protein fields. Removed the ibu_gal_per_lb field. Redesigned the web page. Code cleanup.

Tue, 22 Jan 2019 20:27:45 +0100

author
Michiel Broek <mbroek@mbse.eu>
date
Tue, 22 Jan 2019 20:27:45 +0100
changeset 195
2ac491548d8d
parent 194
d202777ebae5
child 196
531d5458782f

Fermentables database bool to int types. Dropdown lists are using tables with indexes. Dropdown lists display in Dutch. Save and delete in the database now use POST instead of GET. Added the added and dissolved_protein fields. Removed the ibu_gal_per_lb field. Redesigned the web page. Code cleanup.

README.design file | annotate | diff | comparison | revisions
www/import/from_brouwhulp.php file | annotate | diff | comparison | revisions
www/includes/db_inventory_fermentables.php file | annotate | diff | comparison | revisions
www/inv_fermentables.php file | annotate | diff | comparison | revisions
www/js/global.js file | annotate | diff | comparison | revisions
www/js/inv_fermentables.js file | annotate | diff | comparison | revisions
--- a/README.design	Mon Jan 21 20:45:18 2019 +0100
+++ b/README.design	Tue Jan 22 20:27:45 2019 +0100
@@ -31,18 +31,21 @@
 Web interface bouwen met jqwidgets.
 
 
-Database inventaris:		Werking	Maten
-----------------------------	-------	-------
+Database inventaris:		Werking	Maten	Index/Strings Bool/Ints	Utf-8	POST
+----------------------------	-------	-------	------------- ---------	-----	----
 inventory_equipments		Ok.	Ok.
-inventory_fermentables		Ok.	Ok.
+inventory_fermentables		Ok.	Ok.		Ok.	Ok.		Ok.
 inventory_hops			Ok.	Ok.
-profile_mash			Ok.	Ok.
 inventory_miscs			Ok.
-profile_styles			Ok.	Ok.
 inventory_suppliers		Ok.	Ok.
-profile_water			Ok.	Ok.
 inventory_water			Ok.	Ok.
 inventory_yeasts		Ok.	Ok.
+profile_mash                    Ok.     Ok.
+profile_profiles		Ok.	Ok.			Ok.
+profile_styles                  Ok.     Ok.
+profile_water                   Ok.     Ok.
+recipes
+products
 
 Handelsmaten (een zooitje ongeregeld):
 vergistbare ingredienten:	Prijs per kilo, hoeveelheid in gram.
--- a/www/import/from_brouwhulp.php	Mon Jan 21 20:45:18 2019 +0100
+++ b/www/import/from_brouwhulp.php	Tue Jan 22 20:27:45 2019 +0100
@@ -51,15 +51,37 @@
 	foreach ($myfermentables->FERMENTABLE as $fermentable) {
 
 		$sql  = "INSERT INTO inventory_fermentables SET name='" . mysqli_real_escape_string($db, $fermentable->NAME);
-		$sql .= "', type='" . $fermentable->TYPE;
+		if ($fermentable->TYPE == 'Grain')
+			$sql .= "', type='0";
+		else if ($fermentable->TYPE == 'Sugar')
+			$sql .= "', type='1";
+		else if ($fermentable->TYPE == 'Extract')
+			$sql .= "', type='2";
+		else if ($fermentable->TYPE == 'Dry extract')
+			$sql .= "', type='3";
+		else if ($fermentable->TYPE == 'Adjunct')
+			$sql .= "', type='4";
+		else
+			echo "Unknown TYPE " . $fermentable->TYPE . PHP_EOL;
 		if ($fermentable->YIELD)
 			$sql .= "', yield='" . floatval($fermentable->YIELD);
 		if ($fermentable->COLOR) {
-			$srm = floatval($fermentable->COLOR);
-			$ebc = srm_to_ebc($srm);
-			$sql .= "', color='" . $ebc;
+			$sql .= "', color='" . srm_to_ebc(floatval($fermentable->COLOR));
 		}
 		($fermentable->ADD_AFTER_BOIL == "TRUE") ? $sql .= "', add_after_boil='1" : $sql .= "', add_after_boil='0";
+		if ($fermentable->ADDED == 'Mash')
+			$sql .= "', added='0";
+		else if ($fermentable->ADDED == 'Boil')
+			$sql .= "', added='1";
+		else if ($fermentable->ADDED == 'Fermentation')
+			$sql .= "', added='2";
+		else if ($fermentable->ADDED == 'Lagering')
+			$sql .= "', added='3";
+		else if ($fermentable->ADDED == 'Bottle')
+			$sql .= "', added='4";
+		else
+			echo "Unknown ADDED " . $fermentable->ADDED . PHP_EOL;
+
 		$sql .= "', origin='" . mysqli_real_escape_string($db, $fermentable->ORIGIN);
 		$sql .= "', supplier='" . mysqli_real_escape_string($db, $fermentable->SUPPLIER);
 		$sql .= "', notes='" . mysqli_real_escape_string($db, $fermentable->NOTES);
@@ -71,6 +93,8 @@
 			$sql .= "', diastatic_power='" . floatval($fermentable->DIASTATIC_POWER);
 		if ($fermentable->PROTEIN)
 			$sql .= "', protein='" . floatval($fermentable->PROTEIN);
+		if ($fermentable->DISSOLVED_PROTEIN)
+			$sql .= "', dissolved_protein='" . floatval($fermentable->DISSOLVED_PROTEIN);
 		if ($fermentable->MAX_IN_BATCH)
 			$sql .= "', max_in_batch='" . floatval($fermentable->MAX_IN_BATCH);
 		($fermentable->RECOMMEND_MASH == "TRUE") ? $sql .= "', recommend_mash='1" : $sql .= "', recommend_mash='0";
@@ -88,7 +112,22 @@
 			$sql .= "', di_ph='" . floatval($fermentable->DI_pH);
 		if ($fermentable->{'ACID_TO_pH_5.7'})
 			$sql .= "', acid_to_ph_57='" . floatval($fermentable->{'ACID_TO_pH_5.7'});
-		$sql .= "', graintype='" . $fermentable->GRAINTYPE;
+		if ($fermentable->GRAINTYPE == 'Base')
+			$sql .= "', graintype='0";
+		else if ($fermentable->GRAINTYPE == 'Roast')
+			$sql .= "', graintype='1";
+		else if ($fermentable->GRAINTYPE == 'Crystal')
+			$sql .= "', graintype='2";
+		else if ($fermentable->GRAINTYPE == 'Kilned')
+			$sql .= "', graintype='3";
+		else if ($fermentable->GRAINTYPE == 'Sour malt')
+			$sql .= "', graintype='4";
+		else if ($fermentable->GRAINTYPE == 'Special')
+			$sql .= "', graintype='5";
+		else if ($fermentable->GRAINTYPE == 'No malt')
+			$sql .= "', graintype='6";
+		else
+			echo "Unknown GRAINTYPE " . $fermentable->GRAINTYPE . PHP_EOL;
 		$sql .= "';";
 		if (! $result = mysqli_query($db, $sql)) {
 			printf("Error: %s\n", mysqli_error($db));
--- a/www/includes/db_inventory_fermentables.php	Mon Jan 21 20:45:18 2019 +0100
+++ b/www/includes/db_inventory_fermentables.php	Tue Jan 22 20:27:45 2019 +0100
@@ -12,90 +12,79 @@
 mysqli_set_charset($connect, "utf8" );
 
 // get data and store in a json array
-$query = "SELECT * FROM inventory_fermentables ORDER BY supplier,name";
-if (isset($_GET['insert'])) {
-	// INSERT COMMAND
-	$sql  = "INSERT INTO `inventory_fermentables` SET name='" . mysqli_real_escape_string($connect, $_GET['name']);
-	$sql .= "', type='" . $_GET['type'];
-	$sql .= "', yield='" . $_GET['yield'];
-	$sql .= "', color='" . $_GET['color'];
-	($_GET['add_after_boil'] == 'true') ? $sql .= "', add_after_boil='1" : $sql .= "', add_after_boil='0";
-	$sql .= "', origin='" . mysqli_real_escape_string($connect, $_GET['origin']);
-	$sql .= "', supplier='" . mysqli_real_escape_string($connect, $_GET['supplier']);
-	$sql .= "', notes='" . mysqli_real_escape_string($connect, $_GET['notes']);
-	$sql .= "', coarse_fine_diff='" . $_GET['coarse_fine_diff'];
-	$sql .= "', moisture='" . $_GET['moisture'];
-	$sql .= "', diastatic_power='" . $_GET['diastatic_power'];
-	$sql .= "', protein='" . $_GET['protein'];
-	$sql .= "', max_in_batch='" . $_GET['max_in_batch'];
-	($_GET['recommend_mash'] == 'true') ? $sql .= "', recommend_mash='1" : $sql .= "', recommend_mash='0";
-	$sql .= "', ibu_gal_per_lb='" . $_GET['ibu_gal_per_lb'];
-	($_GET['always_on_stock'] == 'true') ? $sql .= "', always_on_stock='1" : $sql .= "', always_on_stock='0";
-	$sql .= "', di_ph='" . $_GET['di_ph'];
-	$sql .= "', acid_to_ph_57='" . $_GET['acid_to_ph_57'];
-	$sql .= "', graintype='" . mysqli_real_escape_string($connect, $_GET['graintype']);
-	$sql .= "', inventory='" . $_GET['inventory'];
-	$sql .= "', cost='" . $_GET['cost'];
-	$sql .= "', production_date='" . $_GET['production_date'];
-	$sql .= "', tht_date='" . $_GET['tht_date'];
-	//$sql .= "', supplier_rec='" . $_GET['supplier_rec'];
-	$sql .= "';";
+if (isset($_POST['insert']) || isset($_POST['update'])) {
+	if (isset($_POST['insert'])) {
+		$sql  = "INSERT INTO `inventory_fermentables` SET ";
+	}
+	if (isset($_POST['update'])) {
+		$sql  = "UPDATE `inventory_fermentables` SET ";
+	}
+
+	$sql .= "name='" . mysqli_real_escape_string($connect, $_POST['name']);
+	$sql .= "', type='" . $_POST['type'];
+	$sql .= "', yield='" . $_POST['yield'];
+	$sql .= "', color='" . $_POST['color'];
+	($_POST['add_after_boil'] == 'true') ? $sql .= "', add_after_boil='1" : $sql .= "', add_after_boil='0";
+	$sql .= "', origin='" . mysqli_real_escape_string($connect, $_POST['origin']);
+	$sql .= "', supplier='" . mysqli_real_escape_string($connect, $_POST['supplier']);
+	$sql .= "', notes='" . mysqli_real_escape_string($connect, $_POST['notes']);
+	$sql .= "', coarse_fine_diff='" . $_POST['coarse_fine_diff'];
+	$sql .= "', moisture='" . $_POST['moisture'];
+	$sql .= "', diastatic_power='" . $_POST['diastatic_power'];
+	$sql .= "', protein='" . $_POST['protein'];
+	$sql .= "', dissolved_protein='" . $_POST['dissolved_protein'];
+	$sql .= "', max_in_batch='" . $_POST['max_in_batch'];
+	($_POST['recommend_mash'] == 'true') ? $sql .= "', recommend_mash='1" : $sql .= "', recommend_mash='0";
+	$sql .= "', added='" . $_POST['added'];
+	($_POST['always_on_stock'] == 'true') ? $sql .= "', always_on_stock='1" : $sql .= "', always_on_stock='0";
+	$sql .= "', di_ph='" . $_POST['di_ph'];
+	$sql .= "', acid_to_ph_57='" . $_POST['acid_to_ph_57'];
+	$sql .= "', graintype='" . $_POST['graintype'];
+	$sql .= "', inventory='" . $_POST['inventory'];
+	$sql .= "', cost='" . $_POST['cost'] . "'";
+	if ($_POST['production_date'] == '')
+		$sql .= ", production_date=NULL";
+	else
+		$sql .= ", production_date='" . $_POST['production_date'] . "'";
+	if ($_POST['tht_date'] == '')
+		$sql .= ", tht_date=NULL";
+	else
+		$sql .= ", tht_date='" . $_POST['tht_date'] . "'";
+	if (isset($_POST['insert'])) {
+		$sql .= ";";
+	}
+	if (isset($_POST['update'])) {
+		$sql .= " WHERE record='" . $_POST['record'] . "';";
+	}
+	syslog(LOG_NOTICE, $sql);
+
 	$result = mysqli_query($connect, $sql);
 	if (! $result) {
 		syslog(LOG_NOTICE, "db_inventory_fermentables: ".$sql." result: ".mysqli_error($connect));
 	} else {
-		syslog(LOG_NOTICE, "db_inventory_fermentables: inserted ".$_GET['name']);
+		if (isset($_POST['update'])) {
+			syslog(LOG_NOTICE, "db_inventory_fermentables: updated record ".$_POST['record']);
+		} else {
+			$lastid = mysqli_insert_id($connect);
+			syslog(LOG_NOTICE, "db_inventory_fermentables: inserted record ".$lastid);
+		}
 	}
 	echo $result;
 
-} else if (isset($_GET['update'])) {
-	// UPDATE COMMAND
-	$sql  = "UPDATE `inventory_fermentables` SET name='" . mysqli_real_escape_string($connect, $_GET['name']);
-	$sql .= "', type='" . $_GET['type'];
-	$sql .= "', yield='" . $_GET['yield'];
-	$sql .= "', color='" . $_GET['color'];
-	($_GET['add_after_boil'] == 'true') ? $sql .= "', add_after_boil='1" : $sql .= "', add_after_boil='0";
-	$sql .= "', origin='" . mysqli_real_escape_string($connect, $_GET['origin']);
-	$sql .= "', supplier='" . mysqli_real_escape_string($connect, $_GET['supplier']);
-	$sql .= "', notes='" . mysqli_real_escape_string($connect, $_GET['notes']);
-	$sql .= "', coarse_fine_diff='" . $_GET['coarse_fine_diff'];
-	$sql .= "', moisture='" . $_GET['moisture'];
-	$sql .= "', diastatic_power='" . $_GET['diastatic_power'];
-	$sql .= "', protein='" . $_GET['protein'];
-	$sql .= "', max_in_batch='" . $_GET['max_in_batch'];
-	($_GET['recommend_mash'] == 'true') ? $sql .= "', recommend_mash='1" : $sql .= "', recommend_mash='0";
-	$sql .= "', ibu_gal_per_lb='" . $_GET['ibu_gal_per_lb'];
-	($_GET['always_on_stock'] == 'true') ? $sql .= "', always_on_stock='1" : $sql .= "', always_on_stock='0";
-	$sql .= "', di_ph='" . $_GET['di_ph'];
-	$sql .= "', acid_to_ph_57='" . $_GET['acid_to_ph_57'];
-	$sql .= "', graintype='" . mysqli_real_escape_string($connect, $_GET['graintype']);
-	$sql .= "', inventory='" . $_GET['inventory'];
-	$sql .= "', cost='" . $_GET['cost'];
-	$sql .= "', production_date='" . $_GET['production_date'];
-	$sql .= "', tht_date='" . $_GET['tht_date'];
-	//$sql .= "', supplier_rec='" . $_GET['supplier_rec'];
-	$sql .= "' WHERE record='" . $_GET['record'] . "';";
+} else if (isset($_POST['delete'])) {
+	// DELETE COMMAND
+	$sql = "DELETE FROM `inventory_fermentables` WHERE record='".$_POST['record']."';";
 	$result = mysqli_query($connect, $sql);
 	if (! $result) {
 		syslog(LOG_NOTICE, "db_inventory_fermentables: ".$sql." result: ".mysqli_error($connect));
 	} else {
-		syslog(LOG_NOTICE, "db_inventory_fermentables: updated record ".$_GET['record']);
-	}
-	echo $result;
-
-} else if (isset($_GET['delete'])) {
-	// DELETE COMMAND
-	$sql = "DELETE FROM `inventory_fermentables` WHERE record='".$_GET['record']."';";
-	$result = mysqli_query($connect, $sql);
-	if (! $result) {
-		syslog(LOG_NOTICE, "db_inventory_fermentables: ".$sql." result: ".mysqli_error($connect));
-	} else {
-		syslog(LOG_NOTICE, "db_inventory_fermentables: deleted record ".$_GET['record']);
+		syslog(LOG_NOTICE, "db_inventory_fermentables: deleted record ".$_POST['record']);
 	}
 	echo $result;
 
 } else {
 	// SELECT COMMAND
+	$query = "SELECT * FROM inventory_fermentables ORDER BY supplier,name";
 	$result = mysqli_query($connect, $query) or die("SQL Error 1: " . mysqli_error($connect));
 	while ($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) {
 		$fermentables[] = array(
@@ -112,9 +101,10 @@
 			'moisture' => $row['moisture'],
 			'diastatic_power' => $row['diastatic_power'],
 			'protein' => $row['protein'],
+			'dissolved_protein' => $row['dissolved_protein'],
 			'max_in_batch' => $row['max_in_batch'],
 			'recommend_mash' => $row['recommend_mash'],
-			'ibu_gal_per_lb' => $row['ibu_gal_per_lb'],
+			'added' => $row['added'],
 			'always_on_stock' => $row['always_on_stock'],
 			'di_ph' => $row['di_ph'],
 			'acid_to_ph_57' => $row['acid_to_ph_57'],
--- a/www/inv_fermentables.php	Mon Jan 21 20:45:18 2019 +0100
+++ b/www/inv_fermentables.php	Tue Jan 22 20:27:45 2019 +0100
@@ -16,70 +16,70 @@
      <table>
       <tr>
        <td align="right" style="vertical-align: top;">Product naam:</td>
-       <td align="left" style="vertical-align: top;"><input id="name" /></td>
-       <td align="right" style="vertical-align: top;">Type:</td>
-       <td align="left"><div id="type"></div></td>
+       <td align="left" colspan="3" style="vertical-align: top;"><input id="name" /></td>
+      </tr>
+      <tr>
+       <td align="right" style="vertical-align: top;">Opmerkingen:</td>
+       <td align="left" colspan="3"><textarea id="notes"></textarea></td>
       </tr>
       <tr>
-       <td align="right" style="vertical-align: top;">Opbrengst:</td>
+       <td align="right" style="vertical-align: top;">Type:</td>
+       <td align="left"><div id="type"></div></td>
+       <td align="right" style="vertical-align: top;">Opbrengst %:</td>
        <td align="left"><div id="yield"></div></td>
-       <td align="right" style="vertical-align: top;">Kleur:</td>
-       <td align="left"><div id="color"></div></td>
       </tr>
       <tr>
-       <td align="right" style="vertical-align: top;">Add after boil:</td>
-       <td align="left"><div id="add_after_boil"></div></td>
-       <td align="right" style="vertical-align: top;">Grof/fijn verschil:</td>
-       <td align="left"><div id="coarse_fine_diff"></div></td>
+       <td align="right" style="vertical-align: top;">Mout type:</td>
+       <td align="left"><div id="graintype"></div></td>
+       <td align="right" style="vertical-align: top;">Kleur EBC:</td>
+       <td align="left"><div id="color"></div></td>
       </tr>
       <tr>
        <td align="right" style="vertical-align: top;">Herkomst:</td>
        <td align="left" style="vertical-align: top;"><input id="origin" /></td>
-       <td align="right" style="vertical-align: top;">Moisture:</td>
+       <td align="right" style="vertical-align: top;">Vochtgehalte %:</td>
        <td align="left"><div id="moisture"></div></td>
       </tr>
       <tr>
        <td align="right" style="vertical-align: top;">Leverancier:</td>
        <td align="left" style="vertical-align: top;"><input id="supplier" /></td>
-       <td align="right" style="vertical-align: top;">Diastatic Power:</td>
+       <td align="right" style="vertical-align: top;">Grof/fijn verschil %:</td>
+       <td align="left"><div id="coarse_fine_diff"></div></td>
+      </tr>
+      <tr>
+       <td align="right" style="vertical-align: top;">Max. in stort %:</td>
+       <td align="left"><div id="max_in_batch"></div></td>
+       <td align="right" style="vertical-align: top;">Eiwitgehalte %:</td>
+       <td align="left"><div id="protein"></div></td>
+      </tr>
+      <tr>
+       <td align="right" style="vertical-align: top;">Maischen nodig:</td>
+       <td align="left"><div id="recommend_mash"></div></td>
+       <td align="right" style="vertical-align: top;">Opgelost eiwit %:</td>
+       <td align="left"><div id="dissolved_protein"></div></td>
+      </tr>
+      <tr>
+       <td align="right" style="vertical-align: top;">Toevoegen na koken:</td>
+       <td align="left"><div id="add_after_boil"></div></td>
+       <td align="right" style="vertical-align: top;">Enzymkracht &deg;WK:</td>
        <td align="left"><div id="diastatic_power"></div></td>
       </tr>
       <tr>
-       <td align="right" style="vertical-align: top;">protein:</td>
-       <td align="left"><div id="protein"></div></td>
-       <td align="right" style="vertical-align: top;">max_in_batch:</td>
-       <td align="left"><div id="max_in_batch"></div></td>
-      </tr>
-      <tr>
-       <td align="right" style="vertical-align: top;">recommend_mash:</td>
-       <td align="left"><div id="recommend_mash"></div></td>
-       <td align="right" style="vertical-align: top;">ibu_gal_per_lb:</td>
-       <td align="left"><div id="ibu_gal_per_lb"></div></td>
-      </tr>
-      <tr>
-       <td align="right" style="vertical-align: top;">always_on_stock:</td>
-       <td align="left"><div id="always_on_stock"></div></td>
-       <td align="right" style="vertical-align: top;">di_ph:</td>
+       <td align="right" style="vertical-align: top;">Toevoegen bij:</td>
+       <td align="left"><div id="added"></div></td>
+       <td align="right" style="vertical-align: top;">pH in demiwater:</td>
        <td align="left"><div id="di_ph"></div></td>
       </tr>
       <tr>
-       <td align="right" style="vertical-align: top;">acid_to_ph_57:</td>
+       <td align="right" style="vertical-align: top;">Altijd op voorraad:</td>
+       <td align="left"><div id="always_on_stock"></div></td>
+       <td align="right" style="vertical-align: top;">Base tot pH 5,7 mEq/l:</td>
        <td align="left"><div id="acid_to_ph_57"></div></td>
-       <td align="right" style="vertical-align: top;">graintype:</td>
-       <td align="left"><div id="graintype"></div></td>
-      </tr>
-<!--      <tr>
-       <td align="right" style="vertical-align: top;">supplier_rec:</td>
-       <td align="left" colspan="3"><div id="supplier_rec"></div></td>
-      </tr> -->
-      <tr>
-       <td align="right" style="vertical-align: top;">Opmerkingen:</td>
-       <td align="left" colspan="3"><textarea id="notes"></textarea></td>
       </tr>
       <tr>
        <td align="right" style="vertical-align: top;">Voorraad:</td>
        <td align="left"><div id="inventory"></div></td>
-       <td align="right" style="vertical-align: top;">Prijs:</td>
+       <td align="right" style="vertical-align: top;">Prijs per kg:</td>
        <td align="left"><div id="cost"></div></td>
       </tr>
       <tr>
@@ -89,10 +89,10 @@
        <td align="left" style="vertical-align: top;"><div id="tht_date"></div></td>
       </tr>
       <tr>
-       <td style="padding-top: 10px;" align="right"><input type="button" id="Delete" value="Delete" /></td>
+       <td style="padding-top: 40px;" align="right"><input type="button" id="Delete" value="Verwijder" /></td>
        <td align="right"></td>
        <td align="right"></td>
-       <td style="padding-top: 10px;" align="right"><input style="margin-right: 5px;" type="button" id="Save" value="Save" /><input id="Cancel" type="button" value="Cancel" /></td>
+       <td style="padding-top: 40px;" align="right"><input style="margin-right: 5px;" type="button" id="Save" value="Sla op" /><input id="Cancel" type="button" value="Annuleer" /></td>
       </tr>
      </table>
     </div>
--- a/www/js/global.js	Mon Jan 21 20:45:18 2019 +0100
+++ b/www/js/global.js	Tue Jan 22 20:27:45 2019 +0100
@@ -21,6 +21,173 @@
  *****************************************************************************/
 
 
+// dropdownlists arrays
+
+var StageData = [
+	{ id: 0,  en: "Plan",        nl: "Plan" },
+	{ id: 1,  en: "Wait",        nl: "Wacht" },
+	{ id: 2,  en: "Brew",        nl: "Brouwen" },
+	{ id: 3,  en: "Primary",     nl: "Hoofdgisting" },
+	{ id: 4,  en: "Secondary",   nl: "Nagisting" },
+	{ id: 5,  en: "Tertiary",    nl: "Lagering" },
+	{ id: 6,  en: "Package",     nl: "Afvullen" },
+	{ id: 7,  en: "Carbonation", nl: "Hergisten" },
+	{ id: 8,  en: "Mature",      nl: "Rijpen" },
+	{ id: 9,  en: "Taste",       nl: "Proeven" },
+	{ id: 10, en: "Ready",       nl: "Gereed" },
+	{ id: 11, en: "Closed",      nl: "Afgesloten" }
+];
+var StageSource = {
+	localdata: StageData,
+	datatype: "array",
+	datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }]
+};
+var StageAdapter = new $.jqx.dataAdapter(StageSource);
+
+var MaterialData = [
+	{ id: 0,  en: "Stainless Steel", nl: "RVS",       sh: 0.11 },
+	{ id: 1,  en: "Aluminium",       nl: "Aluminium", sh: 0.22 },
+	{ id: 2,  en: "Plastics",        nl: "Kunststof", sh: 0.46 },
+	{ id: 3,  en: "Coper",           nl: "Koper",     sh: 0.092 }
+];
+var MaterialSource = {
+	localdata: MaterialData,
+	datatype: "array",
+	datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }, { name: 'sh' }]
+};
+var MaterialAdapter = new $.jqx.dataAdapter(MaterialSource);
+
+var FermentableTypeData = [
+	{ id: 0, en: 'Grain',       nl: 'mout' },
+	{ id: 1, en: 'Sugar',       nl: 'suiker' },
+	{ id: 2, en: 'Extract',     nl: 'vloeibaar extract' },
+	{ id: 3, en: 'Dry extract', nl: 'droog extract' },
+	{ id: 4, en: 'Adjunct',     nl: 'ongemout graan' }
+];
+var FermentableTypeSource = {
+	localdata: FermentableTypeData,
+	datatype: "array",
+	datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }]
+};
+var FermentableTypeAdapter = new $.jqx.dataAdapter(FermentableTypeSource);
+
+var GrainTypeData = [
+	{ id: 0, en: 'Base',      nl: 'basismout' },
+	{ id: 1, en: 'Roast',     nl: 'geroosterde mout' },
+	{ id: 2, en: 'Crystal',   nl: 'cara- of crystalmout' },
+	{ id: 3, en: 'Kilned',    nl: 'geƫeste mout'},
+	{ id: 4, en: 'Sour malt', nl: 'zuurmout' },
+	{ id: 5, en: 'Special',   nl: 'speciale mout' },
+	{ id: 6, en: 'No malt',   nl: 'n.v.t.' }
+];
+var GrainTypeSource = {
+	localdata: GrainTypeData,
+	datatype: "array",
+	datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }]
+};
+var GrainTypeAdapter = new $.jqx.dataAdapter(GrainTypeSource);
+
+var AddedData = [
+	{ id: 0, en: 'Mash', nl: 'maischen' },
+	{ id: 1, en: 'Boil', nl: 'koken' },
+	{ id: 2, en: 'Fermentation', nl: 'vergisten' },
+	{ id: 3, en: 'Lagering', nl: 'nagisten/lageren' },
+	{ id: 4, en: 'Bottle', nl: 'bottelen' }
+];
+var AddedSource = {
+	localdata: AddedData,
+	datatype: "array",
+	datafields: [{ name: 'id' }, { name: 'en' }, { name: 'nl' }]
+};
+var AddedAdapter = new $.jqx.dataAdapter(AddedSource);
+
+
+
+
+// options for editors
+
+var Spin1dec1 = {
+	inputMode: 'simple',
+	spinMode: 'simple',
+	theme: theme,
+	width: 110,
+	height: 23,
+	min: 0,
+	decimalDigits: 1,
+	spinButtons: true,
+	spinButtonsStep: 0.1
+};
+var Spin1dec5 = {
+	inputMode: 'simple',
+	spinMode: 'simple',
+	theme: theme,
+	width: 110,
+	height: 23,
+	min: 0,
+	decimalDigits: 1,
+	spinButtons: true,
+	spinButtonsStep: 0.5
+};
+var SpinpH = {
+	inputMode: 'simple',
+	spinMode: 'simple',
+	theme: theme,
+	width: 110,
+	height: 23,
+	min: 1,
+	max: 14,
+	decimalDigits: 1,
+	spinButtons: true,
+	spinButtonsStep: 0.1
+};
+var Spin2pH = {
+	inputMode: 'simple',
+	spinMode: 'simple',
+	theme: theme,
+	width: 110,
+	height: 23,
+	min: 1,
+	max: 14,
+	decimalDigits: 2,
+	spinButtons: true,
+	spinButtonsStep: 0.05
+};
+var Perc1dec5 = {
+	inputMode: 'simple',
+	spinMode: 'simple',
+	theme: theme,
+	width: 110,
+	height: 23,
+	min: 0,
+	max: 100,
+	decimalDigits: 1,
+	spinButtons: true,
+	spinButtonsStep: 0.5
+};
+var Spin2dec1 = {
+	inputMode: 'simple',
+	spinMode: 'simple',
+	theme: theme,
+	width: 110,
+	height: 23,
+	min: 0,
+	decimalDigits: 2,
+	spinButtons: true,
+	spinButtonsStep: 0.01
+};
+var Dateopts = {
+	theme: theme,
+	width: 150,
+	height: 23,
+	allowNullDate: true,
+	todayString: 'Vandaag',
+	clearString: 'Wissen',
+	showFooter: true,
+	formatString: 'yyyy-MM-dd',
+	enableBrowserBoundsDetection: true
+};
+
+
 var	sugardensity = 1.611; //kg/l in solution
 
 // Styles dropdown list
--- a/www/js/inv_fermentables.js	Mon Jan 21 20:45:18 2019 +0100
+++ b/www/js/inv_fermentables.js	Tue Jan 22 20:27:45 2019 +0100
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * Copyright (C) 2014-2018
+ * Copyright (C) 2014-2019
  *
  * Michiel Broek <mbroek at mbse dot eu>
  *
@@ -51,10 +51,10 @@
 		datafields: [
 			{ name: 'record', type: 'number' },
 			{ name: 'name', type: 'string' },
-			{ name: 'type', type: 'string' },
+			{ name: 'type', type: 'int' },
 			{ name: 'yield', type: 'float' },
 			{ name: 'color', type: 'float' },
-			{ name: 'add_after_boil', type: 'bool' },
+			{ name: 'add_after_boil', type: 'int' },
 			{ name: 'origin', type: 'string' },
 			{ name: 'supplier', type: 'string' },
 			{ name: 'notes', type: 'string' },
@@ -62,13 +62,14 @@
 			{ name: 'moisture', type: 'float' },
 			{ name: 'diastatic_power', type: 'float' },
 			{ name: 'protein', type: 'float' },
+			{ name: 'dissolved_protein', type: 'float' },
 			{ name: 'max_in_batch', type: 'float' },
-			{ name: 'recommend_mash', type: 'bool' },
-			{ name: 'ibu_gal_per_lb', type: 'float' },
-			{ name: 'always_on_stock', type: 'bool' },
+			{ name: 'recommend_mash', type: 'int' },
+			{ name: 'added', type: 'int' },
+			{ name: 'always_on_stock', type: 'int' },
 			{ name: 'di_ph', type: 'float' },
 			{ name: 'acid_to_ph_57', type: 'float' },
-			{ name: 'graintype', type: 'string' },
+			{ name: 'graintype', type: 'int' },
 			{ name: 'inventory', type: 'float' },
 			{ name: 'cost', type: 'float' },
 			{ name: 'production_date', type: 'string' },
@@ -84,6 +85,7 @@
 				url: url,
 				cache: false,
 				data: data,
+				type: "POST",
 				success: function (data, status, xhr) {
 					// delete command is executed.
 					commit(true);
@@ -100,6 +102,7 @@
                                	url: url,
                                	cache: false,
                                	data: data,
+				type: "POST",
                                	success: function (data, status, xhr) {
                                        	commit(true);
                                	},
@@ -115,6 +118,7 @@
 				url: url,
 				cache: false,
 				data: data,
+				type: "POST",
 				success: function (data, status, xhr) {
 					// update command is executed.
 					commit(true);
@@ -125,34 +129,55 @@
 			});
 		}
 	};
-	var srcType = [ "Grain", "Sugar", "Extract", "Dry Extract", "Adjunct" ];
-	var srcGraintype = [ "Base", "Crystal", "Special", "Roast", "Kilned", "No malt" ];
 	// initialize the input fields.
-	$("#name").jqxInput({ theme: theme, width: 250, height: 23 });
-	$("#type").jqxDropDownList({ theme: theme, source: srcType, width: 100, height: 23, dropDownHeight: 156 });
-	$("#yield").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 70, height: 23, min: 0, decimalDigits: 1, spinButtons: true });
-	$("#color").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 70, height: 23, min: 0, decimalDigits: 1, spinButtons: true });
+	$("#name").jqxInput({ theme: theme, width: 640, height: 23 });
+	$("#type").jqxDropDownList({
+		theme: theme,
+		source: FermentableTypeAdapter,
+		valueMember: 'id',
+		displayMember: 'nl',
+		width: 180,
+		height: 23,
+		autoDropDownHeight: true
+	});
+	$("#yield").jqxNumberInput( Spin1dec1 );
+	$("#color").jqxNumberInput( Spin1dec5 );
 	$("#add_after_boil").jqxCheckBox({ theme: theme, width: 120, height: 23 });
 	$("#origin").jqxInput({ theme: theme, width: 250, height: 23 });
 	$("#supplier").jqxInput({ theme: theme, width: 250, height: 23 });
 	$("#notes").jqxInput({ theme: theme, width: 640, height: 100 });
-	$("#coarse_fine_diff").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 70, height: 23, min: 0, decimalDigits: 1, spinButtons: true });
-	$("#moisture").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 70, height: 23, min: 0, decimalDigits: 1, spinButtons: true });
-	$("#diastatic_power").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 70, height: 23, min: 0, decimalDigits: 1, spinButtons: true });
-	$("#protein").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 70, height: 23, min: 0, decimalDigits: 1, spinButtons: true });
-	$("#max_in_batch").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 70, height: 23, min: 0, decimalDigits: 1, spinButtons: true });
+	$("#coarse_fine_diff").jqxNumberInput( Spin1dec1 );
+	$("#moisture").jqxNumberInput( Spin1dec1 );
+	$("#diastatic_power").jqxNumberInput( Spin1dec1 );
+	$("#protein").jqxNumberInput( Spin1dec1 );
+	$("#dissolved_protein").jqxNumberInput( Spin1dec1 );
+	$("#max_in_batch").jqxNumberInput( Perc1dec5 );
 	$("#recommend_mash").jqxCheckBox({ theme: theme, width: 120, height: 23 });
-	$("#ibu_gal_per_lb").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 70, height: 23, min: 0, decimalDigits: 1, spinButtons: true });
+	$("#added").jqxDropDownList({
+		theme: theme,
+		source: AddedAdapter,
+		valueMember: 'id',
+		displayMember: 'nl',
+		width: 180,
+		height: 23,
+		autoDropDownHeight: true
+	});
 	$("#always_on_stock").jqxCheckBox({ theme: theme, width: 120, height: 23 });
-	$("#di_ph").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 70, height: 23, min: 0, decimalDigits: 1, spinButtons: true });
-	$("#acid_to_ph_57").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 70, height: 23, min: 0, decimalDigits: 1, spinButtons: true });
-	$("#graintype").jqxDropDownList({ theme: theme, source: srcGraintype, width: 100, height: 23, dropDownHeight: 185 });
-
-	$("#inventory").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 70, height: 23, min: 0, decimalDigits: 1, spinButtons: true });
-	$("#production_date").jqxDateTimeInput({ theme: theme, width: 100, height: 23, formatString: 'yyyy-MM-dd' });
-
-	$("#cost").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 70, height: 23, min: 0, decimalDigits: 2, spinButtons: true });
-	$("#tht_date").jqxDateTimeInput({ theme: theme, width: 100, height: 23, formatString: 'yyyy-MM-dd' });
+	$("#di_ph").jqxNumberInput( Spin2pH );
+	$("#acid_to_ph_57").jqxNumberInput({ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 110, height: 23, min: -1000, max: 1000, decimalDigits: 2, spinButtons: true, spinButtonsStep: 0.01 });
+	$("#graintype").jqxDropDownList({
+		theme: theme,
+		source: GrainTypeAdapter,
+		valueMember: 'id',
+		displayMember: 'nl',
+		width: 180,
+		height: 23,
+		autoDropDownHeight: true
+	});
+	$("#inventory").jqxNumberInput( Spin1dec1 );
+	$("#production_date").jqxDateTimeInput( Dateopts );
+	$("#cost").jqxNumberInput( Spin2dec1 );
+	$("#tht_date").jqxDateTimeInput( Dateopts );
 	var dataAdapter = new $.jqx.dataAdapter(source);
 	var editrow = -1;
 	// initialize jqxGrid
@@ -168,29 +193,33 @@
 			var 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;'>Nieuw</span></div>");
 			container.append(addButton);
 			statusbar.append(container);
-			addButton.jqxButton({ theme: theme, width: 120, height: 20 });
+			addButton.jqxButton({ theme: theme, width: 90, height: 20 });
 			// add new row.
 			addButton.click(function (event) {
 				editrow = -1;
-				$("#popupWindow").jqxWindow({ position: { x: 230, y: 30 } });
-				$("#name").val('');
-				$("#type").val('Grain');
+				$("#popupWindow").jqxWindow({ position: { x: 110, y: 30 } });
+				$("#name").val('Nieuw product');
+				$("#type").val(0);
 				$("#origin").val('');
 				$("#supplier").val('');
 				$("#notes").val('');
-				$("#coarse_fine_diff").val('');
-				$("#moisture").val('');
-				$("#diastatic_power").val('');
-				$("#protein").val('');
-				$("#max_in_batch").val('');
-				$("#recommend_mash").val('');
-				$("#ibu_gal_per_lb").val('');
-				$("#always_on_stock").val('');
-				$("#di_ph").val('');
-				$("#acid_to_ph_57").val('');
-				$("#graintype").val('');
-				$("#inventory").val('');
-				$("#cost").val('');
+				$("#yield").val(80);
+				$("#color").val(3);
+				$("#coarse_fine_diff").val(3);
+				$("#moisture").val(4);
+				$("#diastatic_power").val(0);
+				$("#protein").val(0);
+				$("#dissolved_protein").val(0);
+				$("#max_in_batch").val(100);
+				$("#recommend_mash").val(1);
+				$("#always_on_stock").val(0);
+				$("#di_ph").val(0);
+				$("#acid_to_ph_57").val(0);
+				$("#graintype").val(0);
+				$("#add_after_boil").val(0);
+				$("#added").val(0);
+				$("#inventory").val(0);
+				$("#cost").val(0);
 				$("#production_date").val('');
 				$("#tht_date").val('');
 				$("#popupWindow").jqxWindow('open');
@@ -199,21 +228,29 @@
 		filterable: true,
 		filtermode: 'excel',
 		columns: [
-		{ text: 'Producent', datafield: 'supplier', width: 200 },
+			{ text: 'Producent', datafield: 'supplier', width: 140 },
 			{ text: 'Vergistbaar product', datafield: 'name' },
-			{ text: 'Soort', datafield: 'type', align: 'center', cellsalign: 'center', width: 90 },
-			{ text: 'Mout type', datafield: 'graintype', align: 'center', cellsalign: 'center', width: 90 },
+			{ text: 'Soort', datafield: 'type', align: 'center', cellsalign: 'center', width: 135,
+			  cellsrenderer: function (index, datafield, value, defaultvalue, column, rowdata) {
+				return "<div style='margin: 4px;' class='jqx-center-align'>" + FermentableTypeData[value].nl + "</div>";
+			  }
+		       	},
+			{ text: 'Graan type', datafield: 'graintype', align: 'center', cellsalign: 'center', width: 125,
+			  cellsrenderer: function (index, datafield, value, defaultvalue, column, rowdata) {
+				return "<div style='margin: 4px;' class='jqx-center-align'>" + GrainTypeData[value].nl + "</div>";
+			  }
+		       	},
 			{ text: 'Herkomst', datafield: 'origin', width: 150 },
-			{ text: 'Kleur', datafield: 'color', width: 70, align: 'right', cellsalign: 'right' },
+			{ text: 'EBC', datafield: 'color', width: 60, align: 'right', cellsalign: 'right' },
 			{ text: 'Opbrengst', datafield: 'yield', width: 70, align: 'right', cellsalign: 'right', cellsformat: 'p1' },
 			{ text: 'Vooraad', datafield: 'inventory', width: 100, align: 'right', cellsalign: 'right', cellsformat: 'f3' },
-			{ text: 'Prijs', datafield: 'cost', width: 100, align: 'right', cellsalign: 'right', cellsformat: 'c2' },
-			{ text: 'Wijzig', datafield: 'Edit', width: 120, align: 'center', columntype: 'button', cellsrenderer: function () {
+			{ text: 'Prijs/kg', datafield: 'cost', width: 100, align: 'right', cellsalign: 'right', cellsformat: 'c2' },
+			{ text: 'Wijzig', datafield: 'Edit', width: 100, align: 'center', columntype: 'button', cellsrenderer: function () {
 				return "Wijzig";
 				}, buttonclick: function (row) {
 					// open the popup window when the user clicks a button.
 					editrow = row;
-					$("#popupWindow").jqxWindow({ position: { x: 230, y: 30 } });
+					$("#popupWindow").jqxWindow({ position: { x: 110, y: 30 } });
 					// get the clicked row's data and initialize the input fields.
 					var dataRecord = $("#jqxgrid").jqxGrid('getrowdata', editrow);
 					$("#name").val(dataRecord.name);
@@ -228,9 +265,10 @@
 					$("#moisture").val(dataRecord.moisture);
 					$("#diastatic_power").val(dataRecord.diastatic_power);
 					$("#protein").val(dataRecord.protein);
+					$("#dissolved_protein").val(dataRecord.dissolved_protein);
 					$("#max_in_batch").val(dataRecord.max_in_batch);
 					$("#recommend_mash").val(dataRecord.recommend_mash);
-					$("#ibu_gal_per_lb").val(dataRecord.ibu_gal_per_lb);
+					$("#added").val(dataRecord.added);
 					$("#always_on_stock").val(dataRecord.always_on_stock);
 					$("#di_ph").val(dataRecord.di_ph);
 					$("#acid_to_ph_57").val(dataRecord.acid_to_ph_57);
@@ -247,12 +285,19 @@
 	});
 	// initialize the popup window and buttons.
 	$("#popupWindow").jqxWindow({
-		width: 860, resizable: false, theme: theme, isModal: true, autoOpen: false, cancelButton: $("#Cancel"), modalOpacity: 0.40
+		width: 1050,
+		height: 550,
+		resizable: false,
+		theme: theme,
+		isModal: true,
+		autoOpen: false,
+		cancelButton: $("#Cancel"),
+		modalOpacity: 0.40
 	});
 	$("#popupWindow").on('open', function () {
 		$("#name").jqxInput('selectAll');
 	});
-	$("#Delete").jqxButton({ theme: theme });
+	$("#Delete").jqxButton({ template: "danger", width: '90px', theme: theme });
 	$("#Delete").click(function () {
 		if (editrow >= 0) {
 			// Open a popup to confirm this action.
@@ -264,71 +309,48 @@
 		}
 		$("#popupWindow").jqxWindow('hide');
 	});
-	$("#Cancel").jqxButton({ theme: theme });
-	$("#Save").jqxButton({ theme: theme });
+	$("#Cancel").jqxButton({ template: "primary", width: '90px', theme: theme });
+	$("#Save").jqxButton({ template: "success", width: '90px', theme: theme });
 	// update the edited row when the user clicks the 'Save' button.
 	$("#Save").click(function () {
+		var rowID = -1;
 		if (editrow >= 0) {
 			var rowID = $('#jqxgrid').jqxGrid('getrowid', editrow);
-			var row = {
-				record: rowID,
-				name: $("#name").val(),
-				type: $("#type").val(),
-				yield: parseFloat($("#yield").jqxNumberInput('decimal')),
-				color: parseFloat($("#color").jqxNumberInput('decimal')),
-				add_after_boil: $("#add_after_boil").val(),
-				origin: $("#origin").val(),
-				supplier: $("#supplier").val(),
-				notes: $("#notes").val(),
-				coarse_fine_diff: parseFloat($("#coarse_fine_diff").jqxNumberInput('decimal')),
-				moisture: parseFloat($("#moisture").jqxNumberInput('decimal')),
-				diastatic_power: parseFloat($("#diastatic_power").jqxNumberInput('decimal')),
-				protein: parseFloat($("#protein").jqxNumberInput('decimal')),
-				max_in_batch: parseFloat($("#max_in_batch").jqxNumberInput('decimal')),
-				recommend_mash: $("#recommend_mash").val(),
-				ibu_gal_per_lb: parseFloat($("#ibu_gal_per_lb").jqxNumberInput('decimal')),
-				always_on_stock: $("#always_on_stock").val(),
-				di_ph: parseFloat($("#di_ph").jqxNumberInput('decimal')),
-				acid_to_ph_57: parseFloat($("#acid_to_ph_57").jqxNumberInput('decimal')),
-				graintype: $("#graintype").val(),
-				inventory: parseFloat($("#inventory").jqxNumberInput('decimal')),
-				cost: parseFloat($("#cost").jqxNumberInput('decimal')),
-				production_date: $("#production_date").val(),
-				tht_date: $("#tht_date").val(),
-			};
+		}
+		var row = {
+			record: rowID,
+			name: $("#name").val(),
+			type: $("#type").val(),
+			yield: parseFloat($("#yield").jqxNumberInput('decimal')),
+			color: parseFloat($("#color").jqxNumberInput('decimal')),
+			add_after_boil: $("#add_after_boil").val(),
+			origin: $("#origin").val(),
+			supplier: $("#supplier").val(),
+			notes: $("#notes").val(),
+			coarse_fine_diff: parseFloat($("#coarse_fine_diff").jqxNumberInput('decimal')),
+			moisture: parseFloat($("#moisture").jqxNumberInput('decimal')),
+			diastatic_power: parseFloat($("#diastatic_power").jqxNumberInput('decimal')),
+			protein: parseFloat($("#protein").jqxNumberInput('decimal')),
+			dissolved_protein: parseFloat($("#dissolved_protein").jqxNumberInput('decimal')),
+			max_in_batch: parseFloat($("#max_in_batch").jqxNumberInput('decimal')),
+			recommend_mash: $("#recommend_mash").val(),
+			added: $("#added").val(),
+			always_on_stock: $("#always_on_stock").val(),
+			di_ph: parseFloat($("#di_ph").jqxNumberInput('decimal')),
+			acid_to_ph_57: parseFloat($("#acid_to_ph_57").jqxNumberInput('decimal')),
+			graintype: $("#graintype").val(),
+			inventory: parseFloat($("#inventory").jqxNumberInput('decimal')),
+			cost: parseFloat($("#cost").jqxNumberInput('decimal')),
+			production_date: $("#production_date").val(),
+			tht_date: $("#tht_date").val(),
+		};
+		if (editrow >= 0) {
 			$('#jqxgrid').jqxGrid('updaterow', rowID, row);
-			$("#popupWindow").jqxWindow('hide');
 		} else {
-			// Insert a record
-			var newrow = {
-				record: -1,
-				name: $("#name").val(),
-				type: $("#type").val(),
-				yield: parseFloat($("#yield").jqxNumberInput('decimal')),
-				color: parseFloat($("#color").jqxNumberInput('decimal')),
-				add_after_boil: $("#add_after_boil").val(),
-				origin: $("#origin").val(),
-				supplier: $("#supplier").val(),
-				notes: $("#notes").val(),
-				coarse_fine_diff: parseFloat($("#coarse_fine_diff").jqxNumberInput('decimal')),
-				moisture: parseFloat($("#moisture").jqxNumberInput('decimal')),
-				diastatic_power: parseFloat($("#diastatic_power").jqxNumberInput('decimal')),
-				protein: parseFloat($("#protein").jqxNumberInput('decimal')),
-				max_in_batch: parseFloat($("#max_in_batch").jqxNumberInput('decimal')),
-				recommend_mash: $("#recommend_mash").val(),
-				ibu_gal_per_lb: parseFloat($("#ibu_gal_per_lb").jqxNumberInput('decimal')),
-				always_on_stock: $("#always_on_stock").val(),
-				di_ph: parseFloat($("#di_ph").jqxNumberInput('decimal')),
-				acid_to_ph_57: parseFloat($("#acid_to_ph_57").jqxNumberInput('decimal')),
-				graintype: $("#graintype").val(),
-				inventory: parseFloat($("#inventory").jqxNumberInput('decimal')),
-				cost: parseFloat($("#cost").jqxNumberInput('decimal')),
-				production_date: $("#production_date").val(),
-				tht_date: $("#tht_date").val(),
-			};
-			$('#jqxgrid').jqxGrid('addrow', null, newrow);
-			$("#popupWindow").jqxWindow('hide');
+			$('#jqxgrid').jqxGrid('addrow', null, row);
 		}
+		$("#popupWindow").jqxWindow('hide');
+		location.reload( true );	// reload ourself.
 	});
 	createDelElements();
 });

mercurial