Below is and chart in which each box corresponds to one week in an average 88-year lifespan, and every filled-in box is one that’s already been lived. This idea came from an article that I will link to down below.
I’m super confident that I can build out these boxes in HTML and CSS, however I’m wondering how I would automate this process with JavaScript so that every passing week from the date of my birth would automatically swap out the image of the next blank box for one that is filled-in.
Any thoughts on this?
Here’s the inspiration for this project
1 Like
So what I would do is:
1: Render the field of empty boxes with HTML
2: Have Javascript figure out the number of weeks since my birth. Ignoring leap-seconds, this is a simple calculation of the number of seconds between now and a fixed date, both of which can be rendered as a timestamp , and then dividing by 604800, and probably flooring the result (or rounding, take your pick)
3: For i = 0, i < number of weeks, i++, color in a box. (The mechanism for doing this depends a little bit on whether you use images or CSS, so… probably best to make a design decision there first!
3 Likes
m3g4p0p
February 20, 2021, 11:30am
3
Hi @CooKachoo , you can get the date of death by setting the year to 88 from the date of birth… e.g.:
const birth = new Date('1980-07-20')
const death = new Date(birth.getTime())
death.setFullYear(birth.getFullYear() + 88)
To get the difference (in ms), date objects can be added and subtracted like numbers:
const now = new Date()
const passed = now - birth
const remaining = death - now
Here’s a pen with a simple text output:
Edit: Oops sorry @m_hutley I didn’t realise you already answered… I had left the tab open for a while. ^^
3 Likes
I like that you phrase it as “weeks left to chill”, when the original article is about using the chart to avoid procrastinating
4 Likes
PaulOB
February 20, 2021, 1:08pm
5
You could use CSS grid to build the boxes roughly like this at 52 per row:
You still have to connect the dots between the JS and the html but there should be enough clues to attempt this now
4 Likes
Another excellent disscussion thank you so much everyone.
3 Likes
I’ve added some JS to fill the boxes, letting us use setTimeout to give a visual depiction of the weeks being filled out disturbingly rapidly.
First, have HAML only show all the boxes as not being filled, so that JS can fill them instead:
<div class="wrap">
- (1...4591).each do |i|
%div{:class => "box" }
</div>
Then, use the array every method to go through every array item until the condition isn’t met.
const currentWeeks = 3576;
const delay = 0; // try 0 to 5
const boxes = document.querySelectorAll("div.box");
Array.from(boxes).every(function (box, week) {
setInterval(function () {
boxes[week].classList.add("filled");
}, delay * week);
return week <= currentWeeks;
});
This works without the setInterval too, but with it there delay can help to achieve different speeds of the weeks being filled out.
2 Likes
That’s clever, I guess you could similarly use find (every reads better though)
['a','b','c','d','e','f','g','h']
.find((elem, i) => (console.log(elem), i === 5))
// a, b, c, d, e, f
2 Likes
Agreed. Though find works, the some array method is equivalent to an OR operation that keeps on processing until it gets a truthy value, and the every method is equivalent to an AND operation that keeps on processing while it continues to get truthy values.
2 Likes
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,height=device-height,initial-scale=1">
<title>Past and Future</title>
<!--
The internal CSS should be transferred to an external file
<link rel="stylesheet" href="screen.css" media="screen">
-->
<style media="screen">
body {
background-color: #f0f0f0;
font: normal 1em / 1.62em sans-serif;
}
#info {
text-align: center;
}
#info input {
width: 6em;
margin-bottom: 0.5em;
}
noscript {
font-size:2em;
text-align: center;
text-transform: capitalize;
}
table {
margin:auto;
background-color: #fff;
}
td {
padding:0.25em;
border: 1px solid #333;
}
.past{
background-color: #999;
}
</style>
</head>
<body>
<div id="info" hidden>
<label for="past"> your past: </label>
<input type="text" id="past">
<label for="future"> your future: </label>
<input type="text" id="future">
</div>
<noscript>
<p>This project requires JavaScript</p>
</noscript>
<script>
(function(d) {
'use strict';
/* allow for javaScript being enabled */
d.querySelector('#info').hidden='';
/* trs equates to hopeful life span in years */
var trs = 88, tds = 52, c, i, tr, td,
tbl = d.createElement('table'),
birth = '2000,1,1', /* yyyy, mm, dd - adjust this value to suit birth date */
then, now, weeks, fill;
/* build table */
for ( c = 0; c < trs; c ++ ){
tr = d.createElement('tr');
for ( i = 0; i < tds; i ++ ) {
td = d.createElement('td');
tr.appendChild(td);
}
tbl.appendChild(tr);
}
/* append the table to the HTML */
d.body.insertBefore(tbl, d.querySelector('noscript'));
/* create the weeks - 88 years = 4576 weeks - (approximately ) trs x tds */
then = new Date(birth).getTime(); /* day of birth */
now = new Date().getTime(); /* today */
weeks = Math.floor( Math.abs( then - now )/( 1000*60*60*24*7 ));
d.querySelector('#past').value = weeks + ' weeks';
d.querySelector('#future').value= trs*tds - weeks + ' weeks';
/* colour the weeks past */
fill = d.querySelectorAll('td');
for ( c = 0; c < weeks; c ++ ){
fill[c].classList.add('past');
}
}(document));
</script>
</body>
</html>
… and let the devil take the hindmost.
coothead
3 Likes
p.s.
If you just want to match your posted image, then
use the 18th to 24th October, 1993 for the date.
coothead
2 Likes
Thank you everyone. I appreciate the help and the code samples!
1 Like
Paul_Wilkins:
- (1...4591).each do |i|
Can you explain to me what’s happening here?
1 Like
That is an HAML loop. I modified what @PaulOB had done.
It seems to be better than having an endlessly scrolling repeat of the following:
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
3 Likes
system
Closed
May 25, 2021, 3:43am
18
This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.