summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Thompson <dthompson@vistahigherlearning.com>2022-01-22 09:17:51 -0500
committerDavid Thompson <dthompson@vistahigherlearning.com>2022-01-22 09:17:51 -0500
commit0aa29be84d4c554ef0d9dddc2d1f0f24859f587d (patch)
treef91212e5fedac4bd9e538501dd43f4d4fc8b2ad6
parent592bc33aa3c03e15d0deccfe8dcfd4188da2015d (diff)
A few more tweaks.
-rw-r--r--css/garden.css18
-rw-r--r--garden.js153
-rw-r--r--index.html16
3 files changed, 100 insertions, 87 deletions
diff --git a/css/garden.css b/css/garden.css
index 2077bd6..796fa73 100644
--- a/css/garden.css
+++ b/css/garden.css
@@ -437,7 +437,7 @@ table {
}
th, td {
- padding: 10px;
+ padding: 0.5rem;
margin: 0;
}
@@ -446,24 +446,19 @@ tbody tr:nth-child(odd) {
}
tbody tr td:nth-child(n+2) {
- font-size: 20pt;
border-left: 2px solid #fff;
}
img.icon {
display: block;
- width: 24px;
- max-width: 24px;
- height: 24px;
- max-height: 24px;
+ width: 1.5rem;
+ height: 1.5rem;
margin: 0 auto;
}
img.key {
- width: 24px;
- max-width: 24px;
- height: 24px;
- max-height: 24px;
+ width: 1.5rem;
+ height: 1.5rem;
}
a {
@@ -475,7 +470,8 @@ a:visited {
}
.crop {
- color: #fff;
+ text-decoration-line: underline;
+ text-decoration-style: dotted;
}
.crop:hover {
diff --git a/garden.js b/garden.js
index 8e27c31..6987c57 100644
--- a/garden.js
+++ b/garden.js
@@ -226,6 +226,7 @@ const CROPS = [
springPlant: 0
}),
new Crop("Kale", {
+ fallCrop: true,
headStart: 4,
maturity: 4,
species: ["brassica napus", "brassica oleracea"],
@@ -268,6 +269,7 @@ const CROPS = [
maturity: 14,
multisow: 3,
spacing: 4,
+ species: ["allium cepa"],
springPlant: -4,
transplant: true
}),
@@ -387,14 +389,14 @@ function makeCropSchedule(crop, season) {
return crop.interval > 0 &&
offset >= crop.springPlant &&
offset <= fallPlant &&
- (offset <= crop.pause ||
- offset >= season.length - crop.resume) &&
+ (offset <= crop.pause || offset >= resume) &&
(offset - start) % crop.interval == 0;
}
const springStart = crop.springPlant - crop.headStart;
const fallPlant = season.length - crop.maturity - FALL_FACTOR;
const fallStart = fallPlant - crop.headStart;
+ const resume = season.length - crop.resume;
return season.weeks.map(week => {
function action(type) {
@@ -443,6 +445,79 @@ function monthAndDay(date) {
return (date.getUTCMonth() + 1) + "/" + date.getUTCDate();
}
+function viewCropDetails(crop) {
+ function close() {
+ container.removeChild(overlay);
+ }
+
+ function addDetail(name, detail) {
+ const p = document.createElement("p");
+ p.appendChild(document.createTextNode(`${name}: ${detail}`));
+ modal.appendChild(p);
+ }
+
+ const container = document.getElementById("container");
+ const overlay = document.createElement("div");
+ const modal = document.createElement("div");
+ const heading = document.createElement("h2");
+ const subheading = document.createElement("h4");
+ const speciesDetail = `(${crop.species.join(", ")})`;
+ heading.appendChild(document.createTextNode(crop.name));
+ subheading.appendChild(document.createTextNode(speciesDetail));
+ subheading.classList.add("detail-subheading");
+ modal.classList.add("modal");
+ modal.appendChild(heading);
+ modal.appendChild(subheading);
+ addDetail("Average time to maturity",
+ `${crop.maturity} weeks from ${crop.transplant ? "transplant" : "seed"}`);
+ if(crop.springPlant == -1) {
+ addDetail("Spring planting time", `1 week before last frost`);
+ } else if(crop.springPlant < 0) {
+ addDetail("Spring planting time",
+ `${Math.abs(crop.springPlant)} weeks before last frost`);
+ } else if(crop.springPlant == 1) {
+ addDetail("Spring planting time", `1 week after last frost`);
+ } else if(crop.springPlant > 0) {
+ addDetail("Spring planting time",
+ `${crop.springPlant} weeks after last frost`);
+ } else if(crop.springPlant == 0) {
+ addDetail("Spring planting time", "On the last frost date");
+ } else {
+ addDetail("Spring planting time", "Not a spring crop");
+ }
+ if(crop.fallCrop) {
+ addDetail("Fall planting time", `${crop.maturity + FALL_FACTOR} weeks before first frost`);
+ } else if(crop.resume != 99) {
+ addDetail("Fall planting time", `Succession planted ${crop.resume} weeks before first frost`);
+ } else if(crop.interval > 0) {
+ addDetail("Fall planting time", `Succession planted until ${crop.maturity + FALL_FACTOR} weeks before first frost`);
+ } else {
+ addDetail("Fall planting time", "Not a fall crop");
+ }
+ addDetail("Planting method", crop.transplant ? "Transplant" : "Direct sow");
+ if(crop.transplant) {
+ addDetail("Start indoors", `${crop.headStart} weeks before planting`);
+ }
+ if(crop.interval > 0) {
+ addDetail("Succession planting interval", `Every ${crop.interval} weeks`);
+ }
+ if(crop.multisow > 1) {
+ addDetail("Multisow", `${crop.multisow} seeds per module`);
+ } else {
+ addDetail("Multisow", "No");
+ }
+ if(crop.spacing >= 1) {
+ addDetail("Spacing", `${crop.spacing} ${crop.multisow > 1 ? "clumps" : "plants"} per square foot`);
+ } else {
+ addDetail("Spacing", `1 per ${Math.floor(1 / crop.spacing)} square feet`);
+ }
+ addDetail("Needs a trellis", crop.trellis ? "Yes" : "No");
+ overlay.classList.add("overlay");
+ overlay.appendChild(modal);
+ container.appendChild(overlay);
+ overlay.addEventListener("click", event => close());
+}
+
function makeDetailLink(crop) {
const span = document.createElement("span");
span.classList.add("crop");
@@ -550,15 +625,21 @@ function refreshInstructions(crops, season, schedule) {
weekDiv.appendChild(heading);
actions.forEach(action => {
const p = document.createElement("p");
- let text;
+ let prefix;
+ let suffix;
if(action.type == "start") {
- text = `Start ${action.crop.name} indoors.`;
+ prefix = "Start ";
+ suffix = " indoors.";
} else if(action.type == "sow") {
- text = `Sow ${action.crop.name} outdoors.`;
+ prefix = "Sow ";
+ suffix = " outdoors.";
} else if(action.type == "transplant") {
- text = `Transplant ${action.crop.name} outdoors.`;
+ prefix = "Transplant ";
+ suffix = " outdoors.";
}
- p.appendChild(document.createTextNode(text));
+ p.appendChild(document.createTextNode(prefix));
+ p.appendChild(makeDetailLink(action.crop));
+ p.appendChild(document.createTextNode(suffix));
weekDiv.appendChild(p);
});
instructionsDiv.appendChild(weekDiv);
@@ -583,64 +664,6 @@ function refreshView() {
}
}
-function viewCropDetails(crop) {
- function close() {
- container.removeChild(overlay);
- }
-
- function addDetail(name, detail) {
- const p = document.createElement("p");
- p.appendChild(document.createTextNode(`${name}: ${detail}`));
- modal.appendChild(p);
- }
-
- const container = document.getElementById("container");
- const overlay = document.createElement("div");
- const modal = document.createElement("div");
- const heading = document.createElement("h2");
- const subheading = document.createElement("h4");
- const speciesDetail = `(${crop.species.join(", ")})`;
- heading.appendChild(document.createTextNode(crop.name));
- subheading.appendChild(document.createTextNode(speciesDetail));
- subheading.classList.add("detail-subheading");
- modal.classList.add("modal");
- modal.appendChild(heading);
- modal.appendChild(subheading);
- if(crop.spacing >= 1) {
- addDetail("Spacing", `${crop.spacing} per square foot`);
- } else {
- addDetail("Spacing", `1 per ${Math.floor(1 / crop.spacing)} square feet`);
- }
- addDetail("Average time to maturity",
- `${crop.maturity} weeks from ${crop.transplant ? "transplant" : "seed"}`);
- if(crop.springPlant < 0) {
- addDetail("Earliest planting time",
- `${Math.abs(crop.springPlant)} weeks before last frost`);
- } else if(crop.springPlant > 0) {
- addDetail("Earliest planting time",
- `${crop.springPlant} weeks after last frost`);
- } else {
- addDetail("Earliest planting time", "week of last frost");
- }
- addDetail("Planting method", crop.transplant ? "Transplant" : "Direct sow");
- if(crop.transplant) {
- addDetail("Start indoors", `${crop.headStart} weeks before planting`);
- }
- if(crop.multisow > 1) {
- addDetail("Multisow", `${crop.multisow} seeds per module`);
- } else {
- addDetail("Multisow", "No");
- }
- addDetail("Needs a trellis", crop.trellis ? "Yes" : "No");
- if(crop.interval > 0) {
- addDetail("Succession planting interval", `Every ${crop.interval} weeks`);
- }
- overlay.classList.add("overlay");
- overlay.appendChild(modal);
- container.appendChild(overlay);
- overlay.addEventListener("click", event => close());
-}
-
function getLastFrostDateInput() {
return document.querySelector("input[name='last-frost-date']");
}
diff --git a/index.html b/index.html
index 5c49e66..cba12e7 100644
--- a/index.html
+++ b/index.html
@@ -12,10 +12,11 @@
This handy tool helps plan your intensively planted, organic,
no-dig, home vegetable garden. Just select your first and
last frost dates and a planting schedule will be generated for
- you.
+ you. Click on a crop's name to view additional details about
+ that crop.
</p>
<p>
- The schedule works by using generalized information about
+ The algorithm works by using generalized information about
different types of crops such as average weeks to maturity,
whether direct sowing or transplanting is preferred, weeks
between plantings for continuous harvests, when and how a fall
@@ -27,15 +28,8 @@
bush beans.
</p>
<p>
- My gardening style is a combination of several intensive
- growing strategies in an attempt to grow as much food as
- possible using the least space and least effort. Those
- strategies are: square foot gardening, "no dig" AKA "no till",
- multisowing, and succession planting.
- </p>
- <p>
- Finally, this planner is intended for gardeners located in the
- nothern areas of the northern hemisphere (USDA zone 7 and below)
+ This planner works best for gardeners located in the nothern
+ areas of the northern hemisphere (USDA zone 7 and below)
where we need to start many summer crops indoors and cannot
harvest during winter without season extension. All planting
dates are made under the assumption that no season extension