@duoduo-oba/ng-devui
Version:
DevUI components based on Angular
665 lines (659 loc) • 23.8 kB
JavaScript
import { EventEmitter, Component, Input, Output, ViewChild, HostListener, NgModule } from '@angular/core';
import isEmpty from 'lodash-es/isEmpty';
import { of, BehaviorSubject, fromEvent } from 'rxjs';
import { map, switchMap, filter, debounceTime } from 'rxjs/operators';
import { FormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';
/**
* @fileoverview added by tsickle
* Generated from: tags.input.component.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
var TagsInputComponent = /** @class */ (function () {
function TagsInputComponent() {
/**
* 【必选】记录输入的标签
*/
this.tags = [];
/**
* 【可选】使用的属性名
*/
this.displayProperty = 'name';
/**
* 【可选】输入的placeholder
*/
this.placeholder = '';
/**
* 【可选】输入标签的最小长度
*/
this.minLength = 3;
/**
* 【可选】输入标签的最大长度
*/
this.maxLength = Number.MAX_SAFE_INTEGER;
/**
* 【可选】标签的最小个数
*/
this.minTags = 0;
/**
* 【可选】标签的最大个数
*/
this.maxTags = Number.MAX_SAFE_INTEGER;
/**
* 【可选】输入框的spellcheck
*/
this.spellcheck = true;
/**
* 【可选】下拉选项
*/
this.suggestionList = [];
/**
* 是否按空格添加tag
*/
this.isAddBySpace = true;
/**
* 大小写敏感
*/
this.caseSensitivity = false;
/**
* 输出函数,当选中某个选项项后,将会调用此函数,参数为当前选择项的值。如果需要获取所有选择状态的值,请参考(ngModelChange)方法
*/
this.valueChange = new EventEmitter();
this.newTag = '';
this.showSuggestionList = false;
this.availableOptions = [];
this.newTagValid = false;
this.isReduce = false;
this.KEYS = {
backspace: 8,
tab: 9,
enter: 13,
escape: 27,
space: 32,
up: 38,
down: 40,
left: 37,
right: 39,
delete: 46,
comma: 188
};
// 下拉选中suggestionList的item索引
this.selectIndex = 0;
}
/**
* @return {?}
*/
TagsInputComponent.prototype.ngOnInit = /**
* @return {?}
*/
function () {
var _this = this;
this.newTag = '';
this.searchFn = (/**
* @param {?} term
* @return {?}
*/
function (term) {
return of((_this.suggestionList ? _this.suggestionList : [])
.filter((/**
* @param {?} item
* @return {?}
*/
function (item) { return term === '' ? true : _this.caseSensitivity ?
(item[_this.displayProperty]).indexOf(term) !== -1 :
(item[_this.displayProperty]).toLowerCase().indexOf(term.toLowerCase()) !== -1; })));
});
this.registerFilterChange();
};
/**
* @param {?} changes
* @return {?}
*/
TagsInputComponent.prototype.ngOnChanges = /**
* @param {?} changes
* @return {?}
*/
function (changes) {
if (changes && changes.suggestionList && changes.suggestionList.currentValue) {
this.reduceSuggestionList();
if (this.sourceSubscription && this.searchFn) {
this.sourceSubscription.next('');
}
}
if (changes && changes.tags && changes.tags.currentValue) {
this.reduceSuggestionList();
}
};
/**
* @return {?}
*/
TagsInputComponent.prototype.registerFilterChange = /**
* @return {?}
*/
function () {
var _this = this;
this.sourceSubscription = new BehaviorSubject('');
this.sourceSubscription.pipe(map((/**
* @param {?} term
* @return {?}
*/
function (term) {
_this.tagIsValid();
return term;
})), switchMap((/**
* @param {?} term
* @return {?}
*/
function (term) { return _this.searchFn(term); })))
.subscribe((/**
* @param {?} options
* @return {?}
*/
function (options) {
_this.availableOptions = options;
if (!_this.availableOptions || _this.availableOptions.length <= 0) {
_this.selectIndex = -1;
}
else {
_this.selectIndex = 0;
}
}));
fromEvent(this.tagInputElement.nativeElement, 'input')
.pipe(map((/**
* @param {?} e
* @return {?}
*/
function (e) { return e['target'].value; })), filter((/**
* @param {?} term
* @return {?}
*/
function (term) { return true; })), debounceTime(100) // hard code need refactory
).subscribe((/**
* @param {?} term
* @return {?}
*/
function (term) { return _this.sourceSubscription.next(term); }));
};
/**
* @return {?}
*/
TagsInputComponent.prototype.reduceSuggestionList = /**
* @return {?}
*/
function () {
var _this = this;
if (this.isReduce) {
return;
}
if (this.suggestionList.length > 0 && this.tags.length > 0) {
this.isReduce = true;
this.suggestionList = this.suggestionList.filter((/**
* @param {?} suggestion
* @return {?}
*/
function (suggestion) {
return _this.tags.findIndex((/**
* @param {?} tag
* @return {?}
*/
function (tag) { return _this.caseSensitivity ?
tag[_this.displayProperty] === suggestion[_this.displayProperty] :
tag[_this.displayProperty].toLowerCase() === suggestion[_this.displayProperty].toLowerCase(); })) === -1;
}));
if (this.sourceSubscription && this.searchFn) {
this.sourceSubscription.next('');
}
}
};
/**
* @return {?}
*/
TagsInputComponent.prototype.host_click = /**
* @return {?}
*/
function () {
this.tagInputElement.nativeElement.focus();
this.selectIndex = 0;
};
/**
* @param {?} event
* @return {?}
*/
TagsInputComponent.prototype.input_keydown = /**
* @param {?} event
* @return {?}
*/
function (event) {
var _this = this;
/** @type {?} */
var hotkeys = [this.KEYS.enter, this.KEYS.tab, this.KEYS.up, this.KEYS.down];
if (this.isAddBySpace) {
hotkeys.push(this.KEYS.space);
}
if (hotkeys.indexOf(event.keyCode) === -1) {
return;
}
else if (event.keyCode === this.KEYS.down) {
// 向下选择选项
this.select(++this.selectIndex);
}
else if (event.keyCode === this.KEYS.up) {
// 向上选择选项
this.select(--this.selectIndex);
}
else if (event.keyCode === this.KEYS.enter || event.keyCode === this.KEYS.tab) {
if (this.selectIndex !== -1) {
// 回车或tab添加selectIndex的值
setTimeout((/**
* @return {?}
*/
function () {
_this.addSuggestionByIndex(_this.selectIndex, _this.availableOptions[_this.selectIndex]);
}), 50);
}
else {
this.addTag();
}
}
else {
// 添加输入的值
this.addTag();
}
};
/**
* @param {?} index
* @return {?}
*/
TagsInputComponent.prototype.select = /**
* @param {?} index
* @return {?}
*/
function (index) {
if (index < 0) {
index = this.suggestionList.length - 1;
}
else if (index >= this.suggestionList.length) {
index = 0;
}
this.selectIndex = index;
};
/**
* @param {?} event
* @return {?}
*/
TagsInputComponent.prototype.input_focus = /**
* @param {?} event
* @return {?}
*/
function (event) {
this.showSuggestionList = true;
};
/**
* @param {?} event
* @return {?}
*/
TagsInputComponent.prototype.input_blur = /**
* @param {?} event
* @return {?}
*/
function (event) {
if (isEmpty(this.newTag)) {
return;
}
this.addTag();
};
/**
* @param {?} index
* @param {?} value
* @return {?}
*/
TagsInputComponent.prototype.addSuggestionByIndex = /**
* @param {?} index
* @param {?} value
* @return {?}
*/
function (index, value) {
var _this = this;
if (index < 0 || index >= this.availableOptions.length || this.maxTags <= this.tags.length
|| this.tags.findIndex((/**
* @param {?} item
* @return {?}
*/
function (item) { return _this.caseSensitivity ? item[_this.displayProperty] === value[_this.displayProperty]
: item[_this.displayProperty].toLowerCase() === value[_this.displayProperty].toLowerCase(); })) !== -1) {
return;
}
this.canAdd().then((/**
* @param {?} result
* @return {?}
*/
function (result) {
if (!result) {
return;
}
_this.tags.push(_this.availableOptions[index]);
_this.valueChange.emit(_this.availableOptions[index]);
/** @type {?} */
var suggestionListIndex = _this.suggestionList.findIndex((/**
* @param {?} item
* @return {?}
*/
function (item) {
return _this.caseSensitivity ? item[_this.displayProperty] === value[_this.displayProperty] :
item[_this.displayProperty].toLowerCase() === value[_this.displayProperty].toLowerCase();
}));
_this.suggestionList.splice(suggestionListIndex, 1);
_this.newTag = '';
_this.sourceSubscription.next(_this.newTag);
}));
};
/**
* @param {?} index
* @return {?}
*/
TagsInputComponent.prototype.removeTag = /**
* @param {?} index
* @return {?}
*/
function (index) {
if (index < 0 || index >= this.tags.length) {
return;
}
this.availableOptions.push(this.tags[index]);
this.suggestionList = this.availableOptions;
/** @type {?} */
var tag = this.tags[index];
this.tags.splice(index, 1);
this.valueChange.emit(tag);
};
/**
* @return {?}
*/
TagsInputComponent.prototype.tagIsValid = /**
* @return {?}
*/
function () {
var _this = this;
/** @type {?} */
var tag = this.newTag;
/** @type {?} */
var tmp = this.displayProperty;
/** @type {?} */
var result = tag && tag.length >= this.minLength
&& tag.length <= this.maxLength
&& this.suggestionList.findIndex((/**
* @param {?} item
* @return {?}
*/
function (item) { return _this.caseSensitivity ? item[tmp] === tag
: item[tmp].toLowerCase() === tag.toLowerCase(); })) === -1
&& this.tags.findIndex((/**
* @param {?} item
* @return {?}
*/
function (item) { return _this.caseSensitivity ? item[tmp] === tag
: item[tmp].toLowerCase() === tag.toLowerCase(); })) === -1
&& !this.isEmptyString(tag);
this.newTagValid = tag === '' || !!result;
return result;
};
/**
* @param {?} tag
* @return {?}
*/
TagsInputComponent.prototype.isEmptyString = /**
* @param {?} tag
* @return {?}
*/
function (tag) {
/** @type {?} */
var temp = tag.match(/\s/g);
if (temp) {
return tag.length === temp.length;
}
else {
return false;
}
};
/**
* @return {?}
*/
TagsInputComponent.prototype.addTag = /**
* @return {?}
*/
function () {
var _this = this;
this.canAdd().then((/**
* @param {?} result
* @return {?}
*/
function (result) {
if (result && _this.maxTags > _this.tags.length) {
if (_this.tagIsValid()) {
/** @type {?} */
var obj = {};
obj[_this.displayProperty] = _this.newTag;
_this.tags.push(obj);
_this.valueChange.emit(_this.newTag);
// this.availableOptions = this.suggestionList;
}
setTimeout((/**
* @return {?}
*/
function () {
// 放在timeout里是因为如果用空格添加tag,会导致添加之后输入框里有个空格。
_this.newTag = '';
}), 50);
}
else {
_this.newTagValid = false;
}
}));
this.sourceSubscription.next('');
};
/**
* @return {?}
*/
TagsInputComponent.prototype.canAdd = /**
* @return {?}
*/
function () {
/** @type {?} */
var checkResult = Promise.resolve(true);
if (this.checkBeforeAdd) {
/** @type {?} */
var result = this.checkBeforeAdd(this.newTag);
if (typeof result !== 'undefined') {
if (result.then) {
checkResult = result;
}
else if (result.subscribe) {
checkResult = ((/** @type {?} */ (result))).toPromise();
}
else {
checkResult = Promise.resolve(result);
}
}
}
return checkResult;
};
/**
* @param {?} $event
* @return {?}
*/
TagsInputComponent.prototype.onDocumentClick = /**
* @param {?} $event
* @return {?}
*/
function ($event) {
if (this.showSuggestionList && !this.selectBoxElement.nativeElement.contains($event.target)) {
this.showSuggestionList = false;
}
};
/**
* @return {?}
*/
TagsInputComponent.prototype.ngOnDestroy = /**
* @return {?}
*/
function () {
if (this.sourceSubscription) {
this.sourceSubscription.unsubscribe();
}
};
TagsInputComponent.decorators = [
{ type: Component, args: [{
selector: 'd-tags-input',
template: "<div #selectBox class=\"devui-tags-host\" tabindex=\"-1\" (click)=\"host_click()\">\r\n <div class=\"devui-tags\">\r\n <ul class=\"devui-tag-list\">\r\n <li class=\"devui-tag-item\" *ngFor=\"let tag of tags; let index = index\">\r\n <span>{{ tag[displayProperty] }}</span>\r\n <a class=\"remove-button\" (click)=\"removeTag(index)\">\u00D7</a>\r\n </li>\r\n </ul>\r\n <input\r\n #tagInput\r\n class=\"input devui-input\"\r\n [(ngModel)]=\"newTag\"\r\n (keydown)=\"input_keydown($event)\"\r\n (focus)=\"input_focus($event)\"\r\n (blur)=\"input_blur($event)\"\r\n (trim)=\"(false)\"\r\n [placeholder]=\"placeholder\"\r\n [spellcheck]=\"spellcheck\"\r\n [ngClass]=\"{ 'invalid-tag': !newTagValid }\"\r\n type=\"text\"\r\n />\r\n </div>\r\n <div class=\"devui-tags-autocomplete\" *ngIf=\"showSuggestionList && availableOptions?.length\">\r\n <ul class=\"devui-suggestion-list\">\r\n <li\r\n class=\"devui-suggestion-item\"\r\n *ngFor=\"let item of availableOptions; let index = index\"\r\n [ngClass]=\"{ selected: index === selectIndex }\"\r\n (mousedown)=\"addSuggestionByIndex(index, item)\"\r\n >\r\n {{ item[displayProperty] }}\r\n </li>\r\n </ul>\r\n </div>\r\n</div>\r\n",
exportAs: 'TagsInput',
styles: [":host{display:block}.devui-tags-host{position:relative;height:100%}.devui-tags-host:active{outline:0}.devui-tags{-moz-appearance:textfield;-webkit-appearance:textfield;padding:2px 5px;overflow:hidden;word-wrap:break-word;cursor:text;background-color:#fff;border:1px solid #adb0b8;border-radius:1px;height:100%}.devui-tags:hover{border-color:#344899}.devui-tags.focused{outline:0}.devui-tags .devui-tag-list{margin:0;padding:0;list-style-type:none}.devui-tags .devui-tag-item{margin:2px;padding:0 5px;display:inline-block;min-height:20px;line-height:20px;border-radius:1px;color:#252b3a;background-color:#eef0f5}.devui-tags .devui-tag-item .remove-button{margin:0 0 0 5px;padding:0;border:none;background:0 0;cursor:pointer;vertical-align:top;font-size:16px;line-height:20px;color:#252b3a}.devui-tags .devui-tag-item .remove-button:hover{text-decoration:none}.devui-tags input.devui-input{border:0;outline:0;float:left;width:100%;height:26px;font-size:14px;padding-left:5px}.devui-tags input.devui-input::-ms-clear{display:none}.devui-tags-autocomplete{margin-top:5px;position:absolute;padding:5px 0;z-index:99999;width:100%;background-color:#fff;border:#adb0b8;box-shadow:0 5px 10px rgba(41,48,64,.2)}.devui-tags-autocomplete .devui-suggestion-list{margin:0;padding:0;list-style-type:none;max-height:280px;overflow-y:auto;position:relative}.devui-tags-autocomplete .devui-suggestion-list .devui-suggestion-item{padding:5px 10px;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:14px;line-height:20px;color:#252b3a;background-color:#fff}.devui-tags-autocomplete .devui-suggestion-list .devui-suggestion-item:hover{background-color:#f2f5fc}.devui-tags-autocomplete .devui-suggestion-list .devui-suggestion-item.selected{color:#5e7ce0;background-color:#f2f5fc}"]
}] }
];
TagsInputComponent.propDecorators = {
tags: [{ type: Input }],
displayProperty: [{ type: Input }],
placeholder: [{ type: Input }],
minLength: [{ type: Input }],
maxLength: [{ type: Input }],
minTags: [{ type: Input }],
maxTags: [{ type: Input }],
spellcheck: [{ type: Input }],
suggestionList: [{ type: Input }],
isAddBySpace: [{ type: Input }],
caseSensitivity: [{ type: Input }],
checkBeforeAdd: [{ type: Input }],
valueChange: [{ type: Output }],
tagInputElement: [{ type: ViewChild, args: ['tagInput', { static: true },] }],
selectBoxElement: [{ type: ViewChild, args: ['selectBox', { static: true },] }],
onDocumentClick: [{ type: HostListener, args: ['document:click', ['$event'],] }]
};
return TagsInputComponent;
}());
if (false) {
/**
* 【必选】记录输入的标签
* @type {?}
*/
TagsInputComponent.prototype.tags;
/**
* 【可选】使用的属性名
* @type {?}
*/
TagsInputComponent.prototype.displayProperty;
/**
* 【可选】输入的placeholder
* @type {?}
*/
TagsInputComponent.prototype.placeholder;
/**
* 【可选】输入标签的最小长度
* @type {?}
*/
TagsInputComponent.prototype.minLength;
/**
* 【可选】输入标签的最大长度
* @type {?}
*/
TagsInputComponent.prototype.maxLength;
/**
* 【可选】标签的最小个数
* @type {?}
*/
TagsInputComponent.prototype.minTags;
/**
* 【可选】标签的最大个数
* @type {?}
*/
TagsInputComponent.prototype.maxTags;
/**
* 【可选】输入框的spellcheck
* @type {?}
*/
TagsInputComponent.prototype.spellcheck;
/**
* 【可选】下拉选项
* @type {?}
*/
TagsInputComponent.prototype.suggestionList;
/**
* 是否按空格添加tag
* @type {?}
*/
TagsInputComponent.prototype.isAddBySpace;
/**
* 大小写敏感
* @type {?}
*/
TagsInputComponent.prototype.caseSensitivity;
/** @type {?} */
TagsInputComponent.prototype.checkBeforeAdd;
/**
* 输出函数,当选中某个选项项后,将会调用此函数,参数为当前选择项的值。如果需要获取所有选择状态的值,请参考(ngModelChange)方法
* @type {?}
*/
TagsInputComponent.prototype.valueChange;
/** @type {?} */
TagsInputComponent.prototype.tagInputElement;
/** @type {?} */
TagsInputComponent.prototype.selectBoxElement;
/** @type {?} */
TagsInputComponent.prototype.newTag;
/** @type {?} */
TagsInputComponent.prototype.showSuggestionList;
/** @type {?} */
TagsInputComponent.prototype.availableOptions;
/** @type {?} */
TagsInputComponent.prototype.newTagValid;
/** @type {?} */
TagsInputComponent.prototype.isReduce;
/** @type {?} */
TagsInputComponent.prototype.searchFn;
/**
* @type {?}
* @private
*/
TagsInputComponent.prototype.sourceSubscription;
/**
* @type {?}
* @private
*/
TagsInputComponent.prototype.KEYS;
/** @type {?} */
TagsInputComponent.prototype.selectIndex;
}
/**
* @fileoverview added by tsickle
* Generated from: tags.input.module.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
var TagsInputModule = /** @class */ (function () {
function TagsInputModule() {
}
TagsInputModule.decorators = [
{ type: NgModule, args: [{
imports: [
CommonModule,
FormsModule
],
exports: [
TagsInputComponent,
],
declarations: [
TagsInputComponent,
]
},] }
];
return TagsInputModule;
}());
/**
* @fileoverview added by tsickle
* Generated from: public-api.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* Generated from: ng-devui-tags-input.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
export { TagsInputComponent, TagsInputModule };
//# sourceMappingURL=ng-devui-tags-input.js.map