mirror of
https://github.com/pterodactyl/documentation.git
synced 2025-12-10 10:44:43 -06:00
138 lines
3.5 KiB
Vue
138 lines
3.5 KiB
Vue
<template>
|
|
<div class="search-box">
|
|
<input
|
|
@input="query = $event.target.value"
|
|
aria-label="Search"
|
|
:value="query"
|
|
placeholder="Search"
|
|
autocomplete="off"
|
|
spellcheck="false"
|
|
@focus="focused = true"
|
|
@blur="focused = false"
|
|
@keyup.enter="go(focusIndex)"
|
|
@keyup.up="onUp"
|
|
@keyup.down="onDown"
|
|
/>
|
|
<div class="suggestion-container" v-if="showSuggestions" @mouseleave="unfocus">
|
|
<div class="suggestion-padding"></div>
|
|
<ul class="suggestions" :class="{ 'align-right': alignRight }">
|
|
<li
|
|
class="suggestion"
|
|
v-for="(s, i) in suggestions"
|
|
:class="{ focused: i === focusIndex }"
|
|
@mousedown="go(i)"
|
|
@mouseenter="focus(i)"
|
|
>
|
|
<a :href="s.path" @click.prevent>
|
|
<span class="page-title">{{ s.title || s.path }}</span>
|
|
<span v-if="s.header" class="header">> {{ s.header.title }}</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
export default {
|
|
data() {
|
|
return {
|
|
query: "",
|
|
focused: false,
|
|
focusIndex: 0
|
|
};
|
|
},
|
|
computed: {
|
|
showSuggestions() {
|
|
return this.focused && this.suggestions && this.suggestions.length;
|
|
},
|
|
suggestions() {
|
|
const query = this.query.trim().toLowerCase();
|
|
if (!query) {
|
|
return;
|
|
}
|
|
|
|
const { pages, themeConfig } = this.$site;
|
|
const max = themeConfig.searchMaxSuggestions || 5;
|
|
const localePath = this.$localePath;
|
|
const matches = item =>
|
|
item.title && item.title.toLowerCase().indexOf(query) > -1;
|
|
const res = [];
|
|
for (let i = 0; i < pages.length; i++) {
|
|
if (res.length >= max) break;
|
|
const p = pages[i];
|
|
// filter out results that do not match current locale
|
|
if (this.getPageLocalePath(p) !== localePath) {
|
|
continue;
|
|
}
|
|
if (matches(p)) {
|
|
res.push(p);
|
|
} else if (p.headers) {
|
|
for (let j = 0; j < p.headers.length; j++) {
|
|
if (res.length >= max) break;
|
|
const h = p.headers[j];
|
|
if (matches(h)) {
|
|
res.push(
|
|
Object.assign({}, p, {
|
|
path: p.path + "#" + h.slug,
|
|
header: h
|
|
})
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return res;
|
|
},
|
|
// make suggestions align right when there are not enough items
|
|
alignRight() {
|
|
const navCount = (this.$site.themeConfig.nav || []).length;
|
|
const repo = this.$site.repo ? 1 : 0;
|
|
return navCount + repo <= 2;
|
|
}
|
|
},
|
|
methods: {
|
|
getPageLocalePath(page) {
|
|
for (const localePath in this.$site.locales || {}) {
|
|
if (localePath !== "/" && page.path.indexOf(localePath) === 0) {
|
|
return localePath;
|
|
}
|
|
}
|
|
return "/";
|
|
},
|
|
onUp() {
|
|
if (this.showSuggestions) {
|
|
if (this.focusIndex > 0) {
|
|
this.focusIndex--;
|
|
} else {
|
|
this.focusIndex = this.suggestions.length - 1;
|
|
}
|
|
}
|
|
},
|
|
onDown() {
|
|
if (this.showSuggestions) {
|
|
if (this.focusIndex < this.suggestions.length - 1) {
|
|
this.focusIndex++;
|
|
} else {
|
|
this.focusIndex = 0;
|
|
}
|
|
}
|
|
},
|
|
go(i) {
|
|
if (!this.showSuggestions) {
|
|
return;
|
|
}
|
|
this.$router.push(this.suggestions[i].path);
|
|
this.query = "";
|
|
this.focusIndex = 0;
|
|
},
|
|
focus(i) {
|
|
this.focusIndex = i;
|
|
},
|
|
unfocus() {
|
|
this.focusIndex = -1;
|
|
}
|
|
}
|
|
};
|
|
</script>
|