[ADF-1924] - Some issues related to search bar (#2702)

* issue #1

Because the input element gets no focus when the search button is clicked, there is no way to toggle off the search input, when user clicks outside the search bar
Added focus on search input when the user click on search input

issue #2

Increased the width of the search results container in order to be able to show more text
translated results container to the left in order to prevent it to overlap the menu items from the navigation bar

* Adding test spec for checking if search input has focus after the user clicks on search button

* removed deprecated render dependency
using this call
	" searchInput.nativeElement.focus()"
to enable input focus

* fixed broken animation on input search focus()

* Fix search control component tests

* Fix rebasing
This commit is contained in:
mihai sirghe 2017-11-28 18:24:27 +02:00 committed by Eugenio Romano
parent c763ba45e0
commit 634e65af96
4 changed files with 64 additions and 34 deletions

View File

@ -1,5 +1,5 @@
<div class="adf-search-container">
<div *ngIf="isLoggedIn()" [@transitionMessages]="subscriptAnimationState">
<div *ngIf="isLoggedIn()" [@transitionMessages]="subscriptAnimationState" (@transitionMessages.done)="applySearchFocus($event)">
<a mat-icon-button
*ngIf="expandable"
id="adf-search-button"
@ -9,8 +9,7 @@
<mat-icon aria-label="search button">search</mat-icon>
</a>
<mat-form-field class="adf-input-form-field-divider">
<input matInput
#inputSearch
<input matInput #searchInput
[type]="inputType"
[autocomplete]="getAutoComplete()"
id="adf-control-input"

View File

@ -35,8 +35,9 @@
&-search-result-autocomplete {
@include mat-menu-base(2);
transform-origin: top left;
transform:translateX(-40px);
position: absolute;
max-width: 200px;
max-width: 235px;
max-height: 400px;
margin-left: 45px;
margin-top: -22px;
@ -47,7 +48,6 @@
border-radius: $mat-menu-border-radius;
@media screen and ($mat-small) {
width: 160px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;

View File

@ -16,7 +16,8 @@
*/
import { DebugElement } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { async, discardPeriodicTasks, fakeAsync, ComponentFixture, TestBed, tick } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { MaterialModule } from '../../material.module';
import { By } from '@angular/platform-browser';
import { AuthenticationService, SearchService } from '@alfresco/adf-core';
@ -39,7 +40,8 @@ describe('SearchControlComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
MaterialModule
MaterialModule,
NoopAnimationsModule
],
declarations: [
SearchControlComponent,
@ -408,31 +410,53 @@ describe('SearchControlComponent', () => {
describe('search button', () => {
it('should NOT display a autocomplete list control when configured not to', async(() => {
it('should NOT display a autocomplete list control when configured not to', fakeAsync(() => {
fixture.detectChanges();
let searchButton: DebugElement = debugElement.query(By.css('#adf-search-button'));
component.subscriptAnimationState = 'active';
fixture.detectChanges();
expect(component.subscriptAnimationState).toBe('active');
searchButton.triggerEventHandler('click', null);
window.setTimeout(() => {
fixture.detectChanges();
expect(component.subscriptAnimationState).toBe('inactive');
}, 100);
fixture.detectChanges();
tick(100);
fixture.detectChanges();
expect(component.subscriptAnimationState).toBe('inactive');
discardPeriodicTasks();
}));
it('click on the search button should open the input box when is close', (done) => {
it('click on the search button should open the input box when is close', fakeAsync(() => {
fixture.detectChanges();
let searchButton: DebugElement = debugElement.query(By.css('#adf-search-button'));
searchButton.triggerEventHandler('click', null);
window.setTimeout(() => {
fixture.detectChanges();
expect(component.subscriptAnimationState).toBe('active');
done();
}, 100);
});
it('Search button should not change the input state too often', async(() => {
tick(100);
fixture.detectChanges();
expect(component.subscriptAnimationState).toBe('active');
discardPeriodicTasks();
}));
it('click on the search button should apply focus on input', fakeAsync(() => {
fixture = TestBed.createComponent(SearchControlComponent);
debugElement = fixture.debugElement;
fixture.detectChanges();
let searchButton: DebugElement = debugElement.query(By.css('#adf-search-button'));
let inputDebugElement = debugElement.query(By.css('#adf-control-input'));
searchButton.triggerEventHandler('click', null);
tick(100);
fixture.detectChanges();
tick(300);
fixture.detectChanges();
expect(document.activeElement.id).toBe(inputDebugElement.nativeElement.id);
discardPeriodicTasks();
}));
it('Search button should not change the input state too often', fakeAsync(() => {
fixture.detectChanges();
let searchButton: DebugElement = debugElement.query(By.css('#adf-search-button'));
component.subscriptAnimationState = 'active';
@ -443,13 +467,13 @@ describe('SearchControlComponent', () => {
searchButton.triggerEventHandler('click', null);
fixture.detectChanges();
window.setTimeout(() => {
fixture.detectChanges();
expect(component.subscriptAnimationState).toBe('inactive');
}, 100);
tick(100);
fixture.detectChanges();
expect(component.subscriptAnimationState).toBe('inactive');
discardPeriodicTasks();
}));
it('Search bar should close when user press ESC button', async(() => {
it('Search bar should close when user press ESC button', fakeAsync(() => {
fixture.detectChanges();
let inputDebugElement = debugElement.query(By.css('#adf-control-input'));
component.subscriptAnimationState = 'active';
@ -457,10 +481,11 @@ describe('SearchControlComponent', () => {
expect(component.subscriptAnimationState).toBe('active');
inputDebugElement.triggerEventHandler('keyup.escape', {});
window.setTimeout(() => {
fixture.detectChanges();
expect(component.subscriptAnimationState).toBe('inactive');
}, 100);
tick(100);
fixture.detectChanges();
expect(component.subscriptAnimationState).toBe('inactive');
discardPeriodicTasks();
}));
});

View File

@ -78,8 +78,8 @@ export class SearchControlComponent implements OnInit, OnDestroy {
@ViewChild(SearchComponent)
searchAutocomplete: SearchComponent;
@ViewChild('inputSearch')
inputSearch: ElementRef;
@ViewChild('searchInput')
searchInput: ElementRef;
@ViewChildren(MatListItem)
private listResultElement: QueryList<MatListItem>;
@ -100,14 +100,20 @@ export class SearchControlComponent implements OnInit, OnDestroy {
if (this.subscriptAnimationState === 'inactive') {
this.searchTerm = '';
this.searchAutocomplete.resetResults();
if ( document.activeElement.id === this.inputSearch.nativeElement.id) {
this.inputSearch.nativeElement.blur();
if ( document.activeElement.id === this.searchInput.nativeElement.id) {
this.searchInput.nativeElement.blur();
}
}
}
});
}
applySearchFocus(animationDoneEvent) {
if (animationDoneEvent.toState === 'active') {
this.searchInput.nativeElement.focus();
}
}
ngOnInit() {
this.subscriptAnimationState = this.expandable ? 'inactive' : 'no-animation';
this.setupFocusEventHandlers();
@ -205,7 +211,7 @@ export class SearchControlComponent implements OnInit, OnDestroy {
if (previousElement) {
previousElement.focus();
}else {
this.inputSearch.nativeElement.focus();
this.searchInput.nativeElement.focus();
this.focusSubject.next(new FocusEvent('focus'));
}
}