-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b4d7232
commit b36d726
Showing
3 changed files
with
325 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
|
||
// ------------------------------------------------------------- | ||
function stringIncrement(string) { | ||
let chunks = string.split('.') | ||
let lastChunk = chunks[chunks.length - 1] | ||
const lastChunkLen = lastChunk.length | ||
|
||
// try incrementing the last chunk | ||
lastChunk = '' + (parseInt(lastChunk,10) + 1) | ||
|
||
// pad last chunk to its original length | ||
while (lastChunk.length < lastChunkLen) { | ||
lastChunk = '0' + lastChunk | ||
} | ||
|
||
// put chunks back together | ||
chunks[chunks.length - 1] = lastChunk | ||
return chunks.join('.') | ||
} | ||
// ------------------------------------------------------------- | ||
function makeDayCell(date, above, left) { | ||
const content = date.toLocaleString('en-AU', { weekday: 'short', day: 'numeric' }) | ||
const [wDay, mDate] = content.split(' ') | ||
|
||
// work out what special classes to add | ||
let classes = [] | ||
// is the day above our same month? | ||
if (above.getMonth() !== date.getMonth()) { | ||
classes.push('differentAbove') | ||
} | ||
if (left.getMonth() !== date.getMonth()) { | ||
classes.push('differentLeft') | ||
} | ||
if (date.getDay() === 0 || date.getDay() === 6) { | ||
classes.push('weekend') | ||
} | ||
|
||
return [ | ||
'<td class="' + classes.join(' ') + '">', | ||
'<span class="dayName">', wDay, '</span>', | ||
'<span class="monthDate">', mDate, '</span>', | ||
'</td>' | ||
].join('') | ||
} | ||
// ------------------------------------------------------------- | ||
function makeMonthCell(date, length, formats) { | ||
let above = new Date(date) | ||
above.setDate(date.getDate() - length) | ||
|
||
// work out what special classes to add | ||
let classes = [] | ||
// is the day above our same month? | ||
if (above.getMonth() !== date.getMonth()) { | ||
classes.push('differentAbove') | ||
} | ||
|
||
const content = date.toLocaleString('en-AU', {month: 'long'}).substring(0, formats.monthFormat) | ||
return '<td class="' + classes.join(' ') + '">' + content + '</td>' | ||
} | ||
// ------------------------------------------------------------- | ||
function makeTextCell(text) { | ||
return '<td>' + text + '</td>' | ||
} | ||
// ------------------------------------------------------------- | ||
function updateSummary(firstDay, length, calendarLength, formats) { | ||
let summary = [ | ||
'Calendar of', | ||
calendarLength, | ||
'sprints of', | ||
length, | ||
'days each, starting on', | ||
firstDay.toLocaleDateString('en-AU', { | ||
weekday: "long", | ||
year: "numeric", | ||
month: "long", | ||
day: "numeric" | ||
}) | ||
].join(' ') | ||
document.querySelector('.summary').textContent = summary | ||
} | ||
// ------------------------------------------------------------- | ||
function makeSprintRow(firstDay, length, name, formats) { | ||
const row = [] | ||
row.push(makeTextCell(name)) | ||
row.push(makeMonthCell(firstDay, length, formats)) | ||
const lastDay = new Date(firstDay) | ||
lastDay.setDate(firstDay.getDate() + length) | ||
|
||
let daysToGo = length | ||
let day = new Date(firstDay) | ||
let left, above | ||
day.setDate(day.getDate() - 1) | ||
while (daysToGo > 0) { | ||
day.setDate(day.getDate() + 1) | ||
|
||
left = new Date(day) | ||
left.setDate(day.getDate() - 1) | ||
|
||
above = new Date(day) | ||
above.setDate(day.getDate() - length) | ||
daysToGo -= 1 | ||
|
||
row.push(makeDayCell(day, above, left)) | ||
} | ||
row.push(makeMonthCell(day, length, formats)) | ||
row.push(makeTextCell(name)) | ||
|
||
return '<tr>' + row.join('\n') + '</tr>' | ||
} | ||
// ------------------------------------------------------------- | ||
function makeCalendar() { | ||
const tableBody = document.querySelector('table.calendar tbody') | ||
|
||
const firstDay = new Date(document.getElementById('sprintStart').value) | ||
const length = parseInt(document.getElementById('sprintLength').value, 10) | ||
const calendarLength = parseInt(document.getElementById('calendarLength').value, 10) | ||
let name = document.getElementById('sprintName').value | ||
|
||
const formats = { | ||
monthFormat: document.getElementById('monthNameFormat').value | ||
} | ||
|
||
updateSummary(firstDay, length, calendarLength, formats) | ||
|
||
let sprints = [] | ||
|
||
for (let sprint=0; sprint < calendarLength; sprint++) { | ||
sprints.push(makeSprintRow(firstDay, length, name, formats)) | ||
firstDay.setDate(firstDay.getDate() + length) | ||
name = stringIncrement(name) | ||
} | ||
tableBody.innerHTML = sprints.join('\n') | ||
} | ||
// ------------------------------------------------------------- | ||
// ------------------------------------------------------------- | ||
// attach handler to button | ||
const goButton = document.getElementById('makeCalendar') | ||
if (goButton) { | ||
goButton.addEventListener('click', function(e) { | ||
makeCalendar() | ||
e.preventDefault() | ||
return false | ||
}) | ||
} | ||
|
||
document.querySelectorAll('input, select').forEach( | ||
el => el.addEventListener('change', makeCalendar) | ||
) | ||
|
||
makeCalendar() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
|
||
<head> | ||
<meta charset="utf-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1"> | ||
<title>Sprint Calendar</title> | ||
<link rel="stylesheet" href="styles.css"> | ||
|
||
<!-- Montserrat --> | ||
<link rel="preconnect" href="https://fonts.googleapis.com"> | ||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | ||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet"> | ||
</head> | ||
|
||
<body> | ||
<header> | ||
<h1>Sprint Calendar</h1> | ||
</header> | ||
|
||
<div id="main"> | ||
|
||
<form id="config"> | ||
<fieldset> | ||
<legend>Sprints</legend> | ||
<label> | ||
Sprint length is | ||
<input type="number" id="sprintLength" name="sprintLength" value="14" /> days | ||
</label> | ||
<label> | ||
Start on | ||
<input type="date" id="sprintStart" name="sprintStart" value="2024-04-25" /> | ||
</label> | ||
<label> | ||
Call it | ||
<input type="text" id="sprintName" name="sprintName" value="24.1.1" /> | ||
</label> | ||
<label> | ||
Calendar should be | ||
<input type="number" id="calendarLength" name="calendarLength" value="7" /> | ||
sprints long | ||
</label> | ||
</fieldset> | ||
<fieldset> | ||
<legend>Display</legend> | ||
<label> | ||
Month names look like | ||
<select id="monthNameFormat"> | ||
<option value="1">J F M</option> | ||
<option value="3">Jan Feb Mar</option> | ||
<option selected value="33">January February March</option> | ||
</select> | ||
</label> | ||
<label> | ||
Day names look like | ||
<select> | ||
<option value="D">M T W</option> | ||
<option value="Ddd">Mon Tue Wed</option> | ||
<option value="Dddd">Monday Tuesday Wednesday</option> | ||
</select> | ||
</label> | ||
<label> | ||
Daily box content looks like | ||
<select> | ||
<option value="D">M T W</option> | ||
<option value="Ddd">Mon Tue Wed</option> | ||
<option value="Dddd">Monday Tuesday Wednesday</option> | ||
</select> | ||
</label> | ||
</fieldset> | ||
<!-- | ||
<fieldset> | ||
<label> | ||
<button id="makeCalendar">Make a sprint calendar</button> | ||
</label> | ||
</fieldset> | ||
--> | ||
</form> | ||
|
||
<p class="summary"></p> | ||
<table class="calendar"> | ||
<thead> | ||
<tr> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
</tbody> | ||
</table> | ||
|
||
</div> | ||
|
||
<footer> | ||
</footer> | ||
<script src="behaviour.js"></script> | ||
</body> | ||
|
||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
|
||
html { | ||
font-family: Montserrat, lato, sans-serif; | ||
font-size: 14px; | ||
font-size: calc(10px + 0.5vw); | ||
line-height: 1.5; | ||
background: white; | ||
padding: 0 1rem; | ||
margin: 0; | ||
} | ||
|
||
fieldset { | ||
margin: 0 0 1rem 0; | ||
border: solid 1px #bdf; | ||
border-width: 1px 0 0 1rem; | ||
} | ||
legend { | ||
padding: 0 0.5em; | ||
} | ||
label { | ||
display: block; | ||
padding: 0.25em 0; | ||
} | ||
input, select, button { | ||
font-size: inherit; | ||
font-family: inherit; | ||
padding: 0.2em 0.5em; | ||
border-radius: 0.25rem; | ||
border: 1px solid #ccc; | ||
} | ||
input[type=number] { | ||
text-align: center; | ||
max-width: 4em; | ||
} | ||
|
||
table.calendar { | ||
border-collapse: collapse; | ||
} | ||
table.calendar td, table.calendar th { | ||
text-align: center; | ||
border: 1px solid #aaa; | ||
padding: 0.5rem 0; | ||
min-width: 3.5rem; | ||
} | ||
table.calendar td.weekend, table.calendar th.weekend { | ||
min-width: 1.66rem; | ||
} | ||
.calendar .dayName, .calendar .monthDate { | ||
display: block; | ||
line-height: 1.0; | ||
padding-top: 0.1em; | ||
font-size: 0.8rem; | ||
} | ||
.calendar .weekend .dayName { font-size: 0.5rem; } | ||
.calendar .monthDate { | ||
font-weight: 700; | ||
opacity: 0.5; | ||
font-size: 1.66rem; | ||
opacity: 0.25; | ||
} | ||
.calendar .weekend .monthDate { font-size: 0.9rem; } | ||
|
||
table.calendar td.differentAbove { | ||
border-top-width: 4px; | ||
} | ||
table.calendar td.differentLeft { | ||
border-left-width: 4px; | ||
} | ||
table.calendar td.weekend { | ||
font-size: 60%; | ||
background: #eee; | ||
} | ||
|
||
@media print { | ||
fieldset { | ||
display: none; | ||
} | ||
} |