Blame view

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