Skip to content

Commit

Permalink
fix(pickers): fixing keyboard control and highlighting
Browse files Browse the repository at this point in the history
  • Loading branch information
Joshua Godi committed Jun 15, 2017
1 parent b4a4b92 commit 593ab19
Show file tree
Hide file tree
Showing 10 changed files with 116 additions and 65 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ novo-elements.providers.d.ts
# IDEs and editors
/.idea
/.vscode
/.history
.project
.classpath
*.launch
Expand Down
18 changes: 10 additions & 8 deletions demo/pages/elements/picker/PickerDemo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,17 @@ import { PickerResults } from './../../../../index';
},
template: `
<novo-loading theme="line" *ngIf="isLoading && !matches.length"></novo-loading>
<ul *ngIf="matches.length > 0">
<li
<novo-list *ngIf="matches.length > 0" direction="vertical">
<novo-list-item
*ngFor="let match of matches"
(click)="selectMatch($event)"
[class.active]="match===activeMatch"
[class.active]="match === activeMatch"
(mouseenter)="selectActive(match)">
**CUSTOM** <b [innerHtml]="highlight(match.label, term)"></b>
</li>
</ul>
<item-content>
**CUSTOM** <b [innerHtml]="highlight(match.label, term)"></b>
</item-content>
</novo-list-item>
</novo-list>
<p class="picker-error" *ngIf="hasError">Oops! An error occured.</p>
<p class="picker-null" *ngIf="!isLoading && !matches.length && !hasError">No results to display...</p>
`
Expand Down Expand Up @@ -153,7 +155,7 @@ export class PickerDemoComponent {
options: collaborators
};

