Blame view

src/components/select/select.vue 26.1 KB
e355dd49   梁灏   add Select Component
1
  <template>
2fbe636b   梁灏   Select support a ...
2
      <div
2fbe636b   梁灏   Select support a ...
3
          :class="classes"
c9b86944   Sergio Crisostomo   Refactor Select!
4
5
          v-click-outside.capture="onClickOutside"
      >
e355dd49   梁灏   add Select Component
6
          <div
4aec6a66   梁灏   support Select
7
              ref="reference"
c9b86944   Sergio Crisostomo   Refactor Select!
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  
              :class="selectionCls"
              :tabindex="selectTabindex"
  
              @blur="toggleHeaderFocus"
              @focus="toggleHeaderFocus"
  
              @click="toggleMenu"
              @keydown.esc="handleKeydown"
              @keydown.enter="handleKeydown"
              @keydown.up="handleKeydown"
              @keydown.down="handleKeydown"
              @keydown.tab="handleKeydown"
              @keydown.delete="handleKeydown"
  
  
              @mouseenter="hasMouseHoverHead = true"
              @mouseleave="hasMouseHoverHead = false"
  
          >
fed3e09d   梁灏   add AutoComplete ...
28
              <slot name="input">
c9b86944   Sergio Crisostomo   Refactor Select!
29
30
31
32
33
34
                  <input type="hidden" :name="name" :value="publicValue">
                  <select-head
                      :filterable="filterable"
                      :multiple="multiple"
                      :values="values"
                      :clearable="canBeCleared"
fed3e09d   梁灏   add AutoComplete ...
35
                      :disabled="disabled"
c9b86944   Sergio Crisostomo   Refactor Select!
36
37
38
39
40
41
42
43
44
                      :remote="remote"
                      :input-element-id="elementId"
                      :initial-label="initialLabel"
                      :placeholder="placeholder"
                      :query-prop="query"
  
                      @on-query-change="onQueryChange"
                      @on-input-focus="isFocused = true"
                      @on-input-blur="isFocused = false"
c9b86944   Sergio Crisostomo   Refactor Select!
45
                  />
fed3e09d   梁灏   add AutoComplete ...
46
              </slot>
e355dd49   梁灏   add Select Component
47
          </div>
e09b07b7   huanghong   解决drop弹出动画异常
48
          <transition name="transition-drop">
595cfa72   梁灏   fixed #1187 #844 ...
49
              <Drop
ecaf8d51   梁灏   Date add transfer...
50
                  :class="dropdownCls"
595cfa72   梁灏   fixed #1187 #844 ...
51
52
53
54
                  v-show="dropVisible"
                  :placement="placement"
                  ref="dropdown"
                  :data-transfer="transfer"
c9b86944   Sergio Crisostomo   Refactor Select!
55
56
57
58
59
60
61
62
63
64
65
                  v-transfer-dom
              >
                  <ul v-show="showNotFoundLabel" :class="[prefixCls + '-not-found']"><li>{{ localeNotFoundText }}</li></ul>
                  <ul :class="prefixCls + '-dropdown-list'">
                    <functional-options
                        v-if="(!remote) || (remote && !loading)"
                        :options="selectOptions"
                        :slot-update-hook="updateSlotOptions"
                        :slot-options="slotOptions"
                    ></functional-options>
                  </ul>
01b54e30   梁灏   Select support re...
66
                  <ul v-show="loading" :class="[prefixCls + '-loading']">{{ localeLoadingText }}</ul>
4aec6a66   梁灏   support Select
67
68
              </Drop>
          </transition>
e355dd49   梁灏   add Select Component
69
70
71
72
      </div>
  </template>
  <script>
      import Icon from '../icon';
4aec6a66   梁灏   support Select
73
      import Drop from './dropdown.vue';
c9b86944   Sergio Crisostomo   Refactor Select!
74
      import vClickOutside from 'v-click-outside-x/index';
595cfa72   梁灏   fixed #1187 #844 ...
75
      import TransferDom from '../../directives/transfer-dom';
c9b86944   Sergio Crisostomo   Refactor Select!
76
      import { oneOf } from '../../utils/assist';
4aec6a66   梁灏   support Select
77
      import Emitter from '../../mixins/emitter';
e5337c81   梁灏   fixed some compon...
78
      import Locale from '../../mixins/locale';
c9b86944   Sergio Crisostomo   Refactor Select!
79
80
      import SelectHead from './select-head.vue';
      import FunctionalOptions from './functional-options.vue';
e355dd49   梁灏   add Select Component
81
82
  
      const prefixCls = 'ivu-select';
523e2c81   Sergio Crisostomo   correct match log...
83
84
      const optionRegexp = /^i-option$|^Option$/;
      const optionGroupRegexp = /option-?group/i;
