Add base for search UI.
This commit is contained in:
parent
7fdf378cee
commit
d7905f5b0a
@ -481,7 +481,14 @@ def as_document(html, title):
|
|||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<nav>
|
||||||
|
<h1><a href="/">Código para llevar [Notes]</a></h1>
|
||||||
|
<input type="text" id="searchbox" disabled="true" placeholder="Search in notes (requires JS)" />
|
||||||
|
</nav>
|
||||||
{html}
|
{html}
|
||||||
|
|
||||||
|
<script src="../static/search-box.js"></script>
|
||||||
|
<script tye="text/javascript">_codigoparallevar_enable_search_box('#searchbox', {{placeholder: 'Search in notes...'}})</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
"""
|
"""
|
||||||
|
@ -49,7 +49,19 @@ func main() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
api.OPTIONS("/search", func(c *gin.Context) {
|
||||||
|
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
|
||||||
|
c.Writer.Header().Set("Access-Control-Allow-Headers", "Accept-Encoding, Authorization, accept, origin, Cache-Control, X-Requested-With")
|
||||||
|
c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
|
||||||
|
|
||||||
|
c.AbortWithStatus(204)
|
||||||
|
})
|
||||||
|
|
||||||
api.GET("/search", func(c *gin.Context) {
|
api.GET("/search", func(c *gin.Context) {
|
||||||
|
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
|
||||||
|
c.Writer.Header().Set("Access-Control-Allow-Headers", "Accept-Encoding, Authorization, accept, origin, Cache-Control, X-Requested-With")
|
||||||
|
c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
|
||||||
|
|
||||||
query := c.Query("q")
|
query := c.Query("q")
|
||||||
|
|
||||||
stm, err := db.Prepare("SELECT note_id, title FROM note_search WHERE title LIKE ?")
|
stm, err := db.Prepare("SELECT note_id, title FROM note_search WHERE title LIKE ?")
|
||||||
|
55
static/search-box.js
Normal file
55
static/search-box.js
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
function _codigoparallevar_enable_search_box(selector, options) {
|
||||||
|
const element = document.querySelector(selector);
|
||||||
|
if ('placeholder' in options) {
|
||||||
|
element.setAttribute('placeholder', options.placeholder);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare backdrop
|
||||||
|
const resultsBoxBackdrop = document.createElement('div');
|
||||||
|
resultsBoxBackdrop.setAttribute('class', 'results-box-container hidden');
|
||||||
|
const resultsBox = document.createElement('div');
|
||||||
|
resultsBox.setAttribute('class', 'results-box');
|
||||||
|
|
||||||
|
resultsBoxBackdrop.appendChild(resultsBox);
|
||||||
|
document.body.appendChild(resultsBoxBackdrop);
|
||||||
|
|
||||||
|
|
||||||
|
const DEBOUNCE_TIME = 500; // Milliseconds
|
||||||
|
const MIN_LENGTH = 3;
|
||||||
|
const SEARCH_ENDPOINT = 'http://localhost:3001/api/search';
|
||||||
|
|
||||||
|
let debounceWaiter = null;
|
||||||
|
let currentQuery = null;
|
||||||
|
|
||||||
|
let lastVal = null;
|
||||||
|
const doQuery = () => {
|
||||||
|
const val = element.value.trim();
|
||||||
|
if ((val.length < MIN_LENGTH) || (val === lastVal)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lastVal = val;
|
||||||
|
|
||||||
|
const uri = SEARCH_ENDPOINT + '?q=' + encodeURIComponent(val);
|
||||||
|
let query = fetch(uri);
|
||||||
|
currentQuery = query;
|
||||||
|
query
|
||||||
|
.then(res => res.json())
|
||||||
|
.then((body) => {
|
||||||
|
if (query !== currentQuery) {
|
||||||
|
console.log("Query out-raced 🤷");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('=>', body);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
element.removeAttribute('disabled');
|
||||||
|
|
||||||
|
element.onkeyup = (ev) => {
|
||||||
|
if (debounceWaiter !== null) {
|
||||||
|
clearTimeout(debounceWaiter);
|
||||||
|
}
|
||||||
|
debounceWaiter = setTimeout(doQuery, DEBOUNCE_TIME);
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
@ -11,6 +11,28 @@ body {
|
|||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body nav {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
body nav h1 {
|
||||||
|
text-align: center;
|
||||||
|
color: #000;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
body nav input {
|
||||||
|
background-color: transparent;
|
||||||
|
color: #000;
|
||||||
|
border: none;
|
||||||
|
border-bottom: 1px solid #222;
|
||||||
|
}
|
||||||
|
.results-box-container {
|
||||||
|
z-index: 5;
|
||||||
|
position: absolute;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
background-color: rgba(0,0,0,0.3);
|
||||||
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "Atkinson Hyperlegible";
|
font-family: "Atkinson Hyperlegible";
|
||||||
src: url('./fonts/atkinson-hyperlegible/eot/Atkinson-Hyperlegible-Regular-102.eot');
|
src: url('./fonts/atkinson-hyperlegible/eot/Atkinson-Hyperlegible-Regular-102.eot');
|
||||||
@ -115,7 +137,7 @@ li .tag::after {
|
|||||||
pre {
|
pre {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
padding: 0.25ex;
|
padding: 0.25ex;
|
||||||
box-shadow: 0px 2px 4px 2px rgba(0, 0, 0, 0.26);
|
box-shadow: 0px 1px 2px 1px rgba(0, 0, 0, 0.25);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
}
|
}
|
||||||
pre > code {
|
pre > code {
|
||||||
@ -212,6 +234,7 @@ tr.__table-separator {
|
|||||||
background-color: #111;
|
background-color: #111;
|
||||||
color: #fafafe;
|
color: #fafafe;
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 a {
|
h2 a {
|
||||||
color: #fafafe;
|
color: #fafafe;
|
||||||
}
|
}
|
||||||
@ -233,6 +256,15 @@ tr.__table-separator {
|
|||||||
border-right: 1px solid #fff;
|
border-right: 1px solid #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Nav bar */
|
||||||
|
body nav h1 {
|
||||||
|
color: #eee;
|
||||||
|
}
|
||||||
|
body nav input {
|
||||||
|
color: #ddd;
|
||||||
|
border-bottom: 1px solid #888;
|
||||||
|
}
|
||||||
|
|
||||||
/* Code blocks */
|
/* Code blocks */
|
||||||
pre {
|
pre {
|
||||||
padding: 0.5ex;
|
padding: 0.5ex;
|
||||||
|
Loading…
Reference in New Issue
Block a user