blob: 50f246bd035b20e5b61159e48ef64c6935728f80 [file] [log] [blame]
/** * Licensed to the Apache Software Foundation (ASF) under one or more *
contributor license agreements. See the NOTICE file distributed with * this work
for additional information regarding copyright ownership. * The ASF licenses
this file to You under the Apache License, Version 2.0 * (the "License"); you
may not use this file except in compliance with * the License. You may obtain a
copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless
required by applicable law or agreed to in writing, software * distributed under
the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. * See the License for the
specific language governing permissions and * limitations under the License. */
<template>
<div :class="`${pre}`">
<div :class="`${pre}-head`">
<a
:class="`${pre}-prev-decade-btn`"
v-show="showYears"
@click="year -= 10"
><svg class="icon sm cp">
<use xlink:href="#angle-double-left"></use></svg
></a>
<a :class="`${pre}-prev-year-btn`" v-show="!showYears" @click="year--"
><svg class="icon sm cp">
<use xlink:href="#angle-double-left"></use></svg
></a>
<a
:class="`${pre}-prev-month-btn`"
v-show="!showYears && !showMonths"
@click="pm"
>
<svg class="icon lg cp">
<use xlink:href="#chevron-left"></use></svg
></a>
<a :class="`${pre}-year-select`" v-show="showYears">{{
ys + '-' + ye
}}</a>
<template v-if="local.yearSuffix">
<a
:class="`${pre}-year-select`"
@click="showYears = !showYears"
v-show="!showYears"
>{{ year }}{{ local.yearSuffix }}</a
>
<a
:class="`${pre}-month-select`"
@click="showMonths = !showMonths"
v-show="!showYears && !showMonths"
>{{ local.monthsHead[month] }}</a
>
</template>
<template v-else>
<a
:class="`${pre}-month-select`"
@click="showMonths = !showMonths"
v-show="!showYears && !showMonths"
>{{ local.monthsHead[month] }}</a
>
<a
:class="`${pre}-year-select`"
@click="showYears = !showYears"
v-show="!showYears"
>{{ year }}</a
>
</template>
<a
:class="`${pre}-next-month-btn`"
v-show="!showYears && !showMonths"
@click="nm"
>
<svg class="icon lg cp">
<use xlink:href="#chevron-right"></use></svg
></a>
<a :class="`${pre}-next-year-btn`" v-show="!showYears" @click="year++"
><svg class="icon sm cp">
<use xlink:href="#angle-double-right"></use></svg
></a>
<a
:class="`${pre}-next-decade-btn`"
v-show="showYears"
@click="year += 10"
><svg class="icon sm cp">
<use xlink:href="#angle-double-right"></use></svg
></a>
</div>
<div :class="`${pre}-body`">
<div :class="`${pre}-days`">
<a :class="`${pre}-week`" v-for="i in local.weeks" :key="i">{{ i }}</a>
<a
v-for="(j, i) in days"
@click="is($event) && ((day = j.i), ok(j))"
:class="[
j.p || j.n ? `${pre}-date-out` : '',
status(j.y, j.m, j.i, hour, minute, second, 'YYYYMMDD'),
]"
:key="i"
>{{ j.i }}</a
>
</div>
<div :class="`${pre}-months`" v-show="showMonths">
<a
v-for="(i, j) in local.months"
@click="
is($event) &&
((showMonths = m === 'M'), (month = j), m === 'M' && ok('m'))
"
:class="[status(year, j, day, hour, minute, second, 'YYYYMM')]"
:key="j"
>{{ i }}</a
>
</div>
<div :class="`${pre}-years`" v-show="showYears">
<a
v-for="(i, j) in years"
@click="
is($event) &&
((showYears = m === 'Y'), (year = i), m === 'Y' && ok('y'))
"
:class="[
j === 0 || j === 11 ? `${pre}-date-out` : '',
status(i, month, day, hour, minute, second, 'YYYY'),
]"
:key="j"
>{{ i }}</a
>
</div>
<div :class="`${pre}-hours scroll_hide`" v-show="showHours">
<div :class="`${pre}-title`">{{ local.hourTip }}</div>
<div class="scroll_hide calendar-overflow">
<a
v-for="(j, i) in 24"
@click="is($event) && ((showHours = false), (hour = i), ok('h'))"
:class="[status(year, month, day, i, minute, second, 'YYYYMMDDHH')]"
:key="i"
>{{ i }}</a
>
</div>
</div>
<div :class="`${pre}-minutes`" v-show="showMinutes">
<div :class="`${pre}-title`">{{ local.minuteTip }}</div>
<div class="scroll_hide calendar-overflow">
<a
v-for="(j, i) in 60"
@click="
is($event) && ((showMinutes = false), (minute = i), ok('h'))
"
:class="[status(year, month, day, hour, i, second, 'YYYYMMDDHHmm')]"
:key="i"
>{{ i }}</a
>
</div>
</div>
<div :class="`${pre}-seconds`" v-show="showSeconds">
<div :class="`${pre}-title`">{{ local.secondTip }}</div>
<div class="scroll_hide calendar-overflow">
<a
v-for="(j, i) in 60"
@click="
is($event) && ((showSeconds = false), (second = i), ok('h'))
"
:class="[
status(year, month, day, hour, minute, i, 'YYYYMMDDHHmmss'),
]"
:key="i"
>{{ i }}</a
>
</div>
</div>
</div>
<div :class="`${pre}-foot`" v-if="m === 'H'">
<div :class="`${pre}-hour`">
<a
:title="local.hourTip"
@click="(showHours = !showHours), (showMinutes = showSeconds = false)"
:class="{ on: showHours }"
>{{ hour | dd }}</a
>
<span>:</span>
<a
:title="local.minuteTip"
@click="
(showMinutes = !showMinutes), (showHours = showSeconds = false)
"
:class="{ on: showMinutes }"
>{{ minute | dd }}</a
>
<span>:</span>
<a
:title="local.secondTip"
@click="
(showSeconds = !showSeconds), (showHours = showMinutes = false)
"
:class="{ on: showSeconds }"
>{{ second | dd }}</a
>
</div>
</div>
</div>
</template>
<script lang="js">
/* eslint-disable */
/* tslint:disable */
export default {
name: 'VueDatepickerLocalCalendar',
props: {
value: { default: null },
left: { default: false },
right: { default: false },
},
data() {
const get = (time) => {
return {
year: time.getFullYear(),
month: time.getMonth(),
day: time.getDate(),
hour: time.getHours(),
minute: time.getMinutes(),
second: time.getSeconds(),
};
};
const time = get(this.value);
return {
pre: 'calendar',
m: 'D',
showYears: false,
showMonths: false,
showHours: false,
showMinutes: false,
showSeconds: false,
year: time.year,
month: time.month,
day: time.day,
hour: time.hour,
minute: time.minute,
second: time.second,
};
},
watch: {
value(val) {
const $this = this;
const time = $this.get(val);
$this.year = time.year;
$this.month = time.month;
$this.day = time.day;
$this.hour = time.hour;
$this.minute = time.minute;
$this.second = time.second;
},
},
computed: {
local() {
return this.$parent.local;
},
format() {
return this.$parent.format;
},
start() {
return this.parse(this.$parent.dates[0]);
},
end() {
return this.parse(this.$parent.dates[1]);
},
ys() {
return Math.floor(this.year / 10) * 10;
},
ye() {
return this.ys + 10;
},
years() {
const arr = [];
let start = this.ys - 1;
while (arr.length < 12) {
arr.push(start += 1);
}
return arr;
},
days() {
const days = [];
const $this = this;
const year = $this.year;
const month = $this.month;
const time = new Date(year, month, 1);
const dow = $this.local.dow || 7;
time.setDate(0); // switch to the last day of last month
let lastDay = time.getDate();
const week = time.getDay() || 7;
let count = dow <= week ? week - dow + 1 : week + (7 - dow + 1);
while (count > 0) {
days.push({
i: lastDay - count + 1,
y: month > 0 ? year : year - 1,
m: month > 0 ? month - 1 : 11,
p: true,
});
count--;
}
time.setMonth(time.getMonth() + 2, 0); // switch to the last day of the current month
lastDay = time.getDate();
let i = 1;
for (i = 1; i <= lastDay; i++) {
days.push({
i: i,
y: year,
m: month,
});
}
for (i = 1; days.length < 42; i++) {
days.push({
i: i,
y: month < 11 ? year : year + 1,
m: month < 11 ? month + 1 : 0,
n: true,
});
}
return days;
},
},
filters: {
dd: val => ('0' + val).slice(-2),
},
methods: {
get(time) {
return {
year: time.getFullYear(),
month: time.getMonth(),
day: time.getDate(),
hour: time.getHours(),
minute: time.getMinutes(),
second: time.getSeconds(),
};
},
parse(num) {
return Math.floor(num / 1000);
},
status(year, month, day, hour, minute, second, format) {
const $this = this;
const maxDay = new Date(year, month + 1, 0).getDate();
const time = new Date(
year,
month,
day > maxDay ? maxDay : day,
hour,
minute,
second
);
const t = $this.parse(time);
const f = $this.$parent.tf;
const classObj = {};
let flag = false;
if (format === 'YYYY') {
flag = year === $this.year;
} else if (format === 'YYYYMM') {
flag = month === $this.month;
} else {
flag = f($this.value, format) === f(time, format);
}
classObj[`${$this.pre}-date`] = true;
classObj[`${$this.pre}-date-disabled`] =
($this.right && t < $this.start) ||
$this.$parent.disabledDate(time, format);
classObj[`${$this.pre}-date-on`] =
($this.left && t > $this.start) || ($this.right && t < $this.end);
classObj[`${$this.pre}-date-selected`] = flag;
return classObj;
},
nm() {
if (this.month < 11) {
this.month++;
} else {
this.month = 0;
this.year++;
}
},
pm() {
if (this.month > 0) {
this.month--;
} else {
this.month = 11;
this.year--;
}
},
is(e) {
return e.target.className.indexOf(`${this.pre}-date-disabled`) === -1;
},
ok(info) {
const $this = this;
let year = '';
let month = '';
let day = '';
info && info.n && $this.nm();
info && info.p && $this.pm();
if (info === 'h') {
const time = $this.get(this.value);
year = time.year;
month = time.month;
} else if (info === 'm' || info === 'y') {
day = '1';
}
const _time = new Date(
year || $this.year,
month || $this.month,
day || $this.day,
$this.hour,
$this.minute,
$this.second
);
if ($this.left && Math.floor(_time.getTime() / 1000) > $this.end) {
this.$parent.dates[1] = _time;
}
$this.$emit('input', _time);
$this.$parent.ok(info === 'h');
},
},
mounted() {
const $this = this;
const is = c => $this.format.indexOf(c) !== -1;
if (is('s') && is('m') && (is('h') || is('H'))) {
$this.m = 'H';
} else if (is('D')) {
$this.m = 'D';
} else if (is('M')) {
$this.m = 'M';
$this.showMonths = true;
} else if (is('Y')) {
$this.m = 'Y';
$this.showYears = true;
}
},
};
</script>
<style scoped>
.calendar {
float: left;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
color: #3d444f;
}
.calendar + .calendar {
border-left: solid 1px #eaeaea;
margin-left: 5px;
padding-left: 5px;
}
.calendar-head {
line-height: 34px;
height: 34px;
text-align: center;
position: relative;
}
.calendar-head a {
color: #666;
cursor: pointer;
display: inline-block;
text-align: center;
position: absolute;
padding: 0 5px;
font-size: 16px;
}
.calendar-head a:hover {
color: #3f97e3;
}
.calendar-head .calendar-year-select,
.calendar-head .calendar-month-select {
font-size: 12px;
padding: 0 2px;
position: relative;
}
.calendar-prev-decade-btn,
.calendar-prev-year-btn {
left: 6px;
}
.calendar-prev-month-btn {
left: 24px;
}
.calendar-next-decade-btn,
.calendar-next-year-btn {
right: 6px;
}
.calendar-next-month-btn {
right: 24px;
}
.calendar-next-month-btn .icon.lg,
.calendar-prev-month-btn .icon.lg {
margin-top: 8px;
}
.calendar-body {
position: relative;
width: 196px;
height: 196px;
}
.calendar-days {
width: 100%;
height: 100%;
}
.calendar-week,
.calendar-date {
font-weight: normal;
width: 14.28%;
height: 14.28%;
text-align: center;
box-sizing: border-box;
overflow: hidden;
float: left;
}
.calendar-week:before,
.calendar-date:before {
content: '';
display: inline-block;
height: 100%;
vertical-align: middle;
}
.calendar-date {
cursor: pointer;
line-height: 29px;
transition: background-color 0.3s;
}
.calendar-date-out {
color: #ccc;
}
.calendar-date:hover,
.calendar-date-on {
color: #3f97e3;
background-color: #f8f8f8;
}
.calendar-date-selected,
.calendar-date-selected:hover {
color: #fff;
font-weight: bold;
border-radius: 14px;
background: #3f97e3;
}
.calendar-date-disabled {
cursor: not-allowed !important;
color: #ccc !important;
background: #fff !important;
}
.calendar-foot {
margin-top: 5px;
}
.calendar-hour {
display: inline-block;
border: 1px solid #e6e5e5;
color: #9e9e9e;
}
.calendar-hour a {
display: inline-block;
padding: 2px 4px;
cursor: pointer;
}
.calendar-hour a:hover,
.calendar-hour a.on {
color: #3f97e3;
}
.calendar-years,
.calendar-months,
.calendar-hours,
.calendar-minutes,
.calendar-seconds {
width: 100%;
height: 100%;
position: absolute;
background: #fff;
left: 0;
top: 0;
}
.calendar-months a {
width: 33.33%;
height: 25%;
}
.calendar-years a {
width: 33.33%;
height: 25%;
}
.calendar-overflow {
overflow-x: scroll;
height: 100%;
}
/* .calendar-hours a {
width: 20%;
height: 20%;
}
.calendar-minutes a,
.calendar-seconds a {
width: 16.66%;
height: 10%;
} */
.calendar-title {
margin-top: -30px;
height: 30px;
line-height: 30px;
background: #fff;
text-align: center;
font-weight: bold;
}
</style>