Slider: add disabled/use tooltip (#589)

pull/594/head
杨奕 2016-10-22 20:12:57 +08:00 committed by cinwell.li
parent 588523e808
commit e51d753ffd
6 changed files with 133 additions and 118 deletions

View File

@ -19,7 +19,7 @@
- 修复 Input Number min max 属性设置后点击加减出现的崩溃的bug
- 优化 TimePicker/DatePicker 输入日期行为
- 修复 DatePicker 输入禁用状态的日期却生效的问题 #484
- 新增 Slider 的 disabled 属性
#### 非兼容性更新

View File

@ -4,9 +4,10 @@
return {
value1: 0,
value2: 50,
value3: 0,
value3: 42,
value4: 0,
value5: 0
value5: 0,
value6: 0,
};
}
}
@ -58,6 +59,10 @@
<span class="demonstration">自定义初始值</span>
<el-slider v-model="value2"></el-slider>
</div>
<div class="block">
<span class="demonstration">禁用</span>
<el-slider v-model="value3" disabled></el-slider>
</div>
</template>
<script>
@ -83,14 +88,14 @@
<div class="block">
<span class="demonstration">不显示间断点</span>
<el-slider
v-model="value3"
v-model="value4"
:step="10">
</el-slider>
</div>
<div class="block">
<span class="demonstration">显示间断点</span>
<el-slider
v-model="value4"
v-model="value5"
:step="10"
show-stops>
</el-slider>
@ -119,7 +124,7 @@
<template>
<div class="block">
<el-slider
v-model="value5"
v-model="value6"
show-input>
</el-slider>
</div>
@ -142,6 +147,7 @@
|---------- |-------------- |---------- |-------------------------------- |-------- |
| min | 最小值 | number | — | 0 |
| max | 最大值 | number | — | 100 |
| disabled | 是否禁用 | boolean | — | false |
| step | 步长 | number | — | 1 |
| show-input | 是否显示输入框 | boolean | — | false |
| show-stops | 是否显示间断点 | boolean | — | false |

View File

