salix/client/core/src/drop-down/drop-down.js

189 lines
5.1 KiB
JavaScript
Raw Normal View History

import {module} from '../module';
import './style.scss';
export default class DropDown {
2017-09-14 11:40:55 +00:00
constructor($element, $filter, $timeout) {
this.$element = $element;
this.$filter = $filter;
2017-09-14 11:40:55 +00:00
this.$timeout = $timeout;
this.parent = this.parent || $element[0].parentNode;
this._search = null;
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
}
get show() {
return this._show;
}
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) {
let inputFilterSearch = this.$element[0].querySelector('input');
2017-09-27 10:27:18 +00:00
this._focusingFilter = true;
this.$timeout(() => {
inputFilterSearch.focus();
2017-09-27 10:27:18 +00:00
this._focusingFilter = false;
}, 250);
}
}
2017-09-14 11:40:55 +00:00
get search() {
return this._search;
}
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-09-14 11:40:55 +00:00
get activeOption() {
return this._activeOption;
}
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;
// AutoLoad items with "scroll" (1st version):
if (value && value >= this.items.length - 3 && !this.removeLoadMore) {
this.loadItems();
}
2017-09-14 11:40:55 +00:00
});
}
filterItems() {
this.itemsFiltered = this.search ? this.$filter('filter')(this.items, this.search) : this.items;
2017-06-29 06:13:30 +00:00
}
onFilterRest() {
2017-09-14 11:40:55 +00:00
this.filterAction({search: this.search});
2017-06-29 06:13:30 +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');
}
if (changesObj.items) {
this.filterItems();
2017-06-29 06:13:30 +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-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-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;
}
}
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-09-14 11:40:55 +00:00
DropDown.$inject = ['$element', '$filter', '$timeout'];
module.component('vnDropDown', {
template: require('./drop-down.html'),
controller: DropDown,
bindings: {
items: '<',
show: '<',
2017-06-21 11:16:37 +00:00
filter: '@?',
selected: '=',
2017-09-14 11:40:55 +00:00
search: '=?',
2017-06-29 06:13:30 +00:00
loadMore: '&?',
removeLoadMore: '<?',
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
}
});