iov-design 2.15.59 → 2.15.61

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (250) hide show
  1. package/README.md +148 -148
  2. package/lib/alert.js +24 -105
  3. package/lib/aside.js +24 -34
  4. package/lib/autocomplete.js +36 -240
  5. package/lib/avatar.js +21 -20
  6. package/lib/backtop.js +27 -52
  7. package/lib/badge.js +30 -58
  8. package/lib/breadcrumb-item.js +24 -53
  9. package/lib/breadcrumb.js +24 -37
  10. package/lib/button-group.js +24 -29
  11. package/lib/button.js +38 -60
  12. package/lib/calendar.js +29 -146
  13. package/lib/card.js +24 -51
  14. package/lib/carousel-item.js +30 -68
  15. package/lib/carousel.js +27 -159
  16. package/lib/cascader-panel.js +41 -64
  17. package/lib/cascader.js +37 -470
  18. package/lib/checkbox-button.js +28 -164
  19. package/lib/checkbox-group.js +24 -37
  20. package/lib/checkbox.js +35 -189
  21. package/lib/col.js +1 -0
  22. package/lib/collapse-item.js +27 -125
  23. package/lib/collapse.js +24 -37
  24. package/lib/color-picker.js +104 -424
  25. package/lib/container.js +24 -34
  26. package/lib/date-picker.js +126 -1981
  27. package/lib/descriptions-item.js +1 -0
  28. package/lib/descriptions.js +1 -0
  29. package/lib/dialog.js +24 -137
  30. package/lib/divider.js +29 -64
  31. package/lib/drawer.js +24 -139
  32. package/lib/dropdown-item.js +27 -45
  33. package/lib/dropdown-menu.js +24 -51
  34. package/lib/dropdown.js +21 -20
  35. package/lib/empty.js +24 -61
  36. package/lib/footer.js +24 -34
  37. package/lib/form-item.js +42 -128
  38. package/lib/form.js +27 -40
  39. package/lib/header.js +24 -34
  40. package/lib/icon.js +24 -29
  41. package/lib/image.js +36 -220
  42. package/lib/index.js +1 -1
  43. package/lib/infinite-scroll.js +1 -0
  44. package/lib/input-number.js +30 -163
  45. package/lib/input.js +42 -274
  46. package/lib/iov-design.common.js +1638 -11132
  47. package/lib/link.js +33 -55
  48. package/lib/loading.js +24 -77
  49. package/lib/locale/format.js +10 -10
  50. package/lib/main.js +24 -29
  51. package/lib/menu-item-group.js +24 -40
  52. package/lib/menu-item.js +27 -83
  53. package/lib/menu.js +21 -20
  54. package/lib/message-box.js +24 -321
  55. package/lib/message.js +30 -82
  56. package/lib/mixins/migrating.js +20 -20
  57. package/lib/notification.js +24 -109
  58. package/lib/option-group.js +24 -50
  59. package/lib/option.js +27 -76
  60. package/lib/page-header.js +24 -56
  61. package/lib/pagination.js +24 -97
  62. package/lib/popconfirm.js +24 -97
  63. package/lib/popover.js +24 -89
  64. package/lib/progress.js +30 -133
  65. package/lib/radio-button.js +29 -111
  66. package/lib/radio-group.js +24 -39
  67. package/lib/radio.js +36 -152
  68. package/lib/rate.js +24 -94
  69. package/lib/result.js +72 -187
  70. package/lib/row.js +1 -0
  71. package/lib/scrollbar.js +1 -0
  72. package/lib/select.js +48 -637
  73. package/lib/skeleton-item.js +36 -68
  74. package/lib/skeleton.js +28 -70
  75. package/lib/slider.js +36 -267
  76. package/lib/spinner.js +24 -51
  77. package/lib/statistic.js +24 -76
  78. package/lib/step.js +29 -118
  79. package/lib/steps.js +27 -40
  80. package/lib/submenu.js +21 -20
  81. package/lib/switch.js +24 -130
  82. package/lib/tab-pane.js +24 -52
  83. package/lib/table-column.js +1 -0
  84. package/lib/table.js +93 -633
  85. package/lib/tabs.js +34 -49
  86. package/lib/tag.js +22 -21
  87. package/lib/theme-chalk/base.css +1 -1
  88. package/lib/theme-chalk/button.css +1 -1
  89. package/lib/theme-chalk/calendar.css +1 -1
  90. package/lib/theme-chalk/cascader-panel.css +1 -1
  91. package/lib/theme-chalk/cascader.css +1 -1
  92. package/lib/theme-chalk/dropdown.css +1 -1
  93. package/lib/theme-chalk/index.css +1 -1
  94. package/lib/theme-chalk/iovfont.css +1 -1
  95. package/lib/theme-chalk/link.css +1 -1
  96. package/lib/theme-chalk/message-box.css +1 -1
  97. package/lib/theme-chalk/pagination.css +1 -1
  98. package/lib/theme-chalk/radio.css +1 -1
  99. package/lib/theme-chalk/select.css +1 -1
  100. package/lib/theme-chalk/table-column.css +1 -1
  101. package/lib/theme-chalk/table.css +1 -1
  102. package/lib/theme-chalk/tabs.css +1 -1
  103. package/lib/theme-chalk/tag.css +1 -1
  104. package/lib/theme-chalk/transfer.css +1 -1
  105. package/lib/time-picker.js +58 -820
  106. package/lib/time-select.js +42 -303
  107. package/lib/timeline-item.js +29 -75
  108. package/lib/timeline.js +21 -20
  109. package/lib/tooltip.js +1 -0
  110. package/lib/transfer.js +36 -299
  111. package/lib/tree.js +54 -243
  112. package/lib/upload.js +86 -654
  113. package/lib/utils/clickoutside.js +7 -7
  114. package/lib/utils/vue-popper.js +7 -7
  115. package/package.json +154 -154
  116. package/packages/autocomplete/src/autocomplete-suggestions.vue +76 -76
  117. package/packages/autocomplete/src/autocomplete.vue +285 -285
  118. package/packages/button/src/button.vue +90 -90
  119. package/packages/calendar/src/date-table.vue +200 -200
  120. package/packages/calendar/src/main.vue +280 -280
  121. package/packages/carousel/src/item.vue +138 -138
  122. package/packages/carousel/src/main.vue +315 -315
  123. package/packages/cascader/src/cascader.vue +776 -776
  124. package/packages/cascader-panel/src/cascader-menu.vue +138 -138
  125. package/packages/cascader-panel/src/cascader-node.vue +246 -246
  126. package/packages/cascader-panel/src/cascader-panel.vue +391 -391
  127. package/packages/cascader-panel/src/node.js +166 -166
  128. package/packages/cascader-panel/src/store.js +58 -58
  129. package/packages/checkbox/src/checkbox-button.vue +199 -199
  130. package/packages/checkbox/src/checkbox-group.vue +49 -49
  131. package/packages/checkbox/src/checkbox.vue +225 -225
  132. package/packages/collapse/src/collapse-item.vue +114 -114
  133. package/packages/color-picker/src/components/picker-dropdown.vue +121 -121
  134. package/packages/color-picker/src/main.vue +188 -188
  135. package/packages/date-picker/src/basic/date-table.vue +441 -441
  136. package/packages/date-picker/src/basic/month-table.vue +269 -269
  137. package/packages/date-picker/src/basic/time-spinner.vue +304 -304
  138. package/packages/date-picker/src/basic/year-table.vue +111 -111
  139. package/packages/date-picker/src/panel/date-range.vue +680 -680
  140. package/packages/date-picker/src/panel/date.vue +609 -609
  141. package/packages/date-picker/src/panel/month-range.vue +289 -289
  142. package/packages/date-picker/src/panel/time-range.vue +248 -248
  143. package/packages/date-picker/src/panel/time-select.vue +178 -178
  144. package/packages/date-picker/src/panel/time.vue +186 -186
  145. package/packages/date-picker/src/picker.vue +967 -967
  146. package/packages/descriptions/src/index.js +180 -180
  147. package/packages/dialog/src/component.vue +262 -262
  148. package/packages/drawer/src/main.vue +205 -205
  149. package/packages/dropdown/src/dropdown-item.vue +37 -37
  150. package/packages/dropdown/src/dropdown-menu.vue +63 -63
  151. package/packages/dropdown/src/dropdown.vue +293 -293
  152. package/packages/empty/src/index.vue +70 -70
  153. package/packages/form/src/form-item.vue +324 -324
  154. package/packages/form/src/form.vue +182 -182
  155. package/packages/image/src/image-viewer.vue +330 -330
  156. package/packages/image/src/main.vue +249 -249
  157. package/packages/infinite-scroll/src/main.js +150 -150
  158. package/packages/input/src/input.vue +477 -477
  159. package/packages/input-number/src/input-number.vue +283 -283
  160. package/packages/link/src/main.vue +2 -0
  161. package/packages/loading/src/directive.js +133 -133
  162. package/packages/loading/src/index.js +106 -106
  163. package/packages/menu/src/menu-item.vue +112 -112
  164. package/packages/menu/src/menu.vue +325 -325
  165. package/packages/menu/src/submenu.vue +349 -349
  166. package/packages/message/src/main.js +91 -91
  167. package/packages/message-box/src/main.js +216 -216
  168. package/packages/message-box/src/main.vue +333 -333
  169. package/packages/notification/src/main.js +94 -94
  170. package/packages/page-header/src/main.vue +30 -30
  171. package/packages/pagination/src/pagination.js +390 -390
  172. package/packages/popconfirm/src/main.vue +104 -104
  173. package/packages/popover/src/main.vue +239 -239
  174. package/packages/radio/src/radio-button.vue +115 -115
  175. package/packages/radio/src/radio-group.vue +115 -115
  176. package/packages/radio/src/radio.vue +148 -148
  177. package/packages/rate/src/main.vue +348 -348
  178. package/packages/scrollbar/src/bar.js +92 -92
  179. package/packages/scrollbar/src/main.js +130 -130
  180. package/packages/select/src/option-group.vue +60 -60
  181. package/packages/select/src/option.vue +171 -171
  182. package/packages/select/src/select-dropdown.vue +74 -74
  183. package/packages/select/src/select.vue +979 -979
  184. package/packages/slider/src/button.vue +238 -238
  185. package/packages/slider/src/main.vue +427 -427
  186. package/packages/statistic/src/main.vue +204 -204
  187. package/packages/steps/src/steps.vue +68 -68
  188. package/packages/switch/src/component.vue +182 -182
  189. package/packages/table/src/config.js +153 -153
  190. package/packages/table/src/filter-panel.vue +194 -194
  191. package/packages/table/src/store/current.js +76 -76
  192. package/packages/table/src/store/helper.js +41 -41
  193. package/packages/table/src/store/index.js +147 -147
  194. package/packages/table/src/store/watcher.js +502 -502
  195. package/packages/table/src/table-body.js +469 -469
  196. package/packages/table/src/table-column.js +328 -328
  197. package/packages/table/src/table-header.js +571 -571
  198. package/packages/table/src/table-layout.js +249 -249
  199. package/packages/table/src/table-row.js +101 -101
  200. package/packages/table/src/table.vue +740 -740
  201. package/packages/table/src/util.js +273 -273
  202. package/packages/tabs/src/tab-bar.vue +57 -57
  203. package/packages/tabs/src/tab-nav.vue +294 -294
  204. package/packages/tabs/src/tabs.vue +201 -201
  205. package/packages/tag/src/tag.vue +1 -1
  206. package/packages/theme-chalk/src/button.scss +416 -416
  207. package/packages/theme-chalk/src/cascader.scss +252 -252
  208. package/packages/theme-chalk/src/checkbox.scss +419 -419
  209. package/packages/theme-chalk/src/common/var.scss +795 -816
  210. package/packages/theme-chalk/src/form.scss +201 -201
  211. package/packages/theme-chalk/src/input.scss +591 -591
  212. package/packages/theme-chalk/src/iovfont.scss +803 -784
  213. package/packages/theme-chalk/src/link.scss +36 -19
  214. package/packages/theme-chalk/src/message-box.scss +207 -207
  215. package/packages/theme-chalk/src/mixins/_button.scss +136 -136
  216. package/packages/theme-chalk/src/mixins/mixins.scss +190 -190
  217. package/packages/theme-chalk/src/radio-button.scss +115 -115
  218. package/packages/theme-chalk/src/radio.scss +1 -0
  219. package/packages/theme-chalk/src/select.scss +270 -270
  220. package/packages/theme-chalk/src/table.scss +1 -2
  221. package/packages/theme-chalk/src/tabs.scss +755 -750
  222. package/packages/theme-chalk/src/tag.scss +4 -4
  223. package/packages/theme-chalk/src/upload.scss +568 -568
  224. package/packages/tooltip/src/main.js +242 -242
  225. package/packages/transfer/src/main.vue +231 -231
  226. package/packages/transfer/src/transfer-panel.vue +251 -251
  227. package/packages/tree/src/model/node.js +484 -484
  228. package/packages/tree/src/tree-node.vue +279 -279
  229. package/packages/tree/src/tree.vue +496 -496
  230. package/packages/upload/src/index.vue +420 -420
  231. package/packages/upload/src/upload-file.vue +98 -98
  232. package/packages/upload/src/upload-list.vue +115 -115
  233. package/packages/upload/src/upload-picture.vue +98 -98
  234. package/packages/upload/src/upload.vue +231 -231
  235. package/packages/upload/src/utils.js +31 -31
  236. package/src/directives/repeat-click.js +26 -26
  237. package/src/index.js +259 -259
  238. package/src/locale/format.js +46 -46
  239. package/src/locale/index.js +48 -48
  240. package/src/locale/lang/lo-LA.js +126 -126
  241. package/src/mixins/locale.js +9 -9
  242. package/src/mixins/migrating.js +54 -54
  243. package/src/transitions/collapse-transition.js +77 -77
  244. package/src/utils/clickoutside.js +76 -76
  245. package/src/utils/date-util.js +282 -282
  246. package/src/utils/popup/index.js +218 -218
  247. package/src/utils/popup/popup-manager.js +194 -194
  248. package/src/utils/util.js +245 -245
  249. package/src/utils/vdom.js +5 -5
  250. package/src/utils/vue-popper.js +198 -198