c9b86944   Sergio Crisostomo   Refactor Select!
85
86
87
88
89
90
91
92
93
94
  
      const findChild = (instance, checkFn) => {
          let match = checkFn(instance);
          if (match) return instance;
          for (let i = 0, l = instance.$children.length; i < l; i++){
              const child = instance.$children[i];
              match = findChild(child, checkFn);
              if (match) return match;
          }
      };
e355dd49   梁灏   add Select Component
95
  
06a74f9e   Sergio Crisostomo   Allow select to n...
96
97
      const findOptionsInVNode = (node) => {
          const opts = node.componentOptions;
523e2c81   Sergio Crisostomo   correct match log...
98
          if (opts && opts.tag.match(optionRegexp)) return [node];
06a74f9e   Sergio Crisostomo   Allow select to n...
99
100
101
102
103
104
105
106
107
108
109
          if (!node.children) return [];
          const options = node.children.reduce(
              (arr, el) => [...arr, ...findOptionsInVNode(el)], []
          ).filter(Boolean);
          return options.length > 0 ? options : [];
      };
  
      const extractOptions = (options) => options.reduce((options, slotEntry) => {
          return options.concat(findOptionsInVNode(slotEntry));
      }, []);
  
aa21cdf9   Sergio Crisostomo   Process also shal...
110
111
112
113
114
115
116
117
118
119
120
121
122
      const applyProp = (node, propName, value) => {
          return {
              ...node,
              componentOptions: {
                  ...node.componentOptions,
                  propsData: {
                      ...node.componentOptions.propsData,
                      [propName]: value,
                  }
              }
          };
      };
  
