Merge pull request #1580 from SergioCrisostomo/2.0
Time-Picker new feature: allow steps in lists
This commit is contained in:
commit
06b2a84839
6 changed files with 114 additions and 38 deletions
|
@ -1,18 +1,18 @@
|
||||||
<template>
|
<template>
|
||||||
<div :class="classes">
|
<div :class="classes">
|
||||||
<div :class="[prefixCls+ '-list']" ref="hours">
|
<div :class="[prefixCls+ '-list']" ref="hours">
|
||||||
<ul :class="[prefixCls + '-ul']" @click="handleClickHours">
|
<ul :class="[prefixCls + '-ul']">
|
||||||
<li :class="getCellCls(item)" v-for="(item, index) in hoursList" v-show="!item.hide" :index="index">{{ formatTime(item.text) }}</li>
|
<li :class="getCellCls(item)" v-for="item in hoursList" v-show="!item.hide" @click="handleClick('hours', item)">{{ formatTime(item.text) }}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div :class="[prefixCls+ '-list']" ref="minutes">
|
<div :class="[prefixCls+ '-list']" ref="minutes">
|
||||||
<ul :class="[prefixCls + '-ul']" @click="handleClickMinutes">
|
<ul :class="[prefixCls + '-ul']">
|
||||||
<li :class="getCellCls(item)" v-for="(item, index) in minutesList" v-show="!item.hide" :index="index">{{ formatTime(item.text) }}</li>
|
<li :class="getCellCls(item)" v-for="item in minutesList" v-show="!item.hide" @click="handleClick('minutes', item)">{{ formatTime(item.text) }}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div :class="[prefixCls+ '-list']" v-show="showSeconds" ref="seconds">
|
<div :class="[prefixCls+ '-list']" v-show="showSeconds" ref="seconds">
|
||||||
<ul :class="[prefixCls + '-ul']" @click="handleClickSeconds">
|
<ul :class="[prefixCls + '-ul']">
|
||||||
<li :class="getCellCls(item)" v-for="(item, index) in secondsList" v-show="!item.hide" :index="index">{{ formatTime(item.text) }}</li>
|
<li :class="getCellCls(item)" v-for="item in secondsList" v-show="!item.hide" @click="handleClick('seconds', item)">{{ formatTime(item.text) }}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -41,10 +41,15 @@
|
||||||
showSeconds: {
|
showSeconds: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
|
},
|
||||||
|
steps: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
spinerSteps: [1, 1, 1].map((one, i) => Math.abs(this.steps[i]) || one),
|
||||||
prefixCls: prefixCls,
|
prefixCls: prefixCls,
|
||||||
compiled: false
|
compiled: false
|
||||||
};
|
};
|
||||||
|
@ -60,6 +65,7 @@
|
||||||
},
|
},
|
||||||
hoursList () {
|
hoursList () {
|
||||||
let hours = [];
|
let hours = [];
|
||||||
|
const step = this.spinerSteps[0];
|
||||||
const hour_tmpl = {
|
const hour_tmpl = {
|
||||||
text: 0,
|
text: 0,
|
||||||
selected: false,
|
selected: false,
|
||||||
|
@ -67,7 +73,7 @@
|
||||||
hide: false
|
hide: false
|
||||||
};
|
};
|
||||||
|
|
||||||
for (let i = 0; i < 24; i++) {
|
for (let i = 0; i < 24; i += step) {
|
||||||
const hour = deepCopy(hour_tmpl);
|
const hour = deepCopy(hour_tmpl);
|
||||||
hour.text = i;
|
hour.text = i;
|
||||||
|
|
||||||
|
@ -83,6 +89,7 @@
|
||||||
},
|
},
|
||||||
minutesList () {
|
minutesList () {
|
||||||
let minutes = [];
|
let minutes = [];
|
||||||
|
const step = this.spinerSteps[1];
|
||||||
const minute_tmpl = {
|
const minute_tmpl = {
|
||||||
text: 0,
|
text: 0,
|
||||||
selected: false,
|
selected: false,
|
||||||
|
@ -90,7 +97,7 @@
|
||||||
hide: false
|
hide: false
|
||||||
};
|
};
|
||||||
|
|
||||||
for (let i = 0; i < 60; i++) {
|
for (let i = 0; i < 60; i += step) {
|
||||||
const minute = deepCopy(minute_tmpl);
|
const minute = deepCopy(minute_tmpl);
|
||||||
minute.text = i;
|
minute.text = i;
|
||||||
|
|
||||||
|
@ -101,11 +108,11 @@
|
||||||
if (this.minutes === i) minute.selected = true;
|
if (this.minutes === i) minute.selected = true;
|
||||||
minutes.push(minute);
|
minutes.push(minute);
|
||||||
}
|
}
|
||||||
|
|
||||||
return minutes;
|
return minutes;
|
||||||
},
|
},
|
||||||
secondsList () {
|
secondsList () {
|
||||||
let seconds = [];
|
let seconds = [];
|
||||||
|
const step = this.spinerSteps[2];
|
||||||
const second_tmpl = {
|
const second_tmpl = {
|
||||||
text: 0,
|
text: 0,
|
||||||
selected: false,
|
selected: false,
|
||||||
|
@ -113,7 +120,7 @@
|
||||||
hide: false
|
hide: false
|
||||||
};
|
};
|
||||||
|
|
||||||
for (let i = 0; i < 60; i++) {
|
for (let i = 0; i < 60; i += step) {
|
||||||
const second = deepCopy(second_tmpl);
|
const second = deepCopy(second_tmpl);
|
||||||
second.text = i;
|
second.text = i;
|
||||||
|
|
||||||
|
@ -138,24 +145,11 @@
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
handleClickHours (event) {
|
handleClick (type, cell) {
|
||||||
this.handleClick('hours', event);
|
if (cell.disabled) return;
|
||||||
},
|
const data = {};
|
||||||
handleClickMinutes (event) {
|
data[type] = cell.text;
|
||||||
this.handleClick('minutes', event);
|
this.$emit('on-change', data);
|
||||||
},
|
|
||||||
handleClickSeconds (event) {
|
|
||||||
this.handleClick('seconds', event);
|
|
||||||
},
|
|
||||||
handleClick (type, event) {
|
|
||||||
const target = event.target;
|
|
||||||
if (target.tagName === 'LI') {
|
|
||||||
const cell = this[`${type}List`][parseInt(event.target.getAttribute('index'))];
|
|
||||||
if (cell.disabled) return;
|
|
||||||
const data = {};
|
|
||||||
data[type] = cell.text;
|
|
||||||
this.$emit('on-change', data);
|
|
||||||
}
|
|
||||||
this.$emit('on-pick-click');
|
this.$emit('on-pick-click');
|
||||||
},
|
},
|
||||||
scroll (type, index) {
|
scroll (type, index) {
|
||||||
|
@ -183,20 +177,24 @@
|
||||||
},
|
},
|
||||||
formatTime (text) {
|
formatTime (text) {
|
||||||
return text < 10 ? '0' + text : text;
|
return text < 10 ? '0' + text : text;
|
||||||
|
},
|
||||||
|
getItemIndex(type, val){
|
||||||
|
const item = this[`${type}List`].find(obj => obj.text == val);
|
||||||
|
return this[`${type}List`].indexOf(item);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
hours (val) {
|
hours (val) {
|
||||||
if (!this.compiled) return;
|
if (!this.compiled) return;
|
||||||
this.scroll('hours', val);
|
this.scroll('hours', this.getItemIndex('hours', val));
|
||||||
},
|
},
|
||||||
minutes (val) {
|
minutes (val) {
|
||||||
if (!this.compiled) return;
|
if (!this.compiled) return;
|
||||||
this.scroll('minutes', val);
|
this.scroll('minutes', this.getItemIndex('minutes', val));
|
||||||
},
|
},
|
||||||
seconds (val) {
|
seconds (val) {
|
||||||
if (!this.compiled) return;
|
if (!this.compiled) return;
|
||||||
this.scroll('seconds', val);
|
this.scroll('seconds', this.getItemIndex('seconds', val));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
|
@ -204,4 +202,4 @@
|
||||||
this.$nextTick(() => this.compiled = true);
|
this.$nextTick(() => this.compiled = true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
<time-spinner
|
<time-spinner
|
||||||
ref="timeSpinner"
|
ref="timeSpinner"
|
||||||
:show-seconds="showSeconds"
|
:show-seconds="showSeconds"
|
||||||
|
:steps="steps"
|
||||||
:hours="hours"
|
:hours="hours"
|
||||||
:minutes="minutes"
|
:minutes="minutes"
|
||||||
:seconds="seconds"
|
:seconds="seconds"
|
||||||
|
@ -39,6 +40,12 @@
|
||||||
name: 'TimePicker',
|
name: 'TimePicker',
|
||||||
mixins: [ Mixin, Locale ],
|
mixins: [ Mixin, Locale ],
|
||||||
components: { TimeSpinner, Confirm },
|
components: { TimeSpinner, Confirm },
|
||||||
|
props: {
|
||||||
|
steps: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
}
|
||||||
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
prefixCls: prefixCls,
|
prefixCls: prefixCls,
|
||||||
|
@ -113,4 +120,4 @@
|
||||||
if (this.$parent && this.$parent.$options.name === 'DatePicker') this.showDate = true;
|
if (this.$parent && this.$parent.$options.name === 'DatePicker') this.showDate = true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -32,7 +32,6 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import Vue from 'vue';
|
|
||||||
import iInput from '../../components/input/input.vue';
|
import iInput from '../../components/input/input.vue';
|
||||||
import Drop from '../../components/select/dropdown.vue';
|
import Drop from '../../components/select/dropdown.vue';
|
||||||
import clickoutside from '../../directives/clickoutside';
|
import clickoutside from '../../directives/clickoutside';
|
||||||
|
@ -397,7 +396,7 @@
|
||||||
let isConfirm = this.confirm;
|
let isConfirm = this.confirm;
|
||||||
const type = this.type;
|
const type = this.type;
|
||||||
|
|
||||||
this.picker = new Vue(this.panel).$mount(this.$refs.picker);
|
this.picker = this.Panel.$mount(this.$refs.picker);
|
||||||
if (type === 'datetime' || type === 'datetimerange') {
|
if (type === 'datetime' || type === 'datetimerange') {
|
||||||
isConfirm = true;
|
isConfirm = true;
|
||||||
this.picker.showTime = true;
|
this.picker.showTime = true;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import Vue from 'vue';
|
||||||
import Picker from '../picker.vue';
|
import Picker from '../picker.vue';
|
||||||
import DatePanel from '../panel/date.vue';
|
import DatePanel from '../panel/date.vue';
|
||||||
import DateRangePanel from '../panel/date-range.vue';
|
import DateRangePanel from '../panel/date-range.vue';
|
||||||
|
@ -31,6 +32,7 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.panel = getPanel(this.type);
|
const panel = getPanel(this.type);
|
||||||
|
this.Panel = new Vue(panel);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import Vue from 'vue';
|
||||||
import Picker from '../picker.vue';
|
import Picker from '../picker.vue';
|
||||||
import TimePanel from '../panel/time.vue';
|
import TimePanel from '../panel/time.vue';
|
||||||
import TimeRangePanel from '../panel/time-range.vue';
|
import TimeRangePanel from '../panel/time-range.vue';
|
||||||
|
@ -21,6 +22,10 @@ export default {
|
||||||
},
|
},
|
||||||
default: 'time'
|
default: 'time'
|
||||||
},
|
},
|
||||||
|
steps: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
value: {}
|
value: {}
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
|
@ -31,6 +36,11 @@ export default {
|
||||||
this.currentValue = '';
|
this.currentValue = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.panel = getPanel(this.type);
|
const Panel = Vue.extend(getPanel(this.type));
|
||||||
|
this.Panel = new Panel({
|
||||||
|
propsData: {
|
||||||
|
steps: this.steps
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
60
test/unit/specs/time-spinner.spec.js
Normal file
60
test/unit/specs/time-spinner.spec.js
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
import { createVue, destroyVM } from '../util';
|
||||||
|
|
||||||
|
describe('TimePicker.vue', () => {
|
||||||
|
let vm;
|
||||||
|
afterEach(() => {
|
||||||
|
destroyVM(vm);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create a TimePicker component with hours, minutes and seconds', done => {
|
||||||
|
vm = createVue(`
|
||||||
|
<Time-Picker></Time-Picker>
|
||||||
|
`);
|
||||||
|
const picker = vm.$children[0];
|
||||||
|
picker.handleIconClick(); // open the picker panels
|
||||||
|
|
||||||
|
vm.$nextTick(() => {
|
||||||
|
const spiners = picker.$el.querySelectorAll('.ivu-time-picker-cells-list');
|
||||||
|
expect(spiners.length).to.equal(3); // hh:mm:ss
|
||||||
|
expect(spiners[0].querySelectorAll('.ivu-time-picker-cells-cell').length).to.equal(24);
|
||||||
|
expect(spiners[1].querySelectorAll('.ivu-time-picker-cells-cell').length).to.equal(60);
|
||||||
|
expect(spiners[2].querySelectorAll('.ivu-time-picker-cells-cell').length).to.equal(60);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create a TimePicker component with only hours and minutes', done => {
|
||||||
|
vm = createVue(`
|
||||||
|
<Time-Picker format="HH:mm"></Time-Picker>
|
||||||
|
`);
|
||||||
|
const picker = vm.$children[0];
|
||||||
|
picker.handleIconClick(); // open the picker panels
|
||||||
|
|
||||||
|
vm.$nextTick(() => {
|
||||||
|
const spiners = picker.$el.querySelectorAll('.ivu-time-picker-cells-list');
|
||||||
|
expect([...spiners].filter(el => el.style.display != 'none').length).to.equal(2); // hh:mm
|
||||||
|
expect(spiners[0].querySelectorAll('.ivu-time-picker-cells-cell').length).to.equal(24);
|
||||||
|
expect(spiners[1].querySelectorAll('.ivu-time-picker-cells-cell').length).to.equal(60);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create a TimePicker component with steps of 15 minutes', done => {
|
||||||
|
vm = createVue(`
|
||||||
|
<Time-Picker :steps="[1, 15]"></Time-Picker>
|
||||||
|
`);
|
||||||
|
const picker = vm.$children[0];
|
||||||
|
picker.handleIconClick(); // open the picker panels
|
||||||
|
|
||||||
|
vm.$nextTick(() => {
|
||||||
|
const spiners = picker.$el.querySelectorAll('.ivu-time-picker-cells-list');
|
||||||
|
const minutesList = [...spiners[1].querySelectorAll('.ivu-time-picker-cells-cell')];
|
||||||
|
|
||||||
|
expect(spiners[0].querySelectorAll('.ivu-time-picker-cells-cell').length).to.equal(24);
|
||||||
|
expect(minutesList.map(el => el.textContent).join(',')).to.equal('00,15,30,45');
|
||||||
|
expect(spiners[1].querySelectorAll('.ivu-time-picker-cells-cell').length).to.equal(4);
|
||||||
|
expect(spiners[2].querySelectorAll('.ivu-time-picker-cells-cell').length).to.equal(60);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Add table
Reference in a new issue