Merge pull request #1580 from SergioCrisostomo/2.0

Time-Picker new feature: allow steps in lists
This commit is contained in:
Aresn 2017-08-13 15:40:53 +08:00 committed by GitHub
commit 06b2a84839
6 changed files with 114 additions and 38 deletions

View file

@ -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>

View file

@ -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>

View file

@ -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;

View file

@ -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);
} }
}; };

View file

@ -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
}
});
} }
}; };

View 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();
});
});
});