@ -7,35 +7,37 @@
@keyup.native="onInputChange"
ref="input"
:step="step"
:disabled="disabled"
:min="min"
:max="max"
size="small">
</el-input-number>
<div class="el-slider__runway"
:class="{ 'show-input': showInput }"
:class="{ 'show-input': showInput, 'disabled': disabled }"
@click="onSliderClick" ref="slider">
<div class="el-slider__bar" :style="{ width: currentPosition }"></div>
<div
class="el-slider__button-wrapper"
@mouseenter="hovering = true"
@mouseleave="hovering = false"
@mouseenter="handleMouseEnter"
@mouseleave="handleMouseLeave"
@mousedown="onButtonDown"
:style="{left: currentPosition}" ref="button">
<div class="el-slider__button" :class="{ 'hover': hovering, 'dragging': dragging }"></div>
:class="{ 'hover': hovering, 'dragging': dragging }"
:style="{left: currentPosition}"
ref="button">
<el-tooltip placement="top" ref="tooltip">
<span slot="content">{{ value }}</span>
<div class="el-slider__button" :class="{ 'hover': hovering, 'dragging': dragging }"></div>
</el-tooltip>
</div>
<transition name="popper-fade">
<div class="el-slider__pop" v-show="showTip" ref="pop">{{ value }}</div>
</transition>
<div class="el-slider__stop" v-for="item in stops" :style="{ 'left': item + '%' }" v-if="showStops"></div>
</div>
</div>
</template>
<script type="text/babel">
import Popper from 'element-ui/src/utils/popper';
import ElInputNumber from 'element-ui/packages/input-number/index.js';
import ElTooltip from 'element-ui/packages/tooltip/index.js';
import { getStyle } from 'wind-dom/src/style';
import { addClass, removeClass } from 'wind-dom/src/class';
export default {
name: 'ElSlider',
@ -68,24 +70,27 @@
showStops: {
type: Boolean,
default: false
},
disabled: {
type: Boolean,
default: false
}
},
components: {
ElInputNumber
ElInputNumber,
ElTooltip
},
data() {
return {
inputValue: null,
timeout: null,
showTip: false,
hovering: false,
dragging: false,
startX: 0,
currentX: 0,
startPos: 0,
popper: null,
newPos: null,
oldValue: this.value,
currentPosition: (this.value - this.min) / (this.max - this.min) * 100 + '%'
@ -97,21 +102,6 @@
this.$emit('input', Number(val));
},
showTip(val) {
if (val) {
this.$nextTick(() => {
this.updatePopper();
});
} else {
this.timeout = setTimeout(() => {
if (this.popper) {
this.popper.destroy();
this.popper = null;
}
}, 300);
}
},
value(val) {
this.$nextTick(() => {
this.updatePopper();
@ -130,27 +120,18 @@
},
methods: {
handlePopperStyle() {
let placementMap = { top: 'bottom', bottom: 'top' };
let placement = this.popper._popper.getAttribute('x-placement').split('-')[0];
let origin = placementMap[placement];
addClass(this.popper._popper, placement);
removeClass(this.popper._popper, placementMap[placement]);
this.popper._popper.style.transformOrigin = `center ${ origin }`;
handleMouseEnter() {
this.hovering = true;
this.$refs.tooltip.showPopper = true;
},
handleMouseLeave() {
this.hovering = false;
this.$refs.tooltip.showPopper = false;
},
updatePopper() {
if (this.popper) {
clearTimeout(this.timeout);
this.popper.update();
this.handlePopperStyle();
} else {
this.popper = new Popper(this.$refs.button, this.$refs.pop, { gpuAcceleration: false, placement: 'top' });
this.popper.onCreate(() => {
this.handlePopperStyle();
});
this.updatePopper();
}
this.$refs.tooltip.updatePopper();
},
setPosition(newPos) {
@ -169,6 +150,7 @@
},
onSliderClick(event) {
if (this.disabled) return;
var currentX = event.clientX;
var sliderOffsetLeft = this.$refs.slider.getBoundingClientRect().left;
var newPos = (currentX - sliderOffsetLeft) / this.$sliderWidth * 100;
@ -192,6 +174,7 @@
onDragging(event) {
if (this.dragging) {
this.$refs.tooltip.showPopper = true;
this.currentX = event.clientX;
var diff = (this.currentX - this.startX) / this.$sliderWidth * 100;
this.newPos = this.startPos + diff;
@ -202,6 +185,7 @@
onDragEnd() {
if (this.dragging) {
this.dragging = false;
this.$refs.tooltip.showPopper = false;
this.setPosition(this.newPos);
window.removeEventListener('mousemove', this.onDragging);
window.removeEventListener('mouseup', this.onDragEnd);
@ -209,6 +193,7 @@
},
onButtonDown(event) {
if (this.disabled) return;
this.onDragStart(event);
window.addEventListener('mousemove', this.onDragging);
window.addEventListener('mouseup', this.onDragEnd);
@ -220,10 +205,6 @@
return parseInt(getStyle(this.$refs.slider, 'width'), 10);
},
showTip() {
return this.dragging || this.hovering;
},
stops() {
let stopCount = (this.max - this.value) / this.step;
let result = [];
@ -245,12 +226,6 @@
this.$nextTick(() => {
this.inputValue = this.inputValue || this.value;
});
},
beforeDestroy() {
if (this.popper) {
this.popper.destroy();
}
}
};
</script>

View File

@ -377,8 +377,9 @@
--------------------------*/
--slider-main-background-color: var(--color-primary);
--slider-runway-background-color: #e5e9f2;
--slider-runway-hover-color: #1d8ce0;
--slider-button-hover-color: #1d8ce0;
--slider-stop-background-color: #c0ccda;
--slider-disable-color: #c0ccda;
/*Steps
--------------------------*/

View File

@ -1,5 +1,6 @@
@charset "UTF-8";
@import "./input-number.css";
@import "./tooltip.css";
@import "./common/var.css";
@component-namespace el {
@ -19,6 +20,42 @@
margin-right: 160px;
width: auto;
}
&.disabled {
cursor: default;
.el-slider__bar, .el-slider__button {
background-color: var(--slider-disable-color);
}
.el-slider__button-wrapper {
&:hover,
&.hover {
cursor: not-allowed;
}
&.dragging {
cursor: not-allowed;
}
}
.el-slider__button {
&:hover,
&.hover,
&.dragging {
transform: scale(1);
}
&:hover,
&.hover {
cursor: not-allowed;
}
&.dragging {
cursor: not-allowed;
}
}
}
}
@e input {
@ -41,60 +78,42 @@
top: -16px;
transform: translateX(-50%);
background-color: transparent;
text-align: center;
.el-tooltip {
margin-top: 9px;
}
&:hover,
&.hover {
cursor: grab;
}
&.dragging {
cursor: grabbing;
}
}
@e button {
size: 12px;
background-color: var(--slider-main-background-color);
border-radius: 50%;
position: absolute;
top: 12px;
left: 12px;
cursor: pointer;
transition: .2s;
&:hover,
&.hover,
&.dragging {
transform: scale(1.5);
background-color: #1d8ce0;
}
}
@e pop {
@utils-user-select none;
font-size: 12px;
line-height: 26px;
text-align: center;
size: 26px;
border-radius: 50%;
background-color: var(--slider-main-background-color);
color: #fff;
cursor: default;
z-index: var(--index-top);
transition: transform .3s, opacity .3s;
transform-origin: center bottom;
&::before {
triangle: 9px top var(--slider-main-background-color);
position: absolute;
top: -14px;
left: 4px;
background-color: var(--slider-button-hover-color);
}
&::after {
triangle: 9px bottom var(--slider-main-background-color);
position: absolute;
bottom: -14px;
left: 4px;
&:hover,
&.hover {
cursor: grab;
}
&.top::after {
content: '';
}
&.bottom::before {
content: '';
&.dragging {
cursor: grabbing;
}
}
@ -105,11 +124,5 @@
background-color: var(--slider-stop-background-color);
transform: translateX(-50%);
}
.popper-fade-enter,
.popper-fade-leave-active {
transform: scale(0.1);
opacity: 0;
}
}
}

View File

@ -4,8 +4,7 @@ import Slider from 'packages/slider';
describe('Slider', () => {
it('create', () => {
const vm = createTest(Slider);
const popup = vm.$el.querySelector('.el-slider__pop');
expect(popup.textContent).to.equal('0');
expect(vm.value).to.equal(0);
});
it('should not exceed min and max', done => {
@ -36,7 +35,7 @@ describe('Slider', () => {
}, 100);
});
it('show tooltip', done => {
it('show tooltip', () => {
const vm = createVue({
template: `
<div>
@ -52,14 +51,10 @@ describe('Slider', () => {
}
}, true);
const slider = vm.$children[0];
const popup = vm.$el.querySelector('.el-slider__pop');
slider.onDragStart({ clientX: 0 });
vm.$nextTick(() => {
expect(popup.style.display).to.not.equal('none');
slider.onDragEnd();
expect(slider.showTip).to.false;
done();
});
slider.handleMouseEnter();
expect(slider.$refs.tooltip.showPopper).to.true;
slider.handleMouseLeave();
expect(slider.$refs.tooltip.showPopper).to.false;
});
it('drag', done => {
@ -110,6 +105,31 @@ describe('Slider', () => {
}, 150);
});
it('disabled', done => {
const vm = createVue({
template: `
<div>
<el-slider v-model="value" disabled></el-slider>
</div>
`,
data() {
return {
value: 0
};
}
}, true);
const slider = vm.$children[0];
setTimeout(() => {
slider.onButtonDown({ clientX: 0 });
slider.onDragging({ clientX: 100 });
slider.onDragEnd();
slider.onSliderClick({ clientX: 200 });
expect(vm.value).to.equal(0);
done();
}, 100);
});
it('show input', done => {
const vm = createVue({
template: `