UNPKG

@duoduo-oba/ng-devui

Version:

DevUI components based on Angular

665 lines (659 loc) 23.8 kB
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