@@ -1,979 +1,979 @@
1
- <template>
2
- <div
3
- class="el-select"
4
- :class="[fill ? 'is-fill' : '', selectSize ? 'el-select--' + selectSize : '', selectDisabled ? 'is-disabled' : '']"
5
- @click.stop="toggleMenu"
6
- v-clickoutside="handleClose">
7
- <div
8
- class="el-select__tags"
9
- :class="{ 'is-focus': visible }"
10
- v-if="multiple"
11
- ref="tags"
12
- :style="{ 'max-width': inputWidth - 32 + 'px', width: (inputWidth - tagsLeft - 32) + 'px', left: tagsLeft + 'px' }">
13
- <span class="el-tag__group" v-if="collapseTags && selected.length">
14
- <template v-for="(item, index) in selected">
15
- <el-tag
16
- :key="getValueKey(item)"
17
- v-if="index <= multipleLimitShow - 1"
18
- :closable="!selectDisabled"
19
- :size="collapseTagSize"
20
- :hit="item.hitState"
21
- :maxWidth="maxWidth"
22
- type="info"
23
- @close="deleteTag($event, item)"
24
- disable-transitions>
25
- <span class="el-select__tags-text">{{ item.currentLabel }}</span>
26
- </el-tag>
27
- </template>
28
- <el-tag
29
- v-if="selected.length > 1 && selected.length > multipleLimitShow || selected.length > 0 && collapseTagsFixed"
30
- :closable="false"
31
- :size="collapseTagSize"
32
- type="info"
33
- ref="tagsCount"
34
- class="el-select__tags-count"
35
- :class="{'el-select__tags-count-fixed': collapseTagsFixed}"
36
- disable-transitions>
37
- <span class="el-select__tags-text">{{collapseTagsFixed ? '' : '+'}}{{ collapseTagsFixed ? selected.length : selected.length - multipleLimitShow }}{{ collapseTagsSuffix }}</span>
38
- </el-tag>
39
- </span>
40
- <transition-group class="el-tag__group" @after-leave="resetInputHeight" v-if="!collapseTags">
41
- <el-tag
42
- v-for="item in selected"
43
- :key="getValueKey(item)"
44
- :closable="!item.disabled && !selectDisabled"
45
- :size="collapseTagSize"
46
- :hit="item.hitState"
47
- :maxWidth="maxWidth"
48
- type="info"
49
- @close="deleteTag($event, item)"
50
- disable-transitions>
51
- <span class="el-select__tags-text">{{ item.currentLabel }}</span>
52
- </el-tag>
53
- </transition-group>
54
-
55
- <input
56
- type="text"
57
- class="el-select__input"
58
- :class="[selectSize ? `is-${ selectSize }` : '']"
59
- :disabled="selectDisabled"
60
- :autocomplete="autoComplete || autocomplete"
61
- @focus="handleFocus"
62
- @blur="softFocus = false"
63
- @keyup="managePlaceholder"
64
- @keydown="resetInputState"
65
- @keydown.down.prevent="handleNavigate('next')"
66
- @keydown.up.prevent="handleNavigate('prev')"
67
- @keydown.enter.prevent="selectOption"
68
- @keydown.esc.stop.prevent="visible = false"
69
- @keydown.delete="deletePrevTag"
70
- @keydown.tab="visible = false"
71
- @compositionstart="handleComposition"
72
- @compositionupdate="handleComposition"
73
- @compositionend="handleComposition"
74
- v-model="query"
75
- @input="debouncedQueryChange"
76
- v-if="filterable"
77
- :style="{ 'flex-grow': '1', width: inputLength / (inputWidth - 32) + '%', 'max-width': inputWidth - 42 + 'px' }"
78
- ref="input">
79
- </div>
80
- <el-input
81
- ref="reference"
82
- v-model="selectedLabel"
83
- type="text"
84
- :placeholder="currentPlaceholder"
85
- :name="name"
86
- :id="id"
87
- :autocomplete="autoComplete || autocomplete"
88
- :size="selectSize"
89
- :disabled="selectDisabled"
90
- :readonly="readonly"
91
- :validate-event="false"
92
- :class="{ 'is-focus': visible }"
93
- :tabindex="(multiple && filterable) ? '-1' : null"
94
- @focus="handleFocus"
95
- @blur="handleBlur"
96
- @input="debouncedOnInputChange"
97
- @keydown.native.down.stop.prevent="handleNavigate('next')"
98
- @keydown.native.up.stop.prevent="handleNavigate('prev')"
99
- @keydown.native.enter.prevent="selectOption"
100
- @keydown.native.esc.stop.prevent="visible = false"
101
- @keydown.native.tab="visible = false"
102
- @compositionstart="handleComposition"
103
- @compositionupdate="handleComposition"
104
- @compositionend="handleComposition"
105
- @mouseenter.native="inputHovering = true"
106
- @mouseleave.native="inputHovering = false">
107
- <template slot="prefixLabel" v-if="$slots.prefixLabel">
108
- <slot name="prefixLabel"></slot>
109
- </template>
110
- <template slot="prefix" v-if="$slots.prefix">
111
- <slot name="prefix"></slot>
112
- </template>
113
- <template slot="suffix">
114
- <i v-show="!showClose" :class="['el-select__caret', 'el-input__icon', 'iov-icon-' + iconClass]"></i>
115
- <i v-if="showClose" style="padding-right: 0;" class="el-input__icon iov-icon-close-mini el-input__clear" @click="handleClearClick"></i>
116
- </template>
117
- </el-input>
118
- <transition
119
- name="el-zoom-in-top"
120
- @before-enter="handleMenuEnter"
121
- @after-leave="doDestroy">
122
- <el-select-menu
123
- ref="popper"
124
- :append-to-body="popperAppendToBody"
125
- v-show="visible && emptyText !== false">
126
- <el-scrollbar
127
- tag="ul"
128
- wrap-class="el-select-dropdown__wrap"
129
- view-class="el-select-dropdown__list"
130
- ref="scrollbar"
131
- :class="{ 'is-empty': !allowCreate && query && filteredOptionsCount === 0 }"
132
- v-show="options.length > 0 && !loading">
133
- <el-option
134
- :value="query"
135
- created
136
- v-if="showNewOption">
137
- </el-option>
138
- <slot></slot>
139
- </el-scrollbar>
140
- <template v-if="emptyText && (!allowCreate || loading || (allowCreate && options.length === 0 ))">
141
- <slot name="empty" v-if="$slots.empty"></slot>
142
- <el-empty v-else :description="emptyText" :type="0" :image-size="60"></el-empty>
143
- </template>
144
- </el-select-menu>
145
- </transition>
146
- </div>
147
- </template>
148
-
149
- <script type="text/babel">
150
- import Emitter from 'iov-design/src/mixins/emitter';
151
- import Focus from 'iov-design/src/mixins/focus';
152
- import Locale from 'iov-design/src/mixins/locale';
153
- import ElInput from 'iov-design/packages/input';
154
- import ElSelectMenu from './select-dropdown.vue';
155
- import ElOption from './option.vue';
156
- import ElTag from 'iov-design/packages/tag';
157
- import ElScrollbar from 'iov-design/packages/scrollbar';
158
- import ElEmpty from 'iov-design/packages/empty';
159
- import debounce from 'throttle-debounce/debounce';
160
- import Clickoutside from 'iov-design/src/utils/clickoutside';
161
- import { addResizeListener, removeResizeListener } from 'iov-design/src/utils/resize-event';
162
- import scrollIntoView from 'iov-design/src/utils/scroll-into-view';
163
- import { getValueByPath, valueEquals, isIE, isEdge } from 'iov-design/src/utils/util';
164
- import NavigationMixin from './navigation-mixin';
165
- import { isKorean } from 'iov-design/src/utils/shared';
166
-
167
- export default {
168
- mixins: [Emitter, Locale, Focus('reference'), NavigationMixin],
169
-
170
- name: 'ElSelect',
171
-
172
- componentName: 'ElSelect',
173
-
174
- inject: {
175
- elForm: {
176
- default: ''
177
- },
178
-
179
- elFormItem: {
180
- default: ''
181
- }
182
- },
183
-
184
- provide() {
185
- return {
186
- 'select': this
187
- };
188
- },
189
-
190
- computed: {
191
- // maxWidth() {
192
- // if (this.collapseTags) {
193
- // if (this.multipleTagMaxWidth && this.multipleTagMaxWidth !== 'none') {
194
- // return this.multipleTagMaxWidth;
195
- // }
196
- // const tagsCountWidth = this.$refs.tagsCount && this.$refs.tagsCount.$el.clientWidth || 0;
197
- // const count = this.selected.length <= this.multipleLimitShow ? this.selected.length : this.multipleLimitShow;
198
- // return Math.floor((this.inputWidth - this.tagsLeft - 32 - tagsCountWidth - 20 - count * 16) / count) + 'px';
199
- // } else {
200
- // return this.multipleTagMaxWidth || 'none';
201
- // }
202
- // },
203
- _elFormItemSize() {
204
- return (this.elFormItem || {}).elFormItemSize;
205
- },
206
-
207
- readonly() {
208
- return !this.filterable || this.multiple || (!isIE() && !isEdge() && !this.visible);
209
- },
210
-
211
- showClose() {
212
- let hasValue = this.multiple
213
- ? Array.isArray(this.value) && this.value.length > 0
214
- : this.value !== undefined && this.value !== null && this.value !== '';
215
- let criteria = this.clearable &&
216
- !this.selectDisabled &&
217
- this.inputHovering &&
218
- hasValue;
219
- return criteria;
220
- },
221
-
222
- iconClass() {
223
- return this.remote && this.filterable ? '' : (this.visible ? 'arrow-up is-reverse' : 'arrow-up');
224
- },
225
-
226
- debounce() {
227
- return this.remote ? 300 : 0;
228
- },
229
-
230
- emptyText() {
231
- if (this.loading) {
232
- return this.loadingText || this.t('el.select.loading');
233
- } else {
234
- if (this.remote && this.query === '' && this.options.length === 0) return false;
235
- if (this.filterable && this.query && this.options.length > 0 && this.filteredOptionsCount === 0) {
236
- return this.noMatchText || this.t('el.select.noMatch');
237
- }
238
- if (this.options.length === 0) {
239
- return this.noDataText || this.t('el.select.noData');
240
- }
241
- }
242
- return null;
243
- },
244
-
245
- showNewOption() {
246
- let hasExistingOption = this.options.filter(option => !option.created)
247
- .some(option => option.currentLabel === this.query);
248
- return this.filterable && this.allowCreate && this.query !== '' && !hasExistingOption;
249
- },
250
-
251
- selectSize() {
252
- return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
253
- },
254
-
255
- selectDisabled() {
256
- return this.disabled || (this.elForm || {}).disabled;
257
- },
258
-
259
- collapseTagSize() {
260
- const sizeMap = {
261
- large: '',
262
- medium: 'medium',
263
- small: 'small',
264
- mini: 'mini'
265
- };
266
- return sizeMap[this.selectSize];
267
- },
268
- propPlaceholder() {
269
- return typeof this.placeholder !== 'undefined' ? this.placeholder : this.t('el.select.placeholder');
270
- }
271
- },
272
-
273
- components: {
274
- ElInput,
275
- ElSelectMenu,
276
- ElOption,
277
- ElTag,
278
- ElScrollbar,
279
- ElEmpty
280
- },
281
-
282
- directives: { Clickoutside },
283
-
284
- props: {
285
- name: String,
286
- id: String,
287
- value: {
288
- required: true
289
- },
290
- autocomplete: {
291
- type: String,
292
- default: 'off'
293
- },
294
- /** @Deprecated in next major version */
295
- autoComplete: {
296
- type: String,
297
- validator(val) {
298
- process.env.NODE_ENV !== 'production' &&
299
- console.warn('[Element Warn][Select]\'auto-complete\' property will be deprecated in next major version. please use \'autocomplete\' instead.');
300
- return true;
301
- }
302
- },
303
- automaticDropdown: Boolean,
304
- size: String,
305
- disabled: Boolean,
306
- clearable: Boolean,
307
- filterable: Boolean,
308
- allowCreate: Boolean,
309
- loading: Boolean,
310
- popperClass: String,
311
- remote: Boolean,
312
- loadingText: String,
313
- noMatchText: String,
314
- noDataText: String,
315
- remoteMethod: Function,
316
- filterMethod: Function,
317
- multiple: Boolean,
318
- multipleLimit: {
319
- type: Number,
320
- default: 0
321
- },
322
- multipleLimitShow: {
323
- type: Number,
324
- default: 1
325
- },
326
- multipleTagMaxWidth: {
327
- type: String,
328
- default: 'none'
329
- },
330
- collapseTagsSuffix: {
331
- type: String,
332
- default: ''
333
- },
334
- collapseTagsFixed: {
335
- type: Boolean,
336
- default: false
337
- },
338
- placeholder: {
339
- type: String,
340
- required: false
341
- },
342
- defaultFirstOption: Boolean,
343
- reserveKeyword: Boolean,
344
- valueKey: {
345
- type: String,
346
- default: 'value'
347
- },
348
- collapseTags: Boolean,
349
- popperAppendToBody: {
350
- type: Boolean,
351
- default: true
352
- },
353
- fill: Boolean
354
- },
355
-
356
- data() {
357
- return {
358
- options: [],
359
- cachedOptions: [],
360
- createdLabel: null,
361
- createdSelected: false,
362
- selected: this.multiple ? [] : {},
363
- inputLength: 20,
364
- inputWidth: 0,
365
- initialInputHeight: 0,
366
- cachedPlaceHolder: '',
367
- optionsCount: 0,
368
- filteredOptionsCount: 0,
369
- visible: false,
370
- softFocus: false,
371
- selectedLabel: '',
372
- hoverIndex: -1,
373
- query: '',
374
- previousQuery: null,
375
- inputHovering: false,
376
- currentPlaceholder: '',
377
- menuVisibleOnFocus: false,
378
- isOnComposition: false,
379
- isSilentBlur: false,
380
- tagsLeft: 0,
381
- maxWidth: 'none'
382
- };
383
- },
384
-
385
- watch: {
386
- selectDisabled() {
387
- this.$nextTick(() => {
388
- this.resetInputHeight();
389
- });
390
- },
391
-
392
- propPlaceholder(val) {
393
- this.cachedPlaceHolder = this.currentPlaceholder = val;
394
- },
395
-
396
- value(val, oldVal) {
397
- if (this.multiple) {
398
- this.resetInputHeight();
399
- if ((val && val.length > 0) || (this.$refs.input && this.query !== '')) {
400
- this.currentPlaceholder = '';
401
- } else {
402
- this.currentPlaceholder = this.cachedPlaceHolder;
403
- }
404
- if (this.filterable && !this.reserveKeyword) {
405
- this.query = '';
406
- this.handleQueryChange(this.query);
407
- }
408
- this.getMaxWidth();
409
- }
410
- this.setSelected();
411
- if (this.filterable && !this.multiple) {
412
- this.inputLength = 20;
413
- }
414
- if (!valueEquals(val, oldVal)) {
415
- this.dispatch('ElFormItem', 'el.form.change', val);
416
- }
417
- },
418
-
419
- visible(val) {
420
- if (!val) {
421
- this.broadcast('ElSelectDropdown', 'destroyPopper');
422
- if (this.$refs.input) {
423
- this.$refs.input.blur();
424
- }
425
- this.query = '';
426
- this.previousQuery = null;
427
- this.selectedLabel = '';
428
- this.inputLength = 20;
429
- this.menuVisibleOnFocus = false;
430
- this.resetHoverIndex();
431
- this.$nextTick(() => {
432
- if (this.$refs.input &&
433
- this.$refs.input.value === '' &&
434
- this.selected.length === 0) {
435
- this.currentPlaceholder = this.cachedPlaceHolder;
436
- }
437
- });
438
- if (!this.multiple) {
439
- if (this.selected) {
440
- if (this.filterable && this.allowCreate &&
441
- this.createdSelected && this.createdLabel) {
442
- this.selectedLabel = this.createdLabel;
443
- } else {
444
- this.selectedLabel = this.selected.currentLabel;
445
- }
446
- if (this.filterable) this.query = this.selectedLabel;
447
- }
448
-
449
- if (this.filterable) {
450
- this.currentPlaceholder = this.cachedPlaceHolder;
451
- }
452
- }
453
- } else {
454
- this.broadcast('ElSelectDropdown', 'updatePopper');
455
- if (this.filterable) {
456
- this.query = this.remote ? '' : this.selectedLabel;
457
- this.handleQueryChange(this.query);
458
- if (this.multiple) {
459
- this.$refs.input.focus();
460
- } else {
461
- if (!this.remote) {
462
- this.broadcast('ElOption', 'queryChange', '');
463
- this.broadcast('ElOptionGroup', 'queryChange');
464
- }
465
-
466
- if (this.selectedLabel) {
467
- this.currentPlaceholder = this.selectedLabel;
468
- this.selectedLabel = '';
469
- }
470
- }
471
- }
472
- }
473
- this.$emit('visible-change', val);
474
- },
475
-
476
- options() {
477
- if (this.$isServer) return;
478
- this.$nextTick(() => {
479
- this.broadcast('ElSelectDropdown', 'updatePopper');
480
- });
481
- if (this.multiple) {
482
- this.resetInputHeight();
483
- }
484
- let inputs = this.$el.querySelectorAll('input');
485
- if ([].indexOf.call(inputs, document.activeElement) === -1) {
486
- this.setSelected();
487
- }
488
- if (this.defaultFirstOption && (this.filterable || this.remote) && this.filteredOptionsCount) {
489
- this.checkDefaultFirstOption();
490
- }
491
- }
492
- },
493
-
494
- methods: {
495
- getMaxWidth() {
496
- this.$nextTick(() => {
497
- if (this.collapseTags) {
498
- if (this.multipleTagMaxWidth && this.multipleTagMaxWidth !== 'none') {
499
- this.maxWidth = this.multipleTagMaxWidth;
500
- }
501
- const tagsCountWidth = this.$refs.tagsCount && this.$refs.tagsCount.$el.clientWidth || 0;
502
- const count = this.selected.length <= this.multipleLimitShow ? this.selected.length : this.multipleLimitShow;
503
- this.maxWidth = Math.floor((this.inputWidth - this.tagsLeft - 32 - tagsCountWidth - 20 - count * 16) / count) + 'px';
504
- } else {
505
- this.maxWidth = this.multipleTagMaxWidth || 'none';
506
- }
507
- });
508
- },
509
- handleNavigate(direction) {
510
- if (this.isOnComposition) return;
511
-
512
- this.navigateOptions(direction);
513
- },
514
- handleComposition(event) {
515
- const text = event.target.value;
516
- if (event.type === 'compositionend') {
517
- this.isOnComposition = false;
518
- this.$nextTick(_ => this.handleQueryChange(text));
519
- } else {
520
- const lastCharacter = text[text.length - 1] || '';
521
- this.isOnComposition = !isKorean(lastCharacter);
522
- }
523
- },
524
- handleQueryChange(val) {
525
- if (this.previousQuery === val || this.isOnComposition) return;
526
- if (
527
- this.previousQuery === null &&
528
- (typeof this.filterMethod === 'function' || typeof this.remoteMethod === 'function')
529
- ) {
530
- this.previousQuery = val;
531
- return;
532
- }
533
- this.previousQuery = val;
534
- this.$nextTick(() => {
535
- if (this.visible) this.broadcast('ElSelectDropdown', 'updatePopper');
536
- });
537
- this.hoverIndex = -1;
538
- if (this.multiple && this.filterable) {
539
- this.$nextTick(() => {
540
- const length = this.$refs.input.value.length * 15 + 20;
541
- this.inputLength = this.collapseTags ? Math.min(50, length) : length;
542
- this.managePlaceholder();
543
- this.resetInputHeight();
544
- });
545
- }
546
- if (this.remote && typeof this.remoteMethod === 'function') {
547
- this.hoverIndex = -1;
548
- this.remoteMethod(val);
549
- } else if (typeof this.filterMethod === 'function') {
550
- this.filterMethod(val);
551
- this.broadcast('ElOptionGroup', 'queryChange');
552
- } else {
553
- this.filteredOptionsCount = this.optionsCount;
554
- this.broadcast('ElOption', 'queryChange', val);
555
- this.broadcast('ElOptionGroup', 'queryChange');
556
- }
557
- if (this.defaultFirstOption && (this.filterable || this.remote) && this.filteredOptionsCount) {
558
- this.checkDefaultFirstOption();
559
- }
560
- },
561
-
562
- scrollToOption(option) {
563
- const target = Array.isArray(option) && option[0] ? option[0].$el : option.$el;
564
- if (this.$refs.popper && target) {
565
- const menu = this.$refs.popper.$el.querySelector('.el-select-dropdown__wrap');
566
- scrollIntoView(menu, target);
567
- }
568
- this.$refs.scrollbar && this.$refs.scrollbar.handleScroll();
569
- },
570
-
571
- handleMenuEnter() {
572
- this.$nextTick(() => this.scrollToOption(this.selected));
573
- },
574
-
575
- emitChange(val) {
576
- if (!valueEquals(this.value, val)) {
577
- this.$emit('change', val);
578
- }
579
- },
580
-
581
- getOption(value) {
582
- let option;
583
- const isObject = Object.prototype.toString.call(value).toLowerCase() === '[object object]';
584
- const isNull = Object.prototype.toString.call(value).toLowerCase() === '[object null]';
585
- const isUndefined = Object.prototype.toString.call(value).toLowerCase() === '[object undefined]';
586
-
587
- for (let i = this.cachedOptions.length - 1; i >= 0; i--) {
588
- const cachedOption = this.cachedOptions[i];
589
- const isEqual = isObject
590
- ? getValueByPath(cachedOption.value, this.valueKey) === getValueByPath(value, this.valueKey)
591
- : cachedOption.value === value;
592
- if (isEqual) {
593
- option = cachedOption;
594
- break;
595
- }
596
- }
597
- if (option) return option;
598
- const label = (!isObject && !isNull && !isUndefined)
599
- ? String(value) : '';
600
- let newOption = {
601
- value: value,
602
- currentLabel: label
603
- };
604
- if (this.multiple) {
605
- newOption.hitState = false;
606
- }
607
- return newOption;
608
- },
609
-
610
- setSelected() {
611
- if (!this.multiple) {
612
- let option = this.getOption(this.value);
613
- if (option.created) {
614
- this.createdLabel = option.currentLabel;
615
- this.createdSelected = true;
616
- } else {
617
- this.createdSelected = false;
618
- }
619
- this.selectedLabel = option.currentLabel;
620
- this.selected = option;
621
- if (this.filterable) this.query = this.selectedLabel;
622
- return;
623
- }
624
- let result = [];
625
- if (Array.isArray(this.value)) {
626
- this.value.forEach(value => {
627
- result.push(this.getOption(value));
628
- });
629
- }
630
- this.selected = result;
631
- this.$nextTick(() => {
632
- this.resetInputHeight();
633
- });
634
- },
635
-
636
- handleFocus(event) {
637
- if (!this.softFocus) {
638
- if (this.automaticDropdown || this.filterable) {
639
- if (this.filterable && !this.visible) {
640
- this.menuVisibleOnFocus = true;
641
- }
642
- this.visible = true;
643
- }
644
- this.$emit('focus', event);
645
- } else {
646
- this.softFocus = false;
647
- }
648
- },
649
-
650
- blur() {
651
- this.visible = false;
652
- this.$refs.reference.blur();
653
- },
654
-
655
- handleBlur(event) {
656
- setTimeout(() => {
657
- if (this.isSilentBlur) {
658
- this.isSilentBlur = false;
659
- } else {
660
- this.$emit('blur', event);
661
- }
662
- }, 50);
663
- this.softFocus = false;
664
- },
665
-
666
- handleClearClick(event) {
667
- this.deleteSelected(event);
668
- },
669
-
670
- doDestroy() {
671
- this.$refs.popper && this.$refs.popper.doDestroy();
672
- },
673
-
674
- handleClose() {
675
- this.visible = false;
676
- },
677
-
678
- toggleLastOptionHitState(hit) {
679
- if (!Array.isArray(this.selected)) return;
680
- const option = this.selected[this.selected.length - 1];
681
- if (!option) return;
682
-
683
- if (hit === true || hit === false) {
684
- option.hitState = hit;
685
- return hit;
686
- }
687
-
688
- option.hitState = !option.hitState;
689
- return option.hitState;
690
- },
691
-
692
- deletePrevTag(e) {
693
- if (e.target.value.length <= 0 && !this.toggleLastOptionHitState()) {
694
- const value = this.value.slice();
695
- value.pop();
696
- this.$emit('input', value);
697
- this.emitChange(value);
698
- }
699
- },
700
-
701
- managePlaceholder() {
702
- if (this.currentPlaceholder !== '') {
703
- this.currentPlaceholder = this.$refs.input.value ? '' : this.cachedPlaceHolder;
704
- }
705
- },
706
-
707
- resetTagsLeft() {
708
- this.$nextTick(() => {
709
- const prefixLabel = this.$el.querySelector('.el-input-group__prefix-label');
710
- const prefix = this.$el.querySelector('.el-input__prefix');
711
- const inputInner = this.$el.querySelector('.el-input__inner');
712
- const prefixLabelWidth = prefixLabel && Math.round(prefixLabel.getBoundingClientRect().width) || 0;
713
- const inputPaddingLeft = prefixLabel || prefix ? Math.round(window.getComputedStyle(inputInner).paddingLeft.replace(/px/, '')) : 0;
714
- this.tagsLeft = prefixLabel ? (prefixLabelWidth + inputPaddingLeft - 4) : 0;
715
- });
716
- },
717
-
718
- resetInputState(e) {
719
- if (e.keyCode !== 8) this.toggleLastOptionHitState(false);
720
- this.inputLength = this.$refs.input.value.length * 15 + 20;
721
- this.resetInputHeight();
722
- },
723
-
724
- resetInputHeight() {
725
- if (this.collapseTags && !this.filterable) return;
726
- this.$nextTick(() => {
727
- if (!this.$refs.reference) return;
728
- const inputInner = this.$el.querySelector('.el-input__inner');
729
- const groupPrefix = this.$el.querySelector('.el-input-group--prefix');
730
- const input = groupPrefix || inputInner;
731
- const tags = this.$refs.tags;
732
- const tagsHeight = tags ? Math.round(tags.getBoundingClientRect().height) : 0;
733
- const sizeInMap = this.initialInputHeight || 36;
734
- input.style.height = this.selected.length === 0
735
- ? sizeInMap + 'px'
736
- : Math.max(
737
- tags ? (tagsHeight + (tagsHeight > sizeInMap ? 6 : 0)) : 0,
738
- sizeInMap
739
- ) + 'px';
740
- if (this.visible && this.emptyText !== false) {
741
- this.broadcast('ElSelectDropdown', 'updatePopper');
742
- }
743
- });
744
- },
745
-
746
- resetHoverIndex() {
747
- setTimeout(() => {
748
- if (!this.multiple) {
749
- this.hoverIndex = this.options.indexOf(this.selected);
750
- } else {
751
- if (this.selected.length > 0) {
752
- this.hoverIndex = Math.min.apply(null, this.selected.map(item => this.options.indexOf(item)));
753
- } else {
754
- this.hoverIndex = -1;
755
- }
756
- }
757
- }, 300);
758
- },
759
-
760
- handleOptionSelect(option, byClick) {
761
- if (this.multiple) {
762
- const value = (this.value || []).slice();
763
- const optionIndex = this.getValueIndex(value, option.value);
764
- if (optionIndex > -1) {
765
- value.splice(optionIndex, 1);
766
- } else if (this.multipleLimit <= 0 || value.length < this.multipleLimit) {
767
- value.push(option.value);
768
- }
769
- this.$emit('input', value);
770
- this.emitChange(value);
771
- if (option.created) {
772
- this.query = '';
773
- this.handleQueryChange('');
774
- this.inputLength = 20;
775
- }
776
- if (this.filterable) this.$refs.input.focus();
777
- } else {
778
- this.$emit('input', option.value);
779
- this.emitChange(option.value);
780
- this.visible = false;
781
- }
782
- this.isSilentBlur = byClick;
783
- // this.setSoftFocus();
784
- if (this.visible) return;
785
- this.$nextTick(() => {
786
- this.scrollToOption(option);
787
- });
788
- },
789
-
790
- setSoftFocus() {
791
- this.softFocus = true;
792
- const input = this.$refs.input || this.$refs.reference;
793
- if (input) {
794
- input.focus();
795
- }
796
- },
797
-
798
- getValueIndex(arr = [], value) {
799
- const isObject = Object.prototype.toString.call(value).toLowerCase() === '[object object]';
800
- if (!isObject) {
801
- return arr.indexOf(value);
802
- } else {
803
- const valueKey = this.valueKey;
804
- let index = -1;
805
- arr.some((item, i) => {
806
- if (getValueByPath(item, valueKey) === getValueByPath(value, valueKey)) {
807
- index = i;
808
- return true;
809
- }
810
- return false;
811
- });
812
- return index;
813
- }
814
- },
815
-
816
- toggleMenu() {
817
- if (!this.selectDisabled) {
818
- if (this.menuVisibleOnFocus) {
819
- this.menuVisibleOnFocus = false;
820
- } else {
821
- this.visible = !this.visible;
822
- }
823
- if (this.visible) {
824
- (this.$refs.input || this.$refs.reference).focus();
825
- }
826
- }
827
- },
828
-
829
- selectOption() {
830
- if (!this.visible) {
831
- this.toggleMenu();
832
- } else {
833
- if (this.options[this.hoverIndex]) {
834
- this.handleOptionSelect(this.options[this.hoverIndex]);
835
- }
836
- }
837
- },
838
-
839
- deleteSelected(event) {
840
- event.stopPropagation();
841
- const value = this.multiple ? [] : '';
842
- this.$emit('input', value);
843
- this.emitChange(value);
844
- this.visible = false;
845
- this.$emit('clear');
846
- },
847
-
848
- deleteTag(event, tag) {
849
- if (tag.disabled) return;
850
- let index = this.selected.indexOf(tag);
851
- if (index > -1 && !this.selectDisabled) {
852
- const value = this.value.slice();
853
- value.splice(index, 1);
854
- this.$emit('input', value);
855
- this.emitChange(value);
856
- this.$emit('remove-tag', tag.value);
857
- }
858
- event.stopPropagation();
859
- },
860
-
861
- onInputChange() {
862
- if (this.filterable && this.query !== this.selectedLabel) {
863
- this.query = this.selectedLabel;
864
- this.handleQueryChange(this.query);
865
- }
866
- },
867
-
868
- onOptionDestroy(index) {
869
- if (index > -1) {
870
- this.optionsCount--;
871
- this.filteredOptionsCount--;
872
- this.options.splice(index, 1);
873
- }
874
- },
875
-
876
- resetInputWidth() {
877
- this.inputWidth = this.$refs.reference.$el.getBoundingClientRect().width;
878
- },
879
-
880
- handleResize() {
881
- this.resetInputWidth();
882
- if (this.multiple) {
883
- this.resetInputHeight();
884
- this.resetTagsLeft();
885
- }
886
- },
887
-
888
- checkDefaultFirstOption() {
889
- this.hoverIndex = -1;
890
- // highlight the created option
891
- let hasCreated = false;
892
- for (let i = this.options.length - 1; i >= 0; i--) {
893
- if (this.options[i].created) {
894
- hasCreated = true;
895
- this.hoverIndex = i;
896
- break;
897
- }
898
- }
899
- if (hasCreated) return;
900
- for (let i = 0; i !== this.options.length; ++i) {
901
- const option = this.options[i];
902
- if (this.query) {
903
- // highlight first options that passes the filter
904
- if (!option.disabled && !option.groupDisabled && option.visible) {
905
- this.hoverIndex = i;
906
- break;
907
- }
908
- } else {
909
- // highlight currently selected option
910
- if (option.itemSelected) {
911
- this.hoverIndex = i;
912
- break;
913
- }
914
- }
915
- }
916
- },
917
-
918
- getValueKey(item) {
919
- if (Object.prototype.toString.call(item.value).toLowerCase() !== '[object object]') {
920
- return item.value;
921
- } else {
922
- return getValueByPath(item.value, this.valueKey);
923
- }
924
- }
925
- },
926
-
927
- created() {
928
- this.cachedPlaceHolder = this.currentPlaceholder = this.propPlaceholder;
929
- if (this.multiple && !Array.isArray(this.value)) {
930
- this.$emit('input', []);
931
- }
932
- if (!this.multiple && Array.isArray(this.value)) {
933
- this.$emit('input', '');
934
- }
935
-
936
- this.debouncedOnInputChange = debounce(this.debounce, () => {
937
- this.onInputChange();
938
- });
939
-
940
- this.debouncedQueryChange = debounce(this.debounce, (e) => {
941
- this.handleQueryChange(e.target.value);
942
- });
943
-
944
- this.$on('handleOptionClick', this.handleOptionSelect);
945
- this.$on('setSelected', this.setSelected);
946
- },
947
-
948
- mounted() {
949
- if (this.multiple && Array.isArray(this.value) && this.value.length > 0) {
950
- this.currentPlaceholder = '';
951
- }
952
- addResizeListener(this.$el, this.handleResize);
953
-
954
- const reference = this.$refs.reference;
955
- if (reference && reference.$el) {
956
- const sizeMap = {
957
- medium: 32,
958
- small: 30,
959
- mini: 26
960
- };
961
- const input = reference.$el;
962
- this.initialInputHeight = input.getBoundingClientRect().height || sizeMap[this.selectSize];
963
- }
964
- if (this.remote && this.multiple) {
965
- this.resetInputHeight();
966
- }
967
- this.$nextTick(() => {
968
- if (reference && reference.$el) {
969
- this.inputWidth = reference.$el.getBoundingClientRect().width;
970
- }
971
- });
972
- this.setSelected();
973
- },
974
-
975
- beforeDestroy() {
976
- if (this.$el && this.handleResize) removeResizeListener(this.$el, this.handleResize);
977
- }
978
- };
979
- </script>
1
+ <template>
2
+ <div
3
+ class="el-select"
4
+ :class="[fill ? 'is-fill' : '', selectSize ? 'el-select--' + selectSize : '', selectDisabled ? 'is-disabled' : '']"
5
+ @click.stop="toggleMenu"
6
+ v-clickoutside="handleClose">
7
+ <div
8
+ class="el-select__tags"
9
+ :class="{ 'is-focus': visible }"
10
+ v-if="multiple"
11
+ ref="tags"
12
+ :style="{ 'max-width': inputWidth - 32 + 'px', width: (inputWidth - tagsLeft - 32) + 'px', left: tagsLeft + 'px' }">
13
+ <span class="el-tag__group" v-if="collapseTags && selected.length">
14
+ <template v-for="(item, index) in selected">
15
+ <el-tag
16
+ :key="getValueKey(item)"
17
+ v-if="index <= multipleLimitShow - 1"
18
+ :closable="!selectDisabled"
19
+ :size="collapseTagSize"
20
+ :hit="item.hitState"
21
+ :maxWidth="maxWidth"
22
+ type="info"
23
+ @close="deleteTag($event, item)"
24
+ disable-transitions>
25
+ <span class="el-select__tags-text">{{ item.currentLabel }}</span>
26
+ </el-tag>
27
+ </template>
28
+ <el-tag
29
+ v-if="selected.length > 1 && selected.length > multipleLimitShow || selected.length > 0 && collapseTagsFixed"
30
+ :closable="false"
31
+ :size="collapseTagSize"
32
+ type="info"
33
+ ref="tagsCount"
34
+ class="el-select__tags-count"
35
+ :class="{'el-select__tags-count-fixed': collapseTagsFixed}"
36
+ disable-transitions>
37
+ <span class="el-select__tags-text">{{collapseTagsFixed ? '' : '+'}}{{ collapseTagsFixed ? selected.length : selected.length - multipleLimitShow }}{{ collapseTagsSuffix }}</span>
38
+ </el-tag>
39
+ </span>
40
+ <transition-group class="el-tag__group" @after-leave="resetInputHeight" v-if="!collapseTags">
41
+ <el-tag
42
+ v-for="item in selected"
43
+ :key="getValueKey(item)"
44
+ :closable="!item.disabled && !selectDisabled"
45
+ :size="collapseTagSize"
46
+ :hit="item.hitState"
47
+ :maxWidth="maxWidth"
48
+ type="info"
49
+ @close="deleteTag($event, item)"
50
+ disable-transitions>
51
+ <span class="el-select__tags-text">{{ item.currentLabel }}</span>
52
+ </el-tag>
53
+ </transition-group>
54
+
55
+ <input
56
+ type="text"
57
+ class="el-select__input"
58
+ :class="[selectSize ? `is-${ selectSize }` : '']"
59
+ :disabled="selectDisabled"
60
+ :autocomplete="autoComplete || autocomplete"
61
+ @focus="handleFocus"
62
+ @blur="softFocus = false"
63
+ @keyup="managePlaceholder"
64
+ @keydown="resetInputState"
65
+ @keydown.down.prevent="handleNavigate('next')"
66
+ @keydown.up.prevent="handleNavigate('prev')"
67
+ @keydown.enter.prevent="selectOption"
68
+ @keydown.esc.stop.prevent="visible = false"
69
+ @keydown.delete="deletePrevTag"
70
+ @keydown.tab="visible = false"
71
+ @compositionstart="handleComposition"
72
+ @compositionupdate="handleComposition"
73
+ @compositionend="handleComposition"
74
+ v-model="query"
75
+ @input="debouncedQueryChange"
76
+ v-if="filterable"
77
+ :style="{ 'flex-grow': '1', width: inputLength / (inputWidth - 32) + '%', 'max-width': inputWidth - 42 + 'px' }"
78
+ ref="input">
79
+ </div>
80
+ <el-input
81
+ ref="reference"
82
+ v-model="selectedLabel"
83
+ type="text"
84
+ :placeholder="currentPlaceholder"
85
+ :name="name"
86
+ :id="id"
87
+ :autocomplete="autoComplete || autocomplete"
88
+ :size="selectSize"
89
+ :disabled="selectDisabled"
90
+ :readonly="readonly"
91
+ :validate-event="false"
92
+ :class="{ 'is-focus': visible }"
93
+ :tabindex="(multiple && filterable) ? '-1' : null"
94
+ @focus="handleFocus"
95
+ @blur="handleBlur"
96
+ @input="debouncedOnInputChange"
97
+ @keydown.native.down.stop.prevent="handleNavigate('next')"
98
+ @keydown.native.up.stop.prevent="handleNavigate('prev')"
99
+ @keydown.native.enter.prevent="selectOption"
100
+ @keydown.native.esc.stop.prevent="visible = false"
101
+ @keydown.native.tab="visible = false"
102
+ @compositionstart="handleComposition"
103
+ @compositionupdate="handleComposition"
104
+ @compositionend="handleComposition"
105
+ @mouseenter.native="inputHovering = true"
106
+ @mouseleave.native="inputHovering = false">
107
+ <template slot="prefixLabel" v-if="$slots.prefixLabel">
108
+ <slot name="prefixLabel"></slot>
109
+ </template>
110
+ <template slot="prefix" v-if="$slots.prefix">
111
+ <slot name="prefix"></slot>
112
+ </template>
113
+ <template slot="suffix">
114
+ <i v-show="!showClose" :class="['el-select__caret', 'el-input__icon', 'iov-icon-' + iconClass]"></i>
115
+ <i v-if="showClose" style="padding-right: 0;" class="el-input__icon iov-icon-close-mini el-input__clear" @click="handleClearClick"></i>
116
+ </template>
117
+ </el-input>
118
+ <transition
119
+ name="el-zoom-in-top"
120
+ @before-enter="handleMenuEnter"
121
+ @after-leave="doDestroy">
122
+ <el-select-menu
123
+ ref="popper"
124
+ :append-to-body="popperAppendToBody"
125
+ v-show="visible && emptyText !== false">
126
+ <el-scrollbar
127
+ tag="ul"
128
+ wrap-class="el-select-dropdown__wrap"
129
+ view-class="el-select-dropdown__list"
130
+ ref="scrollbar"
131
+ :class="{ 'is-empty': !allowCreate && query && filteredOptionsCount === 0 }"
132
+ v-show="options.length > 0 && !loading">
133
+ <el-option
134
+ :value="query"
135
+ created
136
+ v-if="showNewOption">
137
+ </el-option>
138
+ <slot></slot>
139
+ </el-scrollbar>
140
+ <template v-if="emptyText && (!allowCreate || loading || (allowCreate && options.length === 0 ))">
141
+ <slot name="empty" v-if="$slots.empty"></slot>
142
+ <el-empty v-else :description="emptyText" :type="0" :image-size="60"></el-empty>
143
+ </template>
144
+ </el-select-menu>
145
+ </transition>
146
+ </div>
147
+ </template>
148
+
149
+ <script type="text/babel">
150
+ import Emitter from 'iov-design/src/mixins/emitter';
151
+ import Focus from 'iov-design/src/mixins/focus';
152
+ import Locale from 'iov-design/src/mixins/locale';
153
+ import ElInput from 'iov-design/packages/input';
154
+ import ElSelectMenu from './select-dropdown.vue';
155
+ import ElOption from './option.vue';
156
+ import ElTag from 'iov-design/packages/tag';
157
+ import ElScrollbar from 'iov-design/packages/scrollbar';
158
+ import ElEmpty from 'iov-design/packages/empty';
159
+ import debounce from 'throttle-debounce/debounce';
160
+ import Clickoutside from 'iov-design/src/utils/clickoutside';
161
+ import { addResizeListener, removeResizeListener } from 'iov-design/src/utils/resize-event';
162
+ import scrollIntoView from 'iov-design/src/utils/scroll-into-view';
163
+ import { getValueByPath, valueEquals, isIE, isEdge } from 'iov-design/src/utils/util';
164
+ import NavigationMixin from './navigation-mixin';
165
+ import { isKorean } from 'iov-design/src/utils/shared';
166
+
167
+ export default {
168
+ mixins: [Emitter, Locale, Focus('reference'), NavigationMixin],
169
+
170
+ name: 'ElSelect',
171
+
172
+ componentName: 'ElSelect',
173
+
174
+ inject: {
175
+ elForm: {
176
+ default: ''
177
+ },
178
+
179
+ elFormItem: {
180
+ default: ''
181
+ }
182
+ },
183
+
184
+ provide() {
185
+ return {
186
+ 'select': this
187
+ };
188
+ },
189
+
190
+ computed: {
191
+ // maxWidth() {
192
+ // if (this.collapseTags) {
193
+ // if (this.multipleTagMaxWidth && this.multipleTagMaxWidth !== 'none') {
194
+ // return this.multipleTagMaxWidth;
195
+ // }
196
+ // const tagsCountWidth = this.$refs.tagsCount && this.$refs.tagsCount.$el.clientWidth || 0;
197
+ // const count = this.selected.length <= this.multipleLimitShow ? this.selected.length : this.multipleLimitShow;
198
+ // return Math.floor((this.inputWidth - this.tagsLeft - 32 - tagsCountWidth - 20 - count * 16) / count) + 'px';
199
+ // } else {
200
+ // return this.multipleTagMaxWidth || 'none';
201
+ // }
202
+ // },
203
+ _elFormItemSize() {
204
+ return (this.elFormItem || {}).elFormItemSize;
205
+ },
206
+
207
+ readonly() {
208
+ return !this.filterable || this.multiple || (!isIE() && !isEdge() && !this.visible);
209
+ },
210
+
211
+ showClose() {
212
+ let hasValue = this.multiple
213
+ ? Array.isArray(this.value) && this.value.length > 0
214
+ : this.value !== undefined && this.value !== null && this.value !== '';
215
+ let criteria = this.clearable &&
216
+ !this.selectDisabled &&
217
+ this.inputHovering &&
218
+ hasValue;
219
+ return criteria;
220
+ },
221
+
222
+ iconClass() {
223
+ return this.remote && this.filterable ? '' : (this.visible ? 'arrow-up is-reverse' : 'arrow-up');
224
+ },
225
+
226
+ debounce() {
227
+ return this.remote ? 300 : 0;
228
+ },
229
+
230
+ emptyText() {
231
+ if (this.loading) {
232
+ return this.loadingText || this.t('el.select.loading');
233
+ } else {
234
+ if (this.remote && this.query === '' && this.options.length === 0) return false;
235
+ if (this.filterable && this.query && this.options.length > 0 && this.filteredOptionsCount === 0) {
236
+ return this.noMatchText || this.t('el.select.noMatch');
237
+ }
238
+ if (this.options.length === 0) {
239
+ return this.noDataText || this.t('el.select.noData');
240
+ }
241
+ }
242
+ return null;
243
+ },
244
+
245
+ showNewOption() {
246
+ let hasExistingOption = this.options.filter(option => !option.created)
247
+ .some(option => option.currentLabel === this.query);
248
+ return this.filterable && this.allowCreate && this.query !== '' && !hasExistingOption;
249
+ },
250
+
251
+ selectSize() {
252
+ return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
253
+ },
254
+
255
+ selectDisabled() {
256
+ return this.disabled || (this.elForm || {}).disabled;
257
+ },
258
+
259
+ collapseTagSize() {
260
+ const sizeMap = {
261
+ large: '',
262
+ medium: 'medium',
263
+ small: 'small',
264
+ mini: 'mini'
265
+ };
266
+ return sizeMap[this.selectSize];
267
+ },
268
+ propPlaceholder() {
269
+ return typeof this.placeholder !== 'undefined' ? this.placeholder : this.t('el.select.placeholder');
270
+ }
271
+ },
272
+
273
+ components: {
274
+ ElInput,
275
+ ElSelectMenu,
276
+ ElOption,
277
+ ElTag,
278
+ ElScrollbar,
279
+ ElEmpty
280
+ },
281
+
282
+ directives: { Clickoutside },
283
+
284
+ props: {
285
+ name: String,
286
+ id: String,
287
+ value: {
288
+ required: true
289
+ },
290
+ autocomplete: {
291
+ type: String,
292
+ default: 'off'
293
+ },
294
+ /** @Deprecated in next major version */
295
+ autoComplete: {
296
+ type: String,
297
+ validator(val) {
298
+ process.env.NODE_ENV !== 'production' &&
299
+ console.warn('[Element Warn][Select]\'auto-complete\' property will be deprecated in next major version. please use \'autocomplete\' instead.');
300
+ return true;
301
+ }
302
+ },
303
+ automaticDropdown: Boolean,
304
+ size: String,
305
+ disabled: Boolean,
306
+ clearable: Boolean,
307
+ filterable: Boolean,
308
+ allowCreate: Boolean,
309
+ loading: Boolean,
310
+ popperClass: String,
311
+ remote: Boolean,
312
+ loadingText: String,
313
+ noMatchText: String,
314
+ noDataText: String,
315
+ remoteMethod: Function,
316
+ filterMethod: Function,
317
+ multiple: Boolean,
318
+ multipleLimit: {
319
+ type: Number,
320
+ default: 0
321
+ },
322
+ multipleLimitShow: {
323
+ type: Number,
324
+ default: 1
325
+ },
326
+ multipleTagMaxWidth: {
327
+ type: String,
328
+ default: 'none'
329
+ },
330
+ collapseTagsSuffix: {
331
+ type: String,
332
+ default: ''
333
+ },
334
+ collapseTagsFixed: {
335
+ type: Boolean,
336
+ default: false
337
+ },
338
+ placeholder: {
339
+ type: String,
340
+ required: false
341
+ },
342
+ defaultFirstOption: Boolean,
343
+ reserveKeyword: Boolean,
344
+ valueKey: {
345
+ type: String,
346
+ default: 'value'
347
+ },
348
+ collapseTags: Boolean,
349
+ popperAppendToBody: {
350
+ type: Boolean,
351
+ default: true
352
+ },
353
+ fill: Boolean
354
+ },
355
+
356
+ data() {
357
+ return {
358
+ options: [],
359
+ cachedOptions: [],
360
+ createdLabel: null,
361
+ createdSelected: false,
362
+ selected: this.multiple ? [] : {},
363
+ inputLength: 20,
364
+ inputWidth: 0,
365
+ initialInputHeight: 0,
366
+ cachedPlaceHolder: '',
367
+ optionsCount: 0,
368
+ filteredOptionsCount: 0,
369
+ visible: false,
370
+ softFocus: false,
371
+ selectedLabel: '',
372
+ hoverIndex: -1,
373
+ query: '',
374
+ previousQuery: null,
375
+ inputHovering: false,
376
+ currentPlaceholder: '',
377
+ menuVisibleOnFocus: false,
378
+ isOnComposition: false,
379
+ isSilentBlur: false,
380
+ tagsLeft: 0,
381
+ maxWidth: 'none'
382
+ };
383
+ },
384
+
385
+ watch: {
386
+ selectDisabled() {
387
+ this.$nextTick(() => {
388
+ this.resetInputHeight();
389
+ });
390
+ },
391
+
392
+ propPlaceholder(val) {
393
+ this.cachedPlaceHolder = this.currentPlaceholder = val;
394
+ },
395
+
396
+ value(val, oldVal) {
397
+ if (this.multiple) {
398
+ this.resetInputHeight();
399
+ if ((val && val.length > 0) || (this.$refs.input && this.query !== '')) {
400
+ this.currentPlaceholder = '';
401
+ } else {
402
+ this.currentPlaceholder = this.cachedPlaceHolder;
403
+ }
404
+ if (this.filterable && !this.reserveKeyword) {
405
+ this.query = '';
406
+ this.handleQueryChange(this.query);
407
+ }
408
+ this.getMaxWidth();
409
+ }
410
+ this.setSelected();
411
+ if (this.filterable && !this.multiple) {
412
+ this.inputLength = 20;
413
+ }
414
+ if (!valueEquals(val, oldVal)) {
415
+ this.dispatch('ElFormItem', 'el.form.change', val);
416
+ }
417
+ },
418
+
419
+ visible(val) {
420
+ if (!val) {
421
+ this.broadcast('ElSelectDropdown', 'destroyPopper');
422
+ if (this.$refs.input) {
423
+ this.$refs.input.blur();
424
+ }
425
+ this.query = '';
426
+ this.previousQuery = null;
427
+ this.selectedLabel = '';
428
+ this.inputLength = 20;
429
+ this.menuVisibleOnFocus = false;
430
+ this.resetHoverIndex();
431
+ this.$nextTick(() => {
432
+ if (this.$refs.input &&
433
+ this.$refs.input.value === '' &&
434
+ this.selected.length === 0) {
435
+ this.currentPlaceholder = this.cachedPlaceHolder;
436
+ }
437
+ });
438
+ if (!this.multiple) {
439
+ if (this.selected) {
440
+ if (this.filterable && this.allowCreate &&
441
+ this.createdSelected && this.createdLabel) {
442
+ this.selectedLabel = this.createdLabel;
443
+ } else {
444
+ this.selectedLabel = this.selected.currentLabel;
445
+ }
446
+ if (this.filterable) this.query = this.selectedLabel;
447
+ }
448
+
449
+ if (this.filterable) {
450
+ this.currentPlaceholder = this.cachedPlaceHolder;
451
+ }
452
+ }
453
+ } else {
454
+ this.broadcast('ElSelectDropdown', 'updatePopper');
455
+ if (this.filterable) {
456
+ this.query = this.remote ? '' : this.selectedLabel;
457
+ this.handleQueryChange(this.query);
458
+ if (this.multiple) {
459
+ this.$refs.input.focus();
460
+ } else {
461
+ if (!this.remote) {
462
+ this.broadcast('ElOption', 'queryChange', '');
463
+ this.broadcast('ElOptionGroup', 'queryChange');
464
+ }
465
+
466
+ if (this.selectedLabel) {
467
+ this.currentPlaceholder = this.selectedLabel;
468
+ this.selectedLabel = '';
469
+ }
470
+ }
471
+ }
472
+ }
473
+ this.$emit('visible-change', val);
474
+ },
475
+
476
+ options() {
477
+ if (this.$isServer) return;
478
+ this.$nextTick(() => {
479
+ this.broadcast('ElSelectDropdown', 'updatePopper');
480
+ });
481
+ if (this.multiple) {
482
+ this.resetInputHeight();
483
+ }
484
+ let inputs = this.$el.querySelectorAll('input');
485
+ if ([].indexOf.call(inputs, document.activeElement) === -1) {
486
+ this.setSelected();
487
+ }
488
+ if (this.defaultFirstOption && (this.filterable || this.remote) && this.filteredOptionsCount) {
489
+ this.checkDefaultFirstOption();
490
+ }
491
+ }
492
+ },
493
+
494
+ methods: {
495
+ getMaxWidth() {
496
+ this.$nextTick(() => {
497
+ if (this.collapseTags) {
498
+ if (this.multipleTagMaxWidth && this.multipleTagMaxWidth !== 'none') {
499
+ this.maxWidth = this.multipleTagMaxWidth;
500
+ }
501
+ const tagsCountWidth = this.$refs.tagsCount && this.$refs.tagsCount.$el.clientWidth || 0;
502
+ const count = this.selected.length <= this.multipleLimitShow ? this.selected.length : this.multipleLimitShow;
503
+ this.maxWidth = Math.floor((this.inputWidth - this.tagsLeft - 32 - tagsCountWidth - 20 - count * 16) / count) + 'px';
504
+ } else {
505
+ this.maxWidth = this.multipleTagMaxWidth || 'none';
506
+ }
507
+ });
508
+ },
509
+ handleNavigate(direction) {
510
+ if (this.isOnComposition) return;
511
+
512
+ this.navigateOptions(direction);
513
+ },
514
+ handleComposition(event) {
515
+ const text = event.target.value;
516
+ if (event.type === 'compositionend') {
517
+ this.isOnComposition = false;
518
+ this.$nextTick(_ => this.handleQueryChange(text));
519
+ } else {
520
+ const lastCharacter = text[text.length - 1] || '';
521
+ this.isOnComposition = !isKorean(lastCharacter);
522
+ }
523
+ },
524
+ handleQueryChange(val) {
525
+ if (this.previousQuery === val || this.isOnComposition) return;
526
+ if (
527
+ this.previousQuery === null &&
528
+ (typeof this.filterMethod === 'function' || typeof this.remoteMethod === 'function')
529
+ ) {
530
+ this.previousQuery = val;
531
+ return;
532
+ }
533
+ this.previousQuery = val;
534
+ this.$nextTick(() => {
535
+ if (this.visible) this.broadcast('ElSelectDropdown', 'updatePopper');
536
+ });
537
+ this.hoverIndex = -1;
538
+ if (this.multiple && this.filterable) {
539
+ this.$nextTick(() => {
540
+ const length = this.$refs.input.value.length * 15 + 20;
541
+ this.inputLength = this.collapseTags ? Math.min(50, length) : length;
542
+ this.managePlaceholder();
543
+ this.resetInputHeight();
544
+ });
545
+ }
546
+ if (this.remote && typeof this.remoteMethod === 'function') {
547
+ this.hoverIndex = -1;
548
+ this.remoteMethod(val);
549
+ } else if (typeof this.filterMethod === 'function') {
550
+ this.filterMethod(val);
551
+ this.broadcast('ElOptionGroup', 'queryChange');
552
+ } else {
553
+ this.filteredOptionsCount = this.optionsCount;
554
+ this.broadcast('ElOption', 'queryChange', val);
555
+ this.broadcast('ElOptionGroup', 'queryChange');
556
+ }
557
+ if (this.defaultFirstOption && (this.filterable || this.remote) && this.filteredOptionsCount) {
558
+ this.checkDefaultFirstOption();
559
+ }
560
+ },
561
+
562
+ scrollToOption(option) {
563
+ const target = Array.isArray(option) && option[0] ? option[0].$el : option.$el;
564
+ if (this.$refs.popper && target) {
565
+ const menu = this.$refs.popper.$el.querySelector('.el-select-dropdown__wrap');
566
+ scrollIntoView(menu, target);
567
+ }
568
+ this.$refs.scrollbar && this.$refs.scrollbar.handleScroll();
569
+ },
570
+
571
+ handleMenuEnter() {
572
+ this.$nextTick(() => this.scrollToOption(this.selected));
573
+ },
574
+
575
+ emitChange(val) {
576
+ if (!valueEquals(this.value, val)) {
577
+ this.$emit('change', val);
578
+ }
579
+ },
580
+
581
+ getOption(value) {
582
+ let option;
583
+ const isObject = Object.prototype.toString.call(value).toLowerCase() === '[object object]';
584
+ const isNull = Object.prototype.toString.call(value).toLowerCase() === '[object null]';
585
+ const isUndefined = Object.prototype.toString.call(value).toLowerCase() === '[object undefined]';
586
+
587
+ for (let i = this.cachedOptions.length - 1; i >= 0; i--) {
588
+ const cachedOption = this.cachedOptions[i];
589
+ const isEqual = isObject
590
+ ? getValueByPath(cachedOption.value, this.valueKey) === getValueByPath(value, this.valueKey)
591
+ : cachedOption.value === value;
592
+ if (isEqual) {
593
+ option = cachedOption;
594
+ break;
595
+ }
596
+ }
597
+ if (option) return option;
598
+ const label = (!isObject && !isNull && !isUndefined)
599
+ ? String(value) : '';
600
+ let newOption = {
601
+ value: value,
602
+ currentLabel: label
603
+ };
604
+ if (this.multiple) {
605
+ newOption.hitState = false;
606
+ }
607
+ return newOption;
608
+ },
609
+
610
+ setSelected() {
611
+ if (!this.multiple) {
612
+ let option = this.getOption(this.value);
613
+ if (option.created) {
614
+ this.createdLabel = option.currentLabel;
615
+ this.createdSelected = true;
616
+ } else {
617
+ this.createdSelected = false;
618
+ }
619
+ this.selectedLabel = option.currentLabel;
620
+ this.selected = option;
621
+ if (this.filterable) this.query = this.selectedLabel;
622
+ return;
623
+ }
624
+ let result = [];
625
+ if (Array.isArray(this.value)) {
626
+ this.value.forEach(value => {
627
+ result.push(this.getOption(value));
628
+ });
629
+ }
630
+ this.selected = result;
631
+ this.$nextTick(() => {
632
+ this.resetInputHeight();
633
+ });
634
+ },
635
+
636
+ handleFocus(event) {
637
+ if (!this.softFocus) {
638
+ if (this.automaticDropdown || this.filterable) {
639
+ if (this.filterable && !this.visible) {
640
+ this.menuVisibleOnFocus = true;
641
+ }
642
+ this.visible = true;
643
+ }
644
+ this.$emit('focus', event);
645
+ } else {
646
+ this.softFocus = false;
647
+ }
648
+ },
649
+
650
+ blur() {
651
+ this.visible = false;
652
+ this.$refs.reference.blur();
653
+ },
654
+
655
+ handleBlur(event) {
656
+ setTimeout(() => {
657
+ if (this.isSilentBlur) {
658
+ this.isSilentBlur = false;
659
+ } else {
660
+ this.$emit('blur', event);
661
+ }
662
+ }, 50);
663
+ this.softFocus = false;
664
+ },
665
+
666
+ handleClearClick(event) {
667
+ this.deleteSelected(event);
668
+ },
669
+
670
+ doDestroy() {
671
+ this.$refs.popper && this.$refs.popper.doDestroy();
672
+ },
673
+
674
+ handleClose() {
675
+ this.visible = false;
676
+ },
677
+
678
+ toggleLastOptionHitState(hit) {
679
+ if (!Array.isArray(this.selected)) return;
680
+ const option = this.selected[this.selected.length - 1];
681
+ if (!option) return;
682
+
683
+ if (hit === true || hit === false) {
684
+ option.hitState = hit;
685
+ return hit;
686
+ }
687
+
688
+ option.hitState = !option.hitState;
689
+ return option.hitState;
690
+ },
691
+
692
+ deletePrevTag(e) {
693
+ if (e.target.value.length <= 0 && !this.toggleLastOptionHitState()) {
694
+ const value = this.value.slice();
695
+ value.pop();
696
+ this.$emit('input', value);
697
+ this.emitChange(value);
698
+ }
699
+ },
700
+
701
+ managePlaceholder() {
702
+ if (this.currentPlaceholder !== '') {
703
+ this.currentPlaceholder = this.$refs.input.value ? '' : this.cachedPlaceHolder;
704
+ }
705
+ },
706
+
707
+ resetTagsLeft() {
708
+ this.$nextTick(() => {
709
+ const prefixLabel = this.$el.querySelector('.el-input-group__prefix-label');
710
+ const prefix = this.$el.querySelector('.el-input__prefix');
711
+ const inputInner = this.$el.querySelector('.el-input__inner');
712
+ const prefixLabelWidth = prefixLabel && Math.round(prefixLabel.getBoundingClientRect().width) || 0;
713
+ const inputPaddingLeft = prefixLabel || prefix ? Math.round(window.getComputedStyle(inputInner).paddingLeft.replace(/px/, '')) : 0;
714
+ this.tagsLeft = prefixLabel ? (prefixLabelWidth + inputPaddingLeft - 4) : 0;
715
+ });
716
+ },
717
+
718
+ resetInputState(e) {
719
+ if (e.keyCode !== 8) this.toggleLastOptionHitState(false);
720
+ this.inputLength = this.$refs.input.value.length * 15 + 20;
721
+ this.resetInputHeight();
722
+ },
723
+
724
+ resetInputHeight() {
725
+ if (this.collapseTags && !this.filterable) return;
726
+ this.$nextTick(() => {
727
+ if (!this.$refs.reference) return;
728
+ const inputInner = this.$el.querySelector('.el-input__inner');
729
+ const groupPrefix = this.$el.querySelector('.el-input-group--prefix');
730
+ const input = groupPrefix || inputInner;
731
+ const tags = this.$refs.tags;
732
+ const tagsHeight = tags ? Math.round(tags.getBoundingClientRect().height) : 0;
733
+ const sizeInMap = this.initialInputHeight || 36;
734
+ input.style.height = this.selected.length === 0
735
+ ? sizeInMap + 'px'
736
+ : Math.max(
737
+ tags ? (tagsHeight + (tagsHeight > sizeInMap ? 6 : 0)) : 0,
738
+ sizeInMap
739
+ ) + 'px';
740
+ if (this.visible && this.emptyText !== false) {
741
+ this.broadcast('ElSelectDropdown', 'updatePopper');
742
+ }
743
+ });
744
+ },
745
+
746
+ resetHoverIndex() {
747
+ setTimeout(() => {
748
+ if (!this.multiple) {
749
+ this.hoverIndex = this.options.indexOf(this.selected);
750
+ } else {
751
+ if (this.selected.length > 0) {
752
+ this.hoverIndex = Math.min.apply(null, this.selected.map(item => this.options.indexOf(item)));
753
+ } else {
754
+ this.hoverIndex = -1;
755
+ }
756
+ }
757
+ }, 300);
758
+ },
759
+
760
+ handleOptionSelect(option, byClick) {
761
+ if (this.multiple) {
762
+ const value = (this.value || []).slice();
763
+ const optionIndex = this.getValueIndex(value, option.value);
764
+ if (optionIndex > -1) {
765
+ value.splice(optionIndex, 1);
766
+ } else if (this.multipleLimit <= 0 || value.length < this.multipleLimit) {
767
+ value.push(option.value);
768
+ }
769
+ this.$emit('input', value);
770
+ this.emitChange(value);
771
+ if (option.created) {
772
+ this.query = '';
773
+ this.handleQueryChange('');
774
+ this.inputLength = 20;
775
+ }
776
+ if (this.filterable) this.$refs.input.focus();
777
+ } else {
778
+ this.$emit('input', option.value);
779
+ this.emitChange(option.value);
780
+ this.visible = false;
781
+ }
782
+ this.isSilentBlur = byClick;
783
+ // this.setSoftFocus();
784
+ if (this.visible) return;
785
+ this.$nextTick(() => {
786
+ this.scrollToOption(option);
787
+ });
788
+ },
789
+
790
+ setSoftFocus() {
791
+ this.softFocus = true;
792
+ const input = this.$refs.input || this.$refs.reference;
793
+ if (input) {
794
+ input.focus();
795
+ }
796
+ },
797
+
798
+ getValueIndex(arr = [], value) {
799
+ const isObject = Object.prototype.toString.call(value).toLowerCase() === '[object object]';
800
+ if (!isObject) {
801
+ return arr.indexOf(value);
802
+ } else {
803
+ const valueKey = this.valueKey;
804
+ let index = -1;
805
+ arr.some((item, i) => {
806
+ if (getValueByPath(item, valueKey) === getValueByPath(value, valueKey)) {
807
+ index = i;
808
+ return true;
809
+ }
810
+ return false;
811
+ });
812
+ return index;
813
+ }
814
+ },
815
+
816
+ toggleMenu() {
817
+ if (!this.selectDisabled) {
818
+ if (this.menuVisibleOnFocus) {
819
+ this.menuVisibleOnFocus = false;
820
+ } else {
821
+ this.visible = !this.visible;
822
+ }
823
+ if (this.visible) {
824
+ (this.$refs.input || this.$refs.reference).focus();
825
+ }
826
+ }
827
+ },
828
+
829
+ selectOption() {
830
+ if (!this.visible) {
831
+ this.toggleMenu();
832
+ } else {
833
+ if (this.options[this.hoverIndex]) {
834
+ this.handleOptionSelect(this.options[this.hoverIndex]);
835
+ }
836
+ }
837
+ },
838
+
839
+ deleteSelected(event) {
840
+ event.stopPropagation();
841
+ const value = this.multiple ? [] : '';
842
+ this.$emit('input', value);
843
+ this.emitChange(value);
844
+ this.visible = false;
845
+ this.$emit('clear');
846
+ },
847
+
848
+ deleteTag(event, tag) {
849
+ if (tag.disabled) return;
850
+ let index = this.selected.indexOf(tag);
851
+ if (index > -1 && !this.selectDisabled) {
852
+ const value = this.value.slice();
853
+ value.splice(index, 1);
854
+ this.$emit('input', value);
855
+ this.emitChange(value);
856
+ this.$emit('remove-tag', tag.value);
857
+ }
858
+ event.stopPropagation();
859
+ },
860
+
861
+ onInputChange() {
862
+ if (this.filterable && this.query !== this.selectedLabel) {
863
+ this.query = this.selectedLabel;
864
+ this.handleQueryChange(this.query);
865
+ }
866
+ },
867
+
868
+ onOptionDestroy(index) {
869
+ if (index > -1) {
870
+ this.optionsCount--;
871
+ this.filteredOptionsCount--;
872
+ this.options.splice(index, 1);
873
+ }
874
+ },
875
+
876
+ resetInputWidth() {
877
+ this.inputWidth = this.$refs.reference.$el.getBoundingClientRect().width;
878
+ },
879
+
880
+ handleResize() {
881
+ this.resetInputWidth();
882
+ if (this.multiple) {
883
+ this.resetInputHeight();
884
+ this.resetTagsLeft();
885
+ }
886
+ },
887
+
888
+ checkDefaultFirstOption() {
889
+ this.hoverIndex = -1;
890
+ // highlight the created option
891
+ let hasCreated = false;
892
+ for (let i = this.options.length - 1; i >= 0; i--) {
893
+ if (this.options[i].created) {
894
+ hasCreated = true;
895
+ this.hoverIndex = i;
896
+ break;
897
+ }
898
+ }
899
+ if (hasCreated) return;
900
+ for (let i = 0; i !== this.options.length; ++i) {
901
+ const option = this.options[i];
902
+ if (this.query) {
903
+ // highlight first options that passes the filter
904
+ if (!option.disabled && !option.groupDisabled && option.visible) {
905
+ this.hoverIndex = i;
906
+ break;
907
+ }
908
+ } else {
909
+ // highlight currently selected option
910
+ if (option.itemSelected) {
911
+ this.hoverIndex = i;
912
+ break;
913
+ }
914
+ }
915
+ }
916
+ },
917
+
918
+ getValueKey(item) {
919
+ if (Object.prototype.toString.call(item.value).toLowerCase() !== '[object object]') {
920
+ return item.value;
921
+ } else {
922
+ return getValueByPath(item.value, this.valueKey);
923
+ }
924
+ }
925
+ },
926
+
927
+ created() {
928
+ this.cachedPlaceHolder = this.currentPlaceholder = this.propPlaceholder;
929
+ if (this.multiple && !Array.isArray(this.value)) {
930
+ this.$emit('input', []);
931
+ }
932
+ if (!this.multiple && Array.isArray(this.value)) {
933
+ this.$emit('input', '');
934
+ }
935
+
936
+ this.debouncedOnInputChange = debounce(this.debounce, () => {
937
+ this.onInputChange();
938
+ });
939
+
940
+ this.debouncedQueryChange = debounce(this.debounce, (e) => {
941
+ this.handleQueryChange(e.target.value);
942
+ });
943
+
944
+ this.$on('handleOptionClick', this.handleOptionSelect);
945
+ this.$on('setSelected', this.setSelected);
946
+ },
947
+
948
+ mounted() {
949
+ if (this.multiple && Array.isArray(this.value) && this.value.length > 0) {
950
+ this.currentPlaceholder = '';
951
+ }
952
+ addResizeListener(this.$el, this.handleResize);
953
+
954
+ const reference = this.$refs.reference;
955
+ if (reference && reference.$el) {
956
+ const sizeMap = {
957
+ medium: 32,
958
+ small: 30,
959
+ mini: 26
960
+ };
961
+ const input = reference.$el;
962
+ this.initialInputHeight = input.getBoundingClientRect().height || sizeMap[this.selectSize];
963
+ }
964
+ if (this.remote && this.multiple) {
965
+ this.resetInputHeight();
966
+ }
967
+ this.$nextTick(() => {
968
+ if (reference && reference.$el) {
969
+ this.inputWidth = reference.$el.getBoundingClientRect().width;
970
+ }
971
+ });
972
+ this.setSelected();
973
+ },
974
+
975
+ beforeDestroy() {
976
+ if (this.$el && this.handleResize) removeResizeListener(this.$el, this.handleResize);
977
+ }
978
+ };
979
+ </script>