Added vim-like navigation (#12)

This commit is contained in:
Alejandro Angulo 2021-10-09 19:13:18 -07:00 committed by GitHub
parent 175fe64a36
commit b72d1f8502
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 140 additions and 21 deletions

View file

@ -78,3 +78,8 @@ a:hover {
padding: 1em; padding: 1em;
overflow-x: scroll; overflow-x: scroll;
} }
.active:before {
content: "> ";
font-size: 0.7em;
}

View file

@ -8,36 +8,143 @@
* - G (scroll to bottom) * - G (scroll to bottom)
*/ */
const scroll_vertical = 100;
const scroll_behavior = "smooth";
let last_key = null; let last_key = null;
document.addEventListener("keydown", (e) => { class ContentItems {
console.log(e); constructor() {
this.items = document.getElementsByClassName("content-item");
this.current_index = 0;
let scroll_factor = 1; if (this.items.length) {
this.items[0].parentElement.classList.add("active");
if (e.key === "k") { }
scroll_factor *= -1;
} }
get current_item() {
return this.items[this.current_index];
}
_traverse(delta) {
this.current_index += delta;
if (this.current_index >= this.items.length) {
console.warn("Items exhausted (returning last item)");
this.current_index = this.items.length - 1;
} else if (this.current_index < 0) {
console.warn("Items exhausted (returning first item)");
this.current_index = 0;
}
return this.current_item;
}
next() {
return this._traverse(1);
}
prev() {
return this._traverse(-1);
}
begin() {
this.current_index = 0;
return this.current_item;
}
end() {
this.current_index = this.items.length - 1;
return this.current_item;
}
is_empty() {
return this.items.length <= 0;
}
}
let items = new ContentItems();
class KeyNav {
constructor(listing) {
this.listing = listing;
this._vertical_scroll_px = 100;
this._scroll_behavior = "smooth";
}
_is_scrolling() {
return this.listing.is_empty();
}
_toggle_active_element(item) {
item.parentElement.classList.toggle("active");
}
next() {
if (this._is_scrolling()) {
window.scrollBy({
top: this._vertical_scroll_px,
behavior: this._scroll_behavior,
});
} else {
this._toggle_active_element(items.current_item);
this._toggle_active_element(items.next());
}
}
prev() {
if (this._is_scrolling()) {
window.scrollBy({
top: -this._vertical_scroll_px,
behavior: this._scroll_behavior,
});
} else {
this._toggle_active_element(items.current_item);
this._toggle_active_element(items.prev());
}
}
begin() {
if (this._is_scrolling()) {
window.scroll(0, 0);
} else {
this._toggle_active_element(items.current_item);
this._toggle_active_element(items.begin());
}
}
end() {
if (this._is_scrolling()) {
window.scroll(0, document.body.scrollHeight);
} else {
this._toggle_active_element(items.current_item);
this._toggle_active_element(items.end());
}
}
}
let keynav = new KeyNav(items);
document.addEventListener("keydown", (e) => {
switch (e.key) { switch (e.key) {
case "j": case "j":
keynav.next();
break;
case "k": case "k":
window.scrollBy({ keynav.prev();
top: scroll_factor * scroll_vertical,
behavior: scroll_behavior,
});
break; break;
case "g": case "g":
if (last_key === "g") { if (last_key === "g") {
window.scroll(0, 0); keynav.begin();
} }
break; break;
case "G": case "G":
window.scroll(0, document.body.scrollHeight); keynav.end();
break;
case "Enter":
if (items.current_item !== undefined) {
window.location.href = items.current_item.href;
}
break; break;
} }

View file

@ -1,9 +1,16 @@
{{ define "main" }} {{ define "main" }}
{{ $paginator := .Paginate (where .Site.RegularPages.ByPublishDate.Reverse "Type" "posts") }} {{ $paginator := .Paginate (where .Site.RegularPages.ByPublishDate.Reverse "Type" "posts") }}
{{ range $paginator.Pages }} {{ range $paginator.Pages }}
<p> <div>
<h3><a class="title" href="{{ .RelPermalink }}">{{ .Title }}</a></h3> <h3>
<a
id="{{ .File.TranslationBaseName }}"
class="content-item"
href="{{ .RelPermalink }}"
>{{ .Title }}</a
>
</h3>
{{ partial "metadata.html" . }} {{ partial "metadata.html" . }}
</p> </div>
{{ end }} {{ end }}
{{ end }} {{ end }}