display items on map, switch to grid layout

closes #2
This commit is contained in:
jomo 2022-08-05 22:04:56 +02:00
parent fda7352e22
commit 8e19a1dbad
6 changed files with 151 additions and 42 deletions

View file

@ -20,9 +20,9 @@
<b>Coordinates</b> (click on map) <b>Coordinates</b> (click on map)
<div id="plan"> <div id="map">
<img src="80x80.svg" onclick="mapClick(event)"> <img src="80x80.svg" onclick="mapClick(event)">
<div id="grid"></div> <div id="mapgrid"></div>
</div> </div>
<label for="coords_bl">Bottom left</label><label for="coords_tr">Top right</label> <label for="coords_bl">Bottom left</label><label for="coords_tr">Top right</label>

View file

@ -35,7 +35,7 @@ function fillForm() {
document.getElementById('note').value = item.note; document.getElementById('note').value = item.note;
document.getElementById('hidden').checked = item.hidden; document.getElementById('hidden').checked = item.hidden;
coordsToMap(item.coords_bl, item.coords_tr); formCoordsToMap();
} }
const saveBtn = document.getElementById('save'); const saveBtn = document.getElementById('save');

View file

@ -5,27 +5,39 @@
<link rel="stylesheet" href="style.css"> <link rel="stylesheet" href="style.css">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<script src="index.js"></script> <script src="index.js"></script>
<script src="shared.js"></script>
</head> </head>
<body> <body>
<h1>in?</h1> <div id="grid">
<input type="text" id="search" value="" autocomplete="off" placeholder="RegEx search" tabindex="1" autofocus> <div id="searchcontainer">
<label for="showhidden">Show hidden items</label> <input type="checkbox" id="showhidden"> <input type="text" id="search" value="" autocomplete="off" placeholder="RegEx search" tabindex="1" autofocus>
<div id="results"> <label for="showhidden">Show hidden items</label>
<span id="loading">loading…</span> <input type="checkbox" id="showhidden">
<template id="item"> </div>
<div id="" class="result" tabindex="0"> <div id="mapcontainer">
<h2> <div id="map">
<span class="id"></span> <img src="80x80.svg">
<span class="name"></span> <div id="mapgrid"></div>
<a title="edit"></a>
<span class="loc"></span>
</h2>
<div class="type"></div>
<div class="note"></div>
<div class="content"></div>
</div> </div>
</template> <p id="mapnote"></p>
</div>
<div id="results">
<span id="loading">loading…</span>
<template id="item">
<div id="" class="result" tabindex="0" onfocus="showItem(event)" onfocusout="hideItem(event)">
<h2>
<span class="id"></span>
<span class="name"></span>
<a title="edit"></a>
<span class="loc"></span>
</h2>
<div class="type"></div>
<div class="note"></div>
<div class="content"></div>
</div>
</template>
</div>
<a href="form.html" class="btn green">+</a>
</div> </div>
<a href="form.html" class="btn green">+</a>
</body> </body>
</html> </html>

View file

