diff --git a/client/core/src/autocomplete/autocomplete.html b/client/core/src/autocomplete/autocomplete.html deleted file mode 100644 index b08702f52..000000000 --- a/client/core/src/autocomplete/autocomplete.html +++ /dev/null @@ -1,20 +0,0 @@ -
- - - -
diff --git a/client/core/src/autocomplete/autocomplete.js b/client/core/src/autocomplete/autocomplete.js deleted file mode 100644 index d4d17a54c..000000000 --- a/client/core/src/autocomplete/autocomplete.js +++ /dev/null @@ -1,435 +0,0 @@ -import {module} from '../module'; -import Component from '../lib/component'; -import './style.scss'; - -/** - * Combobox like component with search and partial data loading features. - */ -export default class Autocomplete extends Component { - constructor($element, $scope, $http, vnPopover, $transclude, $timeout) { - super($element); - this.input = $element[0].querySelector('input'); - this.item = null; - this.$timeout = $timeout; - // this.data = null; - this.popover = null; - this.popoverId = null; - this.displayData = null; - this.timeoutId = null; - this.lastSearch = null; - this.lastRequest = null; - this.currentRequest = null; - this.moreData = false; - this.activeOption = -1; - this.locked = false; - this.$http = $http; - this.$scope = $scope; - this.vnPopover = vnPopover; - this.$transclude = $transclude; - this.scopes = null; - - Object.assign(this, { - maxRows: 10, - requestDelay: 350, - showField: 'name', - valueField: 'id', - itemAs: 'i' - }); - - componentHandler.upgradeElement($element[0].firstChild); - } - set field(value) { - this.locked = true; - this.setValue(value); - this.locked = false; - } - get field() { - return this.value; - } - set initialData(value) { - if (value) { - if (!this.data) - this.data = []; - this.data.push(value); - } - } - set selectFields(value) { - this._selectFields = []; - - if (!value) - return; - - let res = value.split(','); - for (let i of res) - this._selectFields.push(i.trim()); - } - mdlUpdate() { - let mdlField = this.element.firstChild.MaterialTextfield; - if (mdlField) - mdlField.updateClasses_(); - } - loadData(textFilter) { - textFilter = textFilter ? textFilter : ''; - - if (this.lastSearch === textFilter) { - this.showPopoverIfFocus(); - return; - } - - this.lastSearch = textFilter; - - let lastRequest = this.lastRequest; - let requestWillSame = lastRequest !== null - && !this.moreData - && textFilter.substr(0, lastRequest.length) === lastRequest; - - if (requestWillSame || !this.url) - this.localFilter(textFilter); - else if (this.url) - this.requestData(textFilter, false); - else - this.setDisplayData(this.data); - } - 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; - } - requestData(textFilter, append) { - let where = {}; - let skip = 0; - - if (textFilter) - where[this.showField] = {regexp: textFilter}; - if (append && this.data) - skip = this.data.length; - - let filter = { - fields: this.getRequestFields(), - where: where, - order: `${this.showField} ASC`, - skip: skip, - limit: this.maxRows - }; - - this.lastRequest = textFilter ? textFilter : ''; - let json = JSON.stringify(filter); - - if (this.currentRequest) - this.currentRequest.resolve(); - - this.currentRequest = this.$http.get(`${this.url}?filter=${json}`); - this.currentRequest.then( - json => this.onRequest(json.data, append), - json => this.onRequest([]) - ); - } - onRequest(data, append) { - this.currentRequest = null; - this.moreData = data.length >= this.maxRows; - - if (!append || !this.data) - this.data = data; - else - this.data = this.data.concat(data); - - this.setDisplayData(this.data); - } - localFilter(textFilter) { - let regex = new RegExp(textFilter, 'i'); - let data = this.data.filter(item => { - return regex.test(item[this.showField]); - }); - this.setDisplayData(data); - } - setDisplayData(data) { - this.displayData = data; - this.showPopoverIfFocus(); - } - showPopoverIfFocus() { - if (this.hasFocus) - this.showPopover(); - } - destroyScopes() { - if (this.scopes) - for (let scope of this.scopes) - scope.$destroy(); - } - showPopover() { - let data = this.displayData; - - if (!data) - return; - - let fragment = this.document.createDocumentFragment(); - this.destroyScopes(); - this.scopes = []; - - let hasTemplate = this.$transclude.isSlotFilled('tplItem'); - - for (let i = 0; i < data.length; i++) { - let li = this.document.createElement('li'); - fragment.appendChild(li); - - if (hasTemplate) { - this.$transclude((clone, scope) => { - scope[this.itemAs] = data[i]; - li.appendChild(clone[0]); - this.scopes[i] = scope; - }, null, 'tplItem'); - } else { - let text = this.document.createTextNode(data[i][this.showField]); - li.appendChild(text); - } - } - - if (this.moreData) { - let li = this.document.createElement('li'); - li.appendChild(this.document.createTextNode('Load more')); - li.className = 'load-more'; - fragment.appendChild(li); - } - - if (this.popover) { - this.popover.innerHTML = ''; - this.popover.appendChild(fragment); - } else { - let popover = this.document.createElement('ul'); - popover.addEventListener('click', - e => this.onPopoverClick(e)); - popover.addEventListener('mousedown', - e => this.onPopoverMousedown(e)); - popover.className = 'vn-autocomplete'; - popover.appendChild(fragment); - this.popoverId = this.vnPopover.show(popover, this.input); - this.popover = popover; - } - } - hidePopover() { - if (!this.popover) return; - this.activeOption = -1; - this.vnPopover.hide(this.popoverId); - this.destroyScopes(); - this.popover = null; - } - selectPopoverOption(index) { - if (!this.popover || index === -1) return; - if (index < this.displayData.length) { - this.selectOptionByDataIndex(this.displayData, index); - this.hidePopover(); - } else - this.requestData(this.lastRequest, true); - } - onPopoverClick(event) { - let target = event.target; - let childs = this.popover.childNodes; - - if (target === this.popover) - return; - - while (target.parentNode !== this.popover) - target = target.parentNode; - - for (let i = 0; i < childs.length; i++) - if (childs[i] === target) { - this.selectPopoverOption(i); - break; - } - } - onPopoverMousedown(event) { - // Prevents input from loosing focus - event.preventDefault(); - } - onClear() { - this.setValue(null); - this.$timeout( - () => { - this.mdlUpdate(); - } - ); - } - onClick(event) { - if (!this.popover) - this.showPopover(); - } - onFocus() { - this.hasFocus = true; - this.input.select(); - - this.loadData(); - } - onBlur() { - this.hasFocus = false; - this.restoreShowValue(); - this.hidePopover(); - } - onKeydown(event) { - switch (event.keyCode) { - case 13: // Enter - this.selectPopoverOption(this.activeOption); - break; - case 27: // Escape - this.restoreShowValue(); - this.input.select(); - break; - case 38: // Arrow up - this.activateOption(this.activeOption - 1); - break; - case 40: // Arrow down - this.activateOption(this.activeOption + 1); - break; - default: - return; - } - - event.preventDefault(); - } - onKeyup(event) { - if (!this.isKeycodePrintable(event.keyCode)) return; - if (this.timeoutId) clearTimeout(this.timeoutId); - this.timeoutId = setTimeout(() => this.onTimeout(), this.requestDelay); - } - onTimeout() { - this.loadData(this.input.value); - this.timeoutId = null; - } - isKeycodePrintable(keyCode) { - return keyCode === 32 // Spacebar - || keyCode === 8 // Backspace - || (keyCode > 47 && keyCode < 58) // Numbers - || (keyCode > 64 && keyCode < 91) // Letters - || (keyCode > 95 && keyCode < 112) // Numpad - || (keyCode > 185 && keyCode < 193) // ;=,-./` - || (keyCode > 218 && keyCode < 223); // [\]' - } - restoreShowValue() { - this.putItem(this.item); - } - requestItem() { - if (!this.value) return; - - let where = {}; - where[this.valueField] = this.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); - } - activateOption(index) { - if (!this.popover) - this.showPopover(); - - let popover = this.popover; - let childs = popover.childNodes; - let len = this.displayData.length; - - if (this.activeOption >= 0) - childs[this.activeOption].className = ''; - - if (index >= len) - index = 0; - else if (index < 0) - index = len - 1; - - if (index >= 0) { - let opt = childs[index]; - let top = popover.scrollTop; - let height = popover.clientHeight; - - if (opt.offsetTop + opt.offsetHeight > top + height) - top = opt.offsetTop + opt.offsetHeight - height; - else if (opt.offsetTop < top) - top = opt.offsetTop; - - opt.className = 'active'; - popover.scrollTop = top; - } - - this.activeOption = index; - } - setValue(value) { - this.value = value; - - if (value) { - let data = this.data; - - if (data) - for (let i = 0; i < data.length; i++) - if (data[i][this.valueField] == value) { - this.putItem(data[i]); - return; - } - - this.requestItem(); - } else - this.putItem(null); - } - selectOptionByIndex(index) { - this.selectOptionByDataIndex(this.data, index); - } - selectOptionByDataIndex(data, index) { - if (data && index >= 0 && index < data.length) - this.putItem(data[index]); - else - this.putItem(null); - } - putItem(item) { - this.showItem(item); - let value = item ? item[this.valueField] : undefined; - - if (!this.locked) - this.value = value; - - if (this.onChange) - this.onChange({item: item}); - } - showItem(item) { - this.input.value = item ? item[this.showField] : ''; - this.item = item; - this.mdlUpdate(); - } - $onDestroy() { - this.destroyScopes(); - } -} -Autocomplete.$inject = ['$element', '$scope', '$http', 'vnPopover', '$transclude', '$timeout']; - -module.component('vnAutocomplete', { - template: require('./autocomplete.html'), - bindings: { - url: '@?', - showField: '@?', - valueField: '@?', - selectFields: '@?', - initialData: ' { - describe('Component mdlUpdate', () => { - let $componentController; - let $state; - - beforeEach(() => { - angular.mock.module('client'); - }); - - beforeEach(angular.mock.inject((_$componentController_, _$state_) => { - $componentController = _$componentController_; - $state = _$state_; - $state.params.id = '1234'; - })); - - it('should define and set address property', () => { - let controller = $componentController('vnAddressCreate', {$state: $state}); - expect(controller.address.clientFk).toBe(1234); - expect(controller.address.enabled).toBe(true); - }); - }); -}); diff --git a/client/core/src/autocomplete/style.scss b/client/core/src/autocomplete/style.scss deleted file mode 100644 index 5c4dd1a4b..000000000 --- a/client/core/src/autocomplete/style.scss +++ /dev/null @@ -1,37 +0,0 @@ -ul.vn-autocomplete { - list-style-type: none; - padding: 1em; - margin: 0; - padding: 0; - overflow: auto; - max-height: 300px; - - li { - display: block; - padding: .8em; - margin: 0; - cursor: pointer; - - &.active, - &:hover { - background-color: rgba(1,1,1,.1); - } - &.load-more { - color: #ffa410; - font-weight: bold; - padding: .4em .8em; - } - } -} -vn-autocomplete { - .mdl-chip__action { - position: absolute; - top: 0px; - right: -6px; - margin: 22px 0px; - background-color: white; - } - .material-icons { - font-size: 18px; - } -} \ No newline at end of file