feat(aio): hide search results when click outside search elements
Clicking anywhere except on the search results and the search box will now hide the search results Closes #15095
This commit is contained in:
parent
c95a3048ce
commit
4870f910d6
|
@ -1,7 +1,7 @@
|
|||
<md-toolbar color="primary" class="app-toolbar">
|
||||
<button *ngIf="isHamburgerVisible" class="hamburger" md-button (click)="sidenav.toggle()"><md-icon>menu</md-icon></button>
|
||||
<aio-top-menu *ngIf="isSideBySide" [nodes]="(navigationViews | async)?.TopBar" [homeImageUrl]="homeImageUrl"></aio-top-menu>
|
||||
<aio-search-box></aio-search-box>
|
||||
<aio-search-box #searchBox></aio-search-box>
|
||||
<span class="fill-remaining-space"></span>
|
||||
</md-toolbar>
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
|||
</md-sidenav>
|
||||
|
||||
<section class="sidenav-content">
|
||||
<aio-search-results></aio-search-results>
|
||||
<aio-search-results #searchResults></aio-search-results>
|
||||
<aio-doc-viewer [doc]="currentDocument | async"></aio-doc-viewer>
|
||||
</section>
|
||||
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
import { async, inject, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { APP_BASE_HREF } from '@angular/common';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { AppComponent } from './app.component';
|
||||
import { AppModule } from './app.module';
|
||||
import { GaService } from 'app/shared/ga.service';
|
||||
import { SearchService } from 'app/search/search.service';
|
||||
import { SearchResultsComponent } from 'app/search/search-results/search-results.component';
|
||||
import { SearchBoxComponent } from 'app/search/search-box/search-box.component';
|
||||
import { MockSearchService } from 'testing/search.service';
|
||||
import { LocationService } from 'app/shared/location.service';
|
||||
import { MockLocationService } from 'testing/location.service';
|
||||
|
@ -84,6 +87,27 @@ describe('AppComponent', () => {
|
|||
anchorElement.click();
|
||||
expect(location.handleAnchorClick).toHaveBeenCalledWith(anchorElement, 0, false, false);
|
||||
}));
|
||||
|
||||
it('should intercept clicks not on the search elements and hide the search results', () => {
|
||||
const searchResults: SearchResultsComponent = fixture.debugElement.query(By.directive(SearchResultsComponent)).componentInstance;
|
||||
const docViewer = fixture.debugElement.query(By.css('aio-doc-viewer'));
|
||||
spyOn(searchResults, 'hideResults');
|
||||
docViewer.nativeElement.click();
|
||||
expect(searchResults.hideResults).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not intercept clicks on any of the search elements', () => {
|
||||
const searchResults = fixture.debugElement.query(By.directive(SearchResultsComponent));
|
||||
const searchResultsComponent: SearchResultsComponent = searchResults.componentInstance;
|
||||
const searchBox = fixture.debugElement.query(By.directive(SearchBoxComponent));
|
||||
spyOn(searchResultsComponent, 'hideResults');
|
||||
|
||||
searchResults.nativeElement.click();
|
||||
expect(searchResultsComponent.hideResults).not.toHaveBeenCalled();
|
||||
|
||||
searchBox.nativeElement.click();
|
||||
expect(searchResultsComponent.hideResults).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Component, HostListener, ViewChild, OnInit } from '@angular/core';
|
||||
import { Component, ElementRef, HostListener, OnInit, QueryList, ViewChild, ViewChildren } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
import { GaService } from 'app/shared/ga.service';
|
||||
|
@ -6,6 +6,7 @@ import { LocationService } from 'app/shared/location.service';
|
|||
import { DocumentService, DocumentContents } from 'app/documents/document.service';
|
||||
import { NavigationService, NavigationViews, NavigationNode } from 'app/navigation/navigation.service';
|
||||
import { SearchService } from 'app/search/search.service';
|
||||
import { SearchResultsComponent } from 'app/search/search-results/search-results.component';
|
||||
|
||||
@Component({
|
||||
selector: 'aio-shell',
|
||||
|
@ -23,13 +24,18 @@ export class AppComponent implements OnInit {
|
|||
navigationViews: Observable<NavigationViews>;
|
||||
selectedNodes: Observable<NavigationNode[]>;
|
||||
|
||||
constructor(
|
||||
documentService: DocumentService,
|
||||
gaService: GaService,
|
||||
private locationService: LocationService,
|
||||
navigationService: NavigationService,
|
||||
private searchService: SearchService) {
|
||||
@ViewChildren('searchBox, searchResults', { read: ElementRef })
|
||||
searchElements: QueryList<ElementRef>;
|
||||
|
||||
@ViewChild(SearchResultsComponent)
|
||||
searchResults: SearchResultsComponent;
|
||||
|
||||
constructor(
|
||||
documentService: DocumentService,
|
||||
gaService: GaService,
|
||||
private locationService: LocationService,
|
||||
navigationService: NavigationService,
|
||||
private searchService: SearchService) {
|
||||
this.currentDocument = documentService.currentDocument;
|
||||
locationService.currentUrl.subscribe(url => gaService.locationChanged(url));
|
||||
this.navigationViews = navigationService.navigationViews;
|
||||
|
@ -50,6 +56,16 @@ export class AppComponent implements OnInit {
|
|||
|
||||
@HostListener('click', ['$event.target', '$event.button', '$event.ctrlKey', '$event.metaKey'])
|
||||
onClick(eventTarget: HTMLElement, button: number, ctrlKey: boolean, metaKey: boolean): boolean {
|
||||
|
||||
// Hide the search results if we clicked outside both the search box and the search results
|
||||
if (this.searchResults) {
|
||||
const hits = this.searchElements.filter(element => element.nativeElement.contains(eventTarget));
|
||||
if (hits.length === 0) {
|
||||
this.searchResults.hideResults();
|
||||
}
|
||||
}
|
||||
|
||||
// Deal with anchor clicks
|
||||
if (eventTarget instanceof HTMLAnchorElement) {
|
||||
return this.locationService.handleAnchorClick(eventTarget, button, ctrlKey, metaKey);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue