import {module} from '../module'; import Component from '../lib/component'; import './style.scss'; class Autocomplete extends Component { constructor($element, $scope, $http, $timeout) { super($element); this.$element = $element; this.$scope = $scope; this.$http = $http; this.$timeout = $timeout; this._showDropDown = false; this.finding = false; this.findMore = false; this._value = null; this._field = null; this._preLoad = false; this.maxRow = 10; this.showField = this.showField || 'name'; this.valueField = this.valueField || 'id'; this.order = this.order || 'name ASC'; this.items = this.data || []; this.displayValueMultiCheck = []; this._multiField = []; this.readonly = true; this.removeLoadMore = false; } get showDropDown() { return this._showDropDown; } set showDropDown(value) { if (value && this.url && !this._preLoad) { this._preLoad = true; this.getItems(); } if (value && !this.width) { let rectangle = this.$element[0].getBoundingClientRect(); this.width = Math.round(rectangle.width) - 10; } this._showDropDown = value; } get displayValue() { return this._value; } set displayValue(value) { let val = (value === undefined || value === '') ? null : value; if (this.multiple && val) { let index = this.displayValueMultiCheck.indexOf(val); if (index === -1) this.displayValueMultiCheck.push(val); else this.displayValueMultiCheck.splice(index, 1); this._value = this.displayValueMultiCheck.join(', '); } else { this._value = val; } if (value === null) { this.field = null; if (this.multiple && this.items.length) { this.displayValueMultiCheck = []; this.items.map(item => { item.checked = false; return item; }); } } } get field() { return this.multiple ? this._multiField : this._field; } set field(value) { if (!angular.equals(value, this.field)) { this.finding = true; if (value && value.hasOwnProperty(this.valueField)) { this._field = value[this.valueField]; if (this.multiple) { this.setMultiField(value[this.valueField]); } } else { this.setValue(value); } if (value && value.hasOwnProperty(this.showField)) this.displayValue = value[this.showField]; this.finding = false; if (this.onChange) this.onChange({item: this._field}); } } set initialData(value) { if (value && value.hasOwnProperty(this.valueField)) { this._field = value[this.valueField]; if (this.multiple) { this._multiField = [value[this.valueField]] } if (value.hasOwnProperty(this.showField)) { this.displayValue = value[this.showField]; } } } setMultiField(val) { if (val && typeof val === 'object' && val[this.valueField]) { val = val[this.valueField]; } if (val === null) { this._multiField = []; } else { let index = this._multiField.indexOf(val); if (index === -1) { this._multiField.push(val); } else { this._multiField.splice(index, 1); } } } setValue(value) { if (value) { let data = this.items; if (data && data.length) for (let i = 0; i < data.length; i++) if (data[i][this.valueField] === value) { this.showItem(data[i]); return; } this.requestItem(value); } else { this._field = null; this.setMultiField(null); this.displayValue = ''; } } requestItem(value) { if (!value) return; let where = {}; where[this.valueField] = value; let filter = { fields: this.getRequestFields(), where: where }; let json = JSON.stringify(filter); this.$http.get(`${this.url}?filter=${json}`).then( json => this.onItemRequest(json.data), json => this.onItemRequest(null) ); } onItemRequest(data) { if (data && data.length > 0) this.showItem(data[0]); else this.showItem(null); } showItem(item) { this.displayValue = item ? item[this.showField] : ''; this.field = item; } getRequestFields() { let fields = {}; fields[this.valueField] = true; fields[this.showField] = true; if (this._selectFields) for (let field of this._selectFields) fields[field] = true; return fields; } findItems(search) { if (!this.url) return this.items ? this.items : []; if (search && !this.finding) { this.maxRow = false; let filter = {where: {name: {regexp: search}}}; if (this.filter && this.filter.where) { Object.assign(filter.where, this.filter.where); } let json = JSON.stringify(filter); this.finding = true; this.$http.get(`${this.url}?filter=${json}`).then( json => { this.items = []; json.data.forEach( el => { if (this.multiple) { el.checked = this.field.indexOf(el[this.valueField]) !== -1; } this.items.push(el); } ); this.finding = false; }, () => { this.finding = false; } ); } else if (!search && !this.finding) { this.maxRow = 10; this.items = []; this.getItems(); } } getItems() { let filter = {}; if (!this.finding) { this.finding = true; if (this.maxRow) { if (this.items) { filter.skip = this.items.length; } filter.limit = this.maxRow; filter.order = this.order; } if (this.filter) { Object.assign(filter, this.filter); } let json = JSON.stringify(filter); this.removeLoadMore = false; this.$http.get(`${this.url}?filter=${json}`).then( json => { if (json.data.length) { json.data.forEach( el => { if (this.multiple) { el.checked = this.field.indexOf(el[this.valueField]) !== -1; } this.items.push(el); } ); if (filter.skip === 0 && this.maxRow && json.data.length < this.maxRow) { this.removeLoadMore = true; } } else { this.maxRow = false; } this.finding = false; }, () => { this.finding = false; } ); } } $onInit() { this.findMore = this.url && this.maxRow; this.mouseFocus = false; this.focused = false; this.$element.bind('mouseover', e => { this.$timeout(() => { this.mouseFocus = true; this.showDropDown = this.focused; }); }); this.$element.bind('mouseout', () => { this.$timeout(() => { this.mouseFocus = false; this.showDropDown = this.focused; }); }); this.$element.bind('focusin', e => { this.$timeout(() => { this.focused = true; this.showDropDown = true; }); }); this.$element.bind('focusout', e => { this.$timeout(() => { this.focused = false; this.showDropDown = this.mouseFocus; }); }); } $onDestroy() { this.$element.unbind('mouseover'); this.$element.unbind('mouseout'); this.$element.unbind('focusin'); this.$element.unbind('focusout'); } } Autocomplete.$inject = ['$element', '$scope', '$http', '$timeout']; module.component('vnAutocomplete', { template: require('./autocomplete.html'), controller: Autocomplete, bindings: { url: '@?', showField: '@?', valueField: '@?', selectFields: '@?', initialData: '