Commit 2b87ffa91a0340c757f99c286ca42b398dd6a00d

Authored by Sergio Crisostomo
1 parent e6a09eee

refactor and DRY Slider

Showing 1 changed file with 115 additions and 300 deletions   Show diff stats
src/components/slider/slider.vue
@@ -14,34 +14,26 @@ @@ -14,34 +14,26 @@
14 <div :class="[prefixCls + '-stop']" v-for="item in stops" :style="{ 'left': item + '%' }" @click.self="sliderClick"></div> 14 <div :class="[prefixCls + '-stop']" v-for="item in stops" :style="{ 'left': item + '%' }" @click.self="sliderClick"></div>
15 </template> 15 </template>
16 <div :class="[prefixCls + '-bar']" :style="barStyle" @click.self="sliderClick"></div> 16 <div :class="[prefixCls + '-bar']" :style="barStyle" @click.self="sliderClick"></div>
17 - <template v-if="range">  
18 - <div  
19 - :class="[prefixCls + '-button-wrap']"  
20 - :style="{left: firstPosition + '%'}"  
21 - @mousedown="onFirstButtonDown">  
22 - <Tooltip :controlled="firstDragging" placement="top" :content="tipFormat(currentValue[0])" :disabled="tipDisabled" :always="showTip === 'always'" ref="tooltip">  
23 - <div :class="button1Classes"></div>  
24 - </Tooltip>  
25 - </div>  
26 - <div  
27 - :class="[prefixCls + '-button-wrap']"  
28 - :style="{left: secondPosition + '%'}"  
29 - @mousedown="onSecondButtonDown">  
30 - <Tooltip :controlled="secondDragging" placement="top" :content="tipFormat(currentValue[1])" :disabled="tipDisabled" :always="showTip === 'always'" ref="tooltip2">  
31 - <div :class="button2Classes"></div>  
32 - </Tooltip>  
33 - </div>  
34 - </template>  
35 - <template v-else>  
36 - <div  
37 - :class="[prefixCls + '-button-wrap']"  
38 - :style="{left: singlePosition + '%'}"  
39 - @mousedown="onSingleButtonDown">  
40 - <Tooltip :controlled="dragging" placement="top" :content="tipFormat(currentValue)" :disabled="tipDisabled" :always="showTip === 'always'" ref="tooltip">  
41 - <div :class="buttonClasses"></div>  
42 - </Tooltip>  
43 - </div>  
44 - </template> 17 + <div
  18 + :class="[prefixCls + '-button-wrap']"
  19 + :style="{left: minPosition + '%'}"
  20 + @touchstart="onPointerDown($event, 'min')"
  21 + @mousedown="onPointerDown($event, 'min')">
  22 + <Tooltip :controlled="pointerDown === 'min'" placement="top" :content="tipFormat(currentValue[0])"
  23 + :disabled="tipDisabled" :always="showTip === 'always'" ref="minTooltip">
  24 + <div :class="minButtonClasses"></div>
  25 + </Tooltip>
  26 + </div>
  27 + <div v-if="range"
  28 + :class="[prefixCls + '-button-wrap']"
  29 + :style="{left: maxPosition + '%'}"
  30 + @touchstart="onPointerDown($event, 'max')"
  31 + @mousedown="onPointerDown($event, 'max')">
  32 + <Tooltip :controlled="pointerDown === 'max'" placement="top" :content="tipFormat(currentValue[1])"
  33 + :disabled="tipDisabled" :always="showTip === 'always'" ref="maxTooltip">
  34 + <div :class="maxButtonClasses"></div>
  35 + </Tooltip>
  36 + </div>