this.value = 'Alabama';
this.value = null;
this.async = {
options: (term, page) => {
return new Promise((resolve) => {
Expand All @@ -163,7 +165,7 @@ export class PickerDemoComponent {
} else {
resolve(abbrieviated);
}
}, 300);
}, 100000);
});
}
};
Expand Down
6 changes: 3 additions & 3 deletions src/elements/chips/Chips.scss
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ entity-chips {
position: absolute;
color: black;
novo-list {
max-height: 600px;
max-height: 450px;
overflow: auto;
novo-list-item {
flex: 0 0;
Expand All @@ -202,7 +202,7 @@ entity-chips {
background-color: lighten($positive, 35%);
}
&:hover {
background-color: lighten($positive, 39%);
background-color: lighten($positive, 35%);
}
item-content {
flex-flow: row wrap;
Expand Down Expand Up @@ -251,7 +251,7 @@ entity-chips {
left: 0;
width: 100%;
min-width: 180px;
max-height: 600px;
max-height: 450px;
overflow: auto;
z-index: 900;
border: 1px solid #4A89DC;
Expand Down
10 changes: 7 additions & 3 deletions src/elements/form/Form.scss
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,12 @@ novo-form {
margin-bottom: 0;
}
}
entity-picker-results {
novo-list {
max-height: 450px;
overflow: auto;
}
}
entity-picker-results,
picker-results {
position: absolute;
Expand All @@ -413,10 +419,8 @@ novo-form {
max-width: 100%;
z-index: 10;
top: 100%;
border: 1px solid #4A89DC;
novo-list {
max-height: 600px;
overflow: auto;
border: 1px solid #4A89DC;
novo-list-item {
cursor: pointer;
flex: 0 0;
Expand Down
73 changes: 47 additions & 26 deletions src/elements/picker/Picker.scss
Original file line number Diff line number Diff line change
Expand Up @@ -76,28 +76,29 @@ picker-null-recent-results,
picker-null-results,
picker-results,
quick-note-results {
background-color: white;
background-color: $white;
cursor: default;
line-height: 26px;
overflow: hidden;
max-height: 0;
position: absolute;
transform: translateY(0%);
transition: all 0.15s cubic-bezier(0.35, 0, 0.25, 1);
width: 100%;
box-shadow: 0 3px 1px -2px rgba(0, 0, 0, .2), 0 2px 2px 0 rgba(0, 0, 0, .14), 0 1px 5px 0 rgba(0, 0, 0, .12);
border: 1px solid $positive;
novo-list,
ul {
background-color: $white;
max-height: 200px;
overflow: auto;
list-style: none;
padding: 0;
margin: 0;
box-shadow: 0 3px 1px -2px rgba(0, 0, 0, .2), 0 2px 2px 0 rgba(0, 0, 0, .14), 0 1px 5px 0 rgba(0, 0, 0, .12);
border: 1px solid $positive;
transform: translateY(0%);
transition: all 0.15s cubic-bezier(0.35, 0, 0.25, 1);
display: block;
novo-list-item,
li {
cursor: pointer;
padding: 10px 16px;
box-sizing: border-box;
display: flex;
flex-wrap: wrap;
flex-direction: column;
padding: 5px 16px;
font-size: 0.9em;
span {
display: inline-block;
Expand All @@ -116,44 +117,54 @@ quick-note-results {
&.active,
&:focus,
&:hover {
background: lighten($light, 10%);
color: darken($light, 45%);
background-color: lighten($positive, 35%);
}
&.disabled {
opacity: 0.5;
pointer-events: none;
}
item-content {
display: block;
}
}
novo-loading {
justify-content: center;
}
}
ul {
li {
padding: 10px 16px;
box-sizing: border-box;
display: flex;
flex-wrap: wrap;
flex-direction: column;
}
}
&.active {
max-height: 200px;
overflow: auto;
z-index: 1000;
}
&:focus {
outline: none;
}
}

novo-list-item.disabled,
entity-picker-result.disabled {
opacity: 0.5;
pointer-events: none;
}

entity-picker-result.active {
>novo-list-item {
background-color: lighten($positive, 35%);
}
}

entity-picker-results {
background: $white;
width: 100%;
novo-list {
background: $white;
novo-list-item.disabled,
entity-picker-result.disabled {
opacity: 0.5;
pointer-events: none;
}
entity-picker-result.active {
>novo-list-item {
background: lighten($light, 10%);
color: darken($light, 45%);
}
}
item-content {
>p {
min-width: 15em;
Expand All @@ -175,8 +186,13 @@ picker-null-results,
.picker-loader,
.picker-null-recent-results,
.picker-null-results {
background-color: $white;
text-align: center;
color: darken($light, 15%);
box-shadow: 0 3px 1px -2px rgba(0, 0, 0, .2), 0 2px 2px 0 rgba(0, 0, 0, .14), 0 1px 5px 0 rgba(0, 0, 0, .12);
border: 1px solid $positive;
transform: translateY(0%);
transition: all 0.15s cubic-bezier(0.35, 0, 0.25, 1);
}

p.picker-error,
Expand All @@ -189,7 +205,12 @@ p.picker-null-results {

picker-loader,
.picker-loader {
background-color: $white;
display: flex;
align-items: center;
flex-direction: column;
box-shadow: 0 3px 1px -2px rgba(0, 0, 0, .2), 0 2px 2px 0 rgba(0, 0, 0, .14), 0 1px 5px 0 rgba(0, 0, 0, .12);
border: 1px solid $positive;
transform: translateY(0%);
transition: all 0.15s cubic-bezier(0.35, 0, 0.25, 1);
}
23 changes: 10 additions & 13 deletions src/elements/picker/Picker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const PICKER_VALUE_ACCESSOR = {
[(ngModel)]="term"
(ngModelChange)="checkTerm($event)"
[placeholder]="placeholder"
(keyup)="onKeyUp($event)"
(keydown)="onKeyDown($event)"
(focus)="onFocus($event)"
(click)="onFocus($event)"
(blur)="onTouched($event)"
Expand Down Expand Up @@ -116,14 +116,20 @@ export class NovoPickerElement extends OutsideClick implements OnInit {
// Get all distinct key up events from the input and only fire if long enough and distinct
let input = this.element.nativeElement.querySelector('input');
const observer = Observable.fromEvent(input, 'keyup')
.map((e: any) => e.target.value)
.debounceTime(250)
.distinctUntilChanged();
observer.subscribe(
term => this.show(term),
(event: KeyboardEvent) => this.onDebounedKeyup(event),
err => this.hideResults(err));
}

private onDebounedKeyup(event: KeyboardEvent) {
if ([KeyCodes.ESC, KeyCodes.UP, KeyCodes.DOWN, KeyCodes.ENTER].includes(event.keyCode)) {
return;
}
this.show((event.target as any).value);
}

private show(term?: string): void {
this.container.parent = this;
this.container.show(this.appendToBody);
Expand Down Expand Up @@ -161,16 +167,7 @@ export class NovoPickerElement extends OutsideClick implements OnInit {
}
}

/**
* @name onKeyUp
* @param event - A keyboard event
*
* @description This function is called every time the input value changes. We listen for particular keys (e.g. UP
* arrow, ESC, etc.) to handle certain behaviors of the picker.
* It made sense to filter these out in the controller instead of using multiple listeners on the HTML element
* because the quantity of different behaviors would make a messy element.
*/
onKeyUp(event) {
onKeyDown(event: KeyboardEvent) {
if (this.popup) {
if (event.keyCode === KeyCodes.ESC) {
this.hideResults();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export class BasePickerResults {
element: ElementRef;
page: number = 0;
lastPage: boolean = false;

constructor(element: ElementRef) {
this.element = element;
}
Expand Down Expand Up @@ -200,11 +201,25 @@ export class BasePickerResults {
this.scrollToActive();
}

getListElement() {
return this.element.nativeElement;
}

getChildenOfListElement() {
let list = this.getListElement();
return list.children;
}

scrollToActive() {
let list = this.element.nativeElement;
// let list = element.querySelector('ul');
let list = this.getListElement();
let items = this.getChildenOfListElement();
let index = this.matches.indexOf(this.activeMatch);
list.scrollTop = 65 * (index - 1);
let item = items[index];
if (item) {
list.scrollTop = item.offsetTop;
} else {
console.warn('BasePickerResults - could not find result item to scroll to, try overriding getListElement() or getChildenOfListElement() in your PickerResults Component'); // tslint: disable-line
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { Observable } from 'rxjs/Rx';
<li
*ngFor="let match of section.data; let i = index" [ngClass]="{checked: match.checked}"
(click)="selectMatch($event, match)"
[class.active]="match===activeMatch"
[class.active]="match === activeMatch"
(mouseenter)="selectActive(match)">
<label>
<i [ngClass]="{'bhi-checkbox-empty': !match.checked, 'bhi-checkbox-filled': match.checked, 'bhi-checkbox-indeterminate': match.indeterminate }"></i>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,4 +182,8 @@ export class EntityPickerResults extends BasePickerResults {
constructor(element: ElementRef, public labels: NovoLabelService) {
super(element);
}

getListElement() {
return this.element.nativeElement.querySelector('novo-list');
}
}
23 changes: 15 additions & 8 deletions src/elements/picker/extras/picker-results/PickerResults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,21 @@ import { BasePickerResults } from '../base-picker-results/BasePickerResults';
'class': 'active'
},
template: `
<novo-loading theme="line" *ngIf="isLoading && matches.length === 0"></novo-loading>
<ul *ngIf="matches.length > 0">
<li
<novo-list *ngIf="matches.length > 0" direction="vertical">
<novo-list-item
*ngFor="let match of matches"
(click)="selectMatch($event)"
[class.active]="match===activeMatch"
[class.active]="match === activeMatch"
(mouseenter)="selectActive(match)"
[class.disabled]="preselected(match)">
<span [innerHtml]="highlight(match.label, term)"></span>
</li>
<novo-loading theme="line" *ngIf="isLoading && matches.length > 0"></novo-loading>
</ul>
<item-content>
<span [innerHtml]="highlight(match.label, term)"></span>
</item-content>
</novo-list-item>
</novo-list>
<div class="picker-loader" *ngIf="isLoading && matches.length === 0">
<novo-loading theme="line"></novo-loading>
</div>
<p class="picker-error" *ngIf="hasError">{{ labels.pickerError }}</p>
<p class="picker-null-results" *ngIf="!isLoading && !matches.length && !hasError">{{ labels.pickerEmpty }}</p>
`
Expand All @@ -30,4 +33,8 @@ export class PickerResults extends BasePickerResults {
constructor(element: ElementRef, public labels: NovoLabelService) {
super(element);
}

getListElement() {
return this.element.nativeElement.querySelector('novo-list');
}
}

0 comments on commit 593ab19

Please sign in to comment.