Skip to content

Instantly share code, notes, and snippets.

@stoptime
Last active February 2, 2021 22:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stoptime/c5f21762bb8cbf75492b43e165b64532 to your computer and use it in GitHub Desktop.
Save stoptime/c5f21762bb8cbf75492b43e165b64532 to your computer and use it in GitHub Desktop.
JavaScript Generators and Spiral Matrices
<!-- view here: https://bl.ocks.org/stoptime/raw/c5f21762bb8cbf75492b43e165b64532/ -->
<!doctype html>
<html>
<head>
<title>JavaScript Generators and Spiral Matrices</title>
<style type="text/css">
body {
background-color: black;
color: white;
font-family: Helvetica, sans-serif;
}
h1 {
font-weight: normal;
font-size: 1.5rem;
}
.grid-container {
display: inline-grid;
grid-template-columns: auto auto auto;
background-color: purple;
padding: 5px;
grid-column-gap: 5px;
grid-row-gap: 5px;
width: 300px
}
.grid-item {
background-color: rgba(255, 255, 255, 0.8);
border: 1px solid rgba(0, 0, 0, 0.8);
padding: 12px 10px;
min-height: 20px;
min-width: 20px;
font-size: 15px;
text-align: center;
color: #333;
}
#form-container button {
margin-bottom: 1rem;
margin-left: .5rem
}
/* Desktop */
@media only screen and (min-width: 1024px) {
.grid-container {
padding: 10px
}
.grid-item {
padding: 20px 10px;
min-height: 40px;
min-width: 40px;
font-size: 30px;
}
}
</style>
</head>
<body>
<h1>Fun with JavaScript Generators and Spiral Matrices</h1>
<div id="main">
<div id="form-container">
<label for="grid"># of rows/cols</label>
<select name="grid" id="grid-select">
<option value="2">2</option>
<option value="3">3</option>
<option value="4" selected>4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
</select>
<button id="next" disabled>Gimme One</button>
<button id="finish" disabled>Finish It</button>
</div> <!-- close form container -->
<div class="grid-container" id="container"></div>
</div> <!-- close main -->
<script type="text/javascript">
function* spiral(num) {
let rowStartIndex = 0
let colStartIndex = 0
let rowEndIndex = num - 1
let colEndIndex = num - 1
let counter = 1
while (rowStartIndex <= rowEndIndex && colStartIndex <= colEndIndex) {
// make the top row
for (let i = colStartIndex; i <= rowEndIndex; i++) {
yield { 'row': rowStartIndex, 'col': i, 'counter': counter }
counter++
}
rowStartIndex++
// make the last col
for (let i = rowStartIndex; i <= rowEndIndex; i++) {
yield { 'col': colEndIndex, 'row': i, 'counter': counter }
counter++
}
colEndIndex--
// make the bottom row, in reverse
if (rowStartIndex <= rowEndIndex) {
for (let i = colEndIndex; i >= colStartIndex; i--) {
yield { 'row': rowEndIndex, 'col': i, 'counter': counter }
counter++
}
rowEndIndex--
}
if (colStartIndex <= colEndIndex) {
// make the 1st col, going up
for (let i = rowEndIndex; i >= rowStartIndex; i--) {
yield { 'col': colStartIndex, 'row': i, 'counter': counter }
counter++
}
colStartIndex++
}
}
}
function sizeGrid() {
const container = document.querySelector('#container')
let portMultiplier = 100
if (Math.round(window.visualViewport.width) < 1023) portMultiplier = 50
container.style.width = num * portMultiplier + 'px'
}
function makeGrid(num) {
const container = document.querySelector('#container')
// clear out any prev children
while (container.lastChild) container.removeChild(container.lastChild)
// size it
sizeGrid()
// some dynamic inline css to make our grid matrix
container.style.gridTemplateColumns = 'auto '.repeat(num).trim()
// now populate it
const total = num * num
for (let i = 0; i < num; i++) {
for (let item = -1; item < num - 1; item++) {
const el = document.createElement('div')
let col = item + 1
el.classList.add('grid-item')
el.setAttribute('data-row', i)
el.setAttribute('data-col', col)
container.append(el)
}
}
document.querySelectorAll('button').forEach((b) => {
b.removeAttribute('disabled')
})
}
function doNext(next, time = false) {
if (time) {
setTimeout(function () {
document.querySelector(`[data-row="${next.row}"][data-col="${next.col}"]`).innerText = next.counter
}, time)
} else {
document.querySelector(`[data-row="${next.row}"][data-col="${next.col}"]`).innerText = next.counter
}
}
// make the grid and our spiral generator
let num, spiralGen, next
const gridSelect = document.querySelector('#grid-select')
gridSelect.addEventListener('change', (event) => {
num = event.target.value
makeGrid(num)
spiralGen = spiral(num)
})
document.querySelector('#next').addEventListener('click', (event) => {
next = spiralGen.next().value
doNext(next)
})
document.querySelector('#finish').addEventListener('click', (event) => {
const time = 200
let i = 1
while (next = spiralGen.next().value) {
doNext(next, time * i)
i++
}
})
const container = document.querySelector('#container')
let boxes = document.querySelectorAll('.grid-item')
window.addEventListener('load', () => {
num = 4
makeGrid(num)
spiralGen = spiral(num)
})
window.addEventListener('resize', () => {
sizeGrid()
})
</script>
</body>
<html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment