Blame view

src/components/slider/slider.vue 11.7 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"
adc203b9   Sergio Crisostomo   correct input dis...
8
              :value="currentValue[0]"
69576f47   梁灏   add Slider component
9
10
              :disabled="disabled"
              @on-change="handleInputChange"></Input-number>
1c803cdf   梁灏   support Slider
11
          <div :class="[prefixCls + '-wrap']" ref="slider" @click.self="sliderClick">
0460a1e8   梁灏   fixed #812
12
              <input type="hidden" :name="name" :value="currentValue">
36febc3c   梁灏   add Slider
13
              <template v-if="showStops">
5709f32e   梁灏   Slider support hi...
14
                  <div :class="[prefixCls + '-stop']" v-for="item in stops" :style="{ 'left': item + '%' }" @click.self="sliderClick"></div>
36febc3c   梁灏   add Slider
15
              </template>
5709f32e   梁灏   Slider support hi...
16
              <div :class="[prefixCls + '-bar']" :style="barStyle" @click.self="sliderClick"></div>
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
              <div
                  :class="[prefixCls + '-button-wrap']"
                  :style="{left: minPosition + '%'}"
                  @touchstart="onPointerDown($event, 'min')"
                  @mousedown="onPointerDown($event, 'min')">
                  <Tooltip :controlled="pointerDown === 'min'" placement="top" :content="tipFormat(currentValue[0])"
                           :disabled="tipDisabled" :always="showTip === 'always'" ref="minTooltip">
                      <div :class="minButtonClasses"></div>
                  </Tooltip>
              </div>
              <div v-if="range"
                   :class="[prefixCls + '-button-wrap']"
                   :style="{left: maxPosition + '%'}"
                   @touchstart="onPointerDown($event, 'max')"
                   @mousedown="onPointerDown($event, 'max')">
                  <Tooltip :controlled="pointerDown === 'max'" placement="top" :content="tipFormat(currentValue[1])"
                           :disabled="tipDisabled" :always="showTip === 'always'" ref="maxTooltip">
                      <div :class="maxButtonClasses"></div>
                  </Tooltip>
              </div>
36febc3c   梁灏   add Slider
37
38
39
40
41
42
          </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...
43
      import { getStyle, oneOf } from '../../utils/assist';
825ed580   梁灏   fixed bug
44
      import { on, off } from '../../utils/dom';
cd78c9c4   梁灏   some comps suppor...
45
      import Emitter from '../../mixins/emitter';
36febc3c   梁灏   add Slider
46
47
48
49
  
      const prefixCls = 'ivu-slider';
  
      export default {
b1c118d8   梁灏   support Dropdown
50
          name: 'Slider',
cd78c9c4   梁灏   some comps suppor...
51
          mixins: [ Emitter ],
36febc3c   梁灏   add Slider
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
          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...
91
92
93
94
95
96
97
              },
              showTip: {
                  type: String,
                  default: 'hover',
                  validator (value) {
                      return oneOf(value, ['hover', 'always', 'never']);
                  }
0460a1e8   梁灏   fixed #812
98
99
100
              },
              name: {
                  type: String
36febc3c   梁灏   add Slider
101
102
103
              }
          },
          data () {
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
104
              const val = this.checkLimits(Array.isArray(this.value) ? this.value : [this.value]);
36febc3c   梁灏   add Slider
105
              return {
69576f47   梁灏   add Slider component
106
                  prefixCls: prefixCls,
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
107
                  currentValue: val,
69576f47   梁灏   add Slider component
108
                  dragging: false,
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
109
                  pointerDown: '',
69576f47   梁灏   add Slider component
110
111
112
                  startX: 0,
                  currentX: 0,
                  startPos: 0,
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
113
                  oldValue: val
b0893113   jingsam   :art: add eslint
114
              };
36febc3c   梁灏   add Slider
115
          },
1c803cdf   梁灏   support Slider
116
117
          watch: {
              value (val) {
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
118
119
120
121
                  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
122
123
124
              },
              currentValue (val) {
                  this.$nextTick(() => {
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
125
                      this.$refs.minTooltip.updatePopper();
1c803cdf   梁灏   support Slider
126
                      if (this.range) {
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
127
                          this.$refs.maxTooltip.updatePopper();
1c803cdf   梁灏   support Slider
128
129
                      }
                  });
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
130
131
132
                  const exportValue = this.range ? val : val[0];
                  this.$emit('input', exportValue);
                  this.$emit('on-input', exportValue);
1c803cdf   梁灏   support Slider
133
134
              }
          },