@ -39,23 +39,23 @@ function renderItems() {
} }
function getLocString(items, item) { function getLocString(items, item) {
let ancestors = []; item.ancestors = [];
let next = item; let next = item;
let loop = false; let loop = false;
while (next) { while (next) {
if (ancestors.includes(next)) { if (item.ancestors.includes(next)) {
loop = true; loop = true;
if (ancestors.length == 1) { if (item.ancestors.length == 1) {
ancestors.push(null); item.ancestors.push(null);
} }
break; break;
} }
ancestors.unshift(next); item.ancestors.unshift(next);
next = items[next.is_in]; next = items[next.is_in];
} }
ancestors.pop(); item.ancestors.pop();
let loc = ancestors.map(i => i.id).join(' ➜ ') || '⬚'; let loc = item.ancestors.map(i => i.id).join(' ➜ ') || '⬚';
let longloc = ancestors.map(i => `${i.type || ''} ${i.id} ${i.name && `(${i.name})` || ''}`).join(' ➜ ') || 'universe'; let longloc = item.ancestors.map(i => `${i.type || ''} ${i.id} ${i.name && `(${i.name})` || ''}`).join(' ➜ ') || 'universe';
if (loop) { if (loop) {
loc += ' ↻'; loc += ' ↻';
longloc += ' ↻'; longloc += ' ↻';
@ -69,7 +69,7 @@ function search(e) {
const regex = new RegExp(query, 'i') const regex = new RegExp(query, 'i')
for (const elem of document.getElementsByClassName('result')) { for (const elem of document.getElementsByClassName('result')) {
const item = items[elem.id.substr(5)]; const item = items[elem.id.slice(5)];
let found = false; let found = false;
if (query) { if (query) {
for (const a in searchAttrs) { for (const a in searchAttrs) {
@ -99,3 +99,23 @@ function showhidden(e){
results.classList.remove('showhidden'); results.classList.remove('showhidden');
} }
} }
function showItem(e) {
const item = items[e.target.id.slice(5)];
const ancestors = item.ancestors.concat(item);
for (let i = ancestors.length-1; i >= 0; i--) {
const ancestor = ancestors[i];
if (ancestor.coords_bl && ancestor.coords_tr) {
if (ancestor != item) {
const mapnote = `Showing ${ancestor.type || ''} ${ancestor.id} ${ancestor.name && `(${ancestor.name})` || ''}`;
document.getElementById('mapnote').textContent = mapnote;
}
coordsToMap(ancestor.coords_bl, ancestor.coords_tr);
break;
}
}
}
function hideItem(e) {
clearMap();
}

View file

@ -2,7 +2,7 @@ function renderMap(xx, yy) {
if (xx[0] > 0 && xx[0] < 31 && yy[0] > 0 && yy[0] < 9 && if (xx[0] > 0 && xx[0] < 31 && yy[0] > 0 && yy[0] < 9 &&
xx[1] > 0 && xx[1] < 31 && yy[1] > 0 && yy[1] < 9 && xx[1] > 0 && xx[1] < 31 && yy[1] > 0 && yy[1] < 9 &&
xx[1] >= xx[0] && yy[1] >= yy[0]) { xx[1] >= xx[0] && yy[1] >= yy[0]) {
let grid = document.getElementById('grid'); let grid = document.getElementById('mapgrid');
grid.style.top = `${yy[0]*10}%`; grid.style.top = `${yy[0]*10}%`;
grid.style.left = `${100/31*xx[0]}%`; grid.style.left = `${100/31*xx[0]}%`;
grid.style.height = `${(yy[1] - yy[0] + 1) * 10}%`; grid.style.height = `${(yy[1] - yy[0] + 1) * 10}%`;
@ -12,6 +12,14 @@ function renderMap(xx, yy) {
} }
} }
function clearMap() {
const mapnote = document.getElementById('mapnote');
if (mapnote) {
mapnote.textContent = '';
}
document.getElementById('mapgrid').removeAttribute('style');
}
function coordsToMap(coords_bl, coords_tr) { function coordsToMap(coords_bl, coords_tr) {
let bl_y = coords_bl[0]; let bl_y = coords_bl[0];
let tr_y = coords_tr[0]; let tr_y = coords_tr[0];

View file

@ -4,10 +4,8 @@
body { body {
font-family: sans-serif; font-family: sans-serif;
max-width: 600px;
margin: auto; margin: auto;
padding-bottom: 1em; padding: 1em;
background: #fefefe;
} }
h1, #search { h1, #search {
@ -28,7 +26,12 @@ h1 a {
.result { .result {
background: #eee; background: #eee;
padding: 1em; padding: 1em;
margin: 1em 0; border: 1px solid #bbb;
}
.result:focus {
outline: 2px solid #08f;
border-radius: 1px;
} }
.result a { .result a {
@ -91,8 +94,10 @@ h2 {
font-weight: bold; font-weight: bold;
text-align: center; text-align: center;
font-size: 1.5em; font-size: 1.5em;
margin: 0.5em 0; margin: 0.5em auto;
cursor: pointer; cursor: pointer;
grid-column: 1/-1;
max-width: 400px;
} }
.btn.green { .btn.green {
@ -105,6 +110,11 @@ h2 {
color: white; color: white;
} }
form {
max-width: 600px;
margin: auto;
}
form label { form label {
display: block; display: block;
width: 100%; width: 100%;
@ -127,7 +137,7 @@ input, textarea, select {
padding: 0.3em; padding: 0.3em;
font-family: monospace; font-family: monospace;
font-size: 1.4em; font-size: 1.4em;
background: initial; background: #eee;
border: 1px solid gray; border: 1px solid gray;
} }
@ -135,34 +145,93 @@ input[type=checkbox] {
width: initial; width: initial;
display: initial; display: initial;
min-width: initial; min-width: initial;
margin: 0;
} }
textarea { textarea {
min-height: 8em; min-height: 8em;
} }
#plan { #mapcontainer {
grid-column: 1/-1;
text-align: center;
position: sticky;
pointer-events: none;
top: 0;
}
#mapcontainer * {
pointer-events: all;
}
#map {
position: relative; position: relative;
border: 1px solid black; border: 1px solid black;
background: #fff; background: #fff;
max-width: 800px;
max-height: 50vh;
aspect-ratio: 31 / 10;
margin: 0 auto;
} }
#plan img { #mapnote {
min-height: 1.95em;
font-style: italic;
margin: 0;
padding: 0.5em;
display: inline-block;
background: #fff;
border: 1px solid;
border-top: none;
}
#mapnote:empty {
background: none;
border: none;
}
#map img {
width: 100%; width: 100%;
max-height: 100%;
max-width: 100%;
display: block; display: block;
} }
form #plan { form #map {
margin: 0.3em 0 1em 0; margin: 0.3em 0 1em 0;
} }
#grid { #mapgrid {
position: absolute; position: absolute;
pointer-events: none; pointer-events: none;
outline: 2px solid #f00; outline: 2px solid #f00;
background: #ff08; background: #ff08;
} }
#grid:not([style]) { #mapgrid:not([style]) {
outline: none; outline: none;
} }
#grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
gap: 1em;
}
@media only screen and (max-width: 500px) {
#grid {
grid-template-columns: none;
}
}
#grid #results {
display: contents;
}
#grid #searchcontainer {
grid-column: 1/-1;
width: calc(min(600px, 100%));
max-width: 100%;
text-align: center;
margin: auto;
}