autocomplete recatoring 80%

This commit is contained in:
Dani Herrero 2017-09-14 13:40:55 +02:00
parent f9b3657440
commit 6651f70e07
8 changed files with 141 additions and 39 deletions

View File

@ -1,16 +1,13 @@
<vn-vertical> <vn-vertical ng-click="$ctrl.showDropDown = true">
<vn-one> <vn-textfield vn-one label="{{$ctrl.label}}" model="$ctrl.displayValue"></vn-textfield>
<vn-textfield label="{{$ctrl.label}}" model="$ctrl.displayValue"></vn-textfield> <vn-drop-down vn-one
</vn-one> items="$ctrl.items"
<vn-one> show="$ctrl.showDropDown"
<vn-drop-down selected="$ctrl.field"
items="$ctrl.items" search="$ctrl.displayValue"
show="$ctrl.showDropDown" load-more="$ctrl.getItems()"
selected="$ctrl.field" show-load-more="$ctrl.maxRow"
filter="true" filter-action="$ctrl.findItems(search)"
load-more="$ctrl.getItems()" item-width="$ctrl.width"
show-load-more="$ctrl.maxRow" ></vn-drop-down>
filter-action="$ctrl.findItems(search)"
></vn-drop-down>
</vn-one>
</vn-vertical> </vn-vertical>

View File

@ -16,6 +16,8 @@ class Autocomplete {
this.maxRow = 10; this.maxRow = 10;
this.showField = this.showField || 'name'; this.showField = this.showField || 'name';
this.items = this.data || null; this.items = this.data || null;
this.input = $element[0].querySelector('input');
} }
get showDropDown() { get showDropDown() {
@ -50,6 +52,7 @@ class Autocomplete {
return this.items ? this.items : []; return this.items ? this.items : [];
if (search && !this.finding) { if (search && !this.finding) {
this.maxRow = false;
let filter = {where: {name: {regexp: search}}}; let filter = {where: {name: {regexp: search}}};
let json = JSON.stringify(filter); let json = JSON.stringify(filter);
this.finding = true; this.finding = true;
@ -63,6 +66,7 @@ class Autocomplete {
} }
); );
} else if (!search && !this.finding) { } else if (!search && !this.finding) {
this.maxRow = 10;
this.items = []; this.items = [];
this.getItems(); this.getItems();
} }
@ -112,6 +116,26 @@ class Autocomplete {
this.showDropDown = false; this.showDropDown = false;
}); });
}); });
this.$element.bind('focusin', e => {
this.$timeout(() => {
this.showDropDown = true;
});
});
this.$element.bind('focusout', e => {
this.$timeout(() => {
this.showDropDown = false;
});
});
let rectangle = this.$element[0].getBoundingClientRect();
this.width = Math.round(rectangle.width) - 15;
}
$onDestroy() {
this.$element.unbind('mouseover');
this.$element.unbind('mouseout');
this.$element.unbind('focusin');
this.$element.unbind('focusout');
} }
} }

View File

@ -34,4 +34,7 @@ vn-autocomplete {
.material-icons { .material-icons {
font-size: 18px; font-size: 18px;
} }
vn-drop-down{
margin-top: 50px;
}
} }

View File

@ -1,18 +1,13 @@
<vn-vertical class="dropdown-body" ng-show="$ctrl.show"> <vn-vertical class="dropdown-body" ng-show="$ctrl.show">
<vn-one ng-show="$ctrl.filter" class="filter"> <vn-one ng-show="$ctrl.filter" class="filter">
<vn-horizontal> <vn-horizontal>
<div ng-if="$ctrl.filterAction"> <input vn-one placeholder="{{'Search' | translate}}" type="text" ng-model="$ctrl.search"/>
<input vn-one placeholder="{{'Search' | translate}}" type="text" ng-model="$ctrl.search" ng-change="$ctrl.onFilterRest()"/>
</div>
<div ng-if="!$ctrl.filterAction">
<input vn-one placeholder="{{'Search' | translate}}" type="text" ng-model="$ctrl.search" ng-change="$ctrl.filterItems()"/>
</div>
<vn-icon vn-none icon="clear" ng-click="$ctrl.clearSearch()"></vn-icon> <vn-icon vn-none icon="clear" ng-click="$ctrl.clearSearch()"></vn-icon>
</vn-horizontal> </vn-horizontal>
</vn-one> </vn-one>
<vn-one> <vn-one>
<ul class="dropdown"> <ul class="dropdown">
<li ng-repeat="item in $ctrl.itemsFiltered" ng-click="$ctrl.selected = item">{{::item.name}}</li> <li ng-repeat="item in $ctrl.itemsFiltered track by $index" ng-click="$ctrl.selected = item" ng-class="{'active': $index === $ctrl.activeOption}" ng-mouseover="$ctrl.activeOption = $index">{{::item.name}}</li>
<li ng-if="$ctrl.showLoadMore" class="dropdown__loadMore" ng-click="$ctrl.loadMore()" translate="Load More"></li> <li ng-if="$ctrl.showLoadMore" class="dropdown__loadMore" ng-click="$ctrl.loadMore()" translate="Load More"></li>
</ul> </ul>
</vn-one> </vn-one>

View File

@ -2,12 +2,41 @@ import {module} from '../module';
import './style.scss'; import './style.scss';
export default class DropDown { export default class DropDown {
constructor($element, $filter) { constructor($element, $filter, $timeout) {
this.$element = $element; this.$element = $element;
this.$filter = $filter; this.$filter = $filter;
this.search = ''; this.$timeout = $timeout;
this.itemsFiltered = [];
this.parent = this.parent || $element[0].parentNode;
this._search = null;
this.itemsFiltered = [];
this._activeOption = -1;
}
get search() {
return this._search;
}
set search(value) {
let val = (value === undefined && value === '') ? null : value;
this._search = val;
if (this.filterAction)
this.onFilterRest();
else
this.filterItems();
}
get activeOption() {
return this._activeOption;
}
set activeOption(value) {
if (value < 0) {
value = 0;
} else if (value >= this.items.length) {
value = this.items.length - 1;
}
this.$timeout(() => {
this._activeOption = value;
});
} }
filterItems() { filterItems() {
@ -15,32 +44,66 @@ export default class DropDown {
} }
onFilterRest() { onFilterRest() {
this.showLoadMore = false; this.filterAction({search: this.search});
if (this.filterAction) {
this.filterAction({search: this.search});
}
} }
$onChanges(changesObj) { $onChanges(changesObj) {
if (changesObj.show && changesObj.top && changesObj.top.currentValue) { if (changesObj.show && changesObj.top && changesObj.top.currentValue) {
this.$element.css('top', changesObj.top.currentValue + 'px'); this.$element.css('top', changesObj.top.currentValue + 'px');
} }
if (changesObj.show && changesObj.itemWidth && changesObj.itemWidth.currentValue) {
this.$element.css('width', changesObj.itemWidth.currentValue + 'px');
}
if (changesObj.items) { if (changesObj.items) {
this.filterItems(); this.filterItems();
} }
} }
clearSearch() { clearSearch() {
this.search = ''; this.search = null;
this.showLoadMore = this.loadMore != null; }
if (this.filterAction) {
this.filterAction({search: this.search}); selectOption() {
} else { if (this.activeOption >= 0 && this.items[this.activeOption]) {
this.filterItems(); this.selected = this.items[this.activeOption];
this.clearSearch();
} }
} }
onKeydown(event) {
if (this.show) {
switch (event.keyCode) {
case 13: // Enter
this.$timeout(() => {
this.selectOption();
});
event.preventDefault();
break;
case 27: // Escape
this.clearSearch();
break;
case 38: // Arrow up
this.activeOption--;
break;
case 40: // Arrow down
this.activeOption++;
break;
default:
return;
}
}
}
$onInit() {
if (this.parent)
this.parent.addEventListener('keydown', e => this.onKeydown(e));
}
$onDestroy() {
if (this.parent)
this.parent.removeEventListener('keydown', e => this.onKeydown(e));
}
} }
DropDown.$inject = ['$element', '$filter']; DropDown.$inject = ['$element', '$filter', '$timeout'];
module.component('vnDropDown', { module.component('vnDropDown', {
template: require('./drop-down.html'), template: require('./drop-down.html'),
@ -50,9 +113,12 @@ module.component('vnDropDown', {
show: '<', show: '<',
filter: '@?', filter: '@?',
selected: '=', selected: '=',
search: '=?',
loadMore: '&?', loadMore: '&?',
filterAction: '&?', filterAction: '&?',
showLoadMore: '<?', showLoadMore: '=?',
top: '<?' top: '<?',
itemWidth: '<?',
parent: '<?'
} }
}); });

View File

@ -39,7 +39,7 @@ vn-drop-down {
font-weight: 700; font-weight: 700;
} }
} }
li:hover{ li.active{
background-color: #3D3A3B; background-color: #3D3A3B;
color: white; color: white;
} }

View File

@ -6,6 +6,7 @@
show="$ctrl.showDropDown" show="$ctrl.showDropDown"
selected="$ctrl.selected" selected="$ctrl.selected"
filter="true" filter="true"
parent="$ctrl.element"
></vn-drop-down> ></vn-drop-down>
</div> </div>
<div ng-if="$ctrl.findMore"> <div ng-if="$ctrl.findMore">
@ -17,6 +18,7 @@
load-more="$ctrl.getItems()" load-more="$ctrl.getItems()"
show-load-more="$ctrl.maxRow" show-load-more="$ctrl.maxRow"
filter-action="$ctrl.findItems(search)" filter-action="$ctrl.findItems(search)"
parent="$ctrl.element"
></vn-drop-down> ></vn-drop-down>
</div> </div>
</div> </div>

View File

@ -9,6 +9,7 @@ export default class IconMenu {
this._showDropDown = false; this._showDropDown = false;
this.finding = false; this.finding = false;
this.findMore = false; this.findMore = false;
this.element = $element[0];
} }
get showDropDown() { get showDropDown() {
return this._showDropDown; return this._showDropDown;
@ -34,6 +35,7 @@ export default class IconMenu {
} }
); );
} else if (!search && !this.finding) { } else if (!search && !this.finding) {
this.maxRow = 10;
this.items = []; this.items = [];
this.getItems(); this.getItems();
} }
@ -83,10 +85,23 @@ export default class IconMenu {
this.showDropDown = false; this.showDropDown = false;
}); });
}); });
this.$element.bind('focusin', e => {
this.$timeout(() => {
this.showDropDown = true;
});
});
this.$element.bind('focusout', e => {
this.$timeout(() => {
this.showDropDown = false;
});
});
} }
$onDestroy() { $onDestroy() {
this.$element.unbind('mouseover'); this.$element.unbind('mouseover');
this.$element.unbind('mouseout'); this.$element.unbind('mouseout');
this.$element.unbind('focusin');
this.$element.unbind('focusout');
} }
} }
IconMenu.$inject = ['$element', '$http', '$timeout']; IconMenu.$inject = ['$element', '$http', '$timeout'];