That being the case, I'm going to gloss over most of this with a couple of classic handwaves. As always, if you feel I've left out significant details, get back to me and I'll elaborate.
The outline has three ui elements, each of which controls what is seen in the feedback window, and when any of them change, we want to generate an appropriate calendar based on the current set of three values. So, we add a listener on the appropriate change event for each control, all of which invoke the same method to redraw the calendar.
While I'm about setting that up, I have also added an init method which initializes the default start and end dates to be today and, for good measure, then generates a "default" feedback pane to be this week, starting on Monday. It's not a lot, but it gets you started.
<script src="js/controls.js"></script>What we want to draw is basically the same as what I put in the outline: a nested structure consisting of the whole calendar containing weeks, containing days, containing information about that day. redraw needs to clear out the existing feedback calendar and draw a new one starting the week of the start date from the first day until the end date is in the past.
</head>
<body onload="init()">
<div id="controls">
<label for="start-date">Start date:</label>
<input type="date" id="start-date" onchange="redraw()">
<label for="end-date">End date:</label>
<input type="date" id="end-date" onchange="redraw()">
<label for="first-day">First Day:</label>
<select id="first-day" onchange="redraw()">
<option value="1">Monday</option>
<option value="2">Tuesday</option>
<option value="3">Wednesday</option>
<option value="4">Thursday</option>
<option value="5">Friday</option>
<option value="6">Saturday</option>
<option value="0">Sunday</option>
</select>
</div>
A couple of notes on this code which is, otherwise, fairly straightforward:
- The calculation of the offset for the start of the week works most of the time, but when the start date is a day of the week before the "left column day", the first week might be missed, and it is important to check for this and start the calendar a week earlier.
- It's important to copy the value of from into leftDate (and leftDate into cellDate), otherwise, because dates in JavaScript are references, both leftDate and from will be updated, making this check pointless.
- In order to make this work correctly, I changed the values of the options in the select statement from what I had initially used.
- I have used a "do" loop to make sure at least one week comes out, but after that it is just a question of deciding whether the end date is in the future or the past. This automatically handles the case where the end date is before the start date in a satisfactory way.
- There are comments logged to the console to clarify what is happening.
var start, end, first, fbdiv;The code is under the tag PLANNING_CALENDAR_BASIC_WIRING.
function init() {
start = document.getElementById('start-date');
end = document.getElementById('end-date');
first = document.getElementById('first-day');
fbdiv = document.getElementById('feedback');
start.valueAsDate = new Date();
end.valueAsDate = new Date();
redraw();
}
function redraw() {
var from = new Date(start.value);
var to = new Date(end.value);
var leftColumn = parseInt(first.value);
console.log("Generating calendar from", from, "to", to, "based on", leftColumn);
fbdiv.innerHTML = '';
var leftDate = new Date(from);
leftDate.setDate(leftDate.getDate() - leftDate.getDay() + leftColumn);
if (leftDate > from) {
leftDate.setDate(leftDate.getDate() - 7);
}
do {
console.log(" showing week with", leftDate, "in the left column");
// create a div for the whole week
var week = document.createElement("div");
week.className = "body-week";
fbdiv.appendChild(week);
for (var i=0;i<7;i++) {
var cellDate = new Date(leftDate);
cellDate.setDate(cellDate.getDate() + i);
console.log(" cell", i, "has date", cellDate);
// create a div for each day, to contain all the aspects we will have
var day = document.createElement("div");
day.className = "body-day";
week.appendChild(day);
// the first aspect is the date
var date = document.createElement("div");
date.className = "body-day-date";
day.appendChild(date);
// and set the date text in here
var dateValue = document.createTextNode(cellDate.getDate());
day.appendChild(dateValue);
// add a space between days until we style this
var space = document.createTextNode(" ");
week.appendChild(space);
}
// advance to next week
leftDate.setDate(leftDate.getDate() + 7);
} while (leftDate <= to);
}
No comments:
Post a Comment