220 lines
5.5 KiB
HTML
220 lines
5.5 KiB
HTML
|
<!DOCTYPE html>
|
|||
|
<html>
|
|||
|
<head>
|
|||
|
<meta charset="utf-8">
|
|||
|
<title>Bingo Card Maker</title>
|
|||
|
<style>
|
|||
|
#bingo-cards table {
|
|||
|
box-sizing: border-box;
|
|||
|
border-collapse: collapse;
|
|||
|
width: 100%;
|
|||
|
height: 100%
|
|||
|
table-layout: fixed;
|
|||
|
}
|
|||
|
#bingo-cards td {
|
|||
|
border: 2px solid black;
|
|||
|
height: 1in;
|
|||
|
text-align: center;
|
|||
|
font-size: 16pt;
|
|||
|
}
|
|||
|
#bingo-cards h1 {
|
|||
|
text-align: center;
|
|||
|
}
|
|||
|
#words-input {
|
|||
|
height: 30em;
|
|||
|
width: 20em;
|
|||
|
}
|
|||
|
#title-input {
|
|||
|
width: 20em;
|
|||
|
}
|
|||
|
.pagesep {
|
|||
|
color: gray;
|
|||
|
}
|
|||
|
|
|||
|
@media screen {
|
|||
|
.noshow {
|
|||
|
display: none;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
@media print {
|
|||
|
#bingo-controls {
|
|||
|
display: none;
|
|||
|
}
|
|||
|
#bingo-cards .pagesep {
|
|||
|
display: none;
|
|||
|
}
|
|||
|
#bingo-cards .bingo-card {
|
|||
|
page-break-after: always;
|
|||
|
}
|
|||
|
}
|
|||
|
</style>
|
|||
|
|
|||
|
<script>
|
|||
|
function showError(msg) {
|
|||
|
window.alert(msg);
|
|||
|
}
|
|||
|
|
|||
|
function shuffle(arr) {
|
|||
|
// Returns a random int n where 0 ≤ n < max
|
|||
|
function randomInt(max) {
|
|||
|
return Math.floor(Math.random() * max);
|
|||
|
}
|
|||
|
|
|||
|
for (var i = arr.length - 1; i > 0; i--) {
|
|||
|
var randi = randomInt(i+1);
|
|||
|
var tmp = arr[i];
|
|||
|
arr[i] = arr[randi];
|
|||
|
arr[randi] = tmp;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function makeCard(title, words, includeFree, freeText) {
|
|||
|
var width = 5;
|
|||
|
var height = 5;
|
|||
|
var freeIndex = 12;
|
|||
|
|
|||
|
var card = document.createElement("div");
|
|||
|
card.className = "bingo-card";
|
|||
|
card.innerHTML += "<div class='pagesep'>PAGE BREAK</div>";
|
|||
|
card.innerHTML += "<h1>" + title + "</h1>";
|
|||
|
|
|||
|
var table = document.createElement("table");
|
|||
|
|
|||
|
var row;
|
|||
|
for (var i=0; i < width * height; i++) {
|
|||
|
if (i % width === 0) {
|
|||
|
row = document.createElement("tr");
|
|||
|
table.appendChild(row);
|
|||
|
}
|
|||
|
var cell = document.createElement("td");
|
|||
|
cell.style.width = (100 / width) + "%";
|
|||
|
if (includeFree) {
|
|||
|
if (i === freeIndex) {
|
|||
|
cell.innerText = freeText;
|
|||
|
} else if (i < freeIndex) {
|
|||
|
cell.innerText = words[i];
|
|||
|
} else {
|
|||
|
cell.innerText = words[i - 1];
|
|||
|
}
|
|||
|
} else {
|
|||
|
cell.innerText = words[i];
|
|||
|
}
|
|||
|
row.appendChild(cell);
|
|||
|
}
|
|||
|
|
|||
|
card.appendChild(table);
|
|||
|
|
|||
|
return card;
|
|||
|
}
|
|||
|
|
|||
|
document.addEventListener("DOMContentLoaded", function() {
|
|||
|
var titleInput = document.getElementById("title-input");
|
|||
|
var wordsInput = document.getElementById("words-input");
|
|||
|
var freeInput = document.getElementById("free-input");
|
|||
|
var freeTextInput = document.getElementById("free-text-input");
|
|||
|
var numberInput = document.getElementById("number-input");
|
|||
|
var showInput = document.getElementById("show-input");
|
|||
|
var createButton = document.getElementById("create-button");
|
|||
|
var cards = document.getElementById("bingo-cards");
|
|||
|
|
|||
|
function updateShowCards() {
|
|||
|
if (showInput.checked) {
|
|||
|
cards.classList.remove("noshow");
|
|||
|
} else {
|
|||
|
cards.classList.add("noshow");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
updateShowCards();
|
|||
|
|
|||
|
createButton.addEventListener("click", function() {
|
|||
|
var wordsNeeded = 25;
|
|||
|
if (freeInput.checked) {
|
|||
|
wordsNeeded--;
|
|||
|
}
|
|||
|
|
|||
|
// Validate free space text input
|
|||
|
if (freeInput.checked && freeTextInput.value === "") {
|
|||
|
showError("No free space text given");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
// Validate words input
|
|||
|
var words = wordsInput.value.split("\n");
|
|||
|
for (var i=0; i < words.length; i++) {
|
|||
|
words[i] = words[i].trim();
|
|||
|
}
|
|||
|
words = words.filter(function(s) {
|
|||
|
return s != "";
|
|||
|
});
|
|||
|
console.log(words.length)
|
|||
|
if (words.length < wordsNeeded) {
|
|||
|
showError("Not enough words");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
//Validate # of cards input
|
|||
|
if (!numberInput.checkValidity() || isNaN(numberInput.valueAsNumber)) {
|
|||
|
showError("Invalid number of cards");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
cards.innerHTML = "";
|
|||
|
for (var i=0; i < numberInput.valueAsNumber; i++) {
|
|||
|
shuffle(words);
|
|||
|
var card = makeCard(titleInput.value, words, freeInput.checked, freeTextInput.value);
|
|||
|
cards.appendChild(card);
|
|||
|
}
|
|||
|
|
|||
|
window.print();
|
|||
|
});
|
|||
|
|
|||
|
freeInput.addEventListener("change", function() {
|
|||
|
freeTextInput.disabled = !freeInput.checked;
|
|||
|
});
|
|||
|
|
|||
|
showInput.addEventListener("change", updateShowCards);
|
|||
|
});
|
|||
|
</script>
|
|||
|
</head>
|
|||
|
|
|||
|
<body>
|
|||
|
<div id="bingo-controls">
|
|||
|
<h1>Bingo Card Maker</h1>
|
|||
|
<p>
|
|||
|
By Brandon Dyck<br>
|
|||
|
Distributed under the terms of the <a href="https://opensource.org/licenses/BSD-3-Clause" target="_blank">3-clause BSD license</a>.
|
|||
|
<p>
|
|||
|
<label for="title-input">Title:</label><br>
|
|||
|
<input id="title-input"></input>
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
<label for="words-input">Words:<br>(one per line; at least 24 w/ free space, or 25 otherwise)</label><br>
|
|||
|
<textarea id="words-input"></textarea>
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
<input type="checkbox" id="free-input"></input>
|
|||
|
<label for="free-input">Include free space</label>
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
<label for="free-text-input">Free space text:</label>
|
|||
|
<input type="text" id="free-text-input" value="FREE" disabled></input>
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
<label for="number-input"># of cards (1–100):</label>
|
|||
|
<input type="number" min="1" max="100" value="1" id="number-input">
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
<input type="checkbox" id="show-input"></input>
|
|||
|
<label for="show-input">Show cards</label>
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
<button id="create-button">Create & Print</button>
|
|||
|
</p>
|
|||
|
</div>
|
|||
|
|
|||
|
<div id="bingo-cards"></div>
|
|||
|
</body>
|
|||
|
</html>
|