Skip to content

Instantly share code, notes, and snippets.

@atelierbram
Forked from prof3ssorSt3v3/index.html
Created February 17, 2021 20:40
Show Gist options
  • Save atelierbram/bb6b69eb99591a37ea0295cb6a928574 to your computer and use it in GitHub Desktop.
Save atelierbram/bb6b69eb99591a37ea0295cb6a928574 to your computer and use it in GitHub Desktop.
Code for youtube video on popstate, hashchange, and history.state
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>History popstate and hashchange Events</title>
<link rel="stylesheet" href="./main.css" />
</head>
<body>
<header>
<h1><code>popstate </code>AND<code> hashchange </code>Events</h1>
</header>
<nav>
<a href="#a" data-name="James Holden" data-home="Earth">James Holden</a>
<a href="#b" data-name="Bobbie Draper" data-home="Mars">Bobbie Draper</a>
<a href="#c" data-name="Josephus Miller" data-home="Belt"
>Josephus Miller</a
>
</nav>
<main class="all">
<div class="box earth">Earth</div>
<div class="box mars">Mars</div>
<div class="box belt">Belt</div>
<div class="box mars">Mars</div>
<div class="box earth">Earth</div>
<div class="box belt">Belt</div>
<div class="box mars">Mars</div>
<div class="box earth">Earth</div>
<div class="box mars">Mars</div>
<div class="box earth">Earth</div>
<div class="box mars">Mars</div>
<div class="box belt">Belt</div>
<div class="box earth">Earth</div>
<div class="box belt">Belt</div>
<div class="box mars">Mars</div>
</main>
<script src="main.js" defer></script>
</body>
</html>
:root {
--base-orbit: 4;
}
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
html {
font-size: 24px;
font-weight: 300;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
line-height: 1.5;
color: #eee;
background-color: #333;
}
body {
background-color: #333;
min-height: 100vh;
}
header,
main {
padding: 1rem 2rem;
}
nav {
background-color: orange;
color: #333;
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: center;
}
nav a,
nav a:visited {
font-size: 1.2rem;
font-weight: 500;
line-height: 3.6rem;
letter-spacing: 3px;
padding: 1.2rem 0;
color: #444;
text-shadow: 1px 1px 2px white;
cursor: pointer;
text-decoration-line: overline underline;
position: relative;
z-index: 10;
}
nav a:hover,
nav a:active,
nav a:focus {
color: #000;
}
nav a:hover::before,
nav a:active::before,
nav a:focus::before {
animation-play-state: paused;
}
nav a::before {
content: attr(data-home);
text-decoration-style: none;
text-shadow: none;
position: absolute;
z-index: -1;
color: white;
border-radius: 50%;
width: 5ch;
height: 5ch;
text-align: center;
opacity: 0.6;
top: 2rem;
left: 0;
transform-origin: 5ch 0;
animation-name: orbit;
animation-duration: 2.4s;
animation-iteration-count: infinite;
animation-timing-function: linear;
box-shadow: 1px 1px 2px #333;
}
nav a[data-home='Earth']::before {
background-color: cornflowerblue;
color: white;
width: 7ch;
height: 7ch;
animation-duration: calc(365ms * var(--base-orbit));
}
nav a[data-home='Mars']::before {
background-color: orangered;
color: white;
animation-duration: calc(687ms * var(--base-orbit));
}
nav a[data-home='Belt']::before {
background-color: #888;
border-top-right-radius: 40% 60%;
border-top-left-radius: 30% 70%;
border-bottom-left-radius: 80% 80%;
border-bottom-right-radius: 70% 30%;
height: 4ch;
width: 5ch;
color: white;
animation-duration: calc(2000ms * var(--base-orbit));
}
@keyframes orbit {
0% {
transform: rotate(0deg);
}
50% {
transform: rotate(180deg);
}
100% {
transform: rotate(359deg);
}
}
main {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-items: flex-start;
gap: 1rem;
}
.box {
width: 18vw;
height: 18vw;
padding: 1rem;
border-radius: 1rem;
opacity: 0;
}
.box.earth {
background-color: cornflowerblue;
color: cornsilk;
}
.box.mars {
background-color: orangered;
color: #222;
}
.box.belt {
background-color: #888;
color: #222;
}
main.earth .box.earth {
opacity: 1;
}
main.mars .box.mars {
opacity: 1;
}
main.belt .box.belt {
opacity: 1;
}
main.all .box.earth,
main.all .box.mars,
main.all .box.belt {
opacity: 1;
}
h1 {
color: orange;
}
h2 {
color: orangered;
}
p {
font-size: 1.2rem;
text-align: center;
}
const APP = {
init() {
//when the page loads
//check the state or hash value or both
APP.checkState(); //when the page loads
//add listeners for nav bar
//add listeners for popstate OR hashchange
APP.addListeners();
//APP.updateLayout('earth');
},
addListeners() {
document.querySelector('nav').addEventListener('click', APP.nav);
window.addEventListener('popstate', APP.checkState);
//when the user clicks back or forward
//window.addEventListener('hashchange', APP.tempHC);
},
// tempPop(ev) {
// console.log('popstate');
// console.log(history.state);
// },
// tempHC(ev) {
// console.log('hashchange');
// console.log(history.state);
// },
checkState() {
//do we want to drive our app by state or fragment-identifier(hash) or query?
//called when page loads AND after a popstate event
console.log(location);
console.log(history);
if (!location.hash) {
//default first load
history.replaceState(
{ home: 'Earth', name: 'James Holden' },
'',
'#earth'
);
document.title = 'Earth';
APP.updateLayout('earth');
} else {
let hash = location.hash.replace('#', '');
APP.updateLayout(hash);
document.title = hash; //first letter to uppercase needed
}
},
nav(ev) {
ev.preventDefault();
let anchor = ev.target;
let home = anchor.getAttribute('data-home');
let name = anchor.getAttribute('data-name');
let state = {
home,
name,
};
let hash = `#${home.toLowerCase()}`;
history.pushState(state, '', hash);
document.title = home;
APP.updateLayout(home.toLowerCase());
},
updateLayout(place) {
//accept a className and update the interface based on that
let main = document.querySelector('main');
main.className = place;
},
};
document.addEventListener('DOMContentLoaded', APP.init);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment