'State of the art' responsive design

This commit is contained in:
Claudio Maggioni (maggicl) 2020-11-20 21:58:45 +01:00
parent 12e1344e23
commit 376880c0c1
3 changed files with 194 additions and 98 deletions

View file

@ -7,58 +7,7 @@
<meta charset="utf-8" />
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Fira+Sans&display=swap" rel="stylesheet">
<style>
* { font-size: 14px; }
body {
font-family: 'Fira Sans', sans-serif;
margin: 0;
display: flex;
height: 100vh;
max-height: 100vh;
flex-direction: column;
}
nav { flex: 0 0; }
main { flex: 1; display: flex; flex-grow: 1; min-height: 0 }
#visualization {
width: 15rem;
padding: .25rem;
border-radius: .125rem;
margin-right: .5rem;
background: #AAA;
}
#docs {
flex-grow: 1;
flex: 2;
display: grid;
grid-template-columns: repeat(4,1fr);
overflow-y: scroll;
}
.title {
background: #333;
color: white;
text-align: center;
padding: 1rem;
}
.title h1 { margin: 0; font-size: 1.4rem; }
.searchbox {
padding: 1em;
background: #666;
}
.searchbox input {
width: calc(100% - 2em);
}
.document {
float: left;
margin: .25rem;
background: #CCC;
border-radius: .125rem;
}
.document img { width: calc(100% - 1rem); }
.document h2 { font-size: 1.2rem; }
.document h3 { font-size: 1.1rem; }
.document img { margin: .5rem .5rem 0 .5rem; }
.document h2, .document h3, .document p { margin: .25rem; };
</style>
<link rel="stylesheet" href="./style.css"/>
</head>
<body>
@ -83,7 +32,8 @@ main { flex: 1; display: flex; flex-grow: 1; min-height: 0 }
</div>
<template id="document">
<div class="document" id="doc{{ id }}">
<img src="{{ url }}"/>
<a class="img_box" href="{{ url }}" target="_blank"
style="background-image: url({{ url }})"/></a>
<h2><a href="{{ site_url }}">{{ title }}</a></h2>
<h3>By {{ author }}</h3>
{{ description }}
@ -91,50 +41,6 @@ main { flex: 1; display: flex; flex-grow: 1; min-height: 0 }
</template>
</div>
<script src="./carrotsearch.foamtree.js"></script>
<script>
const solr = "http://localhost:8983/solr/photo";
const q = document.querySelector("#q");
let foamtree = null;
document.querySelector("#form").addEventListener("submit", async function(e) {
e.preventDefault();
let templateHTML = document.querySelector("#document").innerHTML;
let docs = document.querySelector("#docs");
let docMap = {}
const doc = (docData) => {
docMap[docData.id] = docData;
console.log(templateHTML);
return templateHTML
.replaceAll("{{ id }}", docData.id)
.replaceAll("{{ title }}", docData.t_title)
.replaceAll("{{ author }}", docData.t_author)
.replaceAll("{{ description }}", docData.t_description)
.replaceAll("{{ url }}", docData.img_url)
.replaceAll("{{ site_url }}", "#");
};
let list = await fetch(solr + "/clustering?q=" + q.value);
let body = await list.json();
console.log(body);
docs.innerHTML = body.response.docs.map(doc).reduce((a, b) => a + b, "");
let clusters = body.clusters.map(e => { return { label: e.labels[0], weight:
e.score, groups: e.docs.map(id => { return { id, label: docMap[id].t_title }; }) }; });
if (foamtree === null) {
foamtree = new CarrotSearchFoamTree({
id: "visualization",
layout: "squarified",
groupLabelFontFamily: "Fira Sans",
dataObject: {
groups: clusters
}
});
} else {
foamtree.set({ dataObject: { groups: clusters }});
}
});
</script>
<script src="./search.js"></script>
</body>
</html>`

71
ui/search.js Normal file
View file

@ -0,0 +1,71 @@
// vim: set ts=2 sw=2 et tw=80:
const urlParams = new URLSearchParams(window.location.search);
const query = urlParams.get('q');
const solr = "http://localhost:8983/solr/photo";
const q = document.querySelector("#q");
const templateHTML = document.querySelector("#document").innerHTML;
const docs = document.querySelector("#docs");
let foamtree = null;
let queryResult = null;
function buildCard(docData) {
const emptyOr = s => s ? s : "";
return templateHTML
.replaceAll("{{ id }}", emptyOr(docData.id))
.replaceAll("{{ title }}", emptyOr(docData.t_title))
.replaceAll("{{ author }}", emptyOr(docData.t_author))
.replaceAll("{{ description }}", emptyOr(docData.t_description))
.replaceAll("{{ url }}", emptyOr(docData.img_url))
.replaceAll("{{ site_url }}", "#");
}
function updateResults() {
docs.innerHTML = queryResult.response.docs.map(d => {
return buildCard(d);
}).reduce((a, b) => a + b, "");
}
async function buildQuery(e) {
if (e) e.preventDefault();
let docMap = {}
let list = await fetch(solr + "/clustering?q=" + q.value);
queryResult = await list.json();
console.log(queryResult);
updateResults();
for (const e of queryResult.response.docs) {
docMap[e.id] = e;
}
let clusters = queryResult.clusters.map(e => {
return {
label: e.labels[0],
weight: e.score,
groups: e.docs.map(id => {
return { id, label: docMap[id].t_title };
})
};
});
if (foamtree === null) {
foamtree = new CarrotSearchFoamTree({
id: "visualization",
layout: "squarified",
groupLabelFontFamily: "Fira Sans",
dataObject: {
groups: clusters
}
});
} else {
foamtree.set({ dataObject: { groups: clusters }});
}
};
if (query) {
q.value = query;
buildQuery().catch(console.error);
}
document.querySelector("#form").addEventListener("submit", buildQuery);

119
ui/style.css Normal file
View file

@ -0,0 +1,119 @@
/* vim: set ts=2 sw=2 et tw=80: */
:root { --columns: 14; }
@media screen and (max-width: 3000px) { :root { --columns: 13; } }
@media screen and (max-width: 2800px) { :root { --columns: 12; } }
@media screen and (max-width: 2600px) { :root { --columns: 11; } }
@media screen and (max-width: 2400px) { :root { --columns: 10; } }
@media screen and (max-width: 2200px) { :root { --columns: 9; } }
@media screen and (max-width: 2000px) { :root { --columns: 8; } }
@media screen and (max-width: 1800px) { :root { --columns: 7; } }
@media screen and (max-width: 1600px) { :root { --columns: 6; } }
@media screen and (max-width: 1400px) { :root { --columns: 5; } }
@media screen and (max-width: 1200px) { :root { --columns: 4; } }
@media screen and (max-width: 1000px) { :root { --columns: 3; } }
@media screen and (max-width: 800px) { :root { --columns: 2; } }
@media screen and (max-width: 600px) { :root { --columns: 1; } }
* {
font-size: 14px;
}
body {
font-family: 'Fira Sans', sans-serif;
margin: 0;
display: flex;
height: 100vh;
max-height: 100vh;
flex-direction: column;
}
nav {
flex: 0 0;
}
main {
flex: 1;
display: flex;
flex-grow: 1;
min-height: 0;
}
#visualization {
width: 15rem;
padding: .25rem;
border-radius: .125rem;
margin-right: .5rem;
background: #AAA;
}
#docs {
flex-grow: 1;
flex: 2;
display: grid;
grid-template-columns: repeat(var(--columns),1fr);
overflow-y: scroll;
}
.title {
background: #333;
color: white;
text-align: center;
padding: 1rem;
}
.title h1 {
margin: 0;
font-size: 1.4rem;
}
.searchbox {
padding: 1em;
background: #666;
}
.searchbox input {
width: calc(100% - 2em);
}
.document {
float: left;
margin: .25rem;
background: #CCC;
border-radius: .125rem;
text-align: center;
max-width: calc((100vw - 16rem - 20px) / var(--columns) + 1rem);
max-width: calc((100vw - 16rem - 20px) / var(--columns) + 1rem);
}
.document .img_box {
background: #222;
padding: .5rem;
padding-bottom: 0;
display: inline-block;
width: calc((100vw - 16rem - 20px) / var(--columns) - 3rem);
height: calc((100vw - 16rem - 20px) / var(--columns) - 3rem);
background-repeat: no-repeat;
background-position: center center;
background-size: cover;
}
.document p {
word-wrap: break-word;
}
.document h2 {
font-size: 1.2rem;
}
.document h3 {
font-size: 1.1rem;
}
.document img {
margin: .5rem .5rem 0 .5rem;
}
.document h2, .document h3, .document p {
margin: .25rem;
};