36febc3c   梁灏   add Slider
135
136
137
138
139
          computed: {
              classes () {
                  return [
                      `${prefixCls}`,
                      {
69576f47   梁灏   add Slider component
140
                          [`${prefixCls}-input`]: this.showInput && !this.range,
36febc3c   梁灏   add Slider
141
142
143
                          [`${prefixCls}-range`]: this.range,
                          [`${prefixCls}-disabled`]: this.disabled
                      }
b0893113   jingsam   :art: add eslint
144
                  ];
36febc3c   梁灏   add Slider
145
              },
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
146
              minButtonClasses () {
69576f47   梁灏   add Slider component
147
148
149
                  return [
                      `${prefixCls}-button`,
                      {
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
150
                          [`${prefixCls}-button-dragging`]: this.pointerDown === 'min'
69576f47   梁灏   add Slider component
151
152
153
                      }
                  ];
              },
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
154
              maxButtonClasses () {
69576f47   梁灏   add Slider component
155
156
157
                  return [
                      `${prefixCls}-button`,
                      {
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
158
                          [`${prefixCls}-button-dragging`]: this.pointerDown === 'max'
69576f47   梁灏   add Slider component
159
160
161
                      }
                  ];
              },
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
162
163
              minPosition () {
                  const val = this.currentValue;
965b6d8e   Sergio Crisostomo   Fix slider for m...
164
                  return (val[0] - this.min) / this.valueRange * 100;
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
165
166
167
168
              },
              maxPosition: function () {
                  const val = this.currentValue;
  
965b6d8e   Sergio Crisostomo   Fix slider for m...
169
                  return (val[1] - this.min) / this.valueRange * 100;
69576f47   梁灏   add Slider component
170
              },
36febc3c   梁灏   add Slider
171
              barStyle () {
3e9a7f97   Sergio Crisostomo   Correct barStyle ...
172
  
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
173
                  const style = {
965b6d8e   Sergio Crisostomo   Fix slider for m...
174
                      width: (this.currentValue[0] - this.min) / this.valueRange * 100 + '%'
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
175
                  };
36febc3c   梁灏   add Slider
176
177
  
                  if (this.range) {
965b6d8e   Sergio Crisostomo   Fix slider for m...
178
179
                      style.left = (this.currentValue[0] - this.min) / this.valueRange * 100 + '%';
                      style.width = (this.currentValue[1] - this.currentValue[0]) / this.valueRange * 100 + '%';
36febc3c   梁灏   add Slider
180
181
182
183
                  }
  
                  return style;
              },
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
184
              stops () {
965b6d8e   Sergio Crisostomo   Fix slider for m...
185
                  let stopCount = this.valueRange / this.step;
41d90ccf   梁灏   Slider can show s...
186
                  let result = [];
965b6d8e   Sergio Crisostomo   Fix slider for m...
187
                  let stepWidth = 100 * this.step / this.valueRange;
41d90ccf   梁灏   Slider can show s...
188
189
190
191
                  for (let i = 1; i < stopCount; i++) {
                      result.push(i * stepWidth);
                  }
                  return result;
69576f47   梁灏   add Slider component
192
193
              },
              sliderWidth () {
1c803cdf   梁灏   support Slider
194
                  return parseInt(getStyle(this.$refs.slider, 'width'), 10);
59872199   Rijn   added show-tip to...
195
196
              },
              tipDisabled () {
1c803cdf   梁灏   support Slider
197
                  return this.tipFormat(this.currentValue[0]) === null || this.showTip === 'never';
965b6d8e   Sergio Crisostomo   Fix slider for m...
198
199
200
              },
              valueRange(){
                  return this.max - this.min;
36febc3c   梁灏   add Slider
201
202
203
              }
          },
          methods: {
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
204
205
              getPointerX (e) {
                  return e.type.indexOf('touch') !== -1 ? e.touches[0].clientX : e.clientX;
69576f47   梁灏   add Slider component
206
              },
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
207
              checkLimits ([min, max]) {
965b6d8e   Sergio Crisostomo   Fix slider for m...
208
209
                  min = Math.max(this.min, min);
                  min = Math.min(this.max, min);
36febc3c   梁灏   add Slider
210
  
965b6d8e   Sergio Crisostomo   Fix slider for m...
211
212
                  max = Math.max(this.min, min, max);
                  max = Math.min(this.max, max);
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
213
                  return [min, max];
69576f47   梁灏   add Slider component
214
              },
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
215
              onPointerDown (event, type) {
69576f47   梁灏   add Slider component
216
                  if (this.disabled) return;
f2be585e   梁灏   optimize Slider w...
217
                  event.preventDefault();
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
218
219
220
221
222
223
224
                  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
225
              },
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
226
              onPointerDragStart (event) {
ce4c0faa   oustn   修复 Slider 滑动按钮单击时...
227
                  this.dragging = false;
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
228
                  this.startX = this.getPointerX(event);
965b6d8e   Sergio Crisostomo   Fix slider for m...
229
                  this.startPos = (this[`${this.pointerDown}Position`] * this.valueRange / 100) + this.min;
69576f47   梁灏   add Slider component
230
              },
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
231
              onPointerDrag (event) {
ce4c0faa   oustn   修复 Slider 滑动按钮单击时...
232
                  this.dragging = true;
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
233
234
                  this.$refs[`${this.pointerDown}Tooltip`].visible = true;
                  this.currentX = this.getPointerX(event);
965b6d8e   Sergio Crisostomo   Fix slider for m...
235
                  const diff = (this.currentX - this.startX) / this.sliderWidth * this.valueRange;
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
236
  
965b6d8e   Sergio Crisostomo   Fix slider for m...
237
                  this.changeButtonPosition(this.startPos + diff);
69576f47   梁灏   add Slider component
238
              },
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
239
              onPointerDragEnd () {
69576f47   梁灏   add Slider component
240
241
                  if (this.dragging) {
                      this.dragging = false;
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
242
                      this.$refs[`${this.pointerDown}Tooltip`].visible = false;
69576f47   梁灏   add Slider component
243
                  }
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
244
245
246
247
248
249
  
                  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
250
              },
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
251
              changeButtonPosition (newPos, forceType) {
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
252
253
254
255
256
                  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];
  
eb8c6cd9   Sergio Crisostomo   Correct steps cal...
257
                  const modulus = newPos % this.step;
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
258
                  const value = this.currentValue;
eb8c6cd9   Sergio Crisostomo   Correct steps cal...
259
                  value[index] = newPos - modulus;
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
260
261
                  this.currentValue = [...value];
  
a6fc9438   梁灏   fixed #461
262
                  if (!this.dragging) {
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
263
264
265
266
267
                      if (this.currentValue[index] !== this.oldValue[index]) {
                          const exportValue = this.range ? this.currentValue : this.currentValue[0];
                          this.$emit('on-change', exportValue);
                          this.dispatch('FormItem', 'on-form-change', exportValue);
                          this.oldValue[index] = this.currentValue[index];
69576f47   梁灏   add Slider component
268
269
270
                      }
                  }
              },
69576f47   梁灏   add Slider component
271
  
2eccfc99   梁灏   fixed #2852
272
              sliderClick (event) {
69576f47   梁灏   add Slider component
273
                  if (this.disabled) return;
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
274
275
                  const currentX = this.getPointerX(event);
                  const sliderOffsetLeft = this.$refs.slider.getBoundingClientRect().left;
965b6d8e   Sergio Crisostomo   Fix slider for m...
276
                  let newPos = ((currentX - sliderOffsetLeft) / this.sliderWidth * this.valueRange) + this.min;
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
277
278
279
280
  
                  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
281
              },
69576f47   梁灏   add Slider component
282
  
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
283
284
285
286
287
              handleInputChange (val) {
                  this.currentValue = [val, this.currentValue[1]];
                  const exportValue = this.range ? this.currentValue : this.currentValue[0];
                  this.$emit('on-change', exportValue);
                  this.dispatch('FormItem', 'on-form-change', exportValue);
69576f47   梁灏   add Slider component
288
              },
2eccfc99   梁灏   fixed #2852
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
          },
          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
306
          }
b0893113   jingsam   :art: add eslint
307
308
      };
  </script>