mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-10-01 01:36:00 -04:00
Started on a live-preview on global search input
This commit is contained in:
parent
a1b1f8138a
commit
19a792bc12
@ -11,7 +11,7 @@ use Illuminate\Http\Request;
|
||||
|
||||
class SearchController extends Controller
|
||||
{
|
||||
protected $searchRunner;
|
||||
protected SearchRunner $searchRunner;
|
||||
|
||||
public function __construct(SearchRunner $searchRunner)
|
||||
{
|
||||
|
47
resources/js/components/global-search.js
Normal file
47
resources/js/components/global-search.js
Normal file
@ -0,0 +1,47 @@
|
||||
/**
|
||||
* @extends {Component}
|
||||
*/
|
||||
import {htmlToDom} from "../services/dom";
|
||||
|
||||
class GlobalSearch {
|
||||
|
||||
setup() {
|
||||
this.input = this.$refs.input;
|
||||
this.suggestions = this.$refs.suggestions;
|
||||
this.suggestionResultsWrap = this.$refs.suggestionResults;
|
||||
|
||||
this.setupListeners();
|
||||
}
|
||||
|
||||
setupListeners() {
|
||||
this.input.addEventListener('input', () => {
|
||||
const value = this.input.value;
|
||||
if (value.length > 0) {
|
||||
this.updateSuggestions(value);
|
||||
} else {
|
||||
this.hideSuggestions();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async updateSuggestions(search) {
|
||||
const {data: results} = await window.$http.get('/ajax/search/entities', {term: search, count: 5});
|
||||
const resultDom = htmlToDom(results);
|
||||
|
||||
const childrenToTrim = Array.from(resultDom.children).slice(9);
|
||||
for (const child of childrenToTrim) {
|
||||
child.remove();
|
||||
}
|
||||
|
||||
this.suggestions.style.display = 'block';
|
||||
this.suggestionResultsWrap.innerHTML = '';
|
||||
this.suggestionResultsWrap.append(resultDom);
|
||||
}
|
||||
|
||||
hideSuggestions() {
|
||||
this.suggestions.style.display = null;
|
||||
this.suggestionResultsWrap.innerHTML = '';
|
||||
}
|
||||
}
|
||||
|
||||
export default GlobalSearch;
|
@ -57,6 +57,7 @@ import triLayout from "./tri-layout.js"
|
||||
import userSelect from "./user-select.js"
|
||||
import webhookEvents from "./webhook-events";
|
||||
import wysiwygEditor from "./wysiwyg-editor.js"
|
||||
import globalSearch from "./global-search";
|
||||
|
||||
const componentMapping = {
|
||||
"add-remove-rows": addRemoveRows,
|
||||
@ -86,6 +87,7 @@ const componentMapping = {
|
||||
"entity-selector-popup": entitySelectorPopup,
|
||||
"event-emit-select": eventEmitSelect,
|
||||
"expand-toggle": expandToggle,
|
||||
"global-search": globalSearch,
|
||||
"header-mobile-toggle": headerMobileToggle,
|
||||
"homepage-control": homepageControl,
|
||||
"image-manager": imageManager,
|
||||
|
@ -86,11 +86,13 @@
|
||||
.card-title a {
|
||||
line-height: 1;
|
||||
}
|
||||
.card-footer-link {
|
||||
.card-footer-link, button.card-footer-link {
|
||||
display: block;
|
||||
padding: $-s $-m;
|
||||
line-height: 1;
|
||||
border-top: 1px solid;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
@include lightDark(border-color, #DDD, #555);
|
||||
border-radius: 0 0 3px 3px;
|
||||
font-size: 0.9em;
|
||||
|
@ -1010,4 +1010,31 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
|
||||
border: 1px solid #b4b4b4;
|
||||
box-shadow: 0 1px 1px rgba(0, 0, 0, .2), 0 2px 0 0 rgba(255, 255, 255, .7) inset;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.global-search-suggestions {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: -$-s;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: -1;
|
||||
margin-left: -$-xxl;
|
||||
margin-right: -$-xxl;
|
||||
padding-top: 56px;
|
||||
border-radius: 3px;
|
||||
box-shadow: $bs-hover;
|
||||
.entity-item-snippet p {
|
||||
display: none;
|
||||
}
|
||||
.entity-item-snippet {
|
||||
font-size: .8rem;
|
||||
}
|
||||
.entity-list-item-name {
|
||||
font-size: .9rem;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
@ -412,7 +412,7 @@ div[editor-type="markdown"] .title-input.page-title input[type="text"] {
|
||||
.search-box {
|
||||
max-width: 100%;
|
||||
position: relative;
|
||||
button {
|
||||
button[tabindex="-1"] {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
@include lightDark(color, #666, #AAA);
|
||||
|
@ -108,21 +108,6 @@ header .search-box {
|
||||
border: 1px solid rgba(255, 255, 255, 0.4);
|
||||
}
|
||||
}
|
||||
button {
|
||||
z-index: 1;
|
||||
left: 16px;
|
||||
top: 10px;
|
||||
color: #FFF;
|
||||
opacity: 0.6;
|
||||
@include lightDark(color, rgba(255, 255, 255, 0.8), #AAA);
|
||||
@include rtl {
|
||||
left: auto;
|
||||
right: 16px;
|
||||
}
|
||||
svg {
|
||||
margin-block-end: 0;
|
||||
}
|
||||
}
|
||||
input::placeholder {
|
||||
color: #FFF;
|
||||
opacity: 0.6;
|
||||
@ -130,10 +115,25 @@ header .search-box {
|
||||
@include between($l, $xl) {
|
||||
max-width: 200px;
|
||||
}
|
||||
&:focus-within button {
|
||||
&:focus-within #header-search-box-button {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
#header-search-box-button {
|
||||
z-index: 1;
|
||||
left: 16px;
|
||||
top: 10px;
|
||||
color: #FFF;
|
||||
opacity: 0.6;
|
||||
@include lightDark(color, rgba(255, 255, 255, 0.8), #AAA);
|
||||
@include rtl {
|
||||
left: auto;
|
||||
right: 16px;
|
||||
}
|
||||
svg {
|
||||
margin-block-end: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.logo {
|
||||
display: inline-flex;
|
||||
|
@ -19,12 +19,19 @@
|
||||
|
||||
<div class="flex-container-column items-center justify-center hide-under-l">
|
||||
@if (hasAppAccess())
|
||||
<form action="{{ url('/search') }}" method="GET" class="search-box" role="search">
|
||||
<form component="global-search" action="{{ url('/search') }}" method="GET" class="search-box" role="search">
|
||||
<button id="header-search-box-button" type="submit" aria-label="{{ trans('common.search') }}" tabindex="-1">@icon('search') </button>
|
||||
<input id="header-search-box-input" type="text" name="term"
|
||||
<input id="header-search-box-input"
|
||||
refs="global-search@input"
|
||||
type="text"
|
||||
name="term"
|
||||
data-shortcut="global_search"
|
||||
aria-label="{{ trans('common.search') }}" placeholder="{{ trans('common.search') }}"
|
||||
value="{{ isset($searchTerm) ? $searchTerm : '' }}">
|
||||
value="{{ $searchTerm ?? '' }}">
|
||||
<div refs="global-search@suggestions" class="global-search-suggestions card">
|
||||
<div refs="global-search@suggestion-results" class="px-m"></div>
|
||||
<button class="text-button card-footer-link" type="submit">{{ trans('common.view_all') }}</button>
|
||||
</div>
|
||||
</form>
|
||||
@endif
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user