Skip to content

Commit

Permalink
#572 for AutoComplete
Browse files Browse the repository at this point in the history
  • Loading branch information
Çağatay Çivici committed Jul 21, 2016
1 parent 25153aa commit 3778e6a
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 94 deletions.
139 changes: 56 additions & 83 deletions components/autocomplete/autocomplete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {Component,ElementRef,AfterViewInit,AfterViewChecked,DoCheck,Input,Output
import {InputText} from '../inputtext/inputtext';
import {Button} from '../button/button';
import {DomHandler} from '../dom/domhandler';
import {TemplateWrapper} from '../common';
import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms';

const AUTOCOMPLETE_VALUE_ACCESSOR: Provider = new Provider(NG_VALUE_ACCESSOR, {
Expand All @@ -28,18 +29,17 @@ const AUTOCOMPLETE_VALUE_ACCESSOR: Provider = new Provider(NG_VALUE_ACCESSOR, {
><button type="button" pButton icon="fa-fw fa-caret-down" class="ui-autocomplete-dropdown" [disabled]="disabled"
(click)="handleDropdownClick($event)" *ngIf="dropdown"></button>
<div class="ui-autocomplete-panel ui-widget-content ui-corner-all ui-shadow" [style.display]="panelVisible ? 'block' : 'none'" [style.width]="'100%'" [style.max-height]="scrollHeight">
<ul class="ui-autocomplete-items ui-autocomplete-list ui-widget-content ui-widget ui-corner-all ui-helper-reset"
(mouseover)="onItemMouseover($event)" (mouseout)="onItemMouseout($event)" (click)="onItemClick($event)" *ngIf="!itemTemplate">
<li class="ui-autocomplete-list-item ui-corner-all" *ngFor="let item of suggestions">{{field ? item[field] : item}}</li>
</ul>
<ul class="ui-autocomplete-items ui-autocomplete-list ui-widget-content ui-widget ui-corner-all ui-helper-reset"
(mouseover)="onItemMouseover($event)" (mouseout)="onItemMouseout($event)" (click)="onItemClick($event)"*ngIf="itemTemplate">
<template ngFor [ngForOf]="suggestions" [ngForTemplate]="itemTemplate"></template>
<ul class="ui-autocomplete-items ui-autocomplete-list ui-widget-content ui-widget ui-corner-all ui-helper-reset">
<li *ngFor="let option of suggestions" [ngClass]="{'ui-autocomplete-list-item ui-corner-all':true,'ui-state-highlight':(highlightOption==option)}"
(mouseenter)="highlightOption=option" (mouseleave)="highlightOption=null" (click)="selectItem(option)">
<span *ngIf="!itemTemplate">{{field ? option[field] : option}}</span>
<template *ngIf="itemTemplate" [pTemplateWrapper]="itemTemplate" [item]="option"></template>
</li>
</ul>
</div>
</span>
`,
directives: [InputText,Button],
directives: [InputText,Button,TemplateWrapper],
providers: [DomHandler,AUTOCOMPLETE_VALUE_ACCESSOR]
})
export class AutoComplete implements AfterViewInit,DoCheck,AfterViewChecked,ControlValueAccessor {
Expand Down Expand Up @@ -108,6 +108,10 @@ export class AutoComplete implements AfterViewInit,DoCheck,AfterViewChecked,Cont

suggestionsUpdated: boolean;

highlightOption: any;

highlightOptionChanged: boolean;

constructor(private el: ElementRef, private domHandler: DomHandler, differs: IterableDiffers, private renderer: Renderer) {
this.differ = differs.find([]).create(null);
}
Expand Down Expand Up @@ -144,6 +148,14 @@ export class AutoComplete implements AfterViewInit,DoCheck,AfterViewChecked,Cont
this.align();
this.suggestionsUpdated = false;
}

if(this.highlightOptionChanged) {
let listItem = this.domHandler.findSingle(this.panel, 'li.ui-state-highlight');
if(listItem) {
this.domHandler.scrollInView(this.panel, listItem);
}
this.highlightOptionChanged = false;
}
}

writeValue(value: any) : void {
Expand Down Expand Up @@ -195,75 +207,27 @@ export class AutoComplete implements AfterViewInit,DoCheck,AfterViewChecked,Cont
query: query
});
}

onItemMouseover(event) {
if(this.disabled) {
return;
}

let element = event.target;
if(element.nodeName != 'UL') {
let item = this.findListItem(element);
this.domHandler.addClass(item, 'ui-state-highlight');
}
}

onItemMouseout(event) {
if(this.disabled) {
return;
}

let element = event.target;
if(element.nodeName != 'UL') {
let item = this.findListItem(element);
this.domHandler.removeClass(item, 'ui-state-highlight');
}
}

onItemClick(event) {
let element = event.target;
if(element.nodeName != 'UL') {
let item = this.findListItem(element);
this.selectItem(item);
}
}

selectItem(item: any) {
let itemIndex = this.domHandler.index(item);
let selectedValue = this.suggestions[itemIndex];


selectItem(option: any) {
if(this.multiple) {
this.input.value = '';
this.value = this.value||[];
if(!this.isSelected(selectedValue)) {
this.value.push(selectedValue);
if(!this.isSelected(option)) {
this.value.push(option);
this.onModelChange(this.value);
}
}
else {
this.input.value = this.field ? this.resolveFieldData(selectedValue): selectedValue;
this.value = selectedValue;
this.input.value = this.field ? this.resolveFieldData(option): option;
this.value = option;
this.onModelChange(this.value);
}

this.onSelect.emit(selectedValue);
this.onSelect.emit(option);

this.input.focus();
}

findListItem(element) {
if(element.nodeName == 'LI') {
return element;
}
else {
let parent = element.parentElement;
while(parent.nodeName != 'LI') {
parent = parent.parentElement;
}
return parent;
}
}

show() {
if(!this.panelVisible) {
this.panelVisible = true;
Expand Down Expand Up @@ -318,45 +282,40 @@ export class AutoComplete implements AfterViewInit,DoCheck,AfterViewChecked,Cont

onKeydown(event) {
if(this.panelVisible) {
let highlightedItem = this.domHandler.findSingle(this.panel, 'li.ui-state-highlight');
let highlightItemIndex = this.findOptionIndex(this.highlightOption);

switch(event.which) {
//down
case 40:
if(highlightedItem) {
var nextItem = highlightedItem.nextElementSibling;
if(nextItem) {
this.domHandler.removeClass(highlightedItem, 'ui-state-highlight');
this.domHandler.addClass(nextItem, 'ui-state-highlight');
this.domHandler.scrollInView(this.panel, nextItem);
if(highlightItemIndex != -1) {
var nextItemIndex = highlightItemIndex + 1;
if(nextItemIndex != (this.suggestions.length)) {
this.highlightOption = this.suggestions[nextItemIndex];
this.highlightOptionChanged = true;
}
}
else {
let firstItem = this.domHandler.findSingle(this.panel, 'li:first-child');
this.domHandler.addClass(firstItem, 'ui-state-highlight');
this.highlightOption = this.suggestions[0];
}

event.preventDefault();
break;

//up
case 38:
if(highlightedItem) {
var prevItem = highlightedItem.previousElementSibling;
if(prevItem) {
this.domHandler.removeClass(highlightedItem, 'ui-state-highlight');
this.domHandler.addClass(prevItem, 'ui-state-highlight');
this.domHandler.scrollInView(this.panel, prevItem);
}
if(highlightItemIndex > 0) {
let prevItemIndex = highlightItemIndex - 1;
this.highlightOption = this.suggestions[prevItemIndex];
this.highlightOptionChanged = true;
}

event.preventDefault();
break;

//enter
case 13:
if(highlightedItem) {
this.selectItem(highlightedItem);
if(this.highlightOption) {
this.selectItem(this.highlightOption);
this.hide();
}
event.preventDefault();
Expand All @@ -371,8 +330,8 @@ export class AutoComplete implements AfterViewInit,DoCheck,AfterViewChecked,Cont

//tab
case 9:
if(highlightedItem) {
this.selectItem(highlightedItem);
if(this.highlightOption) {
this.selectItem(this.highlightOption);
}
this.hide();
break;
Expand Down Expand Up @@ -406,6 +365,20 @@ export class AutoComplete implements AfterViewInit,DoCheck,AfterViewChecked,Cont
return selected;
}

findOptionIndex(option): number {
let index: number = -1;
if(this.suggestions) {
for(let i = 0; i < this.suggestions.length; i++) {
if(this.domHandler.equals(option, this.suggestions[i])) {
index = i;
break;
}
}
}

return index;
}

ngOnDestroy() {
if(this.documentClickListener) {
this.documentClickListener();
Expand Down
3 changes: 2 additions & 1 deletion components/dom/domhandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,13 +288,14 @@ export class DomHandler {

default:
if (obj1[p] != obj2[p]) return false;
break;
}
}

for (var p in obj2) {
if (typeof (obj1[p]) == 'undefined') return false;
}

return false;
return true;
}
}
20 changes: 10 additions & 10 deletions showcase/demo/autocomplete/autocompletedemo.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ <h3>Advanced</h3>
<p-autoComplete [(ngModel)]="brand" [suggestions]="filteredBrands" (completeMethod)="filterBrands($event)" [size]="30"
[minLength]="1" placeholder="Hint: type 'v' or 'f'" [dropdown]="true" (onDropdownClick)="handleDropdownClick($event)">
<template let-brand>
<li class="ui-autocomplete-list-item ui-helper-clearfix" style="border-bottom:1px solid #D5D5D5">
<img src="showcase/resources/demo/images/car/{{brand}}.gif" style="width:32px;display:inline-block;margin:2px 0 2px 2px"/>
<div class="ui-helper-clearfix" style="border-bottom:1px solid #D5D5D5">
<img src="showcase/resources/demo/images/car/{{brand}}.gif" style="width:32px;display:inline-block;margin:5px 0 2px 5px"/>
<div style="font-size:18px;float:right;margin:10px 10px 0 0">{{brand}}</div>
</li>
</div>
</template>
</p-autoComplete>
<span style="margin-left:50px">Brand: {{brand||'none'}}</span>
Expand Down Expand Up @@ -168,10 +168,10 @@ <h3>Templating</h3>
<code class="language-markup" pCode ngNonBindable>
&lt;p-autoComplete [(ngModel)]="brand" [suggestions]="filteredBrands" (completeMethod)="filterBrands($event)"&gt;
&lt;template let-brand&gt;
&lt;li class="ui-autocomplete-list-item ui-helper-clearfix" style="border-bottom:1px solid #D5D5D5"&gt;
&lt;img src="showcase/resources/demo/images/car/{{brand}}.gif" style="display:inline-block;margin:2px 0 2px 2px"/&gt;
&lt;div style="font-size:20px;float:right;margin:15px 10px 0 0"&gt;{{brand}}&lt;/div&gt;
&lt;/li&gt;
&lt;div class="ui-helper-clearfix" style="border-bottom:1px solid #D5D5D5"&gt;
&lt;img src="showcase/resources/demo/images/car/{{brand}}.gif" style="width:32px;display:inline-block;margin:5px 0 2px 5px"/&gt;
&lt;div style="font-size:18px;float:right;margin:10px 10px 0 0"&gt;{{brand}}&lt;/div&gt;
&lt;/div&gt;
&lt;/template&gt;
&lt;/p-autoComplete&gt;
</code>
Expand Down Expand Up @@ -393,10 +393,10 @@ <h3>Dependencies</h3>
&lt;p-autoComplete [(ngModel)]="brand" [suggestions]="filteredBrands" (completeMethod)="filterBrands($event)" [size]="30"
[minLength]="1" placeholder="Hint: type 'v' or 'f'" [dropdown]="true" (onDropdownClick)="handleDropdownClick($event)"&gt;
&lt;template let-brand&gt;
&lt;li class="ui-autocomplete-list-item ui-helper-clearfix" style="border-bottom:1px solid #D5D5D5"&gt;
&lt;img src="showcase/resources/demo/images/car/{{brand}}.gif" style="width:32px;display:inline-block;margin:2px 0 2px 2px"/&gt;
&lt;div class="ui-helper-clearfix" style="border-bottom:1px solid #D5D5D5"&gt;
&lt;img src="showcase/resources/demo/images/car/{{brand}}.gif" style="width:32px;display:inline-block;margin:5px 0 2px 5px"/&gt;
&lt;div style="font-size:18px;float:right;margin:10px 10px 0 0"&gt;{{brand}}&lt;/div&gt;
&lt;/li&gt;
&lt;/div&gt;
&lt;/template&gt;
&lt;/p-autoComplete&gt;
&lt;span style="margin-left:50px"&gt;Brand: {{brand||'none'}}&lt;/span&gt;
Expand Down

0 comments on commit 3778e6a

Please sign in to comment.