Blame view

src/components/slider/slider.vue 14.8 KB
36febc3c   梁灏   add Slider
1
2
  <template>
      <div :class="classes">
69576f47   梁灏   add Slider component
3
4
5
6
7
          <Input-number
              v-if="!range && showInput"
              :min="min"
              :max="max"
              :step="step"
e3549149   Sergio Crisostomo   normalise public ...
8
              :value="exportValue[0]"
69576f47   梁灏   add Slider component
9
10
              :disabled="disabled"
              @on-change="handleInputChange"></Input-number>
791d254e   Graham Fairweather   Slider: Keyboard ...
11
12
13
14
          <div
              :class="[prefixCls + '-wrap']"
              ref="slider" @click.self="sliderClick"
          >
e3549149   Sergio Crisostomo   normalise public ...
15
              <input type="hidden" :name="name" :value="exportValue">
36febc3c   梁灏   add Slider
16
              <template v-if="showStops">
791d254e   Graham Fairweather   Slider: Keyboard ...
17
18
19
20
21
22
                  <div
                      :class="[prefixCls + '-stop']"
                      v-for="item in stops"
                      :style="{ 'left': item + '%' }"
                      @click.self="sliderClick"
                  ></div>
36febc3c   梁灏   add Slider
23
              </template>
791d254e   Graham Fairweather   Slider: Keyboard ...
24
25
26
27
              <div
                  :class="[prefixCls + '-bar']"
                  :style="barStyle"
                  @click.self="sliderClick"></div>
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
28
29
30
31
32
              <div
                  :class="[prefixCls + '-button-wrap']"
                  :style="{left: minPosition + '%'}"
                  @touchstart="onPointerDown($event, 'min')"
                  @mousedown="onPointerDown($event, 'min')">
791d254e   Graham Fairweather   Slider: Keyboard ...
33
34
35
36
37
38
39
40
41
42
43
                  <Tooltip
                      :controlled="pointerDown === 'min'"
                      placement="top"
                      :content="tipFormat(exportValue[0])"
                      :disabled="tipDisabled"
                      :always="showTip === 'always'"
                      ref="minTooltip"
                  >
                      <div
                          :class="minButtonClasses"
                          tabindex="0"
5cb6ce9e   梁灏   Slider add Toolti...
44
45
                          @focus="handleFocus('min')"
                          @blur="handleBlur('min')"
791d254e   Graham Fairweather   Slider: Keyboard ...
46
47
48
49
50
                          @keydown.left="onKeyLeft($event, 'min')"
                          @keydown.down="onKeyLeft($event, 'min')"
                          @keydown.right="onKeyRight($event, 'min')"
                          @keydown.up="onKeyRight($event, 'min')"
                      ></div>
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
51
52
53
54
55
56
57
                  </Tooltip>
              </div>
              <div v-if="range"
                   :class="[prefixCls + '-button-wrap']"
                   :style="{left: maxPosition + '%'}"
                   @touchstart="onPointerDown($event, 'max')"
                   @mousedown="onPointerDown($event, 'max')">
791d254e   Graham Fairweather   Slider: Keyboard ...
58
59
60
61
62
63
64
65
66
67
68
                  <Tooltip
                      :controlled="pointerDown === 'max'"
                      placement="top"
                      :content="tipFormat(exportValue[1])"
                      :disabled="tipDisabled"
                      :always="showTip === 'always'"
                      ref="maxTooltip"
                  >
                      <div
                          :class="maxButtonClasses"
                          tabindex="0"
5cb6ce9e   梁灏   Slider add Toolti...
69
70
                          @focus="handleFocus('max')"
                          @blur="handleBlur('max')"
791d254e   Graham Fairweather   Slider: Keyboard ...
71
72
73
74
75
                          @keydown.left="onKeyLeft($event, 'max')"
                          @keydown.down="onKeyLeft($event, 'max')"
                          @keydown.right="onKeyRight($event, 'max')"
                          @keydown.up="onKeyRight($event, 'max')"
                      ></div>
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
76
77
                  </Tooltip>
              </div>
36febc3c   梁灏   add Slider
78
79
80
81
82
83
          </div>
      </div>
  </template>
  <script>
      import InputNumber from '../../components/input-number/input-number.vue';
      import Tooltip from '../../components/tooltip/tooltip.vue';
