Blame view

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