isu-element
Version:
Polymer components for building web apps.
1,026 lines (912 loc) • 29.4 kB
JavaScript
import {html, PolymerElement} from "@polymer/polymer";
import {mixinBehaviors} from "@polymer/polymer/lib/legacy/class";
import '@polymer/iron-icon/iron-icon';
import '@polymer/iron-icons/iron-icons';
import '@polymer/iron-icons/social-icons';
import {BaseBehavior} from "./behaviors/base-behavior";
import './behaviors/isu-elements-shared-styles.js';
import {IsuFetch} from './isu-fetch';
import {CacheSearchUtil} from './utils/cacheSearchUtil'
import {PinyinUtil} from './utils/pinyinUtil';
import throttle from 'lodash-es/throttle';
/**
Example:
```html
<isu-picker id="picker" label="单选" mode="text" text="99" attr-for-value="id" placeholder="请选择" clearable></isu-picker>
<isu-picker id="picker1" label="多选" value="1,2,3,4" attr-for-value="id" multi placeholder="请选择" picker-meta='[{"field": "label", "label": "选项"}, {"field": "business", "label": "业务范围"}]'></isu-picker>
<isu-picker id="pickerAll" label="多选" value="1,2,3,4" attr-for-value="id" show-all
multi placeholder="请选择" picker-meta='[{"field": "label", "label": "选项"}, {"field": "business", "label": "业务范围"}]'></isu-picker>
<isu-picker id="picker3" label="只读" value="1,2,3" attr-for-value="id" multi readonly></isu-picker>
<isu-picker id="picker4" label="必填" value="1,2,3" attr-for-value="id" multi required enable-hotkey></isu-picker>
<isu-picker id="pickerNum" label="限制多选数量" attr-for-value="id" multi-limit="3" multi required prompt="公司不能为空" enable-hotkey></isu-picker>
<isu-picker id="picker5" label="修改组件大小" multi="" attr-for-value="id" value="1,2,3,4,5"></isu-picker>
<isu-picker id="picker6" label="默认" attr-for-value="id"></isu-picker>
<isu-picker id="picker7" label="自定义搜索字段" attr-for-value="id"></isu-picker>
<isu-picker id="picker8" src="/init.do" label="自定义初始数据源" attr-for-value="id"></isu-picker>
<isu-picker id="picker9" label="通过接口搜索数据" src="/init.do" multi="" attr-for-value="id"></isu-picker>
<isu-picker id="picker10" label="键盘快捷键操作" src="/api/listProduct" attr-for-value="id" keyword-path="request.keyword" result-path="success.result"
fetch-param='{"request": {"pageRequest": {"limit": 10, "start": 0}}}'></isu-picker>
```
## Styling
The following custom properties and mixins are available for styling:
|Custom property | Description | Default|
|----------------|-------------|----------|
|`--isu-picker-width` | The width of the picker | 300px
|`--isu-ui-font-family` | The font family of the picker | Microsoft YaHei
|`--isu-ui-font-size` | The font size of the picker | 14px
|`--isu-ui-bg` | The basic color of the selected tags,collapse tr`s color when hover tr | linear-gradient(315deg, var(--isu-ui-color_lightblue) 0%, var(--isu-ui-color_skyblue) 100%)
|`--isu-ui-red` | The color of the selected tag`s delete shape when hover the tag | linear-gradient(315deg, #f9a7c3 0%, var(--isu-ui-color_pink) 100%);
|`--isu-picker-input` | Mixin applied to the keyword input | {}
|`--isu-picker-tag` | Mixin applied to the chosed tags | {}
|`--isu-select-tag-deleter` | Mixin applied to the selected tag's delete tag | {}
|`--isu-picker-dropdown` | Mixin applied to the dropdown table | {}
|`--collapase-table-cell` | Mixin applied to the dropdown table's cell | {}
* @customElement
* @polymer
* @demo demo/isu-picker/index.html
*/
class IsuPicker extends mixinBehaviors([BaseBehavior], PolymerElement) {
static get template() {
return html`
<style include="isu-elements-shared-styles">
:host {
display: flex;
height: 32px;
line-height: 32px;
width: var(--isu-picker-width, 300px);
font-family: var(--isu-ui-font-family), sans-serif;
font-size: var(--isu-ui-font-size);
position: relative;
box-sizing: border-box;
}
.input-wrap {
flex: 1;
position: relative;
display: flex;
}
.input-container {
flex: 1;
display: flex;
width: 100%;
}
#keywordInput {
flex: 1;
min-width: 10px;
font-size: 14px;
height: 22px;
line-height: 22px;
padding: 0;
margin: 2px;
border: none;
outline: none;
@apply --isu-picker-input;
}
/*标签容器*/
.tags-input {
flex: 1;
display: flex;
flex-wrap: wrap;
align-content: flex-start;
background: #FFF;
padding: 2px;
overflow-y: auto;
border: 1px solid #CCC;
border-radius: 4px;
position: relative;
}
.tags-input::-webkit-scrollbar {
display: none;
}
.tag {
color: #fff;
background: var(--isu-ui-bg);
border-radius: 4px;
margin: 2px;
padding: 0 4px;
height: 22px;
line-height: 22px;
/*max-width: calc(var(--isu-picker-width)- 30px);*/
display: flex;
font-size: 14px;
white-space: nowrap;
cursor: default;
@apply --isu-picker-tag;
}
.tag-name {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
}
.tag-deleter {
margin-left: 6px;
width: 18px;
color: #fff;
cursor: pointer;
@apply --isu-select-tag-deleter;
}
.tag-deleter:hover {
color: var(--isu-ui-red);
}
#picker-collapse {
display: flex;
position: absolute;
/*top: 100%;*/
width: 100%;
margin-top: 1px;
border-radius: 4px;
font-size: 12px;
z-index: 100;
padding: 0;
background: white;
color: black;
visibility: visible;
opacity: 1;
/*transition: all 150ms ease-in;*/
@apply --isu-picker-dropdown;
}
#picker-collapse[hidden] {
visibility: hidden;
height: 0;
opacity: 0;
}
/*显示下拉面板*/
:host .show {
opacity: 1;
visibility: visible;
}
.collapse-content__table {
width: 100%;
font-size: 12px;
border-collapse: separate;
border-spacing: 0;
text-align: left;
border-radius: 4px;
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
}
.collapse-table__cell {
white-space: nowrap;
padding: 6px 10px;
line-height: 1.42857143;
border-bottom: 1px solid #ddd;
@apply --collapase-table-cell
}
th.collapse-table__cell {
padding-top: 12px;
font-size: 1.1em;
}
tbody > tr:hover {
background: var(--isu-ui-bg);
color: #fff;
cursor: pointer;
}
tr.candidate-item--focus {
background: var(--isu-ui-bg) ;
color: #fff;
}
.table-hotkey {
width: 40px;
}
#placeholder[hidden] {
display: none;
}
#placeholder {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
color: #999;
opacity: 1;
padding: 0 6px;
overflow: hidden;
white-space: nowrap;
}
:host([required]) .input-wrap::before {
content: "*";
color: red;
position: absolute;
left: -10px;
line-height: inherit;
}
:host([data-invalid]) .tags-input {
border-color: var(--isu-ui-color_pink);
}
:host([show-all]) {
height: auto
}
.clear {
width: 12px;
padding: 0 5px;
z-index: 1;
position: absolute;
right: 5px;
top: -2px;
}
.icon-clear {
width: 12px;
height: 12px;
border: 1px solid #ccc;
border-radius: 50%;
color: #ccc;
display: none;
}
:host([clearable]) .input-wrap:hover .icon-clear {
display: inline-block;
}
</style>
<template is="dom-if" if="[[ toBoolean(label) ]]">
<div class="isu-label">[[label]]</div>
</template>
<div class="input-wrap" id="select__container">
<div class="input-container">
<div class="tags-input" on-click="__openCollapse">
<div id="placeholder">[[placeholder]]</div>
<template is="dom-repeat" items="[[ selectedValues ]]">
<span class="tag">
<span class="tag-name" title="[[ getValueByKey(item, attrForLabel) ]]">
[[ __calcTagName(item) ]]
</span>
<iron-icon class="tag-deleter" icon="icons:clear" data-args="[[ getValueByKey(item, attrForValue) ]]" on-click="_deleteTag"></iron-icon>
</span>
</template>
<input id="keywordInput" value="{{ _userInputKeyword::input }}" autocomplete="off" on-focus="__inputFocus">
<div class="clear">
<template is="dom-if" if="[[ isExistTruthy(_userInputKeyword) ]]">
<iron-icon class="icon-clear" icon=icons:clear on-click="clear"></iron-icon>
</template>
</div>
</div> <!-- class=tags-input -->
<div class="mask"></div>
</div>
<div id="picker-collapse" hidden>
<table class="collapse-content__table">
<thead>
<tr>
<template is="dom-repeat" items="[[pickerMeta]]">
<th class="collapse-table__cell">[[item.label]]</th>
</template>
<template is="dom-if" if="[[ enableHotkey ]]">
<th class="collapse-table__cell table-hotkey">快捷键</th>
</template>
</tr>
</thead>
<tbody>
<template is="dom-repeat" items="[[_displayItems]]" as="row">
<tr id="candidate-item__[[index]]" on-click="_selectCollapseItem">
<template is="dom-repeat" items="[[pickerMeta]]" as="col">
<td class="collapse-table__cell">[[ getValueByPath(row, col.field) ]]</td>
</template>
<template is="dom-if" if="[[ enableHotkey ]]">
<td class="collapse-table__cell table-hotkey">[[_getHotKey(index)]]</td>
</template>
</tr>
</template>
</tbody>
</table>
</div>
<div class="prompt-tip__container" data-prompt$="[[prompt]]">
<div class="prompt-tip">
<iron-icon class="prompt-tip-icon" icon="social:sentiment-very-dissatisfied"></iron-icon>
[[prompt]]
</div>
</div>
</div>
`;
}
static get properties() {
return {
/**
* 中文转拼音插件
*/
_pinyinUtil: {
type: Object,
readOnly: true,
value: function () {
return new PinyinUtil();
}
},
/**
* 缓存搜索插件
*/
_cacheSearchUtil: {
type: Object,
readOnly: true,
value: function () {
return new CacheSearchUtil();
}
},
/**
* 发送请求和模拟数据的组件
*/
_fetchUtil: {
type: Object,
readOnly: true,
value: function () {
return new IsuFetch();
}
},
/**
* The label of the picker.
* @type {string}
*/
label: {
type: String
},
/**
* The placeholder of the select.
* @type {String}
*/
placeholder: {
type: String
},
/**
*
* The selected value of this select, if `multi` is true,
* the value will join with comma ( `selectedValues.map(selected => selected[this.attrForValue]).join(',')` ).
* @type {string}
*/
value: {
type: String,
notify: true
},
/**
* The selected value objects of this select.
* @type {array}
*/
selectedValues: {
type: Array,
notify: true
},
/**
* The selected item.
* @type {object}
*/
selectedItem: {
type: Object,
notify: true
},
/**
* A url for fetching local data, the response data of the request should be json.
* @type {string}
*/
src: {
type: String
},
/**
* A url for searching data with user input keywords, the response data of the request should be json.
* @type {string}
*/
// keywordSearchSrc: {
// type: String
// },
/**
* The candidate selection of this picker.
* @type {array}
*/
items: {
type: Array
},
/**
* 下拉面板当前展示的数据集(默认显示items的前10条)
* @type {array}
*/
_displayItems: {
type: Array
},
/**
* 用户输入的模糊搜索关键字
*
*/
_userInputKeyword: {
type: String
},
/**
* Fields to build index for pinyin plugin.
* @type {array}
*/
fieldsForIndex: {
type: Array
},
/**
* 下拉面板中展示的字段,默认为[{"field": "label", "label": "选项"}]
* @type {array}
* @default [{"field": "label", "label": "选项"}]
*/
pickerMeta: {
type: Array,
value: function () {
return [{"field": "label", "label": "选项"}];
}
},
/**
* Attribute name for value.
* @type {string}
* @default 'value'
*/
attrForValue: {
type: String,
value: "value"
},
/**
* Attribute name for label.
* @type {object}
* @default 'label'
*/
attrForLabel: {
type: Object,
value: "label"
},
/**
* 是否禁用拼音搜索
*/
disablePinyinSearch: {
type: Boolean,
value: false
},
/**
* Set to true, if the selection is required.
* @type {boolean}
* @default false
*/
required: {
type: Boolean,
value: false
},
/**
* Set to true, if the picker is readonly.
* @type {boolean}
* @default false
*/
readonly: {
type: Boolean,
value: false
},
/**
* If true, multiple selections are allowed.
* @type {boolean}
* @default false
*/
multi: {
type: Boolean,
value: false
},
/**
* 下拉面板当前选项焦点
*/
__focusIndex: {
type: Number,
value: 0
},
/**
* If true, hotkeys for selecting items are allowed.
* @type {boolean}
* @default false
*/
enableHotkey: {
type: Boolean,
value: false
},
/**
* 多选限制选择的个数
*/
multiLimit: Number,
/**
* url`s params
* @type {Object}
* @default
*/
fetchParam: {
type: Object
},
keywordPath: {
type: String,
value: "keyword"
},
resultPath: {
type: String
},
text: {
type: String,
notify: true,
observer: '__textChanged'
},
mode: {
type: String,
value: 'default'
},
shortcutKey: {
type: String,
value: 'Enter'
},
inputChinese: Boolean,
prompt: String
};
}
static get is() {
return "isu-picker";
}
static get observers() {
return [
'_srcChanged(src)',
'_itemsChanged(items)',
'_userInputKeywordChanged(_userInputKeyword)',
'_selectedValuesChanged(selectedValues.splices)',
'_valueChanged(value)',
'getInvalidAttribute(required, value)'
]
}
connectedCallback() {
super.connectedCallback();
this.$.keywordInput.addEventListener("keydown", this._keyDownHandler.bind(this));
this.$.keywordInput.addEventListener("compositionstart", () => this.inputChinese = true);
this.$.keywordInput.addEventListener("compositionend", () => this.inputChinese = false);
this.addEventListener("blur", e => {
e.stopPropagation();
// if (!this.value) this.text = this._userInputKeyword;
setTimeout(() => { // 解决blur事件和click事件冲突的问题
if (this.shadowRoot.activeElement && this.shadowRoot.activeElement.id === 'keywordInput') return;
this.displayCollapse(false);
}, 200);
});
let parent = this.offsetParent;
while (parent) {
parent.addEventListener('scroll', e => {
this.__collapsePosition()
});
parent = parent.offsetParent;
}
}
__calcTagName(item) {
if (Function.prototype.isPrototypeOf(this.attrForLabel)) {
return this.attrForLabel.call(this, item);
}
return this.getValueByKey(item, this.attrForLabel);
}
_mkRequest(data) {
return {
url: this.src,
method: "POST",
headers: {
"content-type": "application/json;charset=utf-8",
"Cache-Control": "no-cache"
},
credentials: "include",
body: JSON.stringify(data)
};
}
_srcChanged(src) {
if (!src) return;
const request = this._mkRequest(this.fetchParam);
this._fetchUtil.fetchIt(request)
.then(res => res.json())
.then(data => {
let items;
if (this.resultPath) {
items = this.getValueByPath(data, this.resultPath, []);
} else {
items = data || [];
}
let findIndex = items.findIndex(item => item[this.attrForValue] == this.value);
if (findIndex >= 0) {
items = [items[findIndex]].concat(items);
items.splice(findIndex + 1, 1);
this.items = items;
} else {
this.value ? this._getSelectedForItems() : this.items = items;
}
})
.catch(console.error);
}
_getSelectedForItems() {
const requestObj = this.fetchParam;
const req = this.setValueByPath(this.mkObject(this.keywordPath, requestObj), this.keywordPath, this.value + '');
const request = this._mkRequest(req);
this._fetchUtil.fetchIt(request)
.then(res => res.json())
.then(data => {
const items = this.items || [];
if (this.resultPath) {
data = this.getValueByPath(data, this.resultPath, []);
}
const addItems = data.filter(d => !items.find(i => i[this.attrForValue] === d[this.attrForValue]));
if (addItems.length > 0) {
this.items = items.concat(addItems);
}
})
.catch(err => console.error(err));
}
_itemsChanged(items = []) {
this._displayItems = items.slice(0, 9);
// 初始化一次选中项
if (this.value !== undefined && this.value !== null) {
this._valueChanged(this.value);
}
// 清空缓存插件的缓存
this._cacheSearchUtil.resetCache();
items.forEach(item => this._cacheSearchUtil.addCacheItem(item, this._loadPinyinKeys(item, this.fieldsForIndex)));
}
_userInputKeywordChanged() {
if (this._userInputKeyword.length > 0) {
this.displayCollapse(true);
}
const matched = this._cacheSearchUtil.search(this._userInputKeyword, " ");
if (this.src) {
if (!this.__fetchByKeyword) {
this.__fetchByKeyword = throttle(() => {
const requestObj = this.fetchParam;
const req = this.setValueByPath(this.mkObject(this.keywordPath, requestObj), this.keywordPath, this._userInputKeyword);
const request = this._mkRequest(req);
this._fetchUtil.fetchIt(request)
.then(res => res.json())
.then(data => {
let candidateItems = data || [];
if (this.resultPath) {
candidateItems = this.getValueByPath(data, this.resultPath, []);
}
let _displayItems = candidateItems;
candidateItems = candidateItems.filter(i => (this.items || []).every(old => old[this.attrForValue] != i[this.attrForValue]));
if (candidateItems.length > 0) {
// _displayItems will reset when items changed.
this.items = candidateItems.concat(this.items);
} else {
this._displayItems = _displayItems.slice(0, 9);
}
this._switchFocusItemAt(0);
})
.catch(err => console.error(err));
}, 1000);
}
this.__fetchByKeyword();
} else {
this._displayItems = matched.slice(0, 9);
this._switchFocusItemAt(0);
}
this._displayPlaceholder();
}
_selectedValuesChanged() {
if (this.selectedValues.length > 0) {
this.value = this.selectedValues.map(selected => selected[this.attrForValue]).join(',');
this.selectedItem = this.selectedValues[this.selectedValues.length - 1];
} else {
this.value = null;
this.selectedItem = undefined;
}
if (this.mode === 'text') this.text = this.value && !this.multi ? this.value : this._userInputKeyword;
this.displayCollapse(false);
}
/**
* value属性变化监听函数
*/
_valueChanged(value) {
// 本地模式,或远程数据已经就位
if (this.items && this.items.length) {
const flatValues = [...(new Set(String(value).split(",")))];
const selectedValues = this.selectedValues || [];
const dirty = selectedValues.map(selected => selected[this.attrForValue]).join(',');
// this.set('_userInputKeyword', '')
if (value && this.src && !this.multi) {
let _selectedItem = this.items.filter(item => item[this.attrForValue] == value);
if (!_selectedItem.length) {
this._getSelectedForItems();
return;
}
}
if (dirty !== value) {
const tmp = [...selectedValues, ...this.items];
this.selectedValues =
flatValues.map(val => tmp.find(item => item[this.attrForValue] == val))
.filter(selected => !!selected);
}
this._displayPlaceholder();
}
this.getInvalidAttribute(value);
}
__textChanged(text) {
if (this.items && this.items.some(val => val[this.attrForValue] == text)) {
this.set('value', text)
} else if (this.mode === 'text') {
this.set('_userInputKeyword', text ? text : '');
this.set('value', text ? text : '');
}
this.getInvalidAttribute();
}
_displayPlaceholder() {
this.$.placeholder.hidden = this.value || (this.mode && this.text) || this._userInputKeyword;
}
_selectItemAt(index) {
if (index >= 0 && index < this._displayItems.length) {
this._switchFocusItemAt(index);
this._selectItem(this._displayItems[index]);
}
}
/**
* 选择选项
* @param item
*/
_selectItem(item) {
// not yet selected
if (!~(this.selectedValues || []).findIndex(selected => selected[this.attrForValue] == item[this.attrForValue])) {
if (this.multi && this.selectedValues) {
this.push('selectedValues', item);
} else {
this.selectedValues = [item];
}
}
this.displayCollapse(false);
if (this.multi) this.__focusOnKeywordInput();
this._userInputKeyword = "";
}
/**
* 切换焦点到第n个元素,从0开始
* @param index
* @private
*/
_switchFocusItemAt(index) {
setTimeout(() => {
const maxIndex = (this._displayItems || []).length;
const newIndex = (maxIndex + index) % maxIndex;
this.root.querySelectorAll("tr.candidate-item--focus")
.forEach(e => e.classList.remove('candidate-item--focus'));
const newFocusItem = this.root.querySelector(`#candidate-item__${newIndex}`);
if (newFocusItem != null) {
newFocusItem.classList.add('candidate-item--focus');
this.__focusIndex = newIndex;
}
}, 0);
}
_isPickerCollapseHidden() {
return this.$["picker-collapse"].hidden;
}
__openCollapse({target: {classList}}) {
if (classList.contains('tag-deleter')) return;
this.__focusOnKeywordInput();
}
__inputFocus() {
if (this.multiLimit && this.selectedValues && this.multiLimit <= this.selectedValues.length) return
this.displayCollapse(true);
this._switchFocusItemAt(0);
}
__collapsePosition() {
const {left, top} = this.__getElemPos(this);
// this.$['picker-collapse'].style['left'] = left + this.clientWidth - this.$['select__container'].clientWidth + 'px';
this.$['picker-collapse'].style['top'] = this.clientHeight + 'px';
this.$['picker-collapse'].style['width'] = this.$['select__container'].clientWidth + 'px';
}
__getElemPos(obj) {
const {x, y} = obj.getBoundingClientRect();
return {
left: x,
top: y + 2
}
}
__focusOnKeywordInput() {
this.$.keywordInput.focus();
}
_selectCollapseItem(event) {
event.stopPropagation();
this._selectItem(event.model.row);
this.displayCollapse(false)
this.blur();
}
/**
* 输入框键盘按键事件
* @param event
* @private
*/
_keyDownHandler(event) {
if (this.inputChinese) return;
if (this.shortcutKey !== event.key && !this.$["picker-collapse"].hidden) event.stopPropagation();
const key = event.key;
if (event.altKey || key === this.shortcutKey) {
event.preventDefault();
}
const collapseOpend = !this._isPickerCollapseHidden();
if (collapseOpend && this.enableHotkey && event.altKey) {
const ind = event.code.replace(/[A-Za-z]*/g, '') - 1;
this._selectItemAt(ind);
} else {
switch (key) {
case 'ArrowUp':
collapseOpend && this._switchFocusItemAt(this.__focusIndex - 1);
break;
case 'ArrowDown':
if (collapseOpend) {
this._switchFocusItemAt(this.__focusIndex + 1);
} else {
this._switchFocusItemAt(0);
this.displayCollapse(true);
}
break;
case this.shortcutKey:
if (collapseOpend && this._displayItems.length > 0 && this.__focusIndex < this._displayItems.length) {
this._selectItemAt(this.__focusIndex);
}
break;
case 'Backspace':
if (this._userInputKeyword == undefined || this._userInputKeyword.length === 0) {
this.deleteLastTag();
}
break;
}
}
}
/**
* 给对象根据fieldsForIndex给对应的字段做拼音缓存(字段值,字段值全拼和拼音首字母)
*/
_loadPinyinKeys(item, fieldsForIndex = []) {
let keys = [], values = fieldsForIndex.map(sf => item[sf]);
values = values.length === 0 ? Object.values(item) : values;
if (this.disablePinyinSearch) {
keys = values.map(value => String(value));
} else {
values.forEach(
value => {
keys = keys.concat(
String(value),
this._pinyinUtil.convert2CompletePinyin(value),
this._pinyinUtil.convert2PinyinAbbreviation(value)
);
}
);
}
return keys;
}
/**
* Delete the last selected tag.
*/
deleteLastTag() {
if (this.selectedValues && this.selectedValues.length > 0) {
this.pop("selectedValues");
}
}
/**
* 删除Tag项,事件处理函数
*/
_deleteTag(e) {
let value = e.target.dataArgs;
const ind = this.selectedValues.findIndex(selected => selected[this.attrForValue] == value);
this.splice("selectedValues", ind, 1);
if (!this.multi || (this.multi && this.selectedValues.length === 0)) this._userInputKeyword = '';
}
_getHotKey(index) {
return 'Alt+' + (index + 1);
}
/**
* Open or close the collapse
* @param {boolean} display true to open the collapse.
*/
displayCollapse(display) {
this.$["picker-collapse"].hidden = !display;
if (this.$["picker-collapse"].hidden === false) this.__collapsePosition();
}
/**
* Toggle collapse. Side effect: the picker input will get a focus.
*/
toggleCollapse() {
const hidden = this.$["picker-collapse"].hidden;
this.$["picker-collapse"].hidden = !hidden;
this.__focusOnKeywordInput();
}
/**
* Set focus to picker.
*/
doFocus() {
this.__focusOnKeywordInput();
}
/**
* Validate, true if the select is set to be required and this.selectedValues.length > 0, or else false.
* @returns {boolean}
*/
validate() {
if (this.mode === 'text') {
return this.required ? this.text : true;
} else {
return this.required ? (this.selectedValues && this.selectedValues.length > 0) : true;
}
}
clear(e) {
e.stopPropagation();
this._userInputKeyword = '';
}
}
window.customElements.define(IsuPicker.is, IsuPicker);