Blame view

src/components/slider/slider.vue 11.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"
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;
b964efae   Sergio Crisostomo   Emit change on po...
243
                      this.emitChange();
69576f47   梁灏   add Slider component
244
                  }
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
245
246
247
248
249
250
  
                  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
251
              },
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
252
              changeButtonPosition (newPos, forceType) {
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
253
254
255
256
257
                  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...
258
                  const modulus = newPos % this.step;
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
259
                  const value = this.currentValue;
eb8c6cd9   Sergio Crisostomo   Correct steps cal...
260
                  value[index] = newPos - modulus;
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
261
262
                  this.currentValue = [...value];
  
a6fc9438   梁灏   fixed #461
263
                  if (!this.dragging) {
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
264
                      if (this.currentValue[index] !== this.oldValue[index]) {
b964efae   Sergio Crisostomo   Emit change on po...
265
                          this.emitChange();
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
266
                          this.oldValue[index] = this.currentValue[index];
69576f47   梁灏   add Slider component
267
268
269
                      }
                  }
              },
69576f47   梁灏   add Slider component
270
  
b964efae   Sergio Crisostomo   Emit change on po...
271
272
273
274
275
276
              emitChange(){
                  const exportValue = this.range ? this.currentValue : this.currentValue[0];
                  this.$emit('on-change', exportValue);
                  this.dispatch('FormItem', 'on-form-change', exportValue);
              },
  
2eccfc99   梁灏   fixed #2852
277
              sliderClick (event) {
69576f47   梁灏   add Slider component
278
                  if (this.disabled) return;
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
279
280
                  const currentX = this.getPointerX(event);
                  const sliderOffsetLeft = this.$refs.slider.getBoundingClientRect().left;
965b6d8e   Sergio Crisostomo   Fix slider for m...
281
                  let newPos = ((currentX - sliderOffsetLeft) / this.sliderWidth * this.valueRange) + this.min;
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
282
283
284
285
  
                  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
286
              },
69576f47   梁灏   add Slider component
287
  
2b87ffa9   Sergio Crisostomo   refactor and DRY ...
288
289
290
291
292
              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
293
              },
2eccfc99   梁灏   fixed #2852
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
          },
          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
311
          }
b0893113   jingsam   :art: add eslint
312
313
      };
  </script>