This repository was archived by the owner on Dec 18, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 397
/
Copy pathsearchbar.ts
116 lines (96 loc) · 3.41 KB
/
searchbar.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import {Component, ViewChild} from '@angular/core';
import {MdAutocompleteTrigger, MdSnackBar} from '@angular/material';
import {Router} from '@angular/router';
import {FormControl} from '@angular/forms';
import {Observable} from 'rxjs/Observable';
import {Subscription} from 'rxjs/Subscription';
import 'rxjs/add/operator/mergeMap';
import {DocumentationItems, DocItem} from '../../documentation-items/documentation-items';
@Component({
selector: 'search-bar-component',
templateUrl: './searchbar.html',
styleUrls: ['./searchbar.scss'],
host: {
'[class.docs-expanded]': '_isExpanded'
}
})
export class SearchBar {
@ViewChild(MdAutocompleteTrigger)
private _autocompleteTrigger: MdAutocompleteTrigger;
allDocItems: DocItem[];
filteredSuggestions: Observable<DocItem[]>;
searchControl: FormControl = new FormControl('');
subscription: Subscription;
_isExpanded: boolean = false;
constructor(
public _docItems: DocumentationItems,
public _router: Router,
public _snackBar: MdSnackBar
) {
this.allDocItems = _docItems.getAllItems();
this.filteredSuggestions = this.searchControl.valueChanges
.startWith(null)
.map(item => item ? this.filterSearchSuggestions(item) : this.allDocItems.slice());
}
// This handles the user interacting with the autocomplete panel clicks or keyboard.
ngAfterViewInit() {
// We listen to the changes on `filteredSuggestions in order to
// listen to the latest _autocompleteTrigger.optionSelections
this.subscription = this.filteredSuggestions
.flatMap(_ => this._autocompleteTrigger.optionSelections)
.subscribe(evt => this._navigate(evt.source.value.id));
}
ngOnDestroy() {
if (this.subscription) { this.subscription.unsubscribe(); }
}
toggleIsExpanded(evt?: any) {
if (!this._isExpanded && evt === null || evt && evt.tagName === 'MD-OPTION') {
// input not expanded and blurring || input is expanded and we clicked on an option
return;
} else if (this._isExpanded && evt === undefined) {
// input is expanded and we are not blurring
this._delayDropdown(false);
} else {
// defualt behaviour: not expanded and focusing || expanded and blurring
this._delayDropdown(this._isExpanded);
this._isExpanded = !this._isExpanded;
}
}
displayFn(item: DocItem) {
return item.name;
}
filterSearchSuggestions(searchTerm): DocItem[] {
return this.allDocItems.filter(item => new RegExp(`^${searchTerm}`, 'gi').test(item.name));
}
handlePlainSearch(searchTerm) {
const item = this.allDocItems.find(item => item.name.toLowerCase() === searchTerm);
return item ?
this._navigate(item.id) :
this.navigateToClosestMatch(searchTerm);
}
navigateToClosestMatch(term) {
const item = this.filterSearchSuggestions(term)[0];
item ?
this._navigate(item.id) :
this._showError();
}
_navigate(id) {
this._resetSearch();
return id ? this._router.navigateByUrl(`/components/component/${id}`) : null;
}
_resetSearch() {
this.searchControl.reset();
this.searchControl.setValue('');
}
_showError() {
this._snackBar.open('No search results found.', null, {duration: 3000});
}
_delayDropdown(isExpanded: boolean) {
if (isExpanded) {
this._autocompleteTrigger.closePanel();
} else {
this._autocompleteTrigger.closePanel();
setTimeout(() => this._autocompleteTrigger.openPanel(), 210);
}
}
}