Blame view

src/components/select/select.vue 25.9 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';
c9b86944   Sergio Crisostomo   Refactor Select!
83
84
85
86
87
88
89
90
91
92
93
      const optionGroupRegexp = /option\-?group/i;
  
      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
94
  
06a74f9e   Sergio Crisostomo   Allow select to n...
95
96
97
98
99
100
101
102
103
104
105
106
107
108
      const findOptionsInVNode = (node) => {
          const opts = node.componentOptions;
          if (opts && opts.tag === 'Option') return [node];
          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));
      }, []);
  
e355dd49   梁灏   add Select Component
109
      export default {
8f5b1686   梁灏   fixed #196
110
          name: 'iSelect',
e5337c81   梁灏   fixed some compon...
111
          mixins: [ Emitter, Locale ],
c9b86944   Sergio Crisostomo   Refactor Select!
112
113
          components: { FunctionalOptions, Drop, Icon, SelectHead },
          directives: { clickOutside: vClickOutside.directive, TransferDom },
e355dd49   梁灏   add Select Component
114
          props: {
4aec6a66   梁灏   support Select
115
              value: {
e355dd49   梁灏   add Select Component
116
117
118
                  type: [String, Number, Array],
                  default: ''
              },
98bf25b3   梁灏   fixed #1286
119
              // 使用时,也得设置 value 才行
ddc35c9a   梁灏   fixed #952
120
121
122
123
              label: {
                  type: [String, Number, Array],
                  default: ''
              },
e355dd49   梁灏   add Select Component
124
125
126
127
128
129
130
131
132
133
134
135
136
              multiple: {
                  type: Boolean,
                  default: false
              },
              disabled: {
                  type: Boolean,
                  default: false
              },
              clearable: {
                  type: Boolean,
                  default: false
              },
              placeholder: {
e5337c81   梁灏   fixed some compon...
137
                  type: String
e355dd49   梁灏   add Select Component
138
139
140
141
142
143
144
145
              },
              filterable: {
                  type: Boolean,
                  default: false
              },
              filterMethod: {
                  type: Function
              },
01b54e30   梁灏   Select support re...
146
147
148
149
150
151
152
153
154
155
              remoteMethod: {
                  type: Function
              },
              loading: {
                  type: Boolean,
                  default: false
              },
              loadingText: {
                  type: String
              },
e355dd49   梁灏   add Select Component
156
157
              size: {
                  validator (value) {
6932b4d7   梁灏   update Page compo...
158
                      return oneOf(value, ['small', 'large', 'default']);
e355dd49   梁灏   add Select Component
159
160
161
162
163
                  }
              },
              labelInValue: {
                  type: Boolean,
                  default: false
294e2412   梁灏   update Select com...
164
165
              },
              notFoundText: {
e5337c81   梁灏   fixed some compon...
166
                  type: String
f89dd9c2   梁灏   Paeg、Select add p...
167
168
169
170
171
172
              },
              placement: {
                  validator (value) {
                      return oneOf(value, ['top', 'bottom']);
                  },
                  default: 'bottom'
595cfa72   梁灏   fixed #1187 #844 ...
173
174
175
176
              },
              transfer: {
                  type: Boolean,
                  default: false
fed3e09d   梁灏   add AutoComplete ...
177
178
179
180
181
              },
              // Use for AutoComplete
              autoComplete: {
                  type: Boolean,
                  default: false
0460a1e8   梁灏   fixed #812
182
183
184
              },
              name: {
                  type: String
acb79ba3   梁灏   fixed #433
185
186
187
              },
              elementId: {
                  type: String
e355dd49   梁灏   add Select Component
188
189
              }
          },
c9b86944   Sergio Crisostomo   Refactor Select!
190
191
192
193
          mounted(){
              this.$on('on-select-selected', this.onOptionClick);
  
              // set the initial values if there are any
7f63e58c   Sergio Crisostomo   Make possible for...
194
              if (this.values.length > 0 && !this.remote && this.selectOptions.length > 0){
c9b86944   Sergio Crisostomo   Refactor Select!
195
196
                  this.values = this.values.map(this.getOptionData);
              }
7f63e58c   Sergio Crisostomo   Make possible for...
197
198
199
200
  
              if (this.values.length > 0 && this.selectOptions.length === 0){
                  this.hasExpectedValue = this.values;
              }
c9b86944   Sergio Crisostomo   Refactor Select!
201
          },
e355dd49   梁灏   add Select Component
202
          data () {
c9b86944   Sergio Crisostomo   Refactor Select!
203
  
e355dd49   梁灏   add Select Component
204
205
              return {
                  prefixCls: prefixCls,
c9b86944   Sergio Crisostomo   Refactor Select!
206
207
                  values: this.getInitialValue(),
                  dropDownWidth: 0,
e355dd49   梁灏   add Select Component
208
                  visible: false,
c9b86944   Sergio Crisostomo   Refactor Select!
209
210
                  focusIndex: -1,
                  isFocused: false,
e355dd49   梁灏   add Select Component
211
                  query: '',
c9b86944   Sergio Crisostomo   Refactor Select!
212
213
214
215
216
                  initialLabel: this.label,
                  hasMouseHoverHead: false,
                  slotOptions: this.$slots.default,
                  caretPosition: -1,
                  lastRemoteQuery: '',
7f63e58c   Sergio Crisostomo   Make possible for...
217
                  hasExpectedValue: false,
45bcc14d   Sergio Crisostomo   prevent calling r...
218
                  preventRemoteCall: false,
b0893113   jingsam   :art: add eslint
219
              };
e355dd49   梁灏   add Select Component
220
221
222
223
          },
          computed: {
              classes () {
                  return [
4b7138b9   梁灏   fixed some bugs
224
                      `${prefixCls}`,
e355dd49   梁灏   add Select Component
225
                      {
4b7138b9   梁灏   fixed some bugs
226
227
228
229
230
231
                          [`${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
232
                      }
b0893113   jingsam   :art: add eslint
233
                  ];
e355dd49   梁灏   add Select Component
234
              },
ecaf8d51   梁灏   Date add transfer...
235
236
237
              dropdownCls () {
                  return {
                      [prefixCls + '-dropdown-transfer']: this.transfer,
fed3e09d   梁灏   add AutoComplete ...
238
239
240
241
242
243
                      [prefixCls + '-multiple']: this.multiple && this.transfer,
                      ['ivu-auto-complete']: this.autoComplete,
                  };
              },
              selectionCls () {
                  return {
c9b86944   Sergio Crisostomo   Refactor Select!
244
245
                      [`${prefixCls}-selection`]: !this.autoComplete,
                      [`${prefixCls}-selection-focused`]: this.isFocused
ecaf8d51   梁灏   Date add transfer...
246
247
                  };
              },
e5337c81   梁灏   fixed some compon...
248
              localeNotFoundText () {
c9b86944   Sergio Crisostomo   Refactor Select!
249
                  if (typeof this.notFoundText === 'undefined') {
e5337c81   梁灏   fixed some compon...
250
251
252
253
                      return this.t('i.select.noMatch');
                  } else {
                      return this.notFoundText;
                  }
f89dd9c2   梁灏   Paeg、Select add p...
254
              },
01b54e30   梁灏   Select support re...
255
              localeLoadingText () {
c9b86944   Sergio Crisostomo   Refactor Select!
256
                  if (typeof this.loadingText === 'undefined') {
01b54e30   梁灏   Select support re...
257
258
259
260
261
                      return this.t('i.select.loading');
                  } else {
                      return this.loadingText;
                  }
              },
f89dd9c2   梁灏   Paeg、Select add p...
262
263
              transitionName () {
                  return this.placement === 'bottom' ? 'slide-up' : 'slide-down';
ec98f3c3   梁灏   update Select
264
265
266
              },
              dropVisible () {
                  let status = true;
bc348e7e   Sergio Crisostomo   adapt to auto-com...
267
268
                  const noOptions = !this.selectOptions || this.selectOptions.length === 0;
                  if (!this.loading && this.remote && this.query === '' && noOptions) status = false;
fed3e09d   梁灏   add AutoComplete ...
269
  
bc348e7e   Sergio Crisostomo   adapt to auto-com...
270
                  if (this.autoComplete && noOptions) status = false;
fed3e09d   梁灏   add AutoComplete ...
271
  
ec98f3c3   梁灏   update Select
272
                  return this.visible && status;
29264399   梁灏   update Select
273
              },
c9b86944   Sergio Crisostomo   Refactor Select!
274
275
              showNotFoundLabel () {
                  const {loading, remote, selectOptions} = this;
bc348e7e   Sergio Crisostomo   adapt to auto-com...
276
                  return selectOptions && selectOptions.length === 0 && (!remote || (remote && !loading));
e355dd49   梁灏   add Select Component
277
              },
c9b86944   Sergio Crisostomo   Refactor Select!
278
279
280
              publicValue(){
                  if (this.labelInValue){
                      return this.multiple ? this.values : this.values[0];
e355dd49   梁灏   add Select Component
281
                  } else {
c9b86944   Sergio Crisostomo   Refactor Select!
282
                      return this.multiple ? this.values.map(option => option.value) : (this.values[0] || {}).value;
e355dd49   梁灏   add Select Component
283
284
                  }
              },
c9b86944   Sergio Crisostomo   Refactor Select!
285
286
287
288
289
290
291
              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...
292
                  const slotOptions = (this.slotOptions || []);
c9b86944   Sergio Crisostomo   Refactor Select!
293
294
295
                  let optionCounter = -1;
                  const currentIndex = this.focusIndex;
                  const selectedValues = this.values.map(({value}) => value);
06a74f9e   Sergio Crisostomo   Allow select to n...
296
297
298
299
300
301
302
303
304
305
306
307
308
309
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];
  
                      return slotOptions.map(node => copyChildren(node, (child) => {
                          if (child !== selectedSlotOption) return child;
                          return {
                              ...child,
                              componentOptions: {
                                  ...child.componentOptions,
                                  propsData: {
                                      ...child.componentOptions.propsData,
                                      isFocused: true,
                                  }
                              }
                          };
                      }));
                  }
bc348e7e   Sergio Crisostomo   adapt to auto-com...
320
  
06a74f9e   Sergio Crisostomo   Allow select to n...
321
                  for (let option of slotOptions) {
e355dd49   梁灏   add Select Component
322
  
b6c069ca   Sergio Crisostomo   reset query if op...
323
324
                      const cOptions = option.componentOptions;
                      if (!cOptions) continue;
b6c069ca   Sergio Crisostomo   reset query if op...
325
326
                      if (cOptions.tag.match(optionGroupRegexp)){
                          let children = cOptions.children;
e355dd49   梁灏   add Select Component
327
  
c9b86944   Sergio Crisostomo   Refactor Select!
328
329
330
331
332
333
                          // remove filtered children
                          if (this.filterable){
                              children = children.filter(
                                  ({componentOptions}) => this.validateOption(componentOptions)
                              );
                          }
e355dd49   梁灏   add Select Component
334
  
b6c069ca   Sergio Crisostomo   reset query if op...
335
                          cOptions.children = children.map(opt => {
c9b86944   Sergio Crisostomo   Refactor Select!
336
337
338
                              optionCounter = optionCounter + 1;
                              return this.processOption(opt, selectedValues, optionCounter === currentIndex);
                          });
3e855e34   梁灏   fixed #46
339
  
c9b86944   Sergio Crisostomo   Refactor Select!
340
                          // keep the group if it still has children
b6c069ca   Sergio Crisostomo   reset query if op...
341
                          if (cOptions.children.length > 0) selectOptions.push({...option});
c9b86944   Sergio Crisostomo   Refactor Select!
342
343
                      } else {
                          // ignore option if not passing filter
b6c069ca   Sergio Crisostomo   reset query if op...
344
                          const optionPassesFilter = this.filterable ? this.validateOption(cOptions) : option;
c9b86944   Sergio Crisostomo   Refactor Select!
345
                          if (!optionPassesFilter) continue;
3e855e34   梁灏   fixed #46
346
  
c9b86944   Sergio Crisostomo   Refactor Select!
347
348
                          optionCounter = optionCounter + 1;
                          selectOptions.push(this.processOption(option, selectedValues, optionCounter === currentIndex));
3e855e34   梁灏   fixed #46
349
                      }
e355dd49   梁灏   add Select Component
350
351
                  }
  
c9b86944   Sergio Crisostomo   Refactor Select!
352
                  return selectOptions;
e355dd49   梁灏   add Select Component
353
              },
c9b86944   Sergio Crisostomo   Refactor Select!
354
              flatOptions(){
06a74f9e   Sergio Crisostomo   Allow select to n...
355
                  return extractOptions(this.selectOptions);
c9b86944   Sergio Crisostomo   Refactor Select!
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
              },
              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
373
374
                  }
              },
c9b86944   Sergio Crisostomo   Refactor Select!
375
376
377
378
379
              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...
380
                  if (!option) return null;
c9b86944   Sergio Crisostomo   Refactor Select!
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
                  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
406
  
c9b86944   Sergio Crisostomo   Refactor Select!
407
408
409
410
411
                  return {
                      ...option,
                      componentOptions: {
                          ...option.componentOptions,
                          propsData: propsData
e355dd49   梁灏   add Select Component
412
                      }
c9b86944   Sergio Crisostomo   Refactor Select!
413
414
                  };
              },
e355dd49   梁灏   add Select Component
415
  
c9b86944   Sergio Crisostomo   Refactor Select!
416
417
418
419
420
421
              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
422
              },
d87ce40a   梁灏   update Select
423
  
c9b86944   Sergio Crisostomo   Refactor Select!
424
425
426
              toggleMenu (e, force) {
                  if (this.disabled || this.autoComplete) {
                      return false;
d87ce40a   梁灏   update Select
427
                  }
c9b86944   Sergio Crisostomo   Refactor Select!
428
                  this.focusIndex = -1;
d87ce40a   梁灏   update Select
429
  
c9b86944   Sergio Crisostomo   Refactor Select!
430
431
432
                  this.visible = typeof force !== 'undefined' ? force : !this.visible;
                  if (this.visible){
                      this.dropDownWidth = this.$el.getBoundingClientRect().width;
cf753854   Sergio Crisostomo   Corrections after...
433
                      this.broadcast('Drop', 'on-update-popper');
e4ce9917   梁灏   update Select com...
434
                  }
e355dd49   梁灏   add Select Component
435
              },
c9b86944   Sergio Crisostomo   Refactor Select!
436
437
              hideMenu () {
                  this.toggleMenu(null, false);
e355dd49   梁灏   add Select Component
438
              },
c9b86944   Sergio Crisostomo   Refactor Select!
439
440
441
442
              onClickOutside(event){
                  if (this.visible) {
  
                      if (this.filterable) {
ae7579e9   Sergio Crisostomo   Fix input getters...
443
                          const input = this.$el.querySelector('input[type="text"]');
c9b86944   Sergio Crisostomo   Refactor Select!
444
445
446
447
                          this.caretPosition = input.selectionStart;
                          this.$nextTick(() => {
                              const caretPosition = this.caretPosition === -1 ? input.value.length : this.caretPosition;
                              input.setSelectionRange(caretPosition, caretPosition);
e355dd49   梁灏   add Select Component
448
449
450
                          });
                      }
  
ae7579e9   Sergio Crisostomo   Fix input getters...
451
                      if (!this.autoComplete) event.stopPropagation();
c9b86944   Sergio Crisostomo   Refactor Select!
452
453
454
455
456
457
                      event.preventDefault();
                      this.hideMenu();
                      this.isFocused = true;
                  } else {
                      this.caretPosition = -1;
                      this.isFocused = false;
e355dd49   梁灏   add Select Component
458
459
                  }
              },
c9b86944   Sergio Crisostomo   Refactor Select!
460
461
              reset(){
                  this.values = [];
e355dd49   梁灏   add Select Component
462
463
              },
              handleKeydown (e) {
c9b86944   Sergio Crisostomo   Refactor Select!
464
465
466
467
                  if (e.key === 'Backspace'){
                      return; // so we don't call preventDefault
                  }
  
e355dd49   梁灏   add Select Component
468
                  if (this.visible) {
c9b86944   Sergio Crisostomo   Refactor Select!
469
470
471
472
473
                      e.preventDefault();
                      if (e.key === 'Tab'){
                          e.stopPropagation();
                      }
  
e355dd49   梁灏   add Select Component
474
                      // Esc slide-up
c9b86944   Sergio Crisostomo   Refactor Select!
475
                      if (e.key === 'Escape') {
e355dd49   梁灏   add Select Component
476
477
478
                          this.hideMenu();
                      }
                      // next
c9b86944   Sergio Crisostomo   Refactor Select!
479
480
                      if (e.key === 'ArrowUp') {
                          this.navigateOptions(-1);
e355dd49   梁灏   add Select Component
481
482
                      }
                      // prev
c9b86944   Sergio Crisostomo   Refactor Select!
483
484
                      if (e.key === 'ArrowDown') {
                          this.navigateOptions(1);
e355dd49   梁灏   add Select Component
485
486
                      }
                      // enter
c9b86944   Sergio Crisostomo   Refactor Select!
487
488
489
490
                      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
491
                      }
c9b86944   Sergio Crisostomo   Refactor Select!
492
493
494
                  } else {
                      const keysThatCanOpenSelect = ['ArrowUp', 'ArrowDown'];
                      if (keysThatCanOpenSelect.includes(e.key)) this.toggleMenu(null, true);
e355dd49   梁灏   add Select Component
495
496
                  }
  
e355dd49   梁灏   add Select Component
497
  
c9b86944   Sergio Crisostomo   Refactor Select!
498
499
500
              },
              navigateOptions(direction){
                  const optionsLength = this.flatOptions.length - 1;
e4ebd304   梁灏   update Select com...
501
  
c9b86944   Sergio Crisostomo   Refactor Select!
502
503
504
                  let index = this.focusIndex + direction;
                  if (index < 0) index = optionsLength;
                  if (index > optionsLength) index = 0;
e355dd49   梁灏   add Select Component
505
  
c9b86944   Sergio Crisostomo   Refactor Select!
506
507
508
509
510
511
512
                  // 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
513
                      }
c9b86944   Sergio Crisostomo   Refactor Select!
514
515
516
517
518
519
520
                      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...
521
                      }
c9b86944   Sergio Crisostomo   Refactor Select!
522
                      index = nearestActiveOption;
e355dd49   梁灏   add Select Component
523
                  }
e355dd49   梁灏   add Select Component
524
  
c9b86944   Sergio Crisostomo   Refactor Select!
525
                  this.focusIndex = index;
e4ebd304   梁灏   update Select com...
526
              },
c9b86944   Sergio Crisostomo   Refactor Select!
527
528
529
530
531
532
              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...
533
  
c9b86944   Sergio Crisostomo   Refactor Select!
534
535
536
                      const valueIsSelected = this.values.find(({value}) => value === option.value);
                      if (valueIsSelected){
                          this.values = this.values.filter(({value}) => value !== option.value);
e4ebd304   梁灏   update Select com...
537
                      } else {
c9b86944   Sergio Crisostomo   Refactor Select!
538
                          this.values = this.values.concat(option);
e4ebd304   梁灏   update Select com...
539
                      }
c9b86944   Sergio Crisostomo   Refactor Select!
540
541
542
543
544
545
546
547
548
  
                      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...
549
550
                      const inputField = this.$el.querySelector('input[type="text"]');
                      if (!this.autoComplete) this.$nextTick(() => inputField.focus());
e4ce9917   梁灏   update Select com...
551
                  }
88ef37f5   Aresn   fixed in multiple...
552
                  this.broadcast('Drop', 'on-update-popper');
3e855e34   梁灏   fixed #46
553
              },
c9b86944   Sergio Crisostomo   Refactor Select!
554
              onQueryChange(query) {
2f0b086d   梁灏   fixed #116
555
                  this.query = query;
c9b86944   Sergio Crisostomo   Refactor Select!
556
                  if (this.query.length > 0) this.visible = true;
9c3a3e7d   YikaJ   更新 Select 组件
557
              },
c9b86944   Sergio Crisostomo   Refactor Select!
558
559
560
              toggleHeaderFocus({type}){
                  if (this.disabled) {
                      return;
15b72d31   梁灏   fixed #566
561
                  }
c9b86944   Sergio Crisostomo   Refactor Select!
562
                  this.isFocused = type === 'focus';
98bf25b3   梁灏   fixed #1286
563
              },
c9b86944   Sergio Crisostomo   Refactor Select!
564
565
              updateSlotOptions(){
                  this.slotOptions = this.$slots.default;
e355dd49   梁灏   add Select Component
566
567
              }
          },
e355dd49   梁灏   add Select Component
568
          watch: {
c9b86944   Sergio Crisostomo   Refactor Select!
569
570
571
572
573
574
              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
575
                  }
c9b86944   Sergio Crisostomo   Refactor Select!
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
              },
              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
591
                  }
e355dd49   梁灏   add Select Component
592
              },
c9b86944   Sergio Crisostomo   Refactor Select!
593
594
595
596
              query (query) {
                  this.$emit('on-query-change', query);
                  const {remoteMethod, lastRemoteQuery} = this;
                  const hasValidQuery = query !== '' && (query !== lastRemoteQuery || !lastRemoteQuery);
45bcc14d   Sergio Crisostomo   prevent calling r...
597
598
                  const shouldCallRemoteMethod = remoteMethod && hasValidQuery && !this.preventRemoteCall;
                  this.preventRemoteCall = false; // remove the flag
c9b86944   Sergio Crisostomo   Refactor Select!
599
600
601
602
603
604
605
606
607
  
                  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...
608
                      }
e355dd49   梁灏   add Select Component
609
                  }
c9b86944   Sergio Crisostomo   Refactor Select!
610
                  if (query !== '' && this.remote) this.lastRemoteQuery = query;
e4ebd304   梁灏   update Select com...
611
              },
c9b86944   Sergio Crisostomo   Refactor Select!
612
613
614
615
616
617
              loading(state){
                  if (state === false){
                      this.updateSlotOptions();
                  }
              },
              isFocused(focused){
ae7579e9   Sergio Crisostomo   Fix input getters...
618
                  const el = this.filterable ? this.$el.querySelector('input[type="text"]') : this.$el;
c9b86944   Sergio Crisostomo   Refactor Select!
619
                  el[this.isFocused ? 'focus' : 'blur']();
d8bb1771   windywany   let select compon...
620
  
c9b86944   Sergio Crisostomo   Refactor Select!
621
622
623
624
                  // 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...
625
                      if (selectedLabel && this.query !== selectedLabel) {
45bcc14d   Sergio Crisostomo   prevent calling r...
626
627
628
                          this.preventRemoteCall = true;
                          this.query = selectedLabel;
                      }
c9b86944   Sergio Crisostomo   Refactor Select!
629
630
631
                  }
              },
              focusIndex(index){
06a74f9e   Sergio Crisostomo   Allow select to n...
632
                  if (index < 0 || this.autoComplete) return;
c9b86944   Sergio Crisostomo   Refactor Select!
633
634
635
636
637
                  // 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...
638
  
c9b86944   Sergio Crisostomo   Refactor Select!
639
640
641
642
643
644
645
                  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...
646
                  }
cf753854   Sergio Crisostomo   Corrections after...
647
648
649
              },
              dropVisible(open){
                  this.broadcast('Drop', open ? 'on-update-popper' : 'on-destroy-popper');
7f63e58c   Sergio Crisostomo   Make possible for...
650
              },
f7f65c84   Sergio Crisostomo   reset query only ...
651
              selectOptions(){
7f63e58c   Sergio Crisostomo   Make possible for...
652
653
654
655
                  if (this.hasExpectedValue){
                      this.values = this.values.map(this.getOptionData);
                      this.hasExpectedValue = false;
                  }
b6c069ca   Sergio Crisostomo   reset query if op...
656
  
f7f65c84   Sergio Crisostomo   reset query only ...
657
                  if (this.slotOptions && this.slotOptions.length === 0){
b6c069ca   Sergio Crisostomo   reset query if op...
658
659
                      this.query = '';
                  }
e355dd49   梁灏   add Select Component
660
661
              }
          }
b0893113   jingsam   :art: add eslint
662
      };
d6342fe1   jingsam   fixed ie bug
663
  </script>