From 450cf81dedfaeb76f808771d90f37fff2a008ee7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E5=A5=95?= Date: Fri, 17 Feb 2017 19:09:59 +0800 Subject: [PATCH] Slider: add range support (#2751) --- examples/docs/en-US/slider.md | 35 +++- examples/docs/zh-CN/slider.md | 35 +++- packages/slider/src/button.vue | 156 +++++++++++++++++ packages/slider/src/main.vue | 305 ++++++++++++++++++--------------- test/unit/specs/slider.spec.js | 175 ++++++++++++++++--- 5 files changed, 542 insertions(+), 164 deletions(-) create mode 100644 packages/slider/src/button.vue diff --git a/examples/docs/en-US/slider.md b/examples/docs/en-US/slider.md index 44a0e08fb..ce43f7094 100644 --- a/examples/docs/en-US/slider.md +++ b/examples/docs/en-US/slider.md @@ -7,7 +7,8 @@ value3: 42, value4: 0, value5: 0, - value6: 0 + value6: 0, + value7: [4, 8] }; } } @@ -119,6 +120,35 @@ Set value via a input box. ``` ::: +### Range selection + +Selecting a range of values is supported. + +:::demo Setting the `range` attribute activates range mode, where the binding value is an array made up of two boundary values. +```html + + + +``` +::: + ## Attributes | Attribute | Description | Type | Accepted Values | Default | |---------- |-------------- |---------- |-------------------------------- |-------- | @@ -126,9 +156,10 @@ Set value via a input box. | max | maximum value | number | — | 100 | | disabled | whether Slider is disabled | boolean | — | false | | step | step size | number | — | 1 | -| show-input | whether to display an input box | boolean | — | false | +| show-input | whether to display an input box, works when `range` is false | boolean | — | false | | show-input-controls | whether to display control buttons when `show-input` is true | boolean | — | true | | show-stops | whether to display breakpoints | boolean | — | false | +| range | whether to select a range | boolean | — | false | ## Events | Event Name | Description | Parameters | diff --git a/examples/docs/zh-CN/slider.md b/examples/docs/zh-CN/slider.md index 6ea8be003..b5cb8bc25 100644 --- a/examples/docs/zh-CN/slider.md +++ b/examples/docs/zh-CN/slider.md @@ -7,7 +7,8 @@ value3: 42, value4: 0, value5: 0, - value6: 0 + value6: 0, + value7: [4, 8] }; } } @@ -143,6 +144,35 @@ ``` ::: +### 范围选择 + +支持选择某一数值范围 + +:::demo 设置`range`即可开启范围选择,此时绑定值是一个数组,其元素分别为最小边界值和最大边界值 +```html + + + +``` +::: + ### Attributes | 参数 | 说明 | 类型 | 可选值 | 默认值 | |---------- |-------------- |---------- |-------------------------------- |-------- | @@ -150,9 +180,10 @@ | max | 最大值 | number | — | 100 | | disabled | 是否禁用 | boolean | — | false | | step | 步长 | number | — | 1 | -| show-input | 是否显示输入框 | boolean | — | false | +| show-input | 是否显示输入框,仅在非范围选择时有效 | boolean | — | false | | show-input-controls | 在显示输入框的情况下,是否显示输入框的控制按钮 | boolean | — | true| | show-stops | 是否显示间断点 | boolean | — | false | +| range | 是否为范围选择 | boolean | — | false | ### Events | 事件名称 | 说明 | 回调参数 | diff --git a/packages/slider/src/button.vue b/packages/slider/src/button.vue new file mode 100644 index 000000000..37c7fd35a --- /dev/null +++ b/packages/slider/src/button.vue @@ -0,0 +1,156 @@ + + + \ No newline at end of file diff --git a/packages/slider/src/main.vue b/packages/slider/src/main.vue index 9926be6ec..9db0f5793 100644 --- a/packages/slider/src/main.vue +++ b/packages/slider/src/main.vue @@ -2,9 +2,8 @@
-
+ @click="onSliderClick" + ref="slider">
- - {{ value }} -
-
+ class="el-slider__bar" + :style="{ + width: barWidth, + left: barLeft + }"> +
+ + + + +
-
diff --git a/test/unit/specs/slider.spec.js b/test/unit/specs/slider.spec.js index 87941cac5..b7d80db1e 100644 --- a/test/unit/specs/slider.spec.js +++ b/test/unit/specs/slider.spec.js @@ -37,7 +37,7 @@ describe('Slider', () => { done(); }); }); - }, 100); + }, 10); }); it('show tooltip', () => { @@ -55,7 +55,7 @@ describe('Slider', () => { }; } }, true); - const slider = vm.$children[0]; + const slider = vm.$children[0].$children[0]; slider.handleMouseEnter(); expect(slider.$refs.tooltip.showPopper).to.true; slider.handleMouseLeave(); @@ -76,14 +76,14 @@ describe('Slider', () => { }; } }, true); - const slider = vm.$children[0]; + const slider = vm.$children[0].$children[0]; + slider.onButtonDown({ clientX: 0 }); + slider.onDragging({ clientX: 100 }); + slider.onDragEnd(); setTimeout(() => { - slider.onButtonDown({ clientX: 0 }); - slider.onDragging({ clientX: 100 }); - slider.onDragEnd(); expect(vm.value > 0).to.true; done(); - }, 150); + }, 10); }); it('step', done => { @@ -100,14 +100,14 @@ describe('Slider', () => { }; } }, true); - const slider = vm.$children[0]; + const slider = vm.$children[0].$children[0]; + slider.onButtonDown({ clientX: 0 }); + slider.onDragging({ clientX: 100 }); + slider.onDragEnd(); setTimeout(() => { - slider.onButtonDown({ clientX: 0 }); - slider.onDragging({ clientX: 100 }); - slider.onDragEnd(); expect(vm.value > 0.4 && vm.value < 0.6).to.true; done(); - }, 150); + }, 10); }); it('click', done => { @@ -130,8 +130,8 @@ describe('Slider', () => { setTimeout(() => { expect(vm.value > 0).to.true; done(); - }, 150); - }, 150); + }, 10); + }, 10); }); it('disabled', done => { @@ -148,15 +148,14 @@ describe('Slider', () => { }; } }, true); - const slider = vm.$children[0]; + const slider = vm.$children[0].$children[0]; + slider.onButtonDown({ clientX: 0 }); + slider.onDragging({ clientX: 100 }); + slider.onDragEnd(); setTimeout(() => { - slider.onButtonDown({ clientX: 0 }); - slider.onDragging({ clientX: 100 }); - slider.onDragEnd(); - slider.onSliderClick({ clientX: 200 }); expect(vm.value).to.equal(0); done(); - }, 100); + }, 10); }); it('show input', done => { @@ -180,17 +179,145 @@ describe('Slider', () => { setTimeout(() => { expect(vm.value).to.equal(40); done(); - }, 150); - }, 150); + }, 10); + }, 10); }); - it('show stops', done => { + it('show stops', () => { vm = createTest(Slider, { showStops: true, step: 10 }, true); const stops = vm.$el.querySelectorAll('.el-slider__stop'); expect(stops.length).to.equal(9); - done(); + }); + + describe('range', () => { + it('basic ranged slider', () => { + vm = createVue({ + template: ` +
+ +
+ `, + + data() { + return { + value: [10, 20] + }; + } + }, true); + const buttons = vm.$children[0].$children; + expect(buttons.length).to.equal(2); + }); + + it('should not exceed min and max', done => { + vm = createVue({ + template: ` +
+ + +
+ `, + + data() { + return { + value: [50, 60] + }; + } + }, true); + setTimeout(() => { + vm.value = [40, 60]; + setTimeout(() => { + expect(vm.value).to.deep.equal([50, 60]); + vm.value = [50, 120]; + setTimeout(() => { + expect(vm.value).to.deep.equal([50, 100]); + done(); + }, 10); + }, 10); + }, 10); + }); + + it('click', done => { + vm = createVue({ + template: ` +
+ +
+ `, + + data() { + return { + value: [0, 100] + }; + } + }, true); + const slider = vm.$children[0]; + setTimeout(() => { + slider.onSliderClick({ clientX: 100 }); + setTimeout(() => { + expect(vm.value[0] > 0).to.true; + expect(vm.value[1]).to.equal(100); + done(); + }, 10); + }, 10); + }); + + it('responsive to dynamic min and max', done => { + vm = createVue({ + template: ` +
+ + +
+ `, + + data() { + return { + min: 0, + max: 100, + value: [50, 80] + }; + } + }, true); + setTimeout(() => { + vm.min = 60; + setTimeout(() => { + expect(vm.value).to.deep.equal([60, 80]); + vm.min = 30; + vm.max = 40; + setTimeout(() => { + expect(vm.value).to.deep.equal([40, 40]); + done(); + }, 10); + }, 10); + }, 10); + }); + + it('show stops', done => { + vm = createVue({ + template: ` +
+ +
+ `, + + data() { + return { + value: [30, 60] + }; + } + }, true); + setTimeout(() => { + const stops = vm.$el.querySelectorAll('.el-slider__stop'); + expect(stops.length).to.equal(5); + done(); + }, 10); + }); }); });