From 3778e6a2305e76fb17c43d9414656783cb96e50e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=87a=C4=9Fatay=20=C3=87ivici?= Date: Thu, 21 Jul 2016 14:42:28 +0300 Subject: [PATCH] #572 for AutoComplete --- components/autocomplete/autocomplete.ts | 139 +++++++----------- components/dom/domhandler.ts | 3 +- .../demo/autocomplete/autocompletedemo.html | 20 +-- 3 files changed, 68 insertions(+), 94 deletions(-) diff --git a/components/autocomplete/autocomplete.ts b/components/autocomplete/autocomplete.ts index 088ce7988e1..e682baa5a64 100644 --- a/components/autocomplete/autocomplete.ts +++ b/components/autocomplete/autocomplete.ts @@ -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, { @@ -28,18 +29,17 @@ const AUTOCOMPLETE_VALUE_ACCESSOR: Provider = new Provider(NG_VALUE_ACCESSOR, { >
- -
`, - directives: [InputText,Button], + directives: [InputText,Button,TemplateWrapper], providers: [DomHandler,AUTOCOMPLETE_VALUE_ACCESSOR] }) export class AutoComplete implements AfterViewInit,DoCheck,AfterViewChecked,ControlValueAccessor { @@ -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); } @@ -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 { @@ -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; @@ -318,22 +282,20 @@ 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(); @@ -341,13 +303,10 @@ export class AutoComplete implements AfterViewInit,DoCheck,AfterViewChecked,Cont //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(); @@ -355,8 +314,8 @@ export class AutoComplete implements AfterViewInit,DoCheck,AfterViewChecked,Cont //enter case 13: - if(highlightedItem) { - this.selectItem(highlightedItem); + if(this.highlightOption) { + this.selectItem(this.highlightOption); this.hide(); } event.preventDefault(); @@ -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; @@ -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(); diff --git a/components/dom/domhandler.ts b/components/dom/domhandler.ts index 38b3e395ee7..17b9ea0b498 100644 --- a/components/dom/domhandler.ts +++ b/components/dom/domhandler.ts @@ -288,6 +288,7 @@ export class DomHandler { default: if (obj1[p] != obj2[p]) return false; + break; } } @@ -295,6 +296,6 @@ export class DomHandler { if (typeof (obj1[p]) == 'undefined') return false; } - return false; + return true; } } diff --git a/showcase/demo/autocomplete/autocompletedemo.html b/showcase/demo/autocomplete/autocompletedemo.html index 21eb5953297..195efc2265a 100644 --- a/showcase/demo/autocomplete/autocompletedemo.html +++ b/showcase/demo/autocomplete/autocompletedemo.html @@ -15,10 +15,10 @@

Advanced

Brand: {{brand||'none'}} @@ -168,10 +168,10 @@

Templating

<p-autoComplete [(ngModel)]="brand" [suggestions]="filteredBrands" (completeMethod)="filterBrands($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="display:inline-block;margin:2px 0 2px 2px"/> - <div style="font-size:20px;float:right;margin:15px 10px 0 0">{{brand}}</div> - </li> + <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> + </div> </template> </p-autoComplete> @@ -393,10 +393,10 @@

Dependencies

<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>