Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slider #499

Closed
wants to merge 4 commits into from
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix(slider): test
weiyongchao committed Dec 16, 2020

Unverified

No user is associated with the committer email.
commit a5319dd22607acaf892d98156f20be0fe2ffa817
83 changes: 54 additions & 29 deletions packages/element3/packages/slider/Slider.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<div
class="el-slider"
:class="{ 'is-vertical': vertical, 'el-slider--with-input': showInput }"
:class="sliderClass"
role="slider"
:aria-valuemin="min"
:aria-valuemax="max"
@@ -24,7 +24,7 @@
></el-input-number>
<div
class="el-slider__runway"
:class="{ 'show-input': showInput, disabled: sliderDisabled }"
:class="runwayClass"
:style="runwayStyle"
@click="onSliderClick"
ref="slider"
@@ -166,7 +166,7 @@ export default {
},
emits: ['update:modelValue', 'change'],
setup(props, { emit }) {
const { ctx } = getCurrentInstance()
const { proxy } = getCurrentInstance()
// data
const state = reactive({
firstValue: null,
@@ -175,15 +175,16 @@ export default {
dragging: false,
sliderSize: 1
})
const { resetSize } = useCommon(props, state, ctx)
const { resetSize } = useCommon(props, state, proxy)

useLifeCycle(props, state, ctx, resetSize)
useLifeCycle(props, state, proxy, resetSize)

const { minValue, maxValue, valueChanged, setValues } = useModel(
props,
state,
emit
)
const sliderClass = useSliderClasses(props)

const {
stops,
@@ -197,10 +198,12 @@ export default {
getStopStyle
} = useStyle(props, state, minValue, maxValue)

const runwayClass = useRunwayClasses(props, sliderDisabled)

const { onSliderClick, emitChange, setPosition } = useEvent(
props,
state,
ctx,
proxy,
emit,
minValue,
maxValue,
@@ -229,15 +232,17 @@ export default {
onSliderClick,
resetSize,
emitChange,
getStopStyle
getStopStyle,
// classs
sliderClass,
runwayClass
}
}
}

function useCommon(props, state, ctx) {
const useCommon = (props, state, proxy) => {
const { vertical } = toRefs(props)
function resetSize() {
const slider = ctx.$refs.slider
const resetSize = () => {
const slider = proxy.$refs.slider
if (slider) {
state.sliderSize = slider[`client${unref(vertical) ? 'Height' : 'Width'}`]
}
@@ -247,7 +252,7 @@ function useCommon(props, state, ctx) {
}
}

function useLifeCycle(props, state, ctx, resetSize) {
const useLifeCycle = (props, state, proxy, resetSize) => {
const { max, min, modelValue, range, label } = props
let valuetext
if (range) {
@@ -270,10 +275,10 @@ function useLifeCycle(props, state, ctx, resetSize) {
valuetext = state.firstValue
}
onMounted(() => {
ctx.$el.setAttribute('aria-valuetext', valuetext)
proxy.$el.setAttribute('aria-valuetext', valuetext)

// label screen reader
ctx.$el.setAttribute(
proxy.$el.setAttribute(
'aria-label',
// eslint-disable-next-line
label ? label : `slider between ${min} and ${max}`
@@ -284,7 +289,7 @@ function useLifeCycle(props, state, ctx, resetSize) {
onBeforeUnmount(() => window.removeEventListener('resize', resetSize))
}

function useModel(props, state, emit) {
const useModel = (props, state, emit) => {
const { dispatch } = useEmitter()
const { max, min, modelValue, range } = toRefs(props)

@@ -323,7 +328,7 @@ function useModel(props, state, emit) {
watch(min, () => setValues())
watch(max, () => setValues())

function valueChanged() {
const valueChanged = () => {
if (unref(range)) {
return ![minValue, maxValue].every(
(item, index) => unref(item) === state.oldValue[index]
@@ -333,7 +338,7 @@ function useModel(props, state, emit) {
}
}

function setValues() {
const setValues = () => {
const _max = unref(max)
const _min = unref(min)
if (_min > _max) {
@@ -385,23 +390,23 @@ function useModel(props, state, emit) {
}
}

function useEvent(
const useEvent = (
props,
state,
ctx,
proxy,
emit,
minValue,
maxValue,
sliderDisabled,
resetSize
) {
// const { emit, ctx, props } = getCurrentInstance()
) => {
// const { emit, proxy, props } = getCurrentInstance()
const { modelValue, range, vertical, min, max } = toRefs(props)

function onSliderClick(event) {
const onSliderClick = (event) => {
if (unref(sliderDisabled) || state.dragging) return
resetSize()
const slider = ctx.$refs.slider
const slider = proxy.$refs.slider
if (unref(vertical)) {
const sliderOffsetBottom = slider.getBoundingClientRect().bottom
setPosition(
@@ -414,7 +419,7 @@ function useEvent(
emitChange()
}

function emitChange() {
const emitChange = () => {
nextTick(() =>
emit(
'change',
@@ -423,10 +428,10 @@ function useEvent(
)
}

function setPosition(percent) {
const setPosition = (percent) => {
const targetValue = unref(min) + (percent * (unref(max) - unref(min))) / 100
if (!unref(range)) {
ctx.$refs.button1.setPosition(percent)
proxy.$refs.button1.setPosition(percent)
return
}
let button
@@ -438,7 +443,7 @@ function useEvent(
} else {
button = state.firstValue > state.secondValue ? 'button1' : 'button2'
}
ctx.$refs[button].setPosition(percent)
proxy.$refs[button].setPosition(percent)
}

return {
@@ -448,7 +453,7 @@ function useEvent(
}
}

function useStyle(props, state, minValue, maxValue) {
const useStyle = (props, state, minValue, maxValue) => {
const elForm = inject('elFrom', { default: '' })
const {
disabled,
@@ -556,7 +561,7 @@ function useStyle(props, state, minValue, maxValue) {
return unref(disabled) || (elForm.props || {}).disabled
})

function getStopStyle(position) {
const getStopStyle = (position) => {
return unref(vertical)
? { bottom: position + '%' }
: { left: position + '%' }
@@ -573,4 +578,24 @@ function useStyle(props, state, minValue, maxValue) {
getStopStyle
}
}
const useSliderClasses = (props) => {
return computed(() => {
return [
{
'is-vertical': props.vertical,
'el-slider--with-input': props.showInput
}
]
})
}
const useRunwayClasses = (props, sliderDisabled) => {
return computed(() => {
return [
sliderDisabled.value ? 'disabled' : '',
{
'show-input': props.showInput
}
]
})
}
</script>
82 changes: 69 additions & 13 deletions packages/element3/packages/slider/__tests__/Slider.spec.js
Original file line number Diff line number Diff line change
@@ -154,7 +154,6 @@ describe('Slider', () => {
})
})
})

it('accessibility', (done) => {
const slider = ref(0.1)
const wrapper = mount(Slider, {
@@ -227,6 +226,7 @@ describe('Slider', () => {
const wrapper = mount(Slider, {
props: {
modelValue: slider,
type: 'touchmove',
'onUpdate:modelValue': (val) => {
slider.value = val
},
@@ -265,7 +265,6 @@ describe('Slider', () => {
done()
})
})

it('show input', async () => {
const slider = ref(0)
const wrapper = mount(Slider, {
@@ -354,7 +353,69 @@ describe('Slider', () => {
})
})
})

it('min should not be greater than max', async () => {
const wrapper = mount(Slider, {
props: {
min: 100
}
})
wrapper.setProps({ max: 10 })
})
it('a range test', async () => {
var slider = [12, 18]
const wrapper = mount(Slider, {
props: {
min: 10,
modelValue: slider,
range: true
}
})
wrapper.setProps({ modelValue: [24, 25] })
wrapper.setProps({ max: 30 })
wrapper.setProps({ min: 1 })
nextTick(async () => {
await wrapper.setProps({ min: 10 })
await wrapper.setProps({ max: 11 })
await wrapper.setProps({ modelValue: [12, 8] })
})
})
it('a env test', async () => {
const wrapper = mount(Slider, {
props: {
step: 0,
showStops: true,
min: 1,
max: 5
}
})
process.env.NODE_ENV = 'test'
nextTick(() => {
wrapper.setProps({ vertical: true })
process.env.NODE_ENV = 'production'
})
})
it('should not modelValue NAN', async (done) => {
var slider = [40, 60]
const wrapper = mount(Slider, {
props: {
modelValue: slider,
range: false,
min: 50,
'onUpdate:modelValue': (val) => {
slider = val
}
}
})
wrapper.setProps({ modelValue: [40, 60] })
nextTick(async () => {
expect(slider).toEqual([40, 60])
await wrapper.setProps({ modelValue: [40, 60] })
nextTick(() => {
expect(slider).toEqual([40, 60])
done()
})
})
})
it('click', () => {
var slider = [0, 100]
const wrapper = mount(Slider, {
@@ -375,31 +436,26 @@ describe('Slider', () => {
expect(slider.value[1]).toEqual(100)
})
})

it('responsive to dynamic min and max', () => {
var slider = [50, 80]
var slider = ref(0)
const min = ref(0)
const max = ref(100)
const wrapper = mount(Slider, {
props: {
modelValue: slider,
min,
max,
range: true,
'onUpdate:modelValue': (val) => {
slider = val
}
range: true
}
})
mockSliderRunWayClientAttr(wrapper)
min.value = 60
nextTick(() => {
expect(slider).toEqual([60, 80])
wrapper.setProps({ modelValue: [60, 80] })
expect(slider).toEqual([60, 100])
wrapper.setProps({ modelValue: 0 })
min.value = 30
max.value = 40
nextTick(() => {
expect(slider).toEqual([40, 40])
expect(slider).toEqual([30, 40])
})
})
})
48 changes: 26 additions & 22 deletions packages/element3/packages/slider/src/button.vue
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@
@mouseleave="handleMouseLeave"
@mousedown="onButtonDown"
@touchstart.passive="onButtonDown"
:class="{ hover: hovering, dragging: dragging }"
:class="buttonClass"
:style="wrapperStyle"
ref="button"
tabindex="0"
@@ -25,10 +25,7 @@
<template v-slot:content>
<span>{{ formatValue }}</span>
</template>
<div
class="el-slider__button"
:class="{ hover: hovering, dragging: dragging }"
></div>
<div class="el-slider__button" :class="buttonClass"></div>
</el-tooltip>
</div>
</template>
@@ -126,7 +123,7 @@ export default {
displayTooltip,
hideTooltip
)
const buttonClass = useButtonClasses(hovering, dragging)
return {
// data
hovering,
@@ -161,17 +158,19 @@ export default {
onLeftKeyDown,
onRightKeyDown,
// ref
tooltip
tooltip,
// classs
buttonClass
}
}
}
function useToolTip(ctx) {
function displayTooltip() {
const useToolTip = (ctx) => {
const displayTooltip = () => {
ctx.tooltip && (ctx.tooltip.showPopper = true)
}
function hideTooltip() {
const hideTooltip = () => {
ctx.tooltip && (ctx.tooltip.showPopper = false)
}
return {
@@ -180,21 +179,21 @@ function useToolTip(ctx) {
}
}
function useMouseHover(displayTooltip, hideTooltip) {
const useMouseHover = (displayTooltip, hideTooltip) => {
const hovering = ref(false)
function handleMouseEnter() {
const handleMouseEnter = () => {
hovering.value = true
displayTooltip()
}
function handleMouseLeave() {
const handleMouseLeave = () => {
hovering.value = false
hideTooltip()
}
return { hovering, handleMouseEnter, handleMouseLeave }
}
function useDragAndKeyDown(
const useDragAndKeyDown = (
parent,
ctx,
emit,
@@ -208,7 +207,7 @@ function useDragAndKeyDown(
currentPosition,
displayTooltip,
hideTooltip
) {
) => {
const { resetSize, emitChange } = parent.ctx
const dragging = ref(false)
@@ -237,7 +236,7 @@ function useDragAndKeyDown(
window.addEventListener('contextmenu', onDragEnd)
}
function onDragStart(event) {
const onDragStart = (event) => {
dragging.value = true
isClick.value = true
if (event.type === 'touchstart') {
@@ -253,7 +252,7 @@ function useDragAndKeyDown(
newPosition.value = unref(startPosition)
}
function onDragging(event) {
const onDragging = (event) => {
if (unref(dragging)) {
isClick.value = false
displayTooltip()
@@ -275,7 +274,7 @@ function useDragAndKeyDown(
}
}
function onDragEnd() {
const onDragEnd = () => {
if (unref(dragging)) {
/*
* 防止在 mouseup 后立即触发 click,导致滑块有几率产生一小段位移
@@ -302,15 +301,15 @@ function useDragAndKeyDown(
// eslint-disable-next-line
//#region KeyDown methods: onLeftKeyDown, onRightKeyDown
function onLeftKeyDown() {
const onLeftKeyDown = () => {
if (unref(disabled)) return
newPosition.value =
parseFloat(unref(currentPosition)) -
(unref(step) / (unref(max) - unref(min))) * 100
setPosition(unref(newPosition))
emitChange()
}
function onRightKeyDown() {
const onRightKeyDown = () => {
if (unref(disabled)) return
newPosition.value =
parseFloat(unref(currentPosition)) +
@@ -322,7 +321,7 @@ function useDragAndKeyDown(
// eslint-disable-next-line
//#endregion
function setPosition(newPosition) {
const setPosition = (newPosition) => {
if (newPosition === null || isNaN(newPosition)) return
if (newPosition < 0) {
newPosition = 0
@@ -365,7 +364,7 @@ function useDragAndKeyDown(
}
}
function useComputed(modelValue, vertical) {
const useComputed = (modelValue, vertical) => {
const { parent } = getCurrentInstance()
const disabled = computed(() => parent.ctx.sliderDisabled)
@@ -404,4 +403,9 @@ function useComputed(modelValue, vertical) {
wrapperStyle
}
}
const useButtonClasses = (hovering, dragging) => {
return computed(() => {
return [hovering.value ? 'hover' : '', dragging.value ? 'dragging' : '']
})
}
</script>