59872199   Rijn   added show-tip to...
84
      import { getStyle, oneOf } from '../../utils/assist';
825ed580   梁灏   fixed bug
85
      import { on, off } from '../../utils/dom';
cd78c9c4   梁灏   some comps suppor...
86
      import Emitter from '../../mixins/emitter';
36febc3c   梁灏   add Slider
87
88
89
90
  
      const prefixCls = 'ivu-slider';
  
      export default {
b1c118d8   梁灏   support Dropdown
91
          name: 'Slider',
cd78c9c4   梁灏   some comps suppor...
92
          mixins: [ Emitter ],
36febc3c   梁灏   add Slider
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
          components: { InputNumber, Tooltip },
          props: {
              min: {
                  type: Number,
                  default: 0
              },
              max: {
                  type: Number,
                  default: 100
              },
              step: {
                  type: Number,
                  default: 1
              },
              range: {
                  type: Boolean,
                  default: false
              },
              value: {
                  type: [Number, Array],
                  default: 0
              },
              disabled: {
                  type: Boolean,
                  default: false
              },
              showInput: {
                  type: Boolean,
                  default: false
              },
              showStops: {
                  type: Boolean,
                  default: false
              },
              tipFormat: {
                  type: Function,
                  default (val) {
                      return val;
                  }
59872199   Rijn   added show-tip to...
132
133
134
135
136
137
138
              },
              showTip: {
                  type: String,
                  default: 'hover',
                  validator (value) {
                      return oneOf(value, ['hover', 'always', 'never']);
                  }
0460a1e8   梁灏   fixed #812
139
140
141
              },
              name: {
                  type: String
36febc3c   梁灏   add Slider
142
143
144
              }
          },
          data () {
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
145
              const val = this.checkLimits(Array.isArray(this.value) ? this.value : [this.value]);
36febc3c   梁灏   add Slider
146
              return {
69576f47   梁灏   add Slider component
147
                  prefixCls: prefixCls,
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
148
                  currentValue: val,
69576f47   梁灏   add Slider component
149
                  dragging: false,
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
150
                  pointerDown: '',
69576f47   梁灏   add Slider component
151
152
153
                  startX: 0,
                  currentX: 0,
                  startPos: 0,
42ab875d   miomio-xiao   fix Slider not em...
154
                  oldValue: [...val],
791d254e   Graham Fairweather   Slider: Keyboard ...
155
156
157
158
                  valueIndex: {
                      min: 0,
                      max: 1,
                  },
b0893113   jingsam   :art: add eslint
159
              };
36febc3c   梁灏   add Slider
160
          },
1c803cdf   梁灏   support Slider
161
162
          watch: {
              value (val) {
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
163
164
165
166
                  val = this.checkLimits(Array.isArray(val) ? val : [val]);
                  if (val[0] !== this.currentValue[0] || val[1] !== this.currentValue[1]) {
                      this.currentValue = val;
                  }
1c803cdf   梁灏   support Slider
167
              },
e3549149   Sergio Crisostomo   normalise public ...
168
              exportValue (values) {
1c803cdf   梁灏   support Slider
169
                  this.$nextTick(() => {
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
170
                      this.$refs.minTooltip.updatePopper();
1c803cdf   梁灏   support Slider
171
                      if (this.range) {
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
172
                          this.$refs.maxTooltip.updatePopper();
1c803cdf   梁灏   support Slider
173
174
                      }
                  });
e3549149   Sergio Crisostomo   normalise public ...
175
176
177
                  const value = this.range ? values : values[0];
                  this.$emit('input', value);
                  this.$emit('on-input', value);
1c803cdf   梁灏   support Slider
178
179
              }
          },
36febc3c   梁灏   add Slider
180
181
182
183
184
          computed: {
              classes () {
                  return [
                      `${prefixCls}`,
                      {
69576f47   梁灏   add Slider component
185
                          [`${prefixCls}-input`]: this.showInput && !this.range,
36febc3c   梁灏   add Slider
186
187
188
                          [`${prefixCls}-range`]: this.range,
                          [`${prefixCls}-disabled`]: this.disabled
                      }
b0893113   jingsam   :art: add eslint
189
                  ];
36febc3c   梁灏   add Slider
190
              },
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
191
              minButtonClasses () {
69576f47   梁灏   add Slider component
192
193
194
                  return [
                      `${prefixCls}-button`,
                      {
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
195
                          [`${prefixCls}-button-dragging`]: this.pointerDown === 'min'
69576f47   梁灏   add Slider component
196
197
198
                      }
                  ];
              },
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
199
              maxButtonClasses () {
69576f47   梁灏   add Slider component
200
201
202
                  return [
                      `${prefixCls}-button`,
                      {
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
203
                          [`${prefixCls}-button-dragging`]: this.pointerDown === 'max'
69576f47   梁灏   add Slider component
204
205
206
                      }
                  ];
              },
e3549149   Sergio Crisostomo   normalise public ...
207
208
209
210
              exportValue(){
                  const decimalCases = (String(this.step).split('.')[1] || '').length;
                  return this.currentValue.map(nr => Number(nr.toFixed(decimalCases)));
              },
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
211
212
              minPosition () {
                  const val = this.currentValue;
965b6d8e   Sergio Crisostomo   Fix slider for m...
213
                  return (val[0] - this.min) / this.valueRange * 100;
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
214
215
216
217
              },
              maxPosition: function () {
                  const val = this.currentValue;
  
965b6d8e   Sergio Crisostomo   Fix slider for m...
218
                  return (val[1] - this.min) / this.valueRange * 100;
69576f47   梁灏   add Slider component
219
              },
36febc3c   梁灏   add Slider
220
              barStyle () {
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
221
                  const style = {
965b6d8e   Sergio Crisostomo   Fix slider for m...
222
                      width: (this.currentValue[0] - this.min) / this.valueRange * 100 + '%'
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
223
                  };
36febc3c   梁灏   add Slider
224
225
  
                  if (this.range) {
965b6d8e   Sergio Crisostomo   Fix slider for m...
226
227
                      style.left = (this.currentValue[0] - this.min) / this.valueRange * 100 + '%';
                      style.width = (this.currentValue[1] - this.currentValue[0]) / this.valueRange * 100 + '%';
36febc3c   梁灏   add Slider
228
229
230
231
                  }
  
                  return style;
              },
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
232
              stops () {
965b6d8e   Sergio Crisostomo   Fix slider for m...
233
                  let stopCount = this.valueRange / this.step;
41d90ccf   梁灏   Slider can show s...
234
                  let result = [];
965b6d8e   Sergio Crisostomo   Fix slider for m...
235
                  let stepWidth = 100 * this.step / this.valueRange;
41d90ccf   梁灏   Slider can show s...
236
237
238
239
                  for (let i = 1; i < stopCount; i++) {
                      result.push(i * stepWidth);
                  }
                  return result;
69576f47   梁灏   add Slider component
240
241
              },
              sliderWidth () {
1c803cdf   梁灏   support Slider
242
                  return parseInt(getStyle(this.$refs.slider, 'width'), 10);
59872199   Rijn   added show-tip to...
243
244
              },
              tipDisabled () {
1c803cdf   梁灏   support Slider
245
                  return this.tipFormat(this.currentValue[0]) === null || this.showTip === 'never';
965b6d8e   Sergio Crisostomo   Fix slider for m...
246
247
248
              },
              valueRange(){
                  return this.max - this.min;
36febc3c   梁灏   add Slider
249
250
251
              }
          },
          methods: {
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
252
253
              getPointerX (e) {
                  return e.type.indexOf('touch') !== -1 ? e.touches[0].clientX : e.clientX;
69576f47   梁灏   add Slider component
254
              },
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
255
              checkLimits ([min, max]) {
965b6d8e   Sergio Crisostomo   Fix slider for m...
256
257
                  min = Math.max(this.min, min);
                  min = Math.min(this.max, min);
36febc3c   梁灏   add Slider
258
  
965b6d8e   Sergio Crisostomo   Fix slider for m...
259
260
                  max = Math.max(this.min, min, max);
                  max = Math.min(this.max, max);
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
261
                  return [min, max];
69576f47   梁灏   add Slider component
262
              },
791d254e   Graham Fairweather   Slider: Keyboard ...
263
              getCurrentValue (event, type) {
5cb6ce9e   梁灏   Slider add Toolti...
264
265
266
                  if (this.disabled) {
                      return;
                  }
791d254e   Graham Fairweather   Slider: Keyboard ...
267
  
5cb6ce9e   梁灏   Slider add Toolti...
268
269
270
271
                  const index = this.valueIndex[type];
                  if (typeof index === 'undefined') {
                      return;
                  }
791d254e   Graham Fairweather   Slider: Keyboard ...
272
  
5cb6ce9e   梁灏   Slider add Toolti...
273
                  return this.currentValue[index];
791d254e   Graham Fairweather   Slider: Keyboard ...
274
275
              },
              onKeyLeft (event, type) {
5cb6ce9e   梁灏   Slider add Toolti...
276
277
278
279
                  const value = this.getCurrentValue(event, type);
                  if (Number.isFinite(value)) {
                      this.changeButtonPosition(value - this.step, type);
                  }
791d254e   Graham Fairweather   Slider: Keyboard ...
280
281
              },
              onKeyRight (event, type) {
5cb6ce9e   梁灏   Slider add Toolti...
282
283
284
285
                  const value = this.getCurrentValue(event, type);
                  if (Number.isFinite(value)) {
                      this.changeButtonPosition(value + this.step, type);
                  }
791d254e   Graham Fairweather   Slider: Keyboard ...
286
              },
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
287
              onPointerDown (event, type) {
69576f47   梁灏   add Slider component
288
                  if (this.disabled) return;
f2be585e   梁灏   optimize Slider w...
289
                  event.preventDefault();
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
290
291
292
293
294
295
296
                  this.pointerDown = type;
  
                  this.onPointerDragStart(event);
                  on(window, 'mousemove', this.onPointerDrag);
                  on(window, 'touchmove', this.onPointerDrag);
                  on(window, 'mouseup', this.onPointerDragEnd);
                  on(window, 'touchend', this.onPointerDragEnd);
69576f47   梁灏   add Slider component
297
              },
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
298
              onPointerDragStart (event) {
ce4c0faa   oustn   修复 Slider 滑动按钮单击时...
299
                  this.dragging = false;
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
300
                  this.startX = this.getPointerX(event);
965b6d8e   Sergio Crisostomo   Fix slider for m...
301
                  this.startPos = (this[`${this.pointerDown}Position`] * this.valueRange / 100) + this.min;
69576f47   梁灏   add Slider component
302
              },
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
303
              onPointerDrag (event) {
ce4c0faa   oustn   修复 Slider 滑动按钮单击时...
304
                  this.dragging = true;
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
305
306
                  this.$refs[`${this.pointerDown}Tooltip`].visible = true;
                  this.currentX = this.getPointerX(event);
965b6d8e   Sergio Crisostomo   Fix slider for m...
307
                  const diff = (this.currentX - this.startX) / this.sliderWidth * this.valueRange;
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
308
  
965b6d8e   Sergio Crisostomo   Fix slider for m...
309
                  this.changeButtonPosition(this.startPos + diff);
69576f47   梁灏   add Slider component
310
              },
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
311
              onPointerDragEnd () {
69576f47   梁灏   add Slider component
312
313
                  if (this.dragging) {
                      this.dragging = false;
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
314
                      this.$refs[`${this.pointerDown}Tooltip`].visible = false;
b964efae   Sergio Crisostomo   Emit change on po...
315
                      this.emitChange();
69576f47   梁灏   add Slider component
316
                  }
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
317
318
319
320
321
322
  
                  this.pointerDown = '';
                  off(window, 'mousemove', this.onPointerDrag);
                  off(window, 'touchmove', this.onPointerDrag);
                  off(window, 'mouseup', this.onPointerDragEnd);
                  off(window, 'touchend', this.onPointerDragEnd);
69576f47   梁灏   add Slider component
323
              },
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
324
              changeButtonPosition (newPos, forceType) {
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
325
326
327
328
                  const type = forceType || this.pointerDown;
                  const index = type === 'min' ? 0 : 1;
                  if (type === 'min') newPos = this.checkLimits([newPos, this.maxPosition])[0];
                  else newPos = this.checkLimits([this.minPosition, newPos])[1];
d4c9b17b   miomio-xiao   fix Slider组件第一次cl...
329
  
cd077424   bin.yang   slider组件 step为小数...
330
                  const modulus = this.handleDecimal(newPos,this.step);
42ab875d   miomio-xiao   fix Slider not em...
331
                  const value = this.currentValue;
eb8c6cd9   Sergio Crisostomo   Correct steps cal...
332
                  value[index] = newPos - modulus;
42ab875d   miomio-xiao   fix Slider not em...
333
                  this.currentValue = [...value];
d4c9b17b   miomio-xiao   fix Slider组件第一次cl...
334
  
a6fc9438   梁灏   fixed #461
335
                  if (!this.dragging) {
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
336
                      if (this.currentValue[index] !== this.oldValue[index]) {
b964efae   Sergio Crisostomo   Emit change on po...
337
                          this.emitChange();
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
338
                          this.oldValue[index] = this.currentValue[index];
69576f47   梁灏   add Slider component
339
340
341
                      }
                  }
              },
3b71312a   bin.yang   slider组件 step为小数...
342
343
344
345
              handleDecimal(pos,step){
                  if(step<1){
                      let sl = step.toString(),
                          multiple = 1,
cd077424   bin.yang   slider组件 step为小数...
346
                          m;
3b71312a   bin.yang   slider组件 step为小数...
347
                      try {
cd077424   bin.yang   slider组件 step为小数...
348
349
350
351
                          m = sl.split('.')[1].length;
                      } catch (e){
                          m = 0;
                      }
3b71312a   bin.yang   slider组件 step为小数...
352
353
354
355
                      multiple = Math.pow(10,m);
                      return (pos * multiple) % (step * multiple) / multiple;
                  }else return  pos % step;
              },
b964efae   Sergio Crisostomo   Emit change on po...
356
              emitChange(){
e3549149   Sergio Crisostomo   normalise public ...
357
358
359
                  const value = this.range ? this.exportValue : this.exportValue[0];
                  this.$emit('on-change', value);
                  this.dispatch('FormItem', 'on-form-change', value);
b964efae   Sergio Crisostomo   Emit change on po...
360
361
              },
  
2eccfc99   梁灏   fixed #2852
362
              sliderClick (event) {
69576f47   梁灏   add Slider component
363
                  if (this.disabled) return;
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
364
365
                  const currentX = this.getPointerX(event);
                  const sliderOffsetLeft = this.$refs.slider.getBoundingClientRect().left;
965b6d8e   Sergio Crisostomo   Fix slider for m...
366
                  let newPos = ((currentX - sliderOffsetLeft) / this.sliderWidth * this.valueRange) + this.min;
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
367
368
369
370
  
                  if (!this.range || newPos <= this.minPosition) this.changeButtonPosition(newPos, 'min');
                  else if (newPos >= this.maxPosition) this.changeButtonPosition(newPos, 'max');
                  else this.changeButtonPosition(newPos, ((newPos - this.firstPosition) <= (this.secondPosition - newPos)) ? 'min' : 'max');
69576f47   梁灏   add Slider component
371
              },
69576f47   梁灏   add Slider component
372
  
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
373
374
              handleInputChange (val) {
                  this.currentValue = [val, this.currentValue[1]];
e3549149   Sergio Crisostomo   normalise public ...
375
                  this.emitChange();
69576f47   梁灏   add Slider component
376
              },
5cb6ce9e   梁灏   Slider add Toolti...
377
378
379
380
381
382
383
384
  
              handleFocus (type) {
                  this.$refs[`${type}Tooltip`].handleShowPopper();
              },
  
              handleBlur (type) {
                  this.$refs[`${type}Tooltip`].handleClosePopper();
              }
2eccfc99   梁灏   fixed #2852
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
          },
          mounted () {
              // #2852
              this.$on('on-visible-change', (val) => {
                  if (val && this.showTip === 'always') {
                      this.$refs.minTooltip.doDestroy();
                      if (this.range) {
                          this.$refs.maxTooltip.doDestroy();
                      }
                      this.$nextTick(() => {
                          this.$refs.minTooltip.updatePopper();
                          if (this.range) {
                              this.$refs.maxTooltip.updatePopper();
                          }
                      });
                  }
              });
36febc3c   梁灏   add Slider
402
          }
b0893113   jingsam   :art: add eslint
403
404
      };
  </script>