e355dd49   梁灏   add Select Component
123
      export default {
8f5b1686   梁灏   fixed #196
124
          name: 'iSelect',
e5337c81   梁灏   fixed some compon...
125
          mixins: [ Emitter, Locale ],
c9b86944   Sergio Crisostomo   Refactor Select!
126
127
          components: { FunctionalOptions, Drop, Icon, SelectHead },
          directives: { clickOutside: vClickOutside.directive, TransferDom },
e355dd49   梁灏   add Select Component
128
          props: {
4aec6a66   梁灏   support Select
129
              value: {
e355dd49   梁灏   add Select Component
130
131
132
                  type: [String, Number, Array],
                  default: ''
              },
98bf25b3   梁灏   fixed #1286
133
              // 使用时,也得设置 value 才行
ddc35c9a   梁灏   fixed #952
134
135
136
137
              label: {
                  type: [String, Number, Array],
                  default: ''
              },
e355dd49   梁灏   add Select Component
138
139
140
141
142
143
144
145
146
147
148
149
150
              multiple: {
                  type: Boolean,
                  default: false
              },
              disabled: {
                  type: Boolean,
                  default: false
              },
              clearable: {
                  type: Boolean,
                  default: false
              },
              placeholder: {
e5337c81   梁灏   fixed some compon...
151
                  type: String
e355dd49   梁灏   add Select Component
152
153
154
155
156
157
158
159
              },
              filterable: {
                  type: Boolean,
                  default: false
              },
              filterMethod: {
                  type: Function
              },
01b54e30   梁灏   Select support re...
160
161
162
163
164
165
166
167
168
169
              remoteMethod: {
                  type: Function
              },
              loading: {
                  type: Boolean,
                  default: false
              },
              loadingText: {
                  type: String
              },
e355dd49   梁灏   add Select Component
170
171
              size: {
                  validator (value) {
6932b4d7   梁灏   update Page compo...
172
                      return oneOf(value, ['small', 'large', 'default']);
e355dd49   梁灏   add Select Component
173
174
175
176
177
                  }
              },
              labelInValue: {
                  type: Boolean,
                  default: false
294e2412   梁灏   update Select com...
178
179
              },
              notFoundText: {
e5337c81   梁灏   fixed some compon...
180
                  type: String
f89dd9c2   梁灏   Paeg、Select add p...
181
182
183
184
185
186
              },
              placement: {
                  validator (value) {
                      return oneOf(value, ['top', 'bottom']);
                  },
                  default: 'bottom'
595cfa72   梁灏   fixed #1187 #844 ...
187
188
189
190
              },
              transfer: {
                  type: Boolean,
                  default: false
fed3e09d   梁灏   add AutoComplete ...
191
192
193
194
195
              },
              // Use for AutoComplete
              autoComplete: {
                  type: Boolean,
                  default: false
0460a1e8   梁灏   fixed #812
196
197
198
              },
              name: {
                  type: String
acb79ba3   梁灏   fixed #433
199
200
201
              },
              elementId: {
                  type: String
e355dd49   梁灏   add Select Component
202
203
              }
          },
c9b86944   Sergio Crisostomo   Refactor Select!
204
205
206
207
          mounted(){
              this.$on('on-select-selected', this.onOptionClick);
  
              // set the initial values if there are any
7f63e58c   Sergio Crisostomo   Make possible for...
208
              if (this.values.length > 0 && !this.remote && this.selectOptions.length > 0){
c9b86944   Sergio Crisostomo   Refactor Select!
209
210
                  this.values = this.values.map(this.getOptionData);
              }
7f63e58c   Sergio Crisostomo   Make possible for...
211
212
213
214
  
              if (this.values.length > 0 && this.selectOptions.length === 0){
                  this.hasExpectedValue = this.values;
              }
c9b86944   Sergio Crisostomo   Refactor Select!
215
          },
e355dd49   梁灏   add Select Component
216
          data () {
c9b86944   Sergio Crisostomo   Refactor Select!
217
  
e355dd49   梁灏   add Select Component
218
219
              return {
                  prefixCls: prefixCls,
c9b86944   Sergio Crisostomo   Refactor Select!
220
221
                  values: this.getInitialValue(),
                  dropDownWidth: 0,
e355dd49   梁灏   add Select Component
222
                  visible: false,
c9b86944   Sergio Crisostomo   Refactor Select!
223
224
                  focusIndex: -1,
                  isFocused: false,
e355dd49   梁灏   add Select Component
225
                  query: '',
c9b86944   Sergio Crisostomo   Refactor Select!
226
227
228
229
230
                  initialLabel: this.label,
                  hasMouseHoverHead: false,
                  slotOptions: this.$slots.default,
                  caretPosition: -1,
                  lastRemoteQuery: '',
7f63e58c   Sergio Crisostomo   Make possible for...
231
                  hasExpectedValue: false,
45bcc14d   Sergio Crisostomo   prevent calling r...
232
                  preventRemoteCall: false,
b0893113   jingsam   :art: add eslint
233
              };
e355dd49   梁灏   add Select Component
234
235
236
237
          },
          computed: {
              classes () {
                  return [
4b7138b9   梁灏   fixed some bugs
238
                      `${prefixCls}`,
e355dd49   梁灏   add Select Component
239
                      {
4b7138b9   梁灏   fixed some bugs
240
241
242
243
244
245
                          [`${prefixCls}-visible`]: this.visible,
                          [`${prefixCls}-disabled`]: this.disabled,
                          [`${prefixCls}-multiple`]: this.multiple,
                          [`${prefixCls}-single`]: !this.multiple,
                          [`${prefixCls}-show-clear`]: this.showCloseIcon,
                          [`${prefixCls}-${this.size}`]: !!this.size
e355dd49   梁灏   add Select Component
246
                      }
b0893113   jingsam   :art: add eslint
247
                  ];
e355dd49   梁灏   add Select Component
248
              },
ecaf8d51   梁灏   Date add transfer...
249
250
251
              dropdownCls () {
                  return {
                      [prefixCls + '-dropdown-transfer']: this.transfer,
fed3e09d   梁灏   add AutoComplete ...
252
253
254
255
256
257
                      [prefixCls + '-multiple']: this.multiple && this.transfer,
                      ['ivu-auto-complete']: this.autoComplete,
                  };
              },
              selectionCls () {
                  return {
c9b86944   Sergio Crisostomo   Refactor Select!
258
259
                      [`${prefixCls}-selection`]: !this.autoComplete,
                      [`${prefixCls}-selection-focused`]: this.isFocused
ecaf8d51   梁灏   Date add transfer...
260
261
                  };
              },
e5337c81   梁灏   fixed some compon...
262
              localeNotFoundText () {
c9b86944   Sergio Crisostomo   Refactor Select!
263
                  if (typeof this.notFoundText === 'undefined') {
e5337c81   梁灏   fixed some compon...
264
265
266
267
                      return this.t('i.select.noMatch');
                  } else {
                      return this.notFoundText;
                  }
f89dd9c2   梁灏   Paeg、Select add p...
268
              },
01b54e30   梁灏   Select support re...
269
              localeLoadingText () {
c9b86944   Sergio Crisostomo   Refactor Select!
270
                  if (typeof this.loadingText === 'undefined') {
01b54e30   梁灏   Select support re...
271
272
273
274
275
                      return this.t('i.select.loading');
                  } else {
                      return this.loadingText;
                  }
              },
f89dd9c2   梁灏   Paeg、Select add p...
276
277
              transitionName () {
                  return this.placement === 'bottom' ? 'slide-up' : 'slide-down';
ec98f3c3   梁灏   update Select
278
279
280
              },
              dropVisible () {
                  let status = true;
bc348e7e   Sergio Crisostomo   adapt to auto-com...
281
282
                  const noOptions = !this.selectOptions || this.selectOptions.length === 0;
                  if (!this.loading && this.remote && this.query === '' && noOptions) status = false;
fed3e09d   梁灏   add AutoComplete ...
283
  
bc348e7e   Sergio Crisostomo   adapt to auto-com...
284
                  if (this.autoComplete && noOptions) status = false;
fed3e09d   梁灏   add AutoComplete ...
285
  
ec98f3c3   梁灏   update Select
286
                  return this.visible && status;
29264399   梁灏   update Select
287
              },
c9b86944   Sergio Crisostomo   Refactor Select!
288
289
              showNotFoundLabel () {
                  const {loading, remote, selectOptions} = this;
bc348e7e   Sergio Crisostomo   adapt to auto-com...
290
                  return selectOptions && selectOptions.length === 0 && (!remote || (remote && !loading));
e355dd49   梁灏   add Select Component
291
              },
c9b86944   Sergio Crisostomo   Refactor Select!
292
293
294
              publicValue(){
                  if (this.labelInValue){
                      return this.multiple ? this.values : this.values[0];
e355dd49   梁灏   add Select Component
295
                  } else {
c9b86944   Sergio Crisostomo   Refactor Select!
296
                      return this.multiple ? this.values.map(option => option.value) : (this.values[0] || {}).value;
e355dd49   梁灏   add Select Component
297
298
                  }
              },
c9b86944   Sergio Crisostomo   Refactor Select!
299
300
301
302
303
304
305
              canBeCleared(){
                  const uiStateMatch = this.hasMouseHoverHead || this.active;
                  const qualifiesForClear = !this.multiple && this.clearable;
                  return uiStateMatch && qualifiesForClear && this.reset; // we return a function
              },
              selectOptions() {
                  const selectOptions = [];
06a74f9e   Sergio Crisostomo   Allow select to n...
306
                  const slotOptions = (this.slotOptions || []);
c9b86944   Sergio Crisostomo   Refactor Select!
307
308
309
                  let optionCounter = -1;
                  const currentIndex = this.focusIndex;
                  const selectedValues = this.values.map(({value}) => value);
06a74f9e   Sergio Crisostomo   Allow select to n...
310
311
312
313
314
315
316
317
318
319
                  if (this.autoComplete) {
                      const copyChildren = (node, fn) => {
                          return {
                              ...node,
                              children: (node.children || []).map(fn).map(child => copyChildren(child, fn))
                          };
                      };
                      const autoCompleteOptions = extractOptions(slotOptions);
                      const selectedSlotOption = autoCompleteOptions[currentIndex];
  
aa21cdf9   Sergio Crisostomo   Process also shal...
320
321
322
323
324
325
326
                      return slotOptions.map(node => {
                          if (node === selectedSlotOption) return applyProp(node, 'isFocused', true);
                          return copyChildren(node, (child) => {
                              if (child !== selectedSlotOption) return child;
                              return applyProp(child, 'isFocused', true);
                          });
                      });
06a74f9e   Sergio Crisostomo   Allow select to n...
327
                  }
bc348e7e   Sergio Crisostomo   adapt to auto-com...
328
  
06a74f9e   Sergio Crisostomo   Allow select to n...
329
                  for (let option of slotOptions) {
e355dd49   梁灏   add Select Component
330
  
b6c069ca   Sergio Crisostomo   reset query if op...
331
332
                      const cOptions = option.componentOptions;
                      if (!cOptions) continue;
b6c069ca   Sergio Crisostomo   reset query if op...
333
334
                      if (cOptions.tag.match(optionGroupRegexp)){
                          let children = cOptions.children;
e355dd49   梁灏   add Select Component
335
  
c9b86944   Sergio Crisostomo   Refactor Select!
336
337
338
339
340
341
                          // remove filtered children
                          if (this.filterable){
                              children = children.filter(
                                  ({componentOptions}) => this.validateOption(componentOptions)
                              );
                          }
e355dd49   梁灏   add Select Component
342
  
b6c069ca   Sergio Crisostomo   reset query if op...
343
                          cOptions.children = children.map(opt => {
c9b86944   Sergio Crisostomo   Refactor Select!
344
345
346
                              optionCounter = optionCounter + 1;
                              return this.processOption(opt, selectedValues, optionCounter === currentIndex);
                          });
3e855e34   梁灏   fixed #46
347
  
c9b86944   Sergio Crisostomo   Refactor Select!
348
                          // keep the group if it still has children
b6c069ca   Sergio Crisostomo   reset query if op...
349
                          if (cOptions.children.length > 0) selectOptions.push({...option});
c9b86944   Sergio Crisostomo   Refactor Select!
350
351
                      } else {
                          // ignore option if not passing filter
b6c069ca   Sergio Crisostomo   reset query if op...
352
                          const optionPassesFilter = this.filterable ? this.validateOption(cOptions) : option;
c9b86944   Sergio Crisostomo   Refactor Select!
353
                          if (!optionPassesFilter) continue;
3e855e34   梁灏   fixed #46
354
  
c9b86944   Sergio Crisostomo   Refactor Select!
355
356
                          optionCounter = optionCounter + 1;
                          selectOptions.push(this.processOption(option, selectedValues, optionCounter === currentIndex));
3e855e34   梁灏   fixed #46
357
                      }
e355dd49   梁灏   add Select Component
358
359
                  }
  
c9b86944   Sergio Crisostomo   Refactor Select!
360
                  return selectOptions;
e355dd49   梁灏   add Select Component
361
              },
c9b86944   Sergio Crisostomo   Refactor Select!
362
              flatOptions(){
06a74f9e   Sergio Crisostomo   Allow select to n...
363
                  return extractOptions(this.selectOptions);
c9b86944   Sergio Crisostomo   Refactor Select!
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
              },
              selectTabindex(){
                  return this.disabled || this.filterable ? -1 : 0;
              },
              remote(){
                  return typeof this.remoteMethod === 'function';
              }
          },
          methods: {
              setQuery(query){ // PUBLIC API
                  if (query) {
                      this.onQueryChange(query);
                      return;
                  }
                  if (query === null) {
                      this.onQueryChange('');
                      this.values = [];
e355dd49   梁灏   add Select Component
381
382
                  }
              },
c9b86944   Sergio Crisostomo   Refactor Select!
383
384
385
386
387
              clearSingleSelect(){ // PUBLIC API
                  if (this.clearable) this.values = [];
              },
              getOptionData(value){
                  const option = this.flatOptions.find(({componentOptions}) => componentOptions.propsData.value === value);
7f63e58c   Sergio Crisostomo   Make possible for...
388
                  if (!option) return null;
c9b86944   Sergio Crisostomo   Refactor Select!
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
                  const textContent = option.componentOptions.children.reduce((str, child) => str + (child.text || ''), '');
                  const label = option.componentOptions.propsData.label || textContent || '';
                  return {
                      value: value,
                      label: label,
                  };
              },
              getInitialValue(){
                  const {multiple, value} = this;
                  let initialValue = Array.isArray(value) ? value : [value];
                  if (!multiple && (typeof initialValue[0] === 'undefined' || String(initialValue[0]).trim() === '')) initialValue = [];
                  return initialValue;
              },
              processOption(option, values, isFocused){
                  if (!option.componentOptions) return option;
                  const optionValue = option.componentOptions.propsData.value;
                  const disabled = option.componentOptions.propsData.disabled;
                  const isSelected = values.includes(optionValue);
  
                  const propsData = {
                      ...option.componentOptions.propsData,
                      selected: isSelected,
                      isFocused: isFocused,
                      disabled: typeof disabled === 'undefined' ? false : disabled !== false,
                  };
e355dd49   梁灏   add Select Component
414
  
c9b86944   Sergio Crisostomo   Refactor Select!
415
416
417
418
419
                  return {
                      ...option,
                      componentOptions: {
                          ...option.componentOptions,
                          propsData: propsData
e355dd49   梁灏   add Select Component
420
                      }
c9b86944   Sergio Crisostomo   Refactor Select!
421
422
                  };
              },
e355dd49   梁灏   add Select Component
423
  
c9b86944   Sergio Crisostomo   Refactor Select!
424
425
426
427
428
429
              validateOption({elm, propsData}){
                  const value = propsData.value;
                  const label = propsData.label || '';
                  const textContent = elm && elm.textContent || '';
                  const stringValues = JSON.stringify([value, label, textContent]);
                  return stringValues.toLowerCase().includes(this.query.toLowerCase());
e355dd49   梁灏   add Select Component
430
              },
d87ce40a   梁灏   update Select
431
  
c9b86944   Sergio Crisostomo   Refactor Select!
432
433
434
              toggleMenu (e, force) {
                  if (this.disabled || this.autoComplete) {
                      return false;
d87ce40a   梁灏   update Select
435
                  }
c9b86944   Sergio Crisostomo   Refactor Select!
436
                  this.focusIndex = -1;
d87ce40a   梁灏   update Select
437
  
c9b86944   Sergio Crisostomo   Refactor Select!
438
439
440
                  this.visible = typeof force !== 'undefined' ? force : !this.visible;
                  if (this.visible){
                      this.dropDownWidth = this.$el.getBoundingClientRect().width;
cf753854   Sergio Crisostomo   Corrections after...
441
                      this.broadcast('Drop', 'on-update-popper');
e4ce9917   梁灏   update Select com...
442
                  }
e355dd49   梁灏   add Select Component
443
              },
c9b86944   Sergio Crisostomo   Refactor Select!
444
445
              hideMenu () {
                  this.toggleMenu(null, false);
e355dd49   梁灏   add Select Component
446
              },
c9b86944   Sergio Crisostomo   Refactor Select!
447
448
449
450
              onClickOutside(event){
                  if (this.visible) {
  
                      if (this.filterable) {
ae7579e9   Sergio Crisostomo   Fix input getters...
451
                          const input = this.$el.querySelector('input[type="text"]');
c9b86944   Sergio Crisostomo   Refactor Select!
452
453
454
455
                          this.caretPosition = input.selectionStart;
                          this.$nextTick(() => {
                              const caretPosition = this.caretPosition === -1 ? input.value.length : this.caretPosition;
                              input.setSelectionRange(caretPosition, caretPosition);
e355dd49   梁灏   add Select Component
456
457
458
                          });
                      }
  
ae7579e9   Sergio Crisostomo   Fix input getters...
459
                      if (!this.autoComplete) event.stopPropagation();
c9b86944   Sergio Crisostomo   Refactor Select!
460
461
462
463
464
465
                      event.preventDefault();
                      this.hideMenu();
                      this.isFocused = true;
                  } else {
                      this.caretPosition = -1;
                      this.isFocused = false;
e355dd49   梁灏   add Select Component
466
467
                  }
              },
c9b86944   Sergio Crisostomo   Refactor Select!
468
469
              reset(){
                  this.values = [];
e355dd49   梁灏   add Select Component
470
471
              },
              handleKeydown (e) {
c9b86944   Sergio Crisostomo   Refactor Select!
472
473
474
475
                  if (e.key === 'Backspace'){
                      return; // so we don't call preventDefault
                  }
  
e355dd49   梁灏   add Select Component
476
                  if (this.visible) {
c9b86944   Sergio Crisostomo   Refactor Select!
477
478
479
480
481
                      e.preventDefault();
                      if (e.key === 'Tab'){
                          e.stopPropagation();
                      }
  
e355dd49   梁灏   add Select Component
482
                      // Esc slide-up
c9b86944   Sergio Crisostomo   Refactor Select!
483
                      if (e.key === 'Escape') {
e355dd49   梁灏   add Select Component
484
485
486
                          this.hideMenu();
                      }
                      // next
c9b86944   Sergio Crisostomo   Refactor Select!
487
488
                      if (e.key === 'ArrowUp') {
                          this.navigateOptions(-1);
e355dd49   梁灏   add Select Component
489
490
                      }
                      // prev
c9b86944   Sergio Crisostomo   Refactor Select!
491
492
                      if (e.key === 'ArrowDown') {
                          this.navigateOptions(1);
e355dd49   梁灏   add Select Component
493
494
                      }
                      // enter
c9b86944   Sergio Crisostomo   Refactor Select!
495
496
497
498
                      if (e.key === 'Enter' && this.focusIndex > -1) {
                          const optionComponent = this.flatOptions[this.focusIndex];
                          const option = this.getOptionData(optionComponent.componentOptions.propsData.value);
                          this.onOptionClick(option);
e355dd49   梁灏   add Select Component
499
                      }
c9b86944   Sergio Crisostomo   Refactor Select!
500
501
502
                  } else {
                      const keysThatCanOpenSelect = ['ArrowUp', 'ArrowDown'];
                      if (keysThatCanOpenSelect.includes(e.key)) this.toggleMenu(null, true);
e355dd49   梁灏   add Select Component
503
504
                  }
  
e355dd49   梁灏   add Select Component
505
  
c9b86944   Sergio Crisostomo   Refactor Select!
506
507
508
              },
              navigateOptions(direction){
                  const optionsLength = this.flatOptions.length - 1;
e4ebd304   梁灏   update Select com...
509
  
c9b86944   Sergio Crisostomo   Refactor Select!
510
511
512
                  let index = this.focusIndex + direction;
                  if (index < 0) index = optionsLength;
                  if (index > optionsLength) index = 0;
e355dd49   梁灏   add Select Component
513
  
c9b86944   Sergio Crisostomo   Refactor Select!
514
515
516
517
518
519
520
                  // find nearest option in case of disabled options in between
                  if (direction > 0){
                      let nearestActiveOption = -1;
                      for (let i = 0; i < this.flatOptions.length; i++){
                          const optionIsActive = !this.flatOptions[i].componentOptions.propsData.disabled;
                          if (optionIsActive) nearestActiveOption = i;
                          if (nearestActiveOption >= index) break;
e355dd49   梁灏   add Select Component
521
                      }
c9b86944   Sergio Crisostomo   Refactor Select!
522
523
524
525
526
527
528
                      index = nearestActiveOption;
                  } else {
                      let nearestActiveOption = this.flatOptions.length;
                      for (let i = optionsLength; i >= 0; i--){
                          const optionIsActive = !this.flatOptions[i].componentOptions.propsData.disabled;
                          if (optionIsActive) nearestActiveOption = i;
                          if (nearestActiveOption <= index) break;
e4ebd304   梁灏   update Select com...
529
                      }
c9b86944   Sergio Crisostomo   Refactor Select!
530
                      index = nearestActiveOption;
e355dd49   梁灏   add Select Component
531
                  }
e355dd49   梁灏   add Select Component
532
  
c9b86944   Sergio Crisostomo   Refactor Select!
533
                  this.focusIndex = index;
e4ebd304   梁灏   update Select com...
534
              },
c9b86944   Sergio Crisostomo   Refactor Select!
535
536
537
538
539
540
              onOptionClick(option) {
                  if (this.multiple){
  
                      // keep the query for remote select
                      if (this.remote) this.lastRemoteQuery = this.lastRemoteQuery || this.query;
                      else this.lastRemoteQuery = '';
e4ebd304   梁灏   update Select com...
541
  
c9b86944   Sergio Crisostomo   Refactor Select!
542
543
544
                      const valueIsSelected = this.values.find(({value}) => value === option.value);
                      if (valueIsSelected){
                          this.values = this.values.filter(({value}) => value !== option.value);
e4ebd304   梁灏   update Select com...
545
                      } else {
c9b86944   Sergio Crisostomo   Refactor Select!
546
                          this.values = this.values.concat(option);
e4ebd304   梁灏   update Select com...
547
                      }
c9b86944   Sergio Crisostomo   Refactor Select!
548
549
550
551
552
553
554
555
556
  
                      this.isFocused = true; // so we put back focus after clicking with mouse on option elements
                  } else {
                      this.values = [option];
                      this.lastRemoteQuery = '';
                      this.hideMenu();
                  }
  
                  if (this.filterable){
ae7579e9   Sergio Crisostomo   Fix input getters...
557
558
                      const inputField = this.$el.querySelector('input[type="text"]');
                      if (!this.autoComplete) this.$nextTick(() => inputField.focus());
e4ce9917   梁灏   update Select com...
559
                  }
88ef37f5   Aresn   fixed in multiple...
560
                  this.broadcast('Drop', 'on-update-popper');
3e855e34   梁灏   fixed #46
561
              },
c9b86944   Sergio Crisostomo   Refactor Select!
562
              onQueryChange(query) {
2f0b086d   梁灏   fixed #116
563
                  this.query = query;
c9b86944   Sergio Crisostomo   Refactor Select!
564
                  if (this.query.length > 0) this.visible = true;
9c3a3e7d   YikaJ   更新 Select 组件
565
              },
c9b86944   Sergio Crisostomo   Refactor Select!
566
567
568
              toggleHeaderFocus({type}){
                  if (this.disabled) {
                      return;
15b72d31   梁灏   fixed #566
569
                  }
c9b86944   Sergio Crisostomo   Refactor Select!
570
                  this.isFocused = type === 'focus';
98bf25b3   梁灏   fixed #1286
571
              },
c9b86944   Sergio Crisostomo   Refactor Select!
572
573
              updateSlotOptions(){
                  this.slotOptions = this.$slots.default;
e355dd49   梁灏   add Select Component
574
575
              }
          },
e355dd49   梁灏   add Select Component
576
          watch: {
c9b86944   Sergio Crisostomo   Refactor Select!
577
578
579
580
581
582
              value(value){
                  const {getInitialValue, getOptionData, publicValue} = this;
  
                  if (value === '') this.values = [];
                  else if (JSON.stringify(value) !== JSON.stringify(publicValue)) {
                      this.$nextTick(() => this.values = getInitialValue().map(getOptionData));
e355dd49   梁灏   add Select Component
583
                  }
c9b86944   Sergio Crisostomo   Refactor Select!
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
              },
              values(now, before){
                  const newValue = JSON.stringify(now);
                  const oldValue = JSON.stringify(before);
                  const shouldEmitInput = newValue !== oldValue;
  
                  if (shouldEmitInput) {
                      // v-model is always just the value, event with labelInValue === true
                      const vModelValue = this.labelInValue ?
                          (this.multiple ? this.publicValue.map(({value}) => value)
                          :
                          this.publicValue.value) : this.publicValue;
                      this.$emit('input', vModelValue); // to update v-model
                      this.$emit('on-change', this.publicValue);
                      this.dispatch('FormItem', 'on-form-change', this.publicValue);
219e5c92   梁灏   fixed #957
599
                  }
e355dd49   梁灏   add Select Component
600
              },
c9b86944   Sergio Crisostomo   Refactor Select!
601
602
603
604
              query (query) {
                  this.$emit('on-query-change', query);
                  const {remoteMethod, lastRemoteQuery} = this;
                  const hasValidQuery = query !== '' && (query !== lastRemoteQuery || !lastRemoteQuery);
45bcc14d   Sergio Crisostomo   prevent calling r...
605
606
                  const shouldCallRemoteMethod = remoteMethod && hasValidQuery && !this.preventRemoteCall;
                  this.preventRemoteCall = false; // remove the flag
c9b86944   Sergio Crisostomo   Refactor Select!
607
608
609
610
611
612
613
614
615
  
                  if (shouldCallRemoteMethod){
                      this.focusIndex = -1;
                      const promise = this.remoteMethod(query);
                      this.initialLabel = '';
                      if (promise && promise.then){
                          promise.then(options => {
                              if (options) this.options = options;
                          });
b7cf983e   梁灏   update Select com...
616
                      }
e355dd49   梁灏   add Select Component
617
                  }
c9b86944   Sergio Crisostomo   Refactor Select!
618
                  if (query !== '' && this.remote) this.lastRemoteQuery = query;
e4ebd304   梁灏   update Select com...
619
              },
c9b86944   Sergio Crisostomo   Refactor Select!
620
621
622
623
624
625
              loading(state){
                  if (state === false){
                      this.updateSlotOptions();
                  }
              },
              isFocused(focused){
ae7579e9   Sergio Crisostomo   Fix input getters...
626
                  const el = this.filterable ? this.$el.querySelector('input[type="text"]') : this.$el;
c9b86944   Sergio Crisostomo   Refactor Select!
627
                  el[this.isFocused ? 'focus' : 'blur']();
d8bb1771   windywany   let select compon...
628
  
c9b86944   Sergio Crisostomo   Refactor Select!
629
630
631
632
                  // restore query value in filterable single selects
                  const [selectedOption] = this.values;
                  if (selectedOption && this.filterable && !this.multiple && !focused){
                      const selectedLabel = selectedOption.label || selectedOption.value;
9ca6671c   Sergio Crisostomo   Check for selecte...
633
                      if (selectedLabel && this.query !== selectedLabel) {
45bcc14d   Sergio Crisostomo   prevent calling r...
634
635
636
                          this.preventRemoteCall = true;
                          this.query = selectedLabel;
                      }
c9b86944   Sergio Crisostomo   Refactor Select!
637
638
639
                  }
              },
              focusIndex(index){
06a74f9e   Sergio Crisostomo   Allow select to n...
640
                  if (index < 0 || this.autoComplete) return;
c9b86944   Sergio Crisostomo   Refactor Select!
641
642
643
644
645
                  // update scroll
                  const optionValue = this.flatOptions[index].componentOptions.propsData.value;
                  const optionInstance = findChild(this, ({$options}) => {
                      return $options.componentName === 'select-item' && $options.propsData.value === optionValue;
                  });
e4ce9917   梁灏   update Select com...
646
  
c9b86944   Sergio Crisostomo   Refactor Select!
647
648
649
650
651
652
653
                  let bottomOverflowDistance = optionInstance.$el.getBoundingClientRect().bottom - this.$refs.dropdown.$el.getBoundingClientRect().bottom;
                  let topOverflowDistance = optionInstance.$el.getBoundingClientRect().top - this.$refs.dropdown.$el.getBoundingClientRect().top;
                  if (bottomOverflowDistance > 0) {
                      this.$refs.dropdown.$el.scrollTop += bottomOverflowDistance;
                  }
                  if (topOverflowDistance < 0) {
                      this.$refs.dropdown.$el.scrollTop += topOverflowDistance;
01b54e30   梁灏   Select support re...
654
                  }
cf753854   Sergio Crisostomo   Corrections after...
655
656
657
              },
              dropVisible(open){
                  this.broadcast('Drop', open ? 'on-update-popper' : 'on-destroy-popper');
7f63e58c   Sergio Crisostomo   Make possible for...
658
              },
f7f65c84   Sergio Crisostomo   reset query only ...
659
              selectOptions(){
7f63e58c   Sergio Crisostomo   Make possible for...
660
661
662
663
                  if (this.hasExpectedValue){
                      this.values = this.values.map(this.getOptionData);
                      this.hasExpectedValue = false;
                  }
b6c069ca   Sergio Crisostomo   reset query if op...
664
  
f7f65c84   Sergio Crisostomo   reset query only ...
665
                  if (this.slotOptions && this.slotOptions.length === 0){
b6c069ca   Sergio Crisostomo   reset query if op...
666
667
                      this.query = '';
                  }
e355dd49   梁灏   add Select Component
668
669
              }
          }
b0893113   jingsam   :art: add eslint
670
      };
d6342fe1   jingsam   fixed ie bug
671
  </script>