Added vim-like navigation (#12)
This commit is contained in:
parent
175fe64a36
commit
b72d1f8502
|
@ -78,3 +78,8 @@ a:hover {
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
overflow-x: scroll;
|
overflow-x: scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.active:before {
|
||||||
|
content: "> ";
|
||||||
|
font-size: 0.7em;
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 }}
|
||||||
|
|
Loading…
Reference in a new issue