Merge pull request #37 from jozefs/master

Add keyboard shortcuts to navigate to the first search result.
This commit is contained in:
Bastien Wirtz 2020-04-13 09:46:48 -07:00 committed by GitHub
commit d2bf5e5f62
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 32 additions and 3 deletions

View File

@ -3,6 +3,13 @@ A dead simple static **HOM**epage for your serv**ER** to keep your services on h
**Check out the live demo [here](https://homer-demo.netlify.com/).**
It supports keyboard shortcuts:
* `/` Start searching.
* `Escape` Stop searching.
* `Enter` Open the first matching result (respects the bookmark's `_target` property).
* `Alt`/`Option` + `Enter` Open the first matching result in a new tab.
If you need authentication support, you're on your own (it can be secured using a web server auth module or exposing it only through a VPN network / SSH tunnel, ...)
![screenshot](https://raw.github.com/bastienwirtz/homer/master/screenshot.png)

20
app.js
View File

@ -84,6 +84,26 @@ const app = new Vue({
},
toggleMenu: function() {
this.showMenu = !this.showMenu;
},
matchesFilter: function(item) {
return (item.name.toLowerCase().includes(this.filter.toLowerCase())
|| (item.tag && item.tag.toLowerCase().includes(this.filter.toLowerCase())))
},
firstMatchingService: function() {
for (group of this.config.services) {
for (item of group.items) {
if (this.matchesFilter(item)) {
return item;
}
}
}
return null;
},
navigateToFirstService: function(target) {
service = this.firstMatchingService();
if (service) {
window.open(service.url, target || service.target || '_self');
}
}
},
mounted() {

View File

@ -59,7 +59,9 @@
:class="['fas', vlayout ? 'fa-list' : 'fa-columns']"></i></a>
<div class="search-bar">
<label for="search" class="search-label"></label>
<input type="text" id="search" ref="search" v-model="filter" />
<input type="text" id="search" ref="search" v-model="filter"
v-on:keyup.enter.exact="navigateToFirstService()"
v-on:keyup.alt.enter="navigateToFirstService('_blank')" />
</div>
</div>
</div>
@ -95,7 +97,7 @@
v-else>#</span>
{{ group.name }}</h2>
<service v-for="item in group.items" v-bind:item="item" class="column is-one-third-widescreen"
v-if="!filter || (item && (item.name.toLowerCase().includes(filter.toLowerCase()) || (item.tag && item.tag.toLowerCase().includes(filter.toLowerCase()))))">
v-if="!filter || (item && matchesFilter(item))">
</service>
</template>
</div>
@ -106,7 +108,7 @@
<h2 v-if="!filter && group.name"><i v-if="group.icon" :class="group.icon"></i><span v-else>#</span>
{{ group.name }}</h2>
<service v-for="item in group.items" v-bind:item="item"
v-if="!filter || (item && (item.name.toLowerCase().includes(filter.toLowerCase()) || (item.tag && item.tag.toLowerCase().includes(filter.toLowerCase()))))">
v-if="!filter || (item && matchesFilter(item))">
</service>
</div>
</div>