Skip to content

Instantly share code, notes, and snippets.

@ffoodd
Last active October 7, 2019 12:12
Show Gist options
  • Save ffoodd/1b99d9ee6f666883293b5312d7f55e63 to your computer and use it in GitHub Desktop.
Save ffoodd/1b99d9ee6f666883293b5312d7f55e63 to your computer and use it in GitHub Desktop.
Plaan — № 15
<header role="banner" class="sr-only">
<h1>Plan de salle du «&nbsp;Cercle des poètes disparus&nbsp;»</h1>
</header>
<main role="main" id="main">
<ul role="presentation" class="no-list no-margin" id="shadow">
<li role="presentation"></li>
<li role="presentation"></li>
<li role="presentation"></li>
<li role="presentation"></li>
<li role="presentation"></li>
<li role="presentation"></li>
<li role="presentation"></li>
<li role="presentation"></li>
<li role="presentation"></li>
<li role="presentation"></li>
<li role="presentation"></li>
<li role="presentation"></li>
<li role="presentation"></li>
<li role="presentation"></li>
<li role="presentation"></li>
<li role="presentation"></li>
<li role="presentation"></li>
<li role="presentation"></li>
<li role="presentation"></li>
<li role="presentation"></li>
<li role="presentation"></li>
<li role="presentation"></li>
<li role="presentation"></li>
<li role="presentation"></li>
</ul>
<ul class="no-list no-margin" id="plan">
<li style="--x:1; --y:2; --span:2;">M. Keating</li>
<li style="--x:7; --y:4;">Neil Perry</li>
<li style="--x:2; --y:4;">Todd Anderson</li>
<li style="--x:5; --y:4;">Knox Overstreet</li>
<li style="--x:4; --y:4;">Charlie Dalton</li>
<li style="--x:3; --y:3;">Richard Cameron</li>
<li style="--x:2; --y:2;">Steven Meeks</li>
<li style="--x:5; --y:3;">Gerard Pitts</li>
<li style="--x:2; --y:3;">Hopkins</li>
<li style="--x:5; --y:1;">Stick</li>
</ul>
</main>
<aside role="complementary" id="settings" class="no-padding">
</aside>
(function () {
'use strict';
const rows = 4;
const cols = 7;
const room = document.getElementById('main');
const plan = document.getElementById('plan');
const settings = document.getElementById('settings');
function createDetails(prop, x, y) {
const label = prop.toLowerCase().replace(' ', '-');
const template = `
<div class="table">
<h2>${prop}</h2>
<button type="button" data-controls="${label}-y" data-step="down" class="↑" aria-label="Monter">↑</button>
<button type="button" data-controls="${label}-y" data-step="up" class="↓" aria-label="Descendre">↓</button>
<button type="button" data-controls="${label}-x" data-step="up" class="→" aria-label="Décaler à droite">→</button>
<button type="button" data-controls="${label}-x" data-step="down" class="←" aria-label="Décaler à gauche">←</button>
</div>
<form class="sr-only">
<p>
<label for="${label}-y">Ligne</label>
<input type="number" step="1" min="1" max="${rows}" value="${y}" tabindex="-1" data-key="${label}" id="${label}-y"/>
</p>
<p>
<label for="${label}-x">Colonne</label>
<input type="number" step="1" min="1" max="${cols}" value="${x}" tabindex="-1" data-key="${label}" id="${label}-x"/>
</p>
</form>`;
return document.createRange().createContextualFragment(template);
}
function createForm() {
const template = `
<button type="button" class="no-margin">
<span aria-hidden="true">&#9881;</span>&nbsp;Réglages
</button>
<form>
<div class="grid-2">
<a download="plaan.json" class="no-margin">Exporter</a>
<p class="no-margin">
<label for="import">Importer</label>
<input id="import" name="import" type="file" accept="json" class="sr-only"/>
</p>
</div>
<input id="reset" name="reset" type="reset" value="Annuler les modifications"/>
</form>`;
return document.createRange().createContextualFragment(template);
}
document.addEventListener('DOMContentLoaded', () => {
main.style.setProperty('--rows', rows);
main.style.setProperty('--cols', cols);
const form = createForm();
settings.append(form);
const link = document.querySelector('[download]');
const file = document.querySelector('[type="file"]');
const zero = document.querySelector('[type="reset"]');
if (localStorage.length) {
link.href = 'data:text/json,' + JSON.stringify(localStorage);
}
plan.querySelectorAll('[style]').forEach(
item => {
const name = item.textContent;
const x = item.style.getPropertyValue('--x');
const y = item.style.getPropertyValue('--y');
const details = createDetails(name, x, y);
item.innerHTML = '';
item.append(details);
item.querySelectorAll('[type="number"]').forEach( input => {
const max = Number(input.getAttribute('max'));
const axis = (max === rows) ? 'y' : 'x';
const label = input.id.split('-');
const value = localStorage.getItem(label[0]);
let result = {
name: name
};
if (value !== null) {
result = JSON.parse(value);
if (result[axis] !== undefined) {
item.style.setProperty(`--${axis}`, result[axis]);
input.value = result[axis];
}
}
input.addEventListener('input', event => {
const position = event.target.value;
const stored = localStorage.getItem(label[0]);
if (stored !== null) {
result = JSON.parse(stored);
}
result[axis] = position;
item.style.setProperty(`--${axis}`, position);
localStorage.setItem(label[0], JSON.stringify(result));
link.href = 'data:text/json,' + JSON.stringify(localStorage);
}, false);
});
}
);
file.addEventListener('change', event => {
const upload = event.target.files[0];
const reader = new FileReader();
reader.onload = (event => {
JSON.parse(event.target.result, (label, value) => {
localStorage.removeItem(label);
const result = JSON.parse(value);
const vertical = document.getElementById(`${label}-y`);
const horizontal = document.getElementById(`${label}-x`);
const parent = vertical.closest('li');
console.log(result);
if (result.y !== undefined) {
parent.style.setProperty('--y', result.y);
vertical.value = result.y;
}
if (result.x !== undefined) {
parent.style.setProperty('--x', result.x);
horizontal.value = result.x;
}
localStorage.setItem(label, value);
});
});
reader.readAsText(upload);
});
zero.addEventListener('click', () => {
localStorage.clear();
document.location.reload();
});
});
})();
[role="main"] {
display: grid;
gap: 1rem;
grid-template: repeat(var(--rows, 4), 1fr) / repeat(var(--cols, 7), 1fr);
height: 100vh;
margin: 0;
max-width: 100vw;
padding: 1rem;
}
[id="plan"] {
display: contents;
}
[id="plan"] [style] {
background: hsl(var(--accent));
border-radius: .25rem;
grid-area: var(--y, 2) / var(--x, 2) / span var(--span, 1) / auto;
}
[id="plan"] button {
border: 0;
margin: 0;
padding: 0;
}
[id="shadow"] {
display: contents;
}
[id="shadow"] [role="presentation"] {
background: hsla(var(--muted-light), .25);
border-radius: .25rem;
}
@supports not (grid-template-rows: subgrid) {
[id="shadow"] [role="presentation"] {
display: inline-block;
}
[id="shadow"] [role="presentation"]:first-child {
grid-area: 1 / 1;
width: 0;
}
[id="shadow"] [role="presentation"]:last-child {
grid-area: var(--rows) / 1;
width: 0;
}
}
@supports (grid-template-rows: subgrid) {
[id="shadow"] {
display: grid;
gap: 1rem;
grid-area: 1 / 2 / span var(--rows) / span calc(var(--cols) - 1);
grid-template-columns: repeat(calc(var(--cols) - 1), 1fr);
grid-template-rows: subgrid;
}
}
aside {
background: hsl(var(--contrast));
border: 1px solid hsl(var(--accent));
border-radius: .25rem;
clip: rect(0, 2.125rem, 2.125rem, 0);
left: 1rem;
position: fixed;
top: 1rem;
transition: clip .3s var(--move), box-shadow .3s var(--enter);
will-change: clip, box-shadow;
}
aside:hover {
clip: auto;
box-shadow: 0 0 0 .25rem hsla(var(--accent), .25);
}
aside:focus-within {
clip: auto;
box-shadow: 0 0 0 .25rem hsla(var(--accent), .25);
}
aside button {
border-radius: 0 0 .25rem 0;
line-height: .875;
word-spacing: .5rem;
}
aside form {
padding: 1rem;
}
[download],
[download]:hover,
[download]:focus {
color: hsl(var(--muted));
text-decoration: line-through;
}
[download][href] {
color: hsl(var(--secondary-dark));
text-decoration: underline;
}
[download][href]:hover,
[download][href]:focus {
color: hsl(var(--secondary));
}
@supports (clip-path: inset(-.25rem -.25rem -.25rem -.25rem)) {
aside {
clip: unset;
clip-path: inset(0 calc(100% - 2.125rem) calc(100% - 2.125rem) 0);
transition: clip-path .3s var(--move), box-shadow .3s var(--enter);
will-change: clip-path, box-shadow;
}
aside:hover,
aside:focus-within {
clip-path: inset(-.25rem -.25rem -.25rem -.25rem);
box-shadow: 0 0 0 .25rem hsla(var(--accent), .25);
}
}
.table {
contain: strict;
border-radius: .25rem;
display: grid;
grid-template-areas:
"↖ ↑ ↗"
"← • →"
"↙ ↓ ↘";
height: 100%;
margin: auto;
}
.table:hover,
.table:focus-within {
box-shadow: 0 0 0 .25rem hsla(var(--accent-light),.25);
}
.table:hover button,
.table:focus-within button {
background-color: hsl(var(--accent-dark));
}
.table h2 {
all: unset;
color: hsl(var(--contrast));
font-size: 1rem;
grid-area: •;
text-align: center;
}
[class="↑"] {
grid-area: ↑;
}
[class="↓"] {
grid-area: ↓;
}
[class="→"] {
grid-area: →;
}
[class="←"] {
grid-area: ←;
}
[data-controls] {
line-height: 1;
}
@media screen and (orientation: landscape) {
li {
height: 100%;
margin: auto;
width: 8.75rem;
}
.table h2 {
writing-mode: vertical-lr;
writing-mode: sideways-lr;
}
}
@media screen and (orientation: portrait) {
main {
writing-mode: vertical-rl;
}
li {
writing-mode: horizontal-tb;
}
}
<link href="https://ffoodd.github.io/sseeeedd/css/styles.min.css" rel="stylesheet" />
<link href="https://ffoodd.github.io/sseeeedd/css/print.min.css" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment