2017-06-13 11:08:06 +00:00
|
|
|
import {module} from '../module';
|
|
|
|
import './style.scss';
|
|
|
|
|
2017-06-15 05:45:01 +00:00
|
|
|
export default class DropDown {
|
2017-09-14 11:40:55 +00:00
|
|
|
constructor($element, $filter, $timeout) {
|
2017-06-15 05:45:01 +00:00
|
|
|
this.$element = $element;
|
2017-06-29 11:56:52 +00:00
|
|
|
this.$filter = $filter;
|
2017-09-14 11:40:55 +00:00
|
|
|
this.$timeout = $timeout;
|
|
|
|
|
|
|
|
this.parent = this.parent || $element[0].parentNode;
|
|
|
|
this._search = null;
|
2017-06-29 11:56:52 +00:00
|
|
|
this.itemsFiltered = [];
|
2017-09-14 11:40:55 +00:00
|
|
|
this._activeOption = -1;
|
2017-09-27 10:27:18 +00:00
|
|
|
this._focusingFilter = false;
|
2017-09-14 11:40:55 +00:00
|
|
|
}
|
2017-09-21 11:10:30 +00:00
|
|
|
get show() {
|
|
|
|
return this._show;
|
|
|
|
}
|
2017-10-04 06:47:16 +00:00
|
|
|
|
2017-09-21 11:10:30 +00:00
|
|
|
set show(value) {
|
|
|
|
let oldValue = this.show;
|
|
|
|
this._show = value;
|
2017-09-27 10:27:18 +00:00
|
|
|
if (value && !this._focusingFilter && oldValue !== value && this.filter) {
|
2017-09-21 11:10:30 +00:00
|
|
|
let inputFilterSearch = this.$element[0].querySelector('input');
|
2017-09-27 10:27:18 +00:00
|
|
|
this._focusingFilter = true;
|
2017-09-21 11:10:30 +00:00
|
|
|
this.$timeout(() => {
|
|
|
|
inputFilterSearch.focus();
|
2017-09-27 10:27:18 +00:00
|
|
|
this._focusingFilter = false;
|
|
|
|
}, 250);
|
2017-09-21 11:10:30 +00:00
|
|
|
}
|
2017-10-04 06:47:16 +00:00
|
|
|
}
|
|
|
|
|
2017-09-14 11:40:55 +00:00
|
|
|
get search() {
|
|
|
|
return this._search;
|
|
|
|
}
|
2017-10-04 06:47:16 +00:00
|
|
|
|
2017-09-14 11:40:55 +00:00
|
|
|
set search(value) {
|
|
|
|
let val = (value === undefined && value === '') ? null : value;
|
|
|
|
this._search = val;
|
|
|
|
|
|
|
|
if (this.filterAction)
|
|
|
|
this.onFilterRest();
|
|
|
|
else
|
|
|
|
this.filterItems();
|
|
|
|
}
|
2017-10-04 06:47:16 +00:00
|
|
|
|
2017-09-14 11:40:55 +00:00
|
|
|
get activeOption() {
|
|
|
|
return this._activeOption;
|
|
|
|
}
|
2017-10-04 06:47:16 +00:00
|
|
|
|
2017-09-14 11:40:55 +00:00
|
|
|
set activeOption(value) {
|
|
|
|
if (value < 0) {
|
|
|
|
value = 0;
|
|
|
|
} else if (value >= this.items.length) {
|
2017-09-20 09:50:53 +00:00
|
|
|
value = this.showLoadMore ? this.items.length : this.items.length - 1;
|
2017-09-14 11:40:55 +00:00
|
|
|
}
|
|
|
|
this.$timeout(() => {
|
|
|
|
this._activeOption = value;
|
2017-10-03 10:10:30 +00:00
|
|
|
// AutoLoad items with "scroll" (1st version):
|
2017-10-10 10:56:03 +00:00
|
|
|
if (value && value >= this.items.length - 3 && !this.removeLoadMore) {
|
2017-10-03 10:10:30 +00:00
|
|
|
this.loadItems();
|
|
|
|
}
|
2017-09-14 11:40:55 +00:00
|
|
|
});
|
2017-06-15 05:45:01 +00:00
|
|
|
}
|
2017-06-29 11:56:52 +00:00
|
|
|
|
|
|
|
filterItems() {
|
|
|
|
this.itemsFiltered = this.search ? this.$filter('filter')(this.items, this.search) : this.items;
|
2017-06-29 06:13:30 +00:00
|
|
|
}
|
2017-06-29 11:56:52 +00:00
|
|
|
|
|
|
|
onFilterRest() {
|
2017-09-14 11:40:55 +00:00
|
|
|
this.filterAction({search: this.search});
|
2017-06-29 06:13:30 +00:00
|
|
|
}
|
|
|
|
|
2017-06-15 05:45:01 +00:00
|
|
|
$onChanges(changesObj) {
|
|
|
|
if (changesObj.show && changesObj.top && changesObj.top.currentValue) {
|
|
|
|
this.$element.css('top', changesObj.top.currentValue + 'px');
|
|
|
|
}
|
2017-09-14 11:40:55 +00:00
|
|
|
if (changesObj.show && changesObj.itemWidth && changesObj.itemWidth.currentValue) {
|
|
|
|
this.$element.css('width', changesObj.itemWidth.currentValue + 'px');
|
|
|
|
}
|
2017-06-29 11:56:52 +00:00
|
|
|
if (changesObj.items) {
|
|
|
|
this.filterItems();
|
2017-06-29 06:13:30 +00:00
|
|
|
}
|
2017-06-15 05:45:01 +00:00
|
|
|
}
|
2017-06-29 11:56:52 +00:00
|
|
|
|
2017-06-22 10:03:01 +00:00
|
|
|
clearSearch() {
|
2017-09-14 11:40:55 +00:00
|
|
|
this.search = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
selectOption() {
|
2017-09-20 09:50:53 +00:00
|
|
|
if (this.activeOption >= 0 && this.activeOption < this.items.length && this.items[this.activeOption]) {
|
2017-09-14 11:40:55 +00:00
|
|
|
this.selected = this.items[this.activeOption];
|
2017-09-20 09:50:53 +00:00
|
|
|
this.show = false;
|
2017-09-14 11:40:55 +00:00
|
|
|
this.clearSearch();
|
2017-09-20 09:50:53 +00:00
|
|
|
} else if (this.showLoadMore && this.activeOption === this.items.length) {
|
|
|
|
this.loadMore();
|
2017-06-29 11:56:52 +00:00
|
|
|
}
|
2017-06-22 10:03:01 +00:00
|
|
|
}
|
2017-09-14 11:40:55 +00:00
|
|
|
|
|
|
|
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--;
|
2017-09-20 09:50:53 +00:00
|
|
|
this.$timeout(() => {
|
|
|
|
this.setScrollPosition();
|
|
|
|
}, 100);
|
2017-09-14 11:40:55 +00:00
|
|
|
break;
|
|
|
|
case 40: // Arrow down
|
|
|
|
this.activeOption++;
|
2017-09-20 09:50:53 +00:00
|
|
|
this.$timeout(() => {
|
|
|
|
this.setScrollPosition();
|
|
|
|
}, 100);
|
2017-09-14 11:40:55 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-10-04 06:47:16 +00:00
|
|
|
|
2017-09-20 09:50:53 +00:00
|
|
|
setScrollPosition() {
|
|
|
|
let dropdown = this.$element[0].querySelector('ul.dropdown');
|
|
|
|
let child = dropdown ? dropdown.childNodes[this.activeOption] : null;
|
|
|
|
if (child && typeof child.scrollIntoView === 'function') {
|
|
|
|
child.scrollIntoView();
|
|
|
|
}
|
|
|
|
}
|
2017-09-14 11:40:55 +00:00
|
|
|
|
2017-09-20 11:52:53 +00:00
|
|
|
selectItem(item) {
|
|
|
|
this.selected = item;
|
|
|
|
if (this.multiple) {
|
|
|
|
item.checked = !item.checked;
|
|
|
|
this.show = true;
|
|
|
|
} else {
|
|
|
|
this.show = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-03 07:16:02 +00:00
|
|
|
loadItems() {
|
|
|
|
if (this.showLoadMore && this.loadMore) {
|
|
|
|
this.loadMore();
|
|
|
|
}
|
|
|
|
this.show = true;
|
|
|
|
}
|
|
|
|
|
2017-09-14 11:40:55 +00:00
|
|
|
$onInit() {
|
|
|
|
if (this.parent)
|
|
|
|
this.parent.addEventListener('keydown', e => this.onKeydown(e));
|
|
|
|
}
|
|
|
|
$onDestroy() {
|
|
|
|
if (this.parent)
|
|
|
|
this.parent.removeEventListener('keydown', e => this.onKeydown(e));
|
|
|
|
}
|
2017-06-15 05:45:01 +00:00
|
|
|
}
|
2017-10-04 06:47:16 +00:00
|
|
|
|
2017-09-14 11:40:55 +00:00
|
|
|
DropDown.$inject = ['$element', '$filter', '$timeout'];
|
2017-06-13 11:08:06 +00:00
|
|
|
|
|
|
|
module.component('vnDropDown', {
|
|
|
|
template: require('./drop-down.html'),
|
2017-06-15 05:45:01 +00:00
|
|
|
controller: DropDown,
|
2017-06-13 11:08:06 +00:00
|
|
|
bindings: {
|
|
|
|
items: '<',
|
|
|
|
show: '<',
|
2017-06-21 11:16:37 +00:00
|
|
|
filter: '@?',
|
2017-06-15 05:45:01 +00:00
|
|
|
selected: '=',
|
2017-09-14 11:40:55 +00:00
|
|
|
search: '=?',
|
2017-06-29 06:13:30 +00:00
|
|
|
loadMore: '&?',
|
2017-10-10 10:56:03 +00:00
|
|
|
removeLoadMore: '<?',
|
2017-06-29 11:56:52 +00:00
|
|
|
filterAction: '&?',
|
2017-10-10 09:14:35 +00:00
|
|
|
showLoadMore: '<?',
|
2017-09-14 11:40:55 +00:00
|
|
|
top: '<?',
|
|
|
|
itemWidth: '<?',
|
2017-09-20 11:52:53 +00:00
|
|
|
parent: '<?',
|
|
|
|
multiple: '<?'
|
2017-09-20 09:50:53 +00:00
|
|
|
},
|
|
|
|
transclude: {
|
|
|
|
vnItem: '?vnItem'
|
2017-06-21 11:16:37 +00:00
|
|
|
}
|
2017-06-13 11:08:06 +00:00
|
|
|
});
|