Improve UX and add more page links
This commit is contained in:
parent
e2cfd0f266
commit
7e15316ad6
87
404.html
Normal file
87
404.html
Normal file
@ -0,0 +1,87 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>PaulW.XYZ /</title>
|
||||
<meta name="description" content="Paul's Homepage. I do things. Sporadically.">
|
||||
<link rel="stylesheet" href="/stylesheets/persia.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<svg class="m-icon"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
id="svg4546"
|
||||
version="1.1"
|
||||
viewBox="0 0 67.733332 67.733331"
|
||||
height="256"
|
||||
width="256">
|
||||
<defs
|
||||
id="defs4550" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
transform="translate(0,-229.26668)"
|
||||
id="layer1">
|
||||
<path
|
||||
id="rect4524-2"
|
||||
d="M -3.5234382e-6,249.58668 9.0311079,263.13335 -3.5234382e-6,276.68002 v 13.54667 L 18.06222,263.13335 -3.5234382e-6,236.04001 Z"
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:0.2;stroke:none;stroke-width:0.28266668;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
id="rect4524-1-7"
|
||||
d="M 4.5155513,229.26668 27.093332,263.13335 4.5155524,297.00002 h 9.0311116 l 22.57778,-33.86667 -22.57778,-33.86667 z"
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:0.73333333;stroke:none;stroke-width:0.28266668;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
id="rect4524-1-8"
|
||||
d="m 13.546665,229.26668 22.57778,33.86667 -22.57778,33.86667 h 9.031111 l 18.062225,-27.09334 18.062224,27.09334 h 9.031113 L 45.155557,263.13335 22.577776,229.26668 Z"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.28266668;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:0.73333333;stroke:none;stroke-width:0.28266668;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 36.124444,276.68002 13.546667,20.32 h 9.031113 L 40.64,269.90668 Z"
|
||||
id="path4779" />
|
||||
<path
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:0.46666667;stroke:none;stroke-width:0.28266668;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M -3.5234382e-6,236.04001 18.06222,263.13335 -3.5234382e-6,290.22669 v 6.77333 H 4.5155524 L 27.093333,263.13335 4.5155524,229.26668 H -3.5234382e-6 Z"
|
||||
id="path4781" />
|
||||
<path
|
||||
id="path4783"
|
||||
d="m 31.608889,283.45335 9.03111,13.54667 h 9.031112 l -13.546667,-20.32 z"
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:0.46666667;stroke:none;stroke-width:0.28266668;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
id="path4783-1"
|
||||
d="m 27.093332,290.22669 4.515557,6.77333 H 40.64 l -9.031111,-13.54667 z"
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:0.2;stroke:none;stroke-width:0.28266668;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
</svg>
|
||||
<nav>
|
||||
<h1 class="title"><a href="/">PaulW.XYZ</a> / ... ??? </h1>
|
||||
</nav>
|
||||
<div class="block">
|
||||
<h1>Error 404: Not Found</h1>
|
||||
<p>
|
||||
<strong>Uh oh! The page you are looking for does not exist...</strong><br>
|
||||
<strong><a href="https://en.wikipedia.org/wiki/List_of_HTTP_status_codes">[Wikipedia] Learn more about HTTP status codes.</a></strong>
|
||||
</p>
|
||||
</div>
|
||||
<footer>
|
||||
<a href="https://github.com/lambdapaul/www">Hosted on GitHub</a>
|
||||
© 2021 Paul W.
|
||||
</footer>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -74,7 +74,7 @@
|
||||
<div class="fuzzynav">
|
||||
<input class="search" type="text" id="search" placeholder="Go to ... (Try typing `help` or `?`)">
|
||||
<div id="results" class="results">
|
||||
<p><strong>Using the search bar will clear this message and list responses based on your query.</strong></p>
|
||||
<p><strong>Press any key to clear this message...</strong></p>
|
||||
<p>This is a draft of the rationale behind writing pages the way I have. I do not like the traditional web conventions so this is where I experiment the most with interfacing elements. The navigation pane-based design works when they are simple and easy to understand. When they get too complex, people rely on using search bars to get where they want. My goal is to find a method to eliminate the visual noise of the complex navigation panes and find a reasonable alternative them while being easy to use. </p>
|
||||
<h2 id="page-categorization">Page Categorization</h2>
|
||||
<p>The home page or the index page solely acts as a gateway to all the other pages on the site.
|
||||
|
13
pages.json
13
pages.json
@ -1,7 +1,10 @@
|
||||
[
|
||||
["Pages", "/pages/"],
|
||||
["Resources", "/pages/resources"],
|
||||
["Recommended", "/pages/recommended"],
|
||||
["Grade Calculator", "/pages/grade-calc/"],
|
||||
["GitHub", "https://github.com/lambdapaul"]
|
||||
{"title":"Pages", "link": "/pages/"},
|
||||
{"title":"Resources", "link": "/pages/resources"},
|
||||
{"title":"Recommended", "link": "/pages/recommended"},
|
||||
{"title":"Grade Calculator", "link": "/pages/grade-calc/"},
|
||||
{"title":"GitHub", "link": "https://github.com/lambdapaul"},
|
||||
{"title":"GitLab", "link": "https://gitlab.com/lambdapaul"},
|
||||
{"title":"Mastodon", "link": "https://mastodon.social/@lambdapaul"},
|
||||
{"title":"Keybase", "link": "https://keybase.io/lambdapaul"}
|
||||
]
|
128
scripts/fuzzy.js
128
scripts/fuzzy.js
@ -1,19 +1,27 @@
|
||||
// good luck reading through this
|
||||
(function () {
|
||||
var client = new XMLHttpRequest();
|
||||
setTimeout(() => {
|
||||
let searchField = document.querySelector("#search");
|
||||
if (searchField === null)
|
||||
return;
|
||||
|
||||
let client = new XMLHttpRequest();
|
||||
client.open("GET", "/pages.json");
|
||||
client.onreadystatechange = () => {
|
||||
if (client.readyState === 4)
|
||||
fuzzyInit(client.responseText);
|
||||
}
|
||||
client.send();
|
||||
document.querySelector("#search").focus();
|
||||
})();
|
||||
searchField.focus();
|
||||
}, 50);
|
||||
|
||||
function fuzzyInit(pagesFileName) {
|
||||
if (pagesFileName == "")
|
||||
return;
|
||||
|
||||
let searchField = document.querySelector("#search");
|
||||
let resultBlock = document.querySelector("#results");
|
||||
if (searchField === null || resultBlock === null)
|
||||
return;
|
||||
|
||||
var pages;
|
||||
try {
|
||||
pages = JSON.parse(pagesFileName);
|
||||
@ -25,66 +33,97 @@ function fuzzyInit(pagesFileName) {
|
||||
|
||||
pages.sort();
|
||||
|
||||
document.querySelector("#search")
|
||||
.addEventListener("keyup", (e) => {
|
||||
switch (e.code) {
|
||||
case "Enter":
|
||||
if (document.querySelector("#results").childNodes[0].href === undefined)
|
||||
searchField.addEventListener("keyup", (e) => {
|
||||
|
||||
let searchValue = searchField.value ? searchField.value.toLowerCase() : "";
|
||||
|
||||
if (e.code === "Enter") {
|
||||
if (resultBlock.childNodes === null
|
||||
|| resultBlock.childNodes[0] === null
|
||||
|| resultBlock.childNodes[0].href === undefined)
|
||||
return;
|
||||
|
||||
window.location = resultBlock.childNodes[0].href;
|
||||
return;
|
||||
window.location = document.querySelector("#results").childNodes[0].href;
|
||||
break;
|
||||
case "ArrowDown":
|
||||
console.log("S");
|
||||
break;
|
||||
case "ArrowUp":
|
||||
console.log("W");
|
||||
break;
|
||||
}
|
||||
|
||||
// help
|
||||
if (document.querySelector("#search").value === "?" || document.querySelector("#search").value == "help") {
|
||||
document.querySelector("#results").innerHTML = "Enter a page or directory name. If do not know any, clear the search field to list everything. Using the <code>Enter</code> key would take you to the first page in list, if it is not empty."
|
||||
if (searchValue === "?" || searchValue === "help") {
|
||||
resultBlock.innerHTML = "<h2>Help</h2>Enter a page or directory name.<br>If do not know any, clear the search field to list everything.<br> Using the <code>Enter</code> key would take you to the first page in list, if the list is not empty.<br>Alternatively, use the <code>Up</code> and <code>Down</code> arrow keys to select the page you want and use the <code>Enter</code> key."
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// if (document.querySelector("#search").value === ""){
|
||||
// document.querySelector("#results").innerHTML = "Try entering something into the input field...";
|
||||
// return;
|
||||
// }
|
||||
|
||||
let results = [];
|
||||
for (const [i, [title, page]] of pages.entries()) {
|
||||
ret = fuzzySearch(title, document.querySelector("#search").value);
|
||||
for (const [i, page] of pages.entries()) {
|
||||
ret = fuzzySearch(page.title, searchValue);
|
||||
if (ret === null)
|
||||
continue;
|
||||
results.push([ret, page]);
|
||||
results.push({formatted: ret.formatted, link: page.link, score: ret.score});
|
||||
}
|
||||
|
||||
results.sort((x, y) => {return x[0].second - y[0].second});
|
||||
results.sort((x, y) => {return x.score - y.score});
|
||||
|
||||
let output = "";
|
||||
for (const [hfRet, rlink] of results) {
|
||||
output += `<a class="hyperlink" href="${rlink}"><div class="name">${hfRet.first}</div><div class="link">${rlink}</div></a>`;
|
||||
resultBlock.innerHTML = "";
|
||||
for (const res of results) {
|
||||
linkBlock = document.createElement("a");
|
||||
linkBlock.classList.add("hyperlink");
|
||||
linkBlock.href = res.link;
|
||||
linkBlock.innerHTML = `<div class="name">${res.formatted}</div><div class="link">${res.link}</div>`;
|
||||
resultBlock.appendChild(linkBlock);
|
||||
}
|
||||
|
||||
if (output == "")
|
||||
output = "No matches found."
|
||||
|
||||
document.querySelector("#results").innerHTML = output;
|
||||
if (results.length <= 0)
|
||||
resultBlock.innerHTML = "Unknown command or no matching pages found."
|
||||
}
|
||||
);
|
||||
|
||||
document.body.addEventListener("keyup", (e) => {
|
||||
if (e.code === "ArrowDown" || e.code === "ArrowUp") {
|
||||
if (resultBlock.childNodes === null)
|
||||
return;
|
||||
|
||||
resultNodes = resultBlock.childNodes;
|
||||
|
||||
if (resultNodes.length <= 1)
|
||||
return;
|
||||
|
||||
let currNode = document.activeElement;
|
||||
|
||||
if (searchField === currNode) {
|
||||
if (e.code === "ArrowDown")
|
||||
resultNodes[0].focus();
|
||||
else
|
||||
resultNodes[resultNodes.length - 1].focus();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Array.from(resultNodes).indexOf(currNode) < 0)
|
||||
return;
|
||||
|
||||
if (e.code === "ArrowDown")
|
||||
if (currNode.nextElementSibling === null)
|
||||
searchField.focus();
|
||||
else
|
||||
currNode.nextElementSibling.focus();
|
||||
else if (e.code === "ArrowUp")
|
||||
if (currNode.previousElementSibling === null)
|
||||
searchField.focus();
|
||||
else
|
||||
currNode.previousElementSibling.focus();
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function fuzzySearch(list, input) {
|
||||
let search = input.replace(/\s/g, "");
|
||||
function fuzzySearch(findIn, find) {
|
||||
let search = find.replace(/\s/g, "");
|
||||
search = search.toLowerCase();
|
||||
let tokens = list.split('');
|
||||
let tokens = findIn.split('');
|
||||
let pc = 0;
|
||||
let score = 0;
|
||||
|
||||
for (const [i, ch] of tokens.entries()) {
|
||||
if (ch.toLowerCase() == search[pc]) {
|
||||
if (ch.toLowerCase() === search[pc]) {
|
||||
score += i - pc;
|
||||
tokens[i] = `<span class="highlight">${ch}</span>`;
|
||||
pc++;
|
||||
@ -92,8 +131,9 @@ function fuzzySearch(list, input) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (search.length != pc)
|
||||
return null;
|
||||
|
||||
return {first: tokens.join(''), second: (score / search.length)};
|
||||
if (search.length === pc)
|
||||
return {formatted: tokens.join(''), score: (score / search.length)};
|
||||
|
||||
return null;
|
||||
}
|
Loading…
Reference in New Issue
Block a user