Commit 791d254e64d71f0251156c5ccb3a9df659d7161b

Authored by Graham Fairweather
1 parent f0c2af9d

Slider: Keyboard control like native

src/components/slider/slider.vue
@@ -8,20 +8,44 @@ @@ -8,20 +8,44 @@
8 :value="exportValue[0]" 8 :value="exportValue[0]"
9 :disabled="disabled" 9 :disabled="disabled"
10 @on-change="handleInputChange"></Input-number> 10 @on-change="handleInputChange"></Input-number>
11 - <div :class="[prefixCls + '-wrap']" ref="slider" @click.self="sliderClick"> 11 + <div
  12 + :class="[prefixCls + '-wrap']"
  13 + ref="slider" @click.self="sliderClick"
  14 + >
12 <input type="hidden" :name="name" :value="exportValue"> 15 <input type="hidden" :name="name" :value="exportValue">
13 <template v-if="showStops"> 16 <template v-if="showStops">
14 - <div :class="[prefixCls + '-stop']" v-for="item in stops" :style="{ 'left': item + '%' }" @click.self="sliderClick"></div> 17 + <div
  18 + :class="[prefixCls + '-stop']"
  19 + v-for="item in stops"
  20 + :style="{ 'left': item + '%' }"
  21 + @click.self="sliderClick"
  22 + ></div>
15 </template> 23 </template>
16 - <div :class="[prefixCls + '-bar']" :style="barStyle" @click.self="sliderClick"></div> 24 + <div
  25 + :class="[prefixCls + '-bar']"
  26 + :style="barStyle"
  27 + @click.self="sliderClick"></div>
17 <div 28 <div
18 :class="[prefixCls + '-button-wrap']" 29 :class="[prefixCls + '-button-wrap']"
19 :style="{left: minPosition + '%'}" 30 :style="{left: minPosition + '%'}"
20 @touchstart="onPointerDown($event, 'min')" 31 @touchstart="onPointerDown($event, 'min')"
21 @mousedown="onPointerDown($event, 'min')"> 32 @mousedown="onPointerDown($event, 'min')">
22 - <Tooltip :controlled="pointerDown === 'min'" placement="top" :content="tipFormat(exportValue[0])"  
23 - :disabled="tipDisabled" :always="showTip === 'always'" ref="minTooltip">  
24 - <div :class="minButtonClasses"></div> 33 + <Tooltip
  34 + :controlled="pointerDown === 'min'"
  35 + placement="top"
  36 + :content="tipFormat(exportValue[0])"
  37 + :disabled="tipDisabled"
  38 + :always="showTip === 'always'"
  39 + ref="minTooltip"
  40 + >
  41 + <div
  42 + :class="minButtonClasses"
  43 + tabindex="0"
  44 + @keydown.left="onKeyLeft($event, 'min')"
  45 + @keydown.down="onKeyLeft($event, 'min')"
  46 + @keydown.right="onKeyRight($event, 'min')"
  47 + @keydown.up="onKeyRight($event, 'min')"
  48 + ></div>
25 </Tooltip> 49 </Tooltip>
26 </div> 50 </div>
27 <div v-if="range" 51 <div v-if="range"
@@ -29,9 +53,22 @@ @@ -29,9 +53,22 @@
29 :style="{left: maxPosition + '%'}" 53 :style="{left: maxPosition + '%'}"
30 @touchstart="onPointerDown($event, 'max')" 54 @touchstart="onPointerDown($event, 'max')"
31 @mousedown="onPointerDown($event, 'max')"> 55 @mousedown="onPointerDown($event, 'max')">
32 - <Tooltip :controlled="pointerDown === 'max'" placement="top" :content="tipFormat(exportValue[1])"  
33 - :disabled="tipDisabled" :always="showTip === 'always'" ref="maxTooltip">  
34 - <div :class="maxButtonClasses"></div> 56 + <Tooltip
  57 + :controlled="pointerDown === 'max'"
  58 + placement="top"
  59 + :content="tipFormat(exportValue[1])"
  60 + :disabled="tipDisabled"
  61 + :always="showTip === 'always'"
  62 + ref="maxTooltip"
  63 + >
  64 + <div
  65 + :class="maxButtonClasses"
  66 + tabindex="0"
  67 + @keydown.left="onKeyLeft($event, 'max')"
  68 + @keydown.down="onKeyLeft($event, 'max')"
  69 + @keydown.right="onKeyRight($event, 'max')"
  70 + @keydown.up="onKeyRight($event, 'max')"
  71 + ></div>
35 </Tooltip> 72 </Tooltip>
36 </div> 73 </div>
37 </div> 74 </div>
@@ -110,7 +147,11 @@ @@ -110,7 +147,11 @@
110 startX: 0, 147 startX: 0,
111 currentX: 0, 148 currentX: 0,
112 startPos: 0, 149 startPos: 0,
113 - oldValue: val 150 + oldValue: val,
  151 + valueIndex: {
  152 + min: 0,
  153 + max: 1,
  154 + },
114 }; 155 };
115 }, 156 },
116 watch: { 157 watch: {
@@ -173,7 +214,6 @@ @@ -173,7 +214,6 @@
173 return (val[1] - this.min) / this.valueRange * 100; 214 return (val[1] - this.min) / this.valueRange * 100;
174 }, 215 },
175 barStyle () { 216 barStyle () {
176 -  
177 const style = { 217 const style = {
178 width: (this.currentValue[0] - this.min) / this.valueRange * 100 + '%' 218 width: (this.currentValue[0] - this.min) / this.valueRange * 100 + '%'
179 }; 219 };
@@ -216,6 +256,30 @@ @@ -216,6 +256,30 @@
216 max = Math.min(this.max, max); 256 max = Math.min(this.max, max);
217 return [min, max]; 257 return [min, max];
218 }, 258 },
  259 + getCurrentValue (event, type) {
  260 + if (this.disabled) {
  261 + return;
  262 + }
  263 +
  264 + const index = this.valueIndex[type];
  265 + if (typeof index === 'undefined') {
  266 + return;
  267 + }
  268 +
  269 + return this.currentValue[index];
  270 + },
  271 + onKeyLeft (event, type) {
  272 + const value = this.getCurrentValue(event, type);
  273 + if (Number.isFinite(value)) {
  274 + this.changeButtonPosition(value - this.step, type);
  275 + }
  276 + },
  277 + onKeyRight (event, type) {
  278 + const value = this.getCurrentValue(event, type);
  279 + if (Number.isFinite(value)) {
  280 + this.changeButtonPosition(value + this.step, type);
  281 + }
  282 + },
219 onPointerDown (event, type) { 283 onPointerDown (event, type) {
220 if (this.disabled) return; 284 if (this.disabled) return;
221 event.preventDefault(); 285 event.preventDefault();
src/styles/components/slider.less
@@ -34,7 +34,9 @@ @@ -34,7 +34,9 @@
34 border-radius: 50%; 34 border-radius: 50%;
35 background-color: #fff; 35 background-color: #fff;
36 transition: all @transition-time linear; 36 transition: all @transition-time linear;
  37 + outline: 0;
37 38
  39 + &:focus,
38 &:hover, 40 &:hover,
39 &-dragging 41 &-dragging
40 { 42 {