let path = window.location.pathname.split("/");
let basePath = path[1];
+ this.$bvModal.hide("search-modal");
+
// Home Page
if (basePath == "") {
this.currentView = this.views.home;
+ this.$nextTick(function() {
+ this.focusSearchInput();
+ });
}
// Search
});
},
+ focusSearchInput: function() {
+ document.getElementById("search-input").focus();
+ },
+
+ openSearch: function() {
+ if (this.currentView == this.views.home) {
+ this.focusSearchInput();
+ EventBus.$emit("highlight-search-input");
+ } else if (this.currentView != this.views.login) {
+ this.$bvModal.show("search-modal");
+ }
+ },
+
keyboardShortcuts: function(e) {
+ // If the user is focused on a text input or is editing a note, ignore.
+ if (
+ !["e", "/"].includes(e.key) ||
+ document.activeElement.type == "text" ||
+ (this.currentView == this.views.note && this.editMode == true)
+ ) {
+ return;
+ }
+
// 'e' to Edit
if (
e.key == "e" &&
this.toggleEditMode();
}
+ // '/' to Search
+ if (e.key == "/") {
+ e.preventDefault();
+ this.openSearch();
+ }
+
// 'CTRL + s' to Save
// else if (
// e.key == "s" &&
},
mounted: function() {
+ let parent = this;
+
window.addEventListener("popstate", this.route);
+
+ this.$root.$on("bv::modal::shown", function(_, modalId) {
+ if (modalId == "search-modal") {
+ parent.focusSearchInput();
+ }
+ });
},
};
<template>
<div class="container d-flex flex-column align-items-center h-100">
+ <!-- Search Modal -->
+ <b-modal id="search-modal" centered hide-footer hide-header>
+ <SearchInput></SearchInput>
+ </b-modal>
+
<!-- Nav Bar -->
<NavBar
v-if="currentView != views.login"
@navigate-home="navigate('/')"
@new-note="newNote()"
@logout="logout()"
+ @search="openSearch()"
></NavBar>
<!-- Login -->
src="../assets/logo.svg"
class="cursor-pointer"
:class="{ invisible: !showLogo }"
- @click="navigateHome"
+ @click="$emit('navigate-home')"
/>
</div>
<div>
<button
type="button"
class="btn btn-sm btn-outline-primary mx-1"
- @click="newNote"
+ @click="$emit('new-note')"
>
New Note
</button>
<button
type="button"
class="btn btn-sm btn-outline-dark mx-1"
- @click="logout"
+ @click="this.$emit('logout')"
>
Log Out
</button>
+
+ <!-- Search -->
+ <button
+ type="button"
+ id="search-button"
+ class="btn btn-sm btn-outline-dark mx-1"
+ @click="$emit('search')"
+ v-b-tooltip.hover
+ title="Keyboard Shortcut: /"
+ >
+ <BIconSearch />
+ </button>
</div>
</div>
</template>
</style>
<script>
+import { BIconSearch } from "bootstrap-vue";
+
export default {
+ components: {
+ BIconSearch,
+ },
+
props: {
showLogo: {
type: Boolean,
default: true,
},
},
-
- methods: {
- navigateHome: function () {
- this.$emit("navigate-home");
- },
-
- newNote: function () {
- this.$emit("new-note");
- },
-
- logout: function () {
- this.$emit("logout");
- },
- },
};
</script>
<form v-on:submit.prevent="search" class="w-100">
<div class="input-group w-100">
<input
+ id="search-input"
type="text"
class="form-control"
+ :class="{ highlight: includeHighlightClass }"
placeholder="Search"
v-model="searchTermInput"
- autofocus
/>
<div class="input-group-append">
<button class="btn" type="submit">
</template>
<style lang="scss" scoped>
+@keyframes highlight {
+ from {
+ background-color: #ffa76c5d;
+ }
+ to {
+ background-color: white;
+ }
+}
+
+.highlight {
+ animation-name: highlight;
+ animation-duration: 1.5s;
+}
+
.btn {
border: 1px solid #cfd4da;
svg {
import { BIconSearch } from "bootstrap-vue";
export default {
- comments: {
+ components: {
BIconSearch,
},
data: function () {
return {
searchTermInput: null,
+ includeHighlightClass: false,
};
},
});
}
},
+
+ highlightSearchInput: function () {
+ let parent = this;
+ this.includeHighlightClass = true;
+ setTimeout(function () {
+ parent.includeHighlightClass = false;
+ }, 1500);
+ },
+ },
+
+ created: function () {
+ EventBus.$on("highlight-search-input", this.highlightSearchInput);
},
};
</script>
"version": "0.0.0",
"license": "MIT",
"devDependencies": {
+ "@popperjs/core": "^2.11.5",
"@toast-ui/editor-plugin-code-syntax-highlight": "^3.0.0",
"@toast-ui/vue-editor": "^3.0.2",
"@vue/component-compiler-utils": "^3.2.2",
"node": ">= 6.0.0"
}
},
+ "node_modules/@popperjs/core": {
+ "version": "2.11.5",
+ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.5.tgz",
+ "integrity": "sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==",
+ "dev": true,
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/popperjs"
+ }
+ },
"node_modules/@toast-ui/editor": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@toast-ui/editor/-/editor-3.0.2.tgz",
"physical-cpu-count": "^2.0.0"
}
},
+ "@popperjs/core": {
+ "version": "2.11.5",
+ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.5.tgz",
+ "integrity": "sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==",
+ "dev": true
+ },
"@toast-ui/editor": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@toast-ui/editor/-/editor-3.0.2.tgz",
"author": "Adam Dullage",
"license": "MIT",
"devDependencies": {
+ "@popperjs/core": "^2.11.5",
"@toast-ui/editor-plugin-code-syntax-highlight": "^3.0.0",
"@toast-ui/vue-editor": "^3.0.2",
"@vue/component-compiler-utils": "^3.2.2",