45 </div> 37 </div>
46 </div> 38 </div>
47 </template> 39 </template>
@@ -109,38 +101,36 @@ @@ -109,38 +101,36 @@
109 } 101 }
110 }, 102 },
111 data () { 103 data () {
  104 + const val = this.checkLimits(Array.isArray(this.value) ? this.value : [this.value]);
112 return { 105 return {
113 prefixCls: prefixCls, 106 prefixCls: prefixCls,
114 - currentValue: this.value, 107 + currentValue: val,
115 dragging: false, 108 dragging: false,
116 - firstDragging: false,  
117 - secondDragging: false, 109 + pointerDown: '',
118 startX: 0, 110 startX: 0,
119 currentX: 0, 111 currentX: 0,
120 startPos: 0, 112 startPos: 0,
121 newPos: null, 113 newPos: null,
122 - oldSingleValue: this.value,  
123 - oldFirstValue: this.value[0],  
124 - oldSecondValue: this.value[1],  
125 - singlePosition: (this.value - this.min) / (this.max - this.min) * 100,  
126 - firstPosition: (this.value[0] - this.min) / (this.max - this.min) * 100,  
127 - secondPosition: (this.value[1] - this.min) / (this.max - this.min) * 100 114 + oldValue: val
128 }; 115 };
129 }, 116 },
130 watch: { 117 watch: {
131 value (val) { 118 value (val) {
132 - this.currentValue = val; 119 + val = this.checkLimits(Array.isArray(val) ? val : [val]);
  120 + if (val[0] !== this.currentValue[0] || val[1] !== this.currentValue[1]) {
  121 + this.currentValue = val;
  122 + }
133 }, 123 },
134 currentValue (val) { 124 currentValue (val) {
135 this.$nextTick(() => { 125 this.$nextTick(() => {
136 - this.$refs.tooltip.updatePopper(); 126 + this.$refs.minTooltip.updatePopper();
137 if (this.range) { 127 if (this.range) {
138 - this.$refs.tooltip2.updatePopper(); 128 + this.$refs.maxTooltip.updatePopper();
139 } 129 }
140 }); 130 });
141 - this.updateValue(val);  
142 - this.$emit('input', val);  
143 - this.$emit('on-input', val); 131 + const exportValue = this.range ? val : val[0];
  132 + this.$emit('input', exportValue);
  133 + this.$emit('on-input', exportValue);
144 } 134 }
145 }, 135 },
146 computed: { 136 computed: {
@@ -154,47 +144,43 @@ @@ -154,47 +144,43 @@
154 } 144 }
155 ]; 145 ];
156 }, 146 },
157 - buttonClasses () { 147 + minButtonClasses () {
158 return [ 148 return [
159 `${prefixCls}-button`, 149 `${prefixCls}-button`,
160 { 150 {
161 - [`${prefixCls}-button-dragging`]: this.dragging 151 + [`${prefixCls}-button-dragging`]: this.pointerDown === 'min'
162 } 152 }
163 ]; 153 ];
164 }, 154 },
165 - button1Classes () { 155 + maxButtonClasses () {
166 return [ 156 return [
167 `${prefixCls}-button`, 157 `${prefixCls}-button`,
168 { 158 {
169 - [`${prefixCls}-button-dragging`]: this.firstDragging 159 + [`${prefixCls}-button-dragging`]: this.pointerDown === 'max'
170 } 160 }
171 ]; 161 ];
172 }, 162 },
173 - button2Classes () {  
174 - return [  
175 - `${prefixCls}-button`,  
176 - {  
177 - [`${prefixCls}-button-dragging`]: this.secondDragging  
178 - }  
179 - ]; 163 + minPosition () {
  164 + const val = this.currentValue;
  165 + return (val[0] - this.min) / (this.max - this.min) * 100;
  166 + },
  167 + maxPosition: function () {
  168 + const val = this.currentValue;
  169 +
  170 + return (val[1] - this.min) / (this.max - this.min) * 100;
180 }, 171 },
181 barStyle () { 172 barStyle () {
182 - let style; 173 + const style = {
  174 + left: (this.currentValue[0] - this.min) / (this.max - this.min) * 100 + '%'
  175 + };
183 176
184 if (this.range) { 177 if (this.range) {
185 - style = {  
186 - width: (this.currentValue[1] - this.currentValue[0]) / (this.max - this.min) * 100 + '%',  
187 - left: (this.currentValue[0] - this.min) / (this.max - this.min) * 100 + '%'  
188 - };  
189 - } else {  
190 - style = {  
191 - width: (this.currentValue - this.min) / (this.max - this.min) * 100 + '%'  
192 - }; 178 + style.width = (this.currentValue[1] - this.currentValue[0]) / (this.max - this.min) * 100 + '%';
193 } 179 }
194 180
195 return style; 181 return style;
196 }, 182 },
197 - stops() { 183 + stops () {
198 let stopCount = (this.max - this.min) / this.step; 184 let stopCount = (this.max - this.min) / this.step;
199 let result = []; 185 let result = [];
200 let stepWidth = 100 * this.step / (this.max - this.min); 186 let stepWidth = 100 * this.step / (this.max - this.min);
@@ -211,268 +197,97 @@ @@ -211,268 +197,97 @@
211 } 197 }
212 }, 198 },
213 methods: { 199 methods: {
214 - updateValue (val, init = false) {  
215 - if (this.range) {  
216 - let value = [...val];  
217 - if (init) {  
218 - if (value[0] > value[1]) {  
219 - value = [this.min, this.max];  
220 - }  
221 - } else {  
222 - if (value[0] > value[1]) {  
223 - value[0] = value[1];  
224 - }  
225 - }  
226 - if (value[0] < this.min) {  
227 - value[0] = this.min;  
228 - }  
229 - if (value[0] > this.max) {  
230 - value[0] = this.max;  
231 - }  
232 - if (value[1] < this.min) {  
233 - value[1] = this.min;  
234 - }  
235 - if (value[1] > this.max) {  
236 - value[1] = this.max;  
237 - }  
238 - if (this.value[0] === value[0] && this.value[1] === value[1]) {  
239 - this.setFirstPosition(this.currentValue[0]);  
240 - this.setSecondPosition(this.currentValue[1]);  
241 - return;  
242 - }  
243 -  
244 - this.currentValue = value;  
245 - this.setFirstPosition(this.currentValue[0]);  
246 - this.setSecondPosition(this.currentValue[1]);  
247 - } else {  
248 - if (val < this.min) {  
249 - this.currentValue = this.min;  
250 - }  
251 - if (val > this.max) {  
252 - this.currentValue = this.max;  
253 - }  
254 - this.setSinglePosition(this.currentValue);  
255 - } 200 + getPointerX (e) {
  201 + return e.type.indexOf('touch') !== -1 ? e.touches[0].clientX : e.clientX;
256 }, 202 },
257 - sliderClick (event) {  
258 - if (this.disabled) return;  
259 - const currentX = event.clientX;  
260 - const sliderOffsetLeft = this.$refs.slider.getBoundingClientRect().left;  
261 - const newPos = (currentX - sliderOffsetLeft) / this.sliderWidth * 100; 203 + checkLimits ([min, max]) {
  204 + min = Math.max(0, min);
  205 + min = Math.min(100, min);
262 206
263 - if (this.range) {  
264 - let type = '';  
265 - if (newPos <= this.firstPosition) {  
266 - type = 'First';  
267 - } else if (newPos >= this.secondPosition) {  
268 - type = 'Second';  
269 - } else {  
270 - if ((newPos - this.firstPosition) <= (this.secondPosition - newPos)) {  
271 - type = 'First';  
272 - } else {  
273 - type = 'Second';  
274 - }  
275 - }  
276 - this[`change${type}Position`](newPos);  
277 - } else {  
278 - this.changeSinglePosition(newPos);  
279 - } 207 + max = Math.max(0, min, max);
  208 + max = Math.min(100, max);
  209 + return [min, max];
280 }, 210 },
281 - // for single use  
282 - onSingleButtonDown (event) { 211 + onPointerDown (event, type) {
283 if (this.disabled) return; 212 if (this.disabled) return;
284 event.preventDefault(); 213 event.preventDefault();
285 - this.onSingleDragStart(event);  
286 -// window.addEventListener('mousemove', this.onSingleDragging);  
287 -// window.addEventListener('mouseup', this.onSingleDragEnd);  
288 - on(window, 'mousemove', this.onSingleDragging);  
289 - on(window, 'mouseup', this.onSingleDragEnd); 214 + this.pointerDown = type;
  215 +
  216 + this.onPointerDragStart(event);
  217 + on(window, 'mousemove', this.onPointerDrag);
  218 + on(window, 'touchmove', this.onPointerDrag);
  219 + on(window, 'mouseup', this.onPointerDragEnd);
  220 + on(window, 'touchend', this.onPointerDragEnd);
290 }, 221 },
291 - onSingleDragStart (event) { 222 + onPointerDragStart (event) {
292 this.dragging = false; 223 this.dragging = false;
293 - this.startX = event.clientX;  
294 - this.startPos = parseInt(this.singlePosition, 10); 224 + this.startX = this.getPointerX(event);
  225 + this.startPos = parseInt(this[`${this.pointerDown}Position`], 10);
295 }, 226 },
296 - onSingleDragging (event) { 227 + onPointerDrag (event) {
297 this.dragging = true; 228 this.dragging = true;
298 - if (this.dragging) {  
299 - this.$refs.tooltip.visible = true;  
300 - this.currentX = event.clientX;  
301 - const diff = (this.currentX - this.startX) / this.sliderWidth * 100;  
302 - this.newPos = this.startPos + diff;  
303 - this.changeSinglePosition(this.newPos);  
304 - } 229 + this.$refs[`${this.pointerDown}Tooltip`].visible = true;
  230 + this.currentX = this.getPointerX(event);
  231 +
  232 + const diff = (this.currentX - this.startX) / this.sliderWidth * 100;
  233 + this.newPos = this.startPos + diff;
  234 + this.changeButtonPosition(this.newPos);
305 }, 235 },
306 - onSingleDragEnd () { 236 + onPointerDragEnd () {
307 if (this.dragging) { 237 if (this.dragging) {
308 this.dragging = false; 238 this.dragging = false;
309 - this.$refs.tooltip.visible = false;  
310 - this.changeSinglePosition(this.newPos);  
311 -// window.removeEventListener('mousemove', this.onSingleDragging);  
312 -// window.removeEventListener('mouseup', this.onSingleDragEnd); 239 + this.$refs[`${this.pointerDown}Tooltip`].visible = false;
  240 + this.changeButtonPosition(this.newPos);
313 } 241 }
314 - off(window, 'mousemove', this.onSingleDragging);  
315 - off(window, 'mouseup', this.onSingleDragEnd); 242 +
  243 + this.pointerDown = '';
  244 + off(window, 'mousemove', this.onPointerDrag);
  245 + off(window, 'touchmove', this.onPointerDrag);
  246 + off(window, 'mouseup', this.onPointerDragEnd);
  247 + off(window, 'touchend', this.onPointerDragEnd);
316 }, 248 },
317 - changeSinglePosition (newPos) {  
318 - if (newPos < 0) {  
319 - newPos = 0;  
320 - } else if (newPos > 100) {  
321 - newPos = 100;  
322 - } 249 + changeButtonPosition (newPos, forceType) {
  250 +
  251 + const type = forceType || this.pointerDown;
  252 + const index = type === 'min' ? 0 : 1;
  253 + if (type === 'min') newPos = this.checkLimits([newPos, this.maxPosition])[0];
  254 + else newPos = this.checkLimits([this.minPosition, newPos])[1];
  255 +
323 const lengthPerStep = 100 / ((this.max - this.min) / this.step); 256 const lengthPerStep = 100 / ((this.max - this.min) / this.step);
324 const steps = Math.round(newPos / lengthPerStep); 257 const steps = Math.round(newPos / lengthPerStep);
325 258
326 - this.currentValue = Math.round(steps * lengthPerStep * (this.max - this.min) * 0.01 + this.min);  
327 - this.setSinglePosition(this.currentValue); 259 + const value = this.currentValue;
  260 + value[index] = Math.round(steps * lengthPerStep * (this.max - this.min) * 0.01 + this.min);
  261 + this.currentValue = [...value];
  262 +
328 if (!this.dragging) { 263 if (!this.dragging) {
329 - if (this.currentValue !== this.oldSingleValue) {  
330 - this.$emit('on-change', this.currentValue);  
331 - this.dispatch('FormItem', 'on-form-change', this.currentValue);  
332 - this.oldSingleValue = this.currentValue; 264 + if (this.currentValue[index] !== this.oldValue[index]) {
  265 + const exportValue = this.range ? this.currentValue : this.currentValue[0];
  266 + this.$emit('on-change', exportValue);
  267 + this.dispatch('FormItem', 'on-form-change', exportValue);
  268 + this.oldValue[index] = this.currentValue[index];
333 } 269 }
334 } 270 }
335 }, 271 },
336 - setSinglePosition (val) {  
337 - this.singlePosition = (val - this.min) / (this.max - this.min) * 100;  
338 - },  
339 - handleInputChange (val) {  
340 - this.currentValue = val;  
341 - this.setSinglePosition(val);  
342 - this.$emit('on-change', this.currentValue);  
343 - this.dispatch('FormItem', 'on-form-change', this.currentValue);  
344 - },  
345 - // for range use first  
346 - onFirstButtonDown (event) {  
347 - if (this.disabled) return;  
348 - event.preventDefault();  
349 - this.onFirstDragStart(event);  
350 -// window.addEventListener('mousemove', this.onFirstDragging);  
351 -// window.addEventListener('mouseup', this.onFirstDragEnd);  
352 - on(window, 'mousemove', this.onFirstDragging);  
353 - on(window, 'mouseup', this.onFirstDragEnd);  
354 - },  
355 - onFirstDragStart (event) {  
356 - this.firstDragging = false;  
357 - this.startX = event.clientX;  
358 - this.startPos = parseInt(this.firstPosition, 10);  
359 - },  
360 - onFirstDragging (event) {  
361 - this.firstDragging = true;  
362 - if (this.firstDragging) {  
363 - this.$refs.tooltip.visible = true;  
364 - this.currentX = event.clientX;  
365 - const diff = (this.currentX - this.startX) / this.sliderWidth * 100;  
366 - this.newPos = this.startPos + diff;  
367 - this.changeFirstPosition(this.newPos);  
368 - }  
369 - },  
370 - onFirstDragEnd () {  
371 - if (this.firstDragging) {  
372 - this.firstDragging = false;  
373 - this.$refs.tooltip.visible = false;  
374 - this.changeFirstPosition(this.newPos);  
375 -// window.removeEventListener('mousemove', this.onFirstDragging);  
376 -// window.removeEventListener('mouseup', this.onFirstDragEnd);  
377 - }  
378 - off(window, 'mousemove', this.onFirstDragging);  
379 - off(window, 'mouseup', this.onFirstDragEnd);  
380 - },  
381 - changeFirstPosition (newPos) {  
382 - if (newPos < 0) {  
383 - newPos = 0;  
384 - } else if (newPos > this.secondPosition) {  
385 - newPos = this.secondPosition;  
386 - }  
387 - const lengthPerStep = 100 / ((this.max - this.min) / this.step);  
388 - const steps = Math.round(newPos / lengthPerStep);  
389 272
390 - this.currentValue = [Math.round(steps * lengthPerStep * (this.max - this.min) * 0.01 + this.min), this.currentValue[1]];  
391 - this.setFirstPosition(this.currentValue[0]);  
392 - if (!this.firstDragging) {  
393 - if (this.currentValue[0] !== this.oldFirstValue) {  
394 - this.$emit('on-change', this.currentValue);  
395 - this.dispatch('FormItem', 'on-form-change', this.currentValue);  
396 - this.oldFirstValue = this.currentValue[0];  
397 - }  
398 - }  
399 - },  
400 - setFirstPosition (val) {  
401 - this.firstPosition = (val - this.min) / (this.max - this.min) * 100;  
402 - },  
403 - // for range use second  
404 - onSecondButtonDown (event) { 273 +
  274 + sliderClick: function (event) {
405 if (this.disabled) return; 275 if (this.disabled) return;
406 - event.preventDefault();  
407 - this.onSecondDragStart(event);  
408 -// window.addEventListener('mousemove', this.onSecondDragging);  
409 -// window.addEventListener('mouseup', this.onSecondDragEnd);  
410 - on(window, 'mousemove', this.onSecondDragging);  
411 - on(window, 'mouseup', this.onSecondDragEnd);  
412 - },  
413 - onSecondDragStart (event) {  
414 - this.secondDragging = false;  
415 - this.startX = event.clientX;  
416 - this.startPos = parseInt(this.secondPosition, 10);  
417 - },  
418 - onSecondDragging (event) {  
419 - this.secondDragging = true;  
420 - if (this.secondDragging) {  
421 - this.$refs.tooltip2.visible = true;  
422 - this.currentX = event.clientX;  
423 - const diff = (this.currentX - this.startX) / this.sliderWidth * 100;  
424 - this.newPos = this.startPos + diff;  
425 - this.changeSecondPosition(this.newPos);  
426 - }  
427 - },  
428 - onSecondDragEnd () {  
429 - if (this.secondDragging) {  
430 - this.secondDragging = false;  
431 - this.$refs.tooltip2.visible = false;  
432 - this.changeSecondPosition(this.newPos);  
433 -// window.removeEventListener('mousemove', this.onSecondDragging);  
434 -// window.removeEventListener('mouseup', this.onSecondDragEnd);  
435 - }  
436 - off(window, 'mousemove', this.onSecondDragging);  
437 - off(window, 'mouseup', this.onSecondDragEnd); 276 + const currentX = this.getPointerX(event);
  277 + const sliderOffsetLeft = this.$refs.slider.getBoundingClientRect().left;
  278 + const newPos = (currentX - sliderOffsetLeft) / this.sliderWidth * 100;
  279 +
  280 + if (!this.range || newPos <= this.minPosition) this.changeButtonPosition(newPos, 'min');
  281 + else if (newPos >= this.maxPosition) this.changeButtonPosition(newPos, 'max');
  282 + else this.changeButtonPosition(newPos, ((newPos - this.firstPosition) <= (this.secondPosition - newPos)) ? 'min' : 'max');
438 }, 283 },
439 - changeSecondPosition (newPos) {  
440 - if (newPos > 100) {  
441 - newPos = 100;  
442 - } else if (newPos < this.firstPosition) {  
443 - newPos = this.firstPosition;  
444 - }  
445 - const lengthPerStep = 100 / ((this.max - this.min) / this.step);  
446 - const steps = Math.round(newPos / lengthPerStep);  
447 284
448 - this.currentValue = [this.currentValue[0], Math.round(steps * lengthPerStep * (this.max - this.min) * 0.01 + this.min)];  
449 - this.setSecondPosition(this.currentValue[1]);  
450 - if (!this.secondDragging) {  
451 - if (this.currentValue[1] !== this.oldSecondValue) {  
452 - this.$emit('on-change', this.currentValue);  
453 - this.dispatch('FormItem', 'on-form-change', this.currentValue);  
454 - this.oldSecondValue = this.currentValue[1];  
455 - }  
456 - } 285 + handleInputChange (val) {
  286 + this.currentValue = [val, this.currentValue[1]];
  287 + const exportValue = this.range ? this.currentValue : this.currentValue[0];
  288 + this.$emit('on-change', exportValue);
  289 + this.dispatch('FormItem', 'on-form-change', exportValue);
457 }, 290 },
458 - setSecondPosition (val) {  
459 - this.secondPosition = (val - this.min) / (this.max - this.min) * 100;  
460 - }  
461 - },  
462 - mounted () {  
463 - if (this.range) {  
464 - const isArray = Array.isArray(this.currentValue);  
465 - if (!isArray || (isArray && this.currentValue.length != 2) || (isArray && (isNaN(this.currentValue[0]) || isNaN(this.currentValue[1])))) {  
466 - this.currentValue = [this.min, this.max];  
467 - } else {  
468 - this.updateValue(this.currentValue, true);  
469 - }  
470 - } else {  
471 - if (typeof this.currentValue !== 'number') {  
472 - this.currentValue = this.min;  
473 - }  
474 - this.updateValue(this.currentValue);  
475 - }  
476 } 291 }
477 }; 292 };
478 </script> 293 </script>