mirror of
https://github.com/shouptech/humulus.git
synced 2026-02-03 16:09:44 +00:00
Javascript to handle form changes.
This commit is contained in:
parent
e5a9f35fcb
commit
76fa080364
2 changed files with 213 additions and 22 deletions
|
|
@ -13,6 +13,13 @@
|
|||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// unbinds and re-binds the change event
|
||||
function rebindChangeEvents() {
|
||||
$('.ingredient-field').unbind('change');
|
||||
$('.ingredient-field').change(displayAll);
|
||||
}
|
||||
|
||||
// Correct all the indices for forms matching item.
|
||||
function adjustIndices(removedIndex, item) {
|
||||
var $forms = $(item);
|
||||
|
|
@ -51,6 +58,7 @@ function removeForm($remButton, formClass, formsId) {
|
|||
var $fermsDiv = $(formsId);
|
||||
$fermsDiv.data('length', $fermsDiv.data('length') - 1);
|
||||
adjustIndices(removedIndex, formClass);
|
||||
displayAll();
|
||||
}
|
||||
|
||||
// Remove a fermentable
|
||||
|
|
@ -75,14 +83,14 @@ function addFerm() {
|
|||
// Name field
|
||||
'<div class="row"><div class="col"><div class="form-group">' +
|
||||
`<label for="fermentables-${fermsLength}-name">Name</label>` +
|
||||
`<input class="form-control form-control-sm" id="fermentables-${fermsLength}-name"` +
|
||||
`<input class="form-control form-control-sm ingredient-field" id="fermentables-${fermsLength}-name"` +
|
||||
` name="fermentables-${fermsLength}-name" required type="text" value="">` +
|
||||
'</div></div></div>' + // End name field
|
||||
'<div class="row">' +
|
||||
// Type field
|
||||
'<div class="col-sm"><div class="form-group">' +
|
||||
`<label for="fermentables-${fermsLength}-type">Type</label>` +
|
||||
`<select class="form-control form-control-sm" id="fermentables-${fermsLength}-type"` +
|
||||
`<select class="form-control form-control-sm ingredient-field" id="fermentables-${fermsLength}-type"` +
|
||||
` name="fermentables-${fermsLength}-type" required>` +
|
||||
'<option value="Grain">Grain</option>' +
|
||||
'<option value="LME">LME</option>' +
|
||||
|
|
@ -94,19 +102,19 @@ function addFerm() {
|
|||
// Amount field
|
||||
'<div class="col-sm"><div class="form-group">' +
|
||||
`<label for="fermentables-${fermsLength}-amount">Amount (lb)</label>` +
|
||||
`<input class="form-control form-control-sm" id="fermentables-${fermsLength}-amount"` +
|
||||
`<input class="form-control form-control-sm ingredient-field" id="fermentables-${fermsLength}-amount"` +
|
||||
` name="fermentables-${fermsLength}-amount" required type="text" value="">` +
|
||||
'</div></div>' + // End amount field
|
||||
// PPG field
|
||||
'<div class="col-sm"><div class="form-group">' +
|
||||
`<label for="fermentables-${fermsLength}-ppg">PPG</label>` +
|
||||
`<input class="form-control form-control-sm" id="fermentables-${fermsLength}-ppg"` +
|
||||
`<input class="form-control form-control-sm ingredient-field" id="fermentables-${fermsLength}-ppg"` +
|
||||
` name="fermentables-${fermsLength}-ppg" required type="text" value="">` +
|
||||
'</div></div>' + // End PPG field
|
||||
// Color field
|
||||
'<div class="col-sm"><div class="form-group">' +
|
||||
`<label for="fermentables-${fermsLength}-color">Color (°L)</label>` +
|
||||
`<input class="form-control form-control-sm" id="fermentables-${fermsLength}-color"` +
|
||||
`<input class="form-control form-control-sm ingredient-field" id="fermentables-${fermsLength}-color"` +
|
||||
` name="fermentables-${fermsLength}-color" required type="text" value="">` +
|
||||
'</div></div>' + // End PPG field
|
||||
'</div>' +
|
||||
|
|
@ -118,10 +126,13 @@ function addFerm() {
|
|||
'</div>';
|
||||
$fermsDiv.append(newFerm);
|
||||
$fermsDiv.data('length', fermsLength + 1);
|
||||
// Unbind click events and re-bind them. This is needed to prevent multiple click events
|
||||
$('.rem-ferm').unbind('click');
|
||||
$('.rem-ferm').click(removeFerm);
|
||||
rebindChangeEvents();
|
||||
}
|
||||
|
||||
// Add a hop
|
||||
function addHop() {
|
||||
var $hopsDiv = $('#hops');
|
||||
var hopsLength = $hopsDiv.data('length');
|
||||
|
|
@ -134,14 +145,14 @@ function addHop() {
|
|||
// Name field
|
||||
'<div class="row"><div class="col"><div class="form-group">' +
|
||||
`<label for="hops-${hopsLength}-name">Name</label>` +
|
||||
`<input class="form-control form-control-sm" id="hops-${hopsLength}-name"` +
|
||||
`<input class="form-control form-control-sm ingredient-field" id="hops-${hopsLength}-name"` +
|
||||
` name="hops-${hopsLength}-name" required type="text" value="">` +
|
||||
'</div></div></div>' + // End name field
|
||||
'<div class="row">' +
|
||||
// Usage field
|
||||
'<div class="col-sm"><div class="form-group">' +
|
||||
`<label for="hops-${hopsLength}-use">Usage</label>` +
|
||||
`<select class="form-control form-control-sm" id="hops-${hopsLength}-use"` +
|
||||
`<select class="form-control form-control-sm ingredient-field" id="hops-${hopsLength}-use"` +
|
||||
` name="hops-${hopsLength}-use" required>` +
|
||||
'<option value="Boil">Boil</option>' +
|
||||
'<option value="FWH">FWH</option>' +
|
||||
|
|
@ -151,19 +162,19 @@ function addHop() {
|
|||
// Alpha acid % field
|
||||
'<div class="col-sm"><div class="form-group">' +
|
||||
`<label for="hops-${hopsLength}-alpha">Alpha Acid %</label>` +
|
||||
`<input class="form-control form-control-sm" id="hops-${hopsLength}-alpha"` +
|
||||
`<input class="form-control form-control-sm ingredient-field" id="hops-${hopsLength}-alpha"` +
|
||||
` name="hops-${hopsLength}-alpha" required type="text" value="">` +
|
||||
'</div></div>' + // End alpha acid % field
|
||||
// Duration field
|
||||
'<div class="col-sm"><div class="form-group">' +
|
||||
`<label for="hops-${hopsLength}-duration">Duration (min/day)</label>` +
|
||||
`<input class="form-control form-control-sm" id="hops-${hopsLength}-duration"` +
|
||||
`<input class="form-control form-control-sm ingredient-field" id="hops-${hopsLength}-duration"` +
|
||||
` name="hops-${hopsLength}-duration" required type="text" value="">` +
|
||||
'</div></div>' + // End duration field
|
||||
// Amount field
|
||||
'<div class="col-sm"><div class="form-group">' +
|
||||
`<label for="hops-${hopsLength}-amount">Amount (oz)</label>` +
|
||||
`<input class="form-control form-control-sm" id="hops-${hopsLength}-amount"` +
|
||||
`<input class="form-control form-control-sm ingredient-field" id="hops-${hopsLength}-amount"` +
|
||||
` name="hops-${hopsLength}-amount" required type="text" value="">` +
|
||||
'</div></div>' + // End amount field
|
||||
'</div>' +
|
||||
|
|
@ -176,13 +187,167 @@ function addHop() {
|
|||
|
||||
$hopsDiv.append(newHop);
|
||||
$hopsDiv.data('length', hopsLength + 1);
|
||||
// Unbind click events and re-bind them. This is needed to prevent multiple click events
|
||||
$('.rem-hop').unbind('click');
|
||||
$('.rem-hop').click(removeHop);
|
||||
rebindChangeEvents();
|
||||
}
|
||||
|
||||
// Calculate recipe's original gravity
|
||||
function calculateOG() {
|
||||
var fermsLength = $('#ferms').data('length');
|
||||
if (fermsLength == 0) {
|
||||
return 0;
|
||||
}
|
||||
var points = 0;
|
||||
var grain_points = 0;
|
||||
for (var i = 0; i < fermsLength; i++) {
|
||||
var ppg = parseFloat($(`#fermentables-${i}-ppg`).val()) || 0.0;
|
||||
var amt = parseFloat($(`#fermentables-${i}-amount`).val()) || 0.0;
|
||||
|
||||
// Check if type is grain
|
||||
if ($(`#fermentables-${i}-type`).val() == 'Grain') {
|
||||
grain_points += ppg * amt;
|
||||
} else {
|
||||
points += ppg * amt;
|
||||
}
|
||||
}
|
||||
// Add grain_points to points, adjusting for efficiency
|
||||
var efficiency = parseFloat($(`#efficiency`).val()) || 0;
|
||||
var volume = parseFloat($(`#volume`).val()) || 0;
|
||||
points += grain_points * efficiency / 100;
|
||||
return 1 + points / (1000 * volume);
|
||||
}
|
||||
|
||||
// display OG
|
||||
function displayOG() {
|
||||
$('#estimated-og').text(calculateOG().toFixed(3));
|
||||
}
|
||||
|
||||
// Calculate final gravity
|
||||
function calculateFG() {
|
||||
var fermsLength = $('#ferms').data('length');
|
||||
if (fermsLength == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var og = parseFloat(calculateOG()) || 0.0;
|
||||
var og_delta = 0.0;
|
||||
var volume = parseFloat($(`#volume`).val()) || 0;
|
||||
for (var i = 0; i < fermsLength; i++) {
|
||||
if ($(`#fermentables-${i}-type`).val() == 'Non-fermentable') {
|
||||
var ppg = parseFloat($(`#fermentables-${i}-ppg`).val()) || 0.0;
|
||||
var amt = parseFloat($(`#fermentables-${i}-amount`).val()) || 0.0;
|
||||
og_delta += amt * ppg / (volume * 1000)
|
||||
}
|
||||
}
|
||||
|
||||
var low_attenuation = parseFloat($('#yeast-low_attenuation').val()) || 0.0;
|
||||
var high_attenuation = parseFloat($('#yeast-high_attenuation').val()) || 0.0;
|
||||
var attenuation = (low_attenuation + high_attenuation) / 200;
|
||||
return 1 + (og - 1 - og_delta)*(1 - attenuation) + og_delta;
|
||||
}
|
||||
|
||||
// Display FG
|
||||
function displayFG() {
|
||||
$('#estimated-fg').text(calculateFG().toFixed(3));
|
||||
}
|
||||
|
||||
// Calculate ABV
|
||||
function calculate_abv() {
|
||||
return (calculateOG() - calculateFG()) * 131.25;
|
||||
}
|
||||
|
||||
// Display ABV
|
||||
function displayABV() {
|
||||
var abv = calculate_abv().toFixed(1);
|
||||
$('#estimated-abv').text(`${abv} %/vol.`);
|
||||
}
|
||||
|
||||
// Calculate IBU
|
||||
function calculateIBU() {
|
||||
var hopsLength = $('#hops').data('length');
|
||||
if (hopsLength == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var bigness = 1.65 * Math.pow(0.000125, calculateOG() - 1);
|
||||
var ibu = 0;
|
||||
var volume = parseFloat($(`#volume`).val()) || 0;
|
||||
for (var i = 0; i < hopsLength; i++) {
|
||||
var use = $(`#hops-${i}-use`).val();
|
||||
if (use != 'Boil' && use != 'FWH') {
|
||||
continue;
|
||||
}
|
||||
var alpha = parseFloat($(`#hops-${i}-alpha`).val()) || 0.0;
|
||||
var amt = parseFloat($(`#hops-${i}-amount`).val()) || 0.0;
|
||||
var duration = parseFloat($(`#hops-${i}-duration`).val()) || 0.0;
|
||||
var mgl = alpha * amt * 7490 / (volume * 100)
|
||||
var btf = (1 - Math.pow(Math.E, -0.04 * duration)) / 4.15
|
||||
ibu += bigness * btf * mgl;
|
||||
}
|
||||
return ibu;
|
||||
}
|
||||
|
||||
// Display IBU
|
||||
function displayIBU() {
|
||||
var ibu = calculateIBU().toFixed();
|
||||
$('#estimated-ibu').text(`${ibu} IBU`);
|
||||
}
|
||||
|
||||
// Calculate IBU Ratio
|
||||
function calculateIBURatio() {
|
||||
return 0.001 * calculateIBU() / (calculateOG() - 1)
|
||||
}
|
||||
|
||||
// Display IBU Ratio
|
||||
function displayIBURatio() {
|
||||
var iburatio = calculateIBURatio().toFixed(3);
|
||||
$('#estimated-iburatio').text(`${iburatio} IBU/OG`);
|
||||
}
|
||||
|
||||
// Calculate SRM
|
||||
function calculateSRM() {
|
||||
var fermsLength = $('#ferms').data('length');
|
||||
if (fermsLength == 0) {
|
||||
return 0;
|
||||
}
|
||||
var mcu = 0;
|
||||
var volume = parseFloat($(`#volume`).val()) || 0;
|
||||
for (var i = 0; i < fermsLength; i++) {
|
||||
var color = parseFloat($(`#fermentables-${i}-color`).val()) || 0.0;
|
||||
var amt = parseFloat($(`#fermentables-${i}-amount`).val()) || 0.0;
|
||||
mcu += amt * color / volume;
|
||||
}
|
||||
return 1.4922 * Math.pow(mcu, 0.6859)
|
||||
}
|
||||
|
||||
// Display SRM
|
||||
function displaySRM() {
|
||||
var srm = calculateSRM().toFixed();
|
||||
$('#estimated-srm').text(`${srm} SRM`);
|
||||
}
|
||||
|
||||
// Display all specifications
|
||||
function displayAll() {
|
||||
displayOG();
|
||||
displayFG();
|
||||
displayABV();
|
||||
displayIBU();
|
||||
displayIBURatio();
|
||||
displaySRM();
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
// Register clicks
|
||||
$('#add-ferm').click(addFerm);
|
||||
$('.rem-ferm').click(removeFerm);
|
||||
$('#add-hop').click(addHop);
|
||||
$('.rem-hop').click(removeHop);
|
||||
|
||||
// Register change events
|
||||
rebindChangeEvents();
|
||||
|
||||
// Update specifications
|
||||
displayAll();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -26,8 +26,34 @@
|
|||
-#}
|
||||
<div class="row">
|
||||
<div class="col-sm-6">{{ render_field_with_errors(form.name) }}</div>
|
||||
<div class="col-sm-3">{{ render_field_with_errors(form.efficiency) }}</div>
|
||||
<div class="col-sm-3">{{ render_field_with_errors(form.volume) }}</div>
|
||||
<div class="col-sm-3">{{ render_field_with_errors(form.efficiency, 'ingredient-field') }}</div>
|
||||
<div class="col-sm-3">{{ render_field_with_errors(form.volume, 'ingredient-field') }}</div>
|
||||
</div>
|
||||
{#-
|
||||
Recipe specifications
|
||||
-#}
|
||||
<div class="row"><div class="col"><h3>Estimated Specifications</h3></div></div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<dl>
|
||||
<dt>Original Gravity</dt>
|
||||
<dd id="estimated-og"></dd>
|
||||
<dt>Final Gravity</dt>
|
||||
<dd id="estimated-fg"></dd>
|
||||
<dt>Alcohol</dt>
|
||||
<dd id="estimated-abv"></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="col">
|
||||
<dl>
|
||||
<dt>Bitterness</dt>
|
||||
<dd id="estimated-ibu"></dd>
|
||||
<dt>Bitterness Ratio</dt>
|
||||
<dd id="estimated-iburatio"></dd>
|
||||
<dt>Color</dt>
|
||||
<dd id="estimated-srm"></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
{#-
|
||||
Fermentable Ingredients
|
||||
|
|
@ -42,10 +68,10 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm">{{ render_field_with_errors(fermentable.form.type, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(fermentable.form.amount, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(fermentable.form.ppg, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(fermentable.form.color, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(fermentable.form.type, 'form-control-sm ingredient-field') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(fermentable.form.amount, 'form-control-sm ingredient-field') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(fermentable.form.ppg, 'form-control-sm ingredient-field') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(fermentable.form.color, 'form-control-sm ingredient-field') }}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
|
|
@ -73,10 +99,10 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm">{{ render_field_with_errors(hop.form.use, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(hop.form.alpha, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(hop.form.duration, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(hop.form.amount, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(hop.form.use, 'form-control-sm ingredient-field') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(hop.form.alpha, 'form-control-sm ingredient-field') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(hop.form.duration, 'form-control-sm ingredient-field') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(hop.form.amount, 'form-control-sm ingredient-field') }}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
|
|
@ -104,8 +130,8 @@
|
|||
<div class="col-sm-2">{{ render_field_with_errors(form.yeast.form.code, 'form-control-sm') }}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm">{{ render_field_with_errors(form.yeast.form.low_attenuation, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(form.yeast.form.high_attenuation, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(form.yeast.form.low_attenuation, 'form-control-sm ingredient-field') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(form.yeast.form.high_attenuation, 'form-control-sm ingredient-field') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(form.yeast.form.flocculation, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(form.yeast.form.min_temperature, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(form.yeast.form.max_temperature, 'form-control-sm') }}</div>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue