Skip to content

Instantly share code, notes, and snippets.

@BrandonLWhite
Last active December 5, 2019 14:23
Show Gist options
  • Save BrandonLWhite/90520f816c04ba1ae19e02ffce8c4702 to your computer and use it in GitHub Desktop.
Save BrandonLWhite/90520f816c04ba1ae19e02ffce8c4702 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<title>Brewsheet: $NAME</title>
<style type="text/css">
body {
font-size: 16px;
}
#Property
{
}
#PropertiesTable td
{
padding:0;
}
</style>
</head>
<body>
<script type="text/javascript">
if (!String.prototype.includes) {
String.prototype.includes = function(search, start) {
return this.indexOf(search, start) !== -1;
};
}
// We are in IE11, so no ES6 stuff! No arrow functions, no string interpolators.
document.addEventListener('DOMContentLoaded', function() {
setCellStyle('\nWater Agent', 'font-size: xx-small');
addWaterWeights();
});
function addWaterWeights() {
// First find the dom element that contains 'Mash Steps'
const mashStepsTable = queryByTextContent('caption', 'Mash Steps')[0].parentElement;
const mashCells = querySelectorAll(mashStepsTable, 'td');
mashCells.forEach(addMashWaterWeight);
const spargeCell = queryByTextContent('td', 'sparge')[0];
insertWaterWeight(spargeCell, /(\d+.\d+)gal/, WATER_LB_PER_GAL);
}
const WATER_LB_PER_GAL = 8.345404;
function addMashWaterWeight(cell) {
insertWaterWeight(cell, /(\d+.\d+) qt/, WATER_LB_PER_GAL / 4);
}
function insertWaterWeight(cell, volumeRegEx, multiplier) {
const text = cell.textContent;
const match = text.match(volumeRegEx);
if(!match || !match.length > 1) return;
const capture = match[1];
const volume = Number(capture);
const weight = volume * multiplier;
const weightText = ' (<b>' + weight.toFixed(2) + ' lb</b>)';
const insertionPoint = match.index + match[0].length;
const newText = text.slice(0, insertionPoint) + weightText + text.slice(insertionPoint);
cell.innerHTML = newText;
}
function querySelectorAll(node, selector) {
const nodeList = node.querySelectorAll(selector);
const array = [];
for(var idx = 0; idx < nodeList.length; ++idx) {
array.push(nodeList[idx]);
}
return array;
}
function queryByTextContent(cssSelector, textContent) {
return querySelectorAll(document, cssSelector).filter(function(cell) { return cell.textContent.includes(textContent) });
}
function queryByTextContentExact(cssSelector, textContent) {
return querySelectorAll(document, cssSelector).filter(function(cell) { return cell.textContent == textContent });
}
function setCellStyle(textContent, style) {
queryByTextContentExact('td', textContent).forEach(function(cell) { cell.setAttribute('style', style) });
}
</script>
<h2>$NAME &nbsp;&nbsp;&nbsp;<i>($STYLE_NAME)</i></h2>
<table border="0" width="97%" id="PropertiesTable">
<tr>
<td width="40%"><b>Batch Size (fermenter):</b> $DISPLAY_BATCH_SIZE</td>
<td width="52%"><b>Date:</b> $DATE</td>
</tr>
<tr>
<td width="40%"><b>Boil Size:</b> $DISPLAY_BOIL_SIZE</td>
<td width="52%"><b>Total Grain Weight:</b> $GRAIN_WEIGHT</td>
</tr>
<tr>
<td width="40%"><b>Boil Time:</b> $BOIL_TIME min</td>
<td width="52%"><b>Equipment:</b><font size="1"> $EQUIPMENT</font></td>
</tr>
<tr>
<td width="40%"><b>IBU:</b> $IBU</td>
<td width="52%"><b>Brewhouse Efficiency:</b> $EFFICIENCY</td>
</tr>
<tr>
<td width="40%"><b>ABV:</b> $ABV</td>
<td width="52%"><b>Mash Efficiency:</b> $EST_MASH_EFFICIENCY</td>
</tr>
</table>
<table border="1" width="97%" bordercolor="#000000" style="border-collapse:collapse">
<tr>
<td width="4%">&nbsp;</td>
<td width="95%">
Total Water Needed: $TOTAL_WATER
$WATER_PREP
</td>
</tr>
<tr>
<td width="4%">&nbsp;</td>
<td width="95%"align="left">$MASH_INGREDIENTS $STEEP_INGREDIENTS</td>
</tr>
<tr>
<td width="4%">&nbsp;</td>
<td width="95%">$MASH_STEPS</td>
</tr>
<tr>
<td width="4%">&nbsp;</td>
<td width="95%">$SPARGE_STEPS<br>
$FIRST_WORT_HOPS</td>
</tr>
<tr>
<td width="4%">&nbsp;</td>
<td width="95%" align="left">Estimated pre-boil gravity is <b>$PRE_BOIL_OG</b> and volume <b>$DISPLAY_BOIL_SIZE</b></td>
</tr>
<tr>
<td width="4%">&nbsp;</td>
<td width="95%" align="left">$BOIL_INGREDIENTS</td>
</tr>
<tr>
<td width="4%">&nbsp;</td>
<td width="95%">$STEEP_HOPS</td>
</tr>
<tr>
<td width="4%">&nbsp;</td>
<td width="95%">Estimated Post Boil Vol: $POST_BOIL_VOLUME and Est Post Boil Gravity: $EST_OG</td>
</tr>
<tr>
<td width="4%">&nbsp;</td>
<td width="95%">$FERMENT_INGREDIENTS</td>
</tr>
<tr>
<td width="4%">&nbsp;</td>
<td width="95%">Measure Actual Original Gravity _______&nbsp;&nbsp;&nbsp;&nbsp; (Target: $EST_OG)</td>
</tr>
<tr>
<td width="4%">&nbsp;</td>
<td width="95%">Measure Actual Batch Volume _______&nbsp;&nbsp;&nbsp;&nbsp; (Target: $DISPLAY_BATCH_SIZE)</td>
</tr>
<tr>
<td width="4%">&nbsp;</td>
<td width="95%" align="left">$PRIMARY_STEP $PRIMARY_INGREDIENTS</td>
</tr>
<tr>
<td width="4%">&nbsp;</td>
<td width="95%">$BOTTLING_INGREDIENTS</td>
</tr>
<tr>
<td width="4%">&nbsp;</td>
<td width="95%">Measure Final Gravity: _________&nbsp; (Estimate: $EST_FG)</td>
</tr>
</table>
$NOTES
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<title>Brewsheet: $NAME</title>
<style type="text/css">
body {
font-size: 16px;
}
#Property
{
}
#PropertiesTable td
{
padding:0;
}
</style>
</head>
<body>
<script type="text/javascript">
if (!String.prototype.includes) {
String.prototype.includes = function(search, start) {
return this.indexOf(search, start) !== -1;
};
}
// We are in IE11, so no ES6 stuff! No arrow functions, no string interpolators.
document.addEventListener('DOMContentLoaded', function() {
setCellStyle('\nWater Agent', 'font-size: xx-small');
addWaterWeights();
});
function addWaterWeights() {
// First find the dom element that contains 'Mash Steps'
const mashStepsTable = queryByTextContent('caption', 'Mash Steps')[0].parentElement;
const mashCells = querySelectorAll(mashStepsTable, 'td');
mashCells.forEach(addMashWaterWeight);
const spargeCell = queryByTextContent('td', 'sparge')[0];
insertWaterWeight(spargeCell, /(\d+.\d+)gal/, WATER_LB_PER_GAL);
}
const WATER_LB_PER_GAL = 8.345404;
function addMashWaterWeight(cell) {
insertWaterWeight(cell, /(\d+.\d+) qt/, WATER_LB_PER_GAL / 4);
}
function insertWaterWeight(cell, volumeRegEx, multiplier) {
const text = cell.textContent;
const match = text.match(volumeRegEx);
if(!match || !match.length > 1) return;
const capture = match[1];
const volume = Number(capture);
const weight = volume * multiplier;
const weightText = ' (<b>' + weight.toFixed(2) + ' lb</b>)';
const insertionPoint = match.index + match[0].length;
const newText = text.slice(0, insertionPoint) + weightText + text.slice(insertionPoint);
cell.innerHTML = newText;
}
function querySelectorAll(node, selector) {
const nodeList = node.querySelectorAll(selector);
const array = [];
for(var idx = 0; idx < nodeList.length; ++idx) {
array.push(nodeList[idx]);
}
return array;
}
function queryByTextContent(cssSelector, textContent) {
return querySelectorAll(document, cssSelector).filter(function(cell) { return cell.textContent.includes(textContent) });
}
function queryByTextContentExact(cssSelector, textContent) {
return querySelectorAll(document, cssSelector).filter(function(cell) { return cell.textContent == textContent });
}
function setCellStyle(textContent, style) {
queryByTextContentExact('td', textContent).forEach(function(cell) { cell.setAttribute('style', style) });
}
</script>
<h2>$NAME &nbsp;&nbsp;&nbsp;<i>($STYLE_NAME)</i></h2>
<table border="0" width="97%" id="PropertiesTable">
<tr>
<td width="40%"><b>Batch Size (fermenter):</b> $DISPLAY_BATCH_SIZE</td>
<td width="52%"><b>Date:</b> $DATE</td>
</tr>
<tr>
<td width="40%"><b>Boil Size:</b> $DISPLAY_BOIL_SIZE</td>
<td width="52%"><b>Total Grain Weight:</b> $GRAIN_WEIGHT</td>
</tr>
<tr>
<td width="40%"><b>Boil Time:</b> $BOIL_TIME min</td>
<td width="52%"><b>Equipment:</b><font size="1"> $EQUIPMENT</font></td>
</tr>
<tr>
<td width="40%"><b>IBU:</b> $IBU</td>
<td width="52%"><b>Brewhouse Efficiency:</b> $EFFICIENCY</td>
</tr>
<tr>
<td width="40%"><b>ABV:</b> $ABV</td>
<td width="52%"><b>Mash Efficiency:</b> $EST_MASH_EFFICIENCY</td>
</tr>
</table>
<table border="1" width="97%" bordercolor="#000000" style="border-collapse:collapse">
<tr>
<td width="4%">&nbsp;</td>
<td width="95%">
Total Water Needed: $TOTAL_WATER
$WATER_PREP
</td>
</tr>
<tr>
<td width="4%">&nbsp;</td>
<td width="95%"align="left">$MASH_INGREDIENTS $STEEP_INGREDIENTS</td>
</tr>
<tr>
<td width="4%">&nbsp;</td>
<td width="95%">$MASH_STEPS</td>
</tr>
<tr>
<td width="4%">&nbsp;</td>
<td width="95%">$SPARGE_STEPS<br>
$FIRST_WORT_HOPS</td>
</tr>
<tr>
<td width="4%">&nbsp;</td>
<td width="95%" align="left">Estimated pre-boil gravity is <b>$PRE_BOIL_OG</b> and volume <b>$DISPLAY_BOIL_SIZE</b></td>
</tr>
<tr>
<td width="4%">&nbsp;</td>
<td width="95%" align="left">$BOIL_INGREDIENTS</td>
</tr>
<tr>
<td width="4%">&nbsp;</td>
<td width="95%">$STEEP_HOPS</td>
</tr>
<tr>
<td width="4%">&nbsp;</td>
<td width="95%">Estimated Post Boil Vol: $POST_BOIL_VOLUME and Est Post Boil Gravity: $EST_OG</td>
</tr>
<tr>
<td width="4%">&nbsp;</td>
<td width="95%">$FERMENT_INGREDIENTS</td>
</tr>
<tr>
<td width="4%">&nbsp;</td>
<td width="95%">Measure Actual Original Gravity _______&nbsp;&nbsp;&nbsp;&nbsp; (Target: $EST_OG)</td>
</tr>
<tr>
<td width="4%">&nbsp;</td>
<td width="95%">Measure Actual Batch Volume _______&nbsp;&nbsp;&nbsp;&nbsp; (Target: $DISPLAY_BATCH_SIZE)</td>
</tr>
<tr>
<td width="4%">&nbsp;</td>
<td width="95%" align="left">$PRIMARY_STEP $PRIMARY_INGREDIENTS</td>
</tr>
<tr>
<td width="4%">&nbsp;</td>
<td width="95%">$BOTTLING_INGREDIENTS</td>
</tr>
<tr>
<td width="4%">&nbsp;</td>
<td width="95%">Measure Final Gravity: _________&nbsp; (Estimate: $EST_FG)</td>
</tr>
</table>
$NOTES
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment