Implemented Slider Component
parent
92b3987ebf
commit
82c1cf6258
|
@ -16,6 +16,7 @@
|
|||
<router-link to="/radiobutton">● RadioButton</router-link>
|
||||
<router-link to="/rating">● Rating</router-link>
|
||||
<router-link to="/selectbutton">● SelectButton</router-link>
|
||||
<router-link to="/slider">● Slider</router-link>
|
||||
<router-link to="/spinner">● Spinner</router-link>
|
||||
<router-link to="/textarea">● Textarea</router-link>
|
||||
<router-link to="/togglebutton">● ToggleButton</router-link>
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
@import '../../components/panel/Panel.css';
|
||||
@import '../../components/radiobutton/RadioButton.css';
|
||||
@import '../../components/rating/Rating.css';
|
||||
@import '../../components/slider/Slider.css';
|
||||
@import '../../components/spinner/Spinner.css';
|
||||
@import '../../components/tabview/TabView.css';
|
||||
@import '../../components/textarea/Textarea.css';
|
||||
|
|
|
@ -168,7 +168,7 @@ export default {
|
|||
let item = event.currentTarget;
|
||||
|
||||
switch (event.which) {
|
||||
//up arrow
|
||||
//down
|
||||
case 40:
|
||||
var nextItem = this.findNextItem(item);
|
||||
if(nextItem) {
|
||||
|
@ -178,7 +178,7 @@ export default {
|
|||
event.preventDefault();
|
||||
break;
|
||||
|
||||
//down arrow
|
||||
//up
|
||||
case 38:
|
||||
var prevItem = this.findPrevItem(item);
|
||||
if(prevItem) {
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
.p-slider {
|
||||
position: relative;
|
||||
text-align: left;
|
||||
}
|
||||
.p-slider .p-slider-handle {
|
||||
position: absolute;
|
||||
width: 1.2em;
|
||||
height: 1.2em;
|
||||
cursor: default;
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
}
|
||||
.p-slider .p-slider-range {
|
||||
position: absolute;
|
||||
font-size: .7em;
|
||||
display: block;
|
||||
border: 0;
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
.p-slider-horizontal {
|
||||
height: .8em;
|
||||
}
|
||||
.p-slider-horizontal .p-slider-handle {
|
||||
top: -.3em;
|
||||
margin-left: -.6em;
|
||||
}
|
||||
.p-slider-horizontal .p-slider-range {
|
||||
top: 0;
|
||||
height: 100%;
|
||||
}
|
||||
.p-slider-vertical {
|
||||
width: .8em;
|
||||
height: 100px;
|
||||
}
|
||||
.p-slider-vertical .p-slider-handle {
|
||||
left: -.3em;
|
||||
margin-left: 0;
|
||||
margin-bottom: -.6em;
|
||||
}
|
||||
.p-slider-vertical .p-slider-range {
|
||||
left: 0;
|
||||
width: 100%;
|
||||
bottom: 0;
|
||||
}
|
|
@ -0,0 +1,320 @@
|
|||
<template>
|
||||
<div :class="containerClass" @click="onBarClick" ref="container">
|
||||
<span class="p-slider-range" :style="rangeStyle"></span>
|
||||
<span v-if="!range" class="p-slider-handle" :style="handleStyle" @mousedown="onHandleMouseDown($event)" @keydown="onHandleKeyDown($event)" tabindex="0"></span>
|
||||
<span v-if="range" class="p-slider-handle" :style="rangeStartHandleStyle" @mousedown="onHandleMouseDown($event, 0)" @keydown="onHandleKeyDown($event, 0)" tabindex="0"></span>
|
||||
<span v-if="range" class="p-slider-handle" :style="rangeEndHandleStyle" @mousedown="onHandleMouseDown($event, 1)" @keydown="onHandleKeyDown($event, 1)" tabindex="0"></span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DomHandler from '../utils/DomHandler';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
value: [Number,Array],
|
||||
disabled: Boolean,
|
||||
step: Number,
|
||||
range: Boolean,
|
||||
min: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
max: {
|
||||
type: Number,
|
||||
default: 100
|
||||
},
|
||||
orientation: {
|
||||
type: String,
|
||||
default: 'horizontal'
|
||||
}
|
||||
},
|
||||
dragging: false,
|
||||
handleIndex: null,
|
||||
initX: null,
|
||||
initY: null,
|
||||
barWidth: null,
|
||||
barHeight: null,
|
||||
dragListener: null,
|
||||
mouseupListener: null,
|
||||
beforeDestroy() {
|
||||
this.unbindDragListeners();
|
||||
},
|
||||
methods: {
|
||||
updateDomData() {
|
||||
let rect = this.$refs.container.getBoundingClientRect();
|
||||
this.initX = rect.left + DomHandler.getWindowScrollLeft();
|
||||
this.initY = rect.top + DomHandler.getWindowScrollTop();
|
||||
this.barWidth = this.$refs.container.offsetWidth;
|
||||
this.barHeight = this.$refs.container.offsetHeight;
|
||||
},
|
||||
setValueFromHandlePosition(event, handlePosition) {
|
||||
let newValue = (this.max - this.min) * (handlePosition / 100) + this.min;
|
||||
|
||||
if (this.range) {
|
||||
if (this.step)
|
||||
this.handleStepChange(event, newValue, this.value[this.handleIndex]);
|
||||
else
|
||||
this.updateModel(event, newValue);
|
||||
}
|
||||
else {
|
||||
if (this.step)
|
||||
this.handleStepChange(event, newValue, this.value);
|
||||
else
|
||||
this.updateModel(event, newValue);
|
||||
}
|
||||
},
|
||||
onSlide(event) {
|
||||
let handlePosition = this.horizontal ? ((event.pageX - this.initX) * 100) / (this.barWidth) : (((this.initY + this.barHeight) - event.pageY) * 100) / (this.barHeight);
|
||||
this.setValueFromHandlePosition(event, handlePosition);
|
||||
},
|
||||
handleStepChange(event, newValue, oldValue) {
|
||||
let diff = (newValue - oldValue);
|
||||
let val = oldValue;
|
||||
|
||||
if (diff < 0)
|
||||
val = oldValue + Math.ceil(newValue / this.step - oldValue / this.step) * this.step;
|
||||
else if (diff > 0)
|
||||
val = oldValue + Math.floor(newValue / this.step - oldValue / this.step) * this.step;
|
||||
|
||||
this.updateModel(event, val);
|
||||
},
|
||||
updateModel(event, value) {
|
||||
let newValue = value;
|
||||
let modelValue;
|
||||
|
||||
if (this.range) {
|
||||
if (this.handleIndex == 0) {
|
||||
if (newValue < this.min)
|
||||
newValue = this.min;
|
||||
else if (value > this.value[1])
|
||||
newValue = this.value[1];
|
||||
}
|
||||
else {
|
||||
if (newValue > this.max)
|
||||
newValue = this.max;
|
||||
else if (newValue < this.value[0])
|
||||
newValue = this.value[0];
|
||||
}
|
||||
|
||||
modelValue = [...this.value];
|
||||
modelValue[this.handleIndex] = Math.floor(value);
|
||||
}
|
||||
else {
|
||||
if (newValue < this.min)
|
||||
newValue = this.min;
|
||||
else if (newValue > this.max)
|
||||
newValue = this.max;
|
||||
|
||||
modelValue = Math.floor(newValue);
|
||||
}
|
||||
|
||||
this.$emit('input', modelValue);
|
||||
this.$emit('change', modelValue);
|
||||
},
|
||||
onBarClick(event) {
|
||||
if (this.disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!DomHandler.hasClass(event.target, 'p-slider-handle')) {
|
||||
this.updateDomData();
|
||||
this.onSlide(event);
|
||||
}
|
||||
},
|
||||
onHandleMouseDown(event, index) {
|
||||
if (this.disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.dragging = true;
|
||||
this.updateDomData();
|
||||
this.handleIndex = index;
|
||||
this.bindDragListeners();
|
||||
event.preventDefault();
|
||||
},
|
||||
onHandleKeyDown(event, index) {
|
||||
this.handleIndex = index;
|
||||
|
||||
switch (event.which) {
|
||||
//down
|
||||
case 40:
|
||||
if (this.vertical) {
|
||||
this.decrementValue(event, index);
|
||||
event.preventDefault();
|
||||
}
|
||||
break;
|
||||
|
||||
//up
|
||||
case 38:
|
||||
if (this.vertical) {
|
||||
this.incrementValue(event, index);
|
||||
event.preventDefault();
|
||||
}
|
||||
break;
|
||||
|
||||
//left
|
||||
case 37:
|
||||
if (this.horizontal) {
|
||||
this.decrementValue(event, index);
|
||||
event.preventDefault();
|
||||
}
|
||||
break;
|
||||
|
||||
//right
|
||||
case 39:
|
||||
if (this.horizontal) {
|
||||
this.incrementValue(event, index);
|
||||
event.preventDefault();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
},
|
||||
decrementValue(event, index) {
|
||||
let newValue;
|
||||
|
||||
if (this.range) {
|
||||
if (this.step)
|
||||
newValue = this.value[index] - this.step;
|
||||
else
|
||||
newValue = this.value[index] - 1;
|
||||
}
|
||||
else {
|
||||
if (this.step)
|
||||
newValue = this.value - this.step;
|
||||
else
|
||||
newValue = this.value - 1;
|
||||
}
|
||||
|
||||
this.updateModel(event, newValue);
|
||||
|
||||
event.preventDefault();
|
||||
},
|
||||
incrementValue(event, index) {
|
||||
let newValue;
|
||||
|
||||
if (this.range) {
|
||||
if (this.step)
|
||||
newValue = this.value[index] + this.step;
|
||||
else
|
||||
newValue = this.value[index] + 1;
|
||||
}
|
||||
else {
|
||||
if (this.step)
|
||||
newValue = this.value + this.step;
|
||||
else
|
||||
newValue = this.value + 1;
|
||||
}
|
||||
|
||||
this.updateModel(event, newValue);
|
||||
|
||||
event.preventDefault();
|
||||
},
|
||||
bindDragListeners() {
|
||||
if (!this.dragListener) {
|
||||
this.dragListener = (event) => {
|
||||
if (this.dragging) {
|
||||
this.onSlide(event);
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('mousemove', this.dragListener);
|
||||
}
|
||||
|
||||
if (!this.mouseupListener) {
|
||||
this.mouseupListener = (event) => {
|
||||
if (this.dragging) {
|
||||
this.dragging = false;
|
||||
this.$emit('slideend', {originalEvent: event, values: this.value});
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('mouseup', this.mouseupListener);
|
||||
}
|
||||
},
|
||||
unbindDragListeners() {
|
||||
if (this.dragListener) {
|
||||
document.removeEventListener('mousemove', this.dragListener);
|
||||
this.dragListener = null;
|
||||
}
|
||||
|
||||
if (this.mouseupListener) {
|
||||
document.removeEventListener('mouseup', this.mouseupListener);
|
||||
this.mouseupListener = null;
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
containerClass() {
|
||||
return ['p-slider p-component', {
|
||||
'p-disabled': this.disabled,
|
||||
'p-slider-horizontal': (this.orientation === 'horizontal'),
|
||||
'p-slider-vertical': (this.orientation === 'vertical')
|
||||
}];
|
||||
},
|
||||
horizontal() {
|
||||
return this.orientation === 'horizontal';
|
||||
},
|
||||
vertical() {
|
||||
return this.orientation === 'vertical';
|
||||
},
|
||||
rangeStyle() {
|
||||
if (this.range) {
|
||||
if (this.horizontal)
|
||||
return {'left': this.rangeStartPosition + '%', width: (this.rangeEndPosition - this.rangeStartPosition + '%')};
|
||||
else
|
||||
return {'bottom': this.rangeStartPosition + '%', height: (this.rangeEndPosition - this.rangeStartHandlePosition + '%')};
|
||||
}
|
||||
else {
|
||||
if (this.horizontal)
|
||||
return {'width': this.handlePosition + '%'};
|
||||
else
|
||||
return {'height': this.handlePosition + '%'};
|
||||
}
|
||||
},
|
||||
handleStyle() {
|
||||
if (this.horizontal)
|
||||
return {'left': this.handlePosition + '%'};
|
||||
else if (this.vertical)
|
||||
return {'bottom': this.handlePosition + '%'};
|
||||
},
|
||||
handlePosition() {
|
||||
if (this.value === 0)
|
||||
return 0;
|
||||
else if (this.value < this.min)
|
||||
return 0;
|
||||
else if (this.value > this.max)
|
||||
return 100;
|
||||
else
|
||||
return (this.value - this.min) * 100 / (this.max - this.min);
|
||||
},
|
||||
rangeStartPosition() {
|
||||
if (this.value)
|
||||
return (this.value[0] < this.min ? 0 : this.value[0] - this.min) * 100 / (this.max - this.min);
|
||||
else
|
||||
return 0;
|
||||
},
|
||||
rangeEndPosition() {
|
||||
if (this.value)
|
||||
return (this.value[1] > this.max ? 100 : this.value[1] - this.min) * 100 / (this.max - this.min);
|
||||
else
|
||||
return 0;
|
||||
},
|
||||
rangeStartHandleStyle() {
|
||||
if (this.horizontal)
|
||||
return {'left': this.rangeStartPosition + '%'};
|
||||
else if (this.vertical)
|
||||
return {'bottom': this.rangeStartPosition + '%'};
|
||||
},
|
||||
rangeEndHandleStyle() {
|
||||
if (this.horizontal)
|
||||
return {'left': this.rangeEndPosition + '%'};
|
||||
else if (this.vertical)
|
||||
return {'bottom': this.rangeEndPosition + '%'};
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -15,6 +15,7 @@ import Panel from './components/panel/Panel';
|
|||
import Rating from './components/rating/Rating';
|
||||
import RadioButton from './components/radiobutton/RadioButton';
|
||||
import SelectButton from './components/selectbutton/SelectButton';
|
||||
import Slider from './components/slider/Slider';
|
||||
import Spinner from './components/spinner/Spinner';
|
||||
import Textarea from './components/textarea/Textarea';
|
||||
import Toolbar from './components/toolbar/Toolbar';
|
||||
|
@ -43,6 +44,7 @@ Vue.component('p-panel', Panel);
|
|||
Vue.component('p-radioButton', RadioButton);
|
||||
Vue.component('p-rating', Rating);
|
||||
Vue.component('p-selectButton', SelectButton);
|
||||
Vue.component('p-slider', Slider);
|
||||
Vue.component('p-spinner', Spinner);
|
||||
Vue.component('p-tabView', TabView);
|
||||
Vue.component('p-tabPanel', TabPanel);
|
||||
|
|
|
@ -81,6 +81,11 @@ export default new Router({
|
|||
name: 'selectbutton',
|
||||
component: () => import('./views/selectbutton/SelectButtonDemo.vue')
|
||||
},
|
||||
{
|
||||
path: '/slider',
|
||||
name: 'slider',
|
||||
component: () => import('./views/slider/SliderDemo.vue')
|
||||
},
|
||||
{
|
||||
path: '/spinner',
|
||||
name: 'spinner',
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="content-section introduction">
|
||||
<div class="feature-intro">
|
||||
<h1>Slider</h1>
|
||||
<p>Slider is an input component to provide a numerical input.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-section implementation">
|
||||
<h3 class="first">Basic: {{value1}}</h3>
|
||||
<p-slider v-model="value1" />
|
||||
|
||||
<h3>Input: {{value2}}</h3>
|
||||
<p-inputtext v-model.number="value2" />
|
||||
<p-slider v-model="value2" />
|
||||
|
||||
<h3>Step: {{value3}}</h3>
|
||||
<p-slider v-model="value3" :step="20" />
|
||||
|
||||
<h3>Range: {{value4}}</h3>
|
||||
<p-slider v-model="value4" :range="true" />
|
||||
|
||||
<h3>Vertical: {{value5}}</h3>
|
||||
<p-slider v-model="value5" orientation="vertical" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
value1: null,
|
||||
value2: 50,
|
||||
value3: 20,
|
||||
value4: [20,80],
|
||||
value5: 50
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.p-slider-horizontal, .p-inputtext {
|
||||
width: 14em;
|
||||
}
|
||||
|
||||
.p-slider-vertical {
|
||||
height: 14em;
|
||||
}
|
||||
</style>
|
Loading…
Reference in New Issue