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,
791d254e   Graham Fairweather   Slider: Keyboard ...
154
155
156
157
158
                  oldValue: val,
                  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];
3b71312a   bin.yang   slider组件 step为小数...
329
                  
cd077424   bin.yang   slider组件 step为小数...
330
                  const modulus = this.handleDecimal(newPos,this.step);
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
331
                  const value = this.currentValue;
eb8c6cd9   Sergio Crisostomo   Correct steps cal...
332
                  value[index] = newPos - modulus;
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
333
                  this.currentValue = [...value];
a6fc9438   梁灏   fixed #461
334
                  if (!this.dragging) {
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
335
                      if (this.currentValue[index] !== this.oldValue[index]) {
b964efae   Sergio Crisostomo   Emit change on po...
336
                          this.emitChange();
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
337
                          this.oldValue[index] = this.currentValue[index];
69576f47   梁灏   add Slider component
338
339
340
                      }
                  }
              },
3b71312a   bin.yang   slider组件 step为小数...
341
342
343
344
              handleDecimal(pos,step){
                  if(step<1){
                      let sl = step.toString(),
                          multiple = 1,
cd077424   bin.yang   slider组件 step为小数...
345
                          m;
3b71312a   bin.yang   slider组件 step为小数...
346
                      try {
cd077424   bin.yang   slider组件 step为小数...
347
348
349
350
                          m = sl.split('.')[1].length;
                      } catch (e){
                          m = 0;
                      }
3b71312a   bin.yang   slider组件 step为小数...
351
352
353
354
                      multiple = Math.pow(10,m);
                      return (pos * multiple) % (step * multiple) / multiple;
                  }else return  pos % step;
              },
b964efae   Sergio Crisostomo   Emit change on po...
355
              emitChange(){
e3549149   Sergio Crisostomo   normalise public ...
356
357
358
                  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...
359
360
              },
  
2eccfc99   梁灏   fixed #2852
361
              sliderClick (event) {
69576f47   梁灏   add Slider component
362
                  if (this.disabled) return;
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
363
364
                  const currentX = this.getPointerX(event);
                  const sliderOffsetLeft = this.$refs.slider.getBoundingClientRect().left;
965b6d8e   Sergio Crisostomo   Fix slider for m...
365
                  let newPos = ((currentX - sliderOffsetLeft) / this.sliderWidth * this.valueRange) + this.min;
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
366
367
368
369
  
                  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
370
              },
69576f47   梁灏   add Slider component
371
  
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
372
373
              handleInputChange (val) {
                  this.currentValue = [val, this.currentValue[1]];
e3549149   Sergio Crisostomo   normalise public ...
374
                  this.emitChange();
69576f47   梁灏   add Slider component
375
              },
5cb6ce9e   梁灏   Slider add Toolti...
376
377
378
379
380
381
382
383
  
              handleFocus (type) {
                  this.$refs[`${type}Tooltip`].handleShowPopper();
              },
  
              handleBlur (type) {
                  this.$refs[`${type}Tooltip`].handleClosePopper();
              }
2eccfc99   梁灏   fixed #2852
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
          },
          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
401
          }
b0893113   jingsam   :art: add eslint
402
403
      };
  </script>