391 lines
11 KiB
JavaScript
391 lines
11 KiB
JavaScript
|
/**
|
|||
|
*
|
|||
|
* @authors yutent (yutent@doui.cc)
|
|||
|
* @date 2016-02-14 13:58:39
|
|||
|
*
|
|||
|
*/
|
|||
|
"use strict";
|
|||
|
|
|||
|
define([
|
|||
|
'text!./main.htm',
|
|||
|
'css!./style.css',
|
|||
|
], function(tpl){
|
|||
|
|
|||
|
yua.ui.datepicker = '1.0.0'
|
|||
|
yua.component('datepicker', {
|
|||
|
$template: tpl,
|
|||
|
$construct: function(sys, option, attr){
|
|||
|
|
|||
|
// 先合并config的配置及元素的属性
|
|||
|
var opts = Object.assign({}, option, attr),
|
|||
|
defVal;
|
|||
|
|
|||
|
if(!opts.value){
|
|||
|
return yua.error('日历组件必须设置value属性')
|
|||
|
}
|
|||
|
|
|||
|
//获取初始值
|
|||
|
defVal = sys.$up[opts.value]
|
|||
|
|
|||
|
//日期格式化, 默认会调用过滤器的格式'Y-m-d H:i:s'
|
|||
|
if(!opts.showTime && !opts.format){
|
|||
|
opts.format = 'Y-m-d';
|
|||
|
}
|
|||
|
|
|||
|
// 修正默认值, 如果不是Date对象, 则转为Date对象
|
|||
|
if(!defVal){
|
|||
|
if(opts.minDate){
|
|||
|
defVal = opts.minDate;
|
|||
|
}else if(opts.maxDate){
|
|||
|
defVal = opts.maxDate;
|
|||
|
}else{
|
|||
|
defVal = new Date()
|
|||
|
}
|
|||
|
}
|
|||
|
if(!Date.isDate(defVal)){
|
|||
|
defVal = new Date(defVal)
|
|||
|
}
|
|||
|
|
|||
|
opts.update_value = opts.value
|
|||
|
opts.value = defVal.format(opts.format)
|
|||
|
|
|||
|
opts.calendar = {
|
|||
|
list: [1],
|
|||
|
year: defVal.format('Y'),
|
|||
|
month: defVal.format('m'),
|
|||
|
day: defVal.format('d'),
|
|||
|
hour: defVal.format('H'),
|
|||
|
minute: defVal.format('i'),
|
|||
|
second: defVal.format('s'),
|
|||
|
minYear: 0,
|
|||
|
minMonth: 0,
|
|||
|
minDay: 0,
|
|||
|
maxYear: 0,
|
|||
|
maxMonth: 0,
|
|||
|
maxDay: 0
|
|||
|
}
|
|||
|
|
|||
|
if(opts.minDate){
|
|||
|
if(!Date.isDate(opts.minDate)){
|
|||
|
opts.minDate = new Date(opts.minDate)
|
|||
|
}
|
|||
|
opts.calendar.minYear = opts.minDate.format('Y')
|
|||
|
opts.calendar.minMonth = opts.minDate.format('m')
|
|||
|
opts.calendar.minDay = opts.minDate.format('d')
|
|||
|
}
|
|||
|
|
|||
|
if(opts.maxDate){
|
|||
|
if(!Date.isDate(opts.maxDate)){
|
|||
|
opts.maxDate = new Date(opts.maxDate)
|
|||
|
}
|
|||
|
opts.calendar.maxYear = opts.maxDate.format('Y')
|
|||
|
opts.calendar.maxMonth = opts.maxDate.format('m')
|
|||
|
opts.calendar.maxDay = opts.maxDate.format('d')
|
|||
|
}
|
|||
|
log(opts)
|
|||
|
//移除部分属性
|
|||
|
delete opts.minDate;
|
|||
|
delete opts.maxDate;
|
|||
|
return yua.mix(sys, opts)
|
|||
|
},
|
|||
|
$ready: function(vm, ele){
|
|||
|
var last = {
|
|||
|
year: +vm.calendar.year,
|
|||
|
month: +vm.calendar.month,
|
|||
|
day: +vm.calendar.day
|
|||
|
},
|
|||
|
timer;
|
|||
|
|
|||
|
getCalendar(vm, last) //初始化日历显示
|
|||
|
|
|||
|
//日历按钮,未超出限制时切换日历
|
|||
|
vm.$turn = function(type, step){
|
|||
|
var year = +vm.calendar.year,
|
|||
|
month = +vm.calendar.month;
|
|||
|
|
|||
|
if(type === 1){
|
|||
|
year += step;
|
|||
|
}else{
|
|||
|
month += step;
|
|||
|
if(month < 1){
|
|||
|
month = 12;
|
|||
|
year--
|
|||
|
}
|
|||
|
if(month > 12){
|
|||
|
month = 1;
|
|||
|
year++
|
|||
|
}
|
|||
|
}
|
|||
|
if(isLimited(vm.calendar, year, month) === true){
|
|||
|
vm.tips = '日期超出限制';
|
|||
|
return;
|
|||
|
}
|
|||
|
vm.calendar.year = year;
|
|||
|
vm.calendar.month = numberFormat(month, 2);
|
|||
|
}
|
|||
|
|
|||
|
//选择日期
|
|||
|
vm.$getDate = function(disabled, day){
|
|||
|
if(disabled)
|
|||
|
return;
|
|||
|
|
|||
|
vm.calendar.day = day;
|
|||
|
|
|||
|
changeStyle(vm.calendar, day);
|
|||
|
updateTime(vm, last);
|
|||
|
vm.showCalendar = !1;
|
|||
|
}
|
|||
|
|
|||
|
//输入框获取焦点时,显示日历
|
|||
|
vm.$focus = function(){
|
|||
|
vm.showCalendar = !0;
|
|||
|
}
|
|||
|
|
|||
|
//获取当前时间
|
|||
|
vm.$now = function(){
|
|||
|
var now = new Date(),
|
|||
|
year = now.format('Y'),
|
|||
|
month = now.format('m'),
|
|||
|
day = now.format('d');
|
|||
|
|
|||
|
var isLimitYM = isLimited(year, month),
|
|||
|
disabled = disabledDay(day, isLimitYM);
|
|||
|
|
|||
|
if(disabled){
|
|||
|
vm.tips = '今天超出了限制日期';
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
vm.calendar.year = year;
|
|||
|
vm.calendar.month = month;
|
|||
|
vm.calendar.day = day;
|
|||
|
vm.calendar.hour = now.format('H');
|
|||
|
vm.calendar.minute = now.format('i');
|
|||
|
vm.calendar.second = now.format('s');
|
|||
|
|
|||
|
changeStyle(vm.calendar, day);
|
|||
|
updateTime(vm, last);
|
|||
|
|
|||
|
vm.showCalendar = !1;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/************************************************************/
|
|||
|
|
|||
|
vm.$watch('calendar.year', function(){
|
|||
|
getCalendar(vm, last);
|
|||
|
})
|
|||
|
|
|||
|
vm.$watch('calendar.month', function(){
|
|||
|
getCalendar(vm, last);
|
|||
|
})
|
|||
|
vm.$watch('calendar.hour', function(v){
|
|||
|
vm.calendar.hour = v
|
|||
|
updateTime(vm, last)
|
|||
|
})
|
|||
|
vm.$watch('calendar.minute', function(v){
|
|||
|
vm.calendar.minute = v
|
|||
|
updateTime(vm, last)
|
|||
|
})
|
|||
|
vm.$watch('calendar.second', function(v){
|
|||
|
vm.calendar.second = v
|
|||
|
updateTime(vm, last)
|
|||
|
})
|
|||
|
|
|||
|
vm.$watch('showCalendar', function(v){
|
|||
|
if(v || !vm.value)
|
|||
|
return;
|
|||
|
|
|||
|
vm.$up[vm.update_value] = vm.value
|
|||
|
vm.$onUpdate(vm.value);
|
|||
|
})
|
|||
|
|
|||
|
vm.$watch('tips', function(v){
|
|||
|
if(!v)
|
|||
|
return;
|
|||
|
clearTimeout(timer);
|
|||
|
timer = setTimeout(function(){
|
|||
|
vm.tips = '';
|
|||
|
}, 1500)
|
|||
|
})
|
|||
|
|
|||
|
document.addEventListener('click', function(){
|
|||
|
vm.showCalendar = !1;
|
|||
|
})
|
|||
|
|
|||
|
},
|
|||
|
showTime: false, //对话框上显示时间
|
|||
|
showCalendar: false, //显示日历对话框
|
|||
|
disabled: false, //是否禁用
|
|||
|
tips: '',
|
|||
|
format: '', // 日期显示格式
|
|||
|
value: '', // 用于显示在输入框里的日期变量
|
|||
|
btns: { //切换年份/月份的按钮上的字符
|
|||
|
prevYear: '<<',
|
|||
|
nextYear: '>>',
|
|||
|
prevMonth: '<',
|
|||
|
nextMonth: '>'
|
|||
|
},
|
|||
|
$focus: yua.noop,
|
|||
|
$turn: yua.noop,
|
|||
|
$getDate: yua.noop,
|
|||
|
$now: yua.noop,
|
|||
|
$cancelBubble: function(event){
|
|||
|
event.stopPropagation && event.stopPropagation() || (event.cancelBubble = true);
|
|||
|
},
|
|||
|
$onUpdate: yua.noop, //日期被修改后的回调
|
|||
|
})
|
|||
|
|
|||
|
/**************** 公共函数 *****************/
|
|||
|
//计算日历数组
|
|||
|
function getCalendar(vm, last){
|
|||
|
var year = +vm.calendar.year,
|
|||
|
month = +vm.calendar.month,
|
|||
|
nums = getTotalDays(year, month),
|
|||
|
numsFixed = -getFirstDay(year, month) + 1,
|
|||
|
isLimitYM = isLimited(vm.calendar, year, month);
|
|||
|
|
|||
|
vm.calendar.list.clear();
|
|||
|
|
|||
|
for(var i = numsFixed; i <= nums; i++){
|
|||
|
|
|||
|
var day = {
|
|||
|
weeken: !1,
|
|||
|
day: '',
|
|||
|
selected: !1,
|
|||
|
disable: !0
|
|||
|
}
|
|||
|
if(i > 0){
|
|||
|
var d = getFirstDay(year, month, i)
|
|||
|
day = {
|
|||
|
weeken: d == 0 || d == 6,
|
|||
|
day: i,
|
|||
|
selected: isSelected(vm.calendar, last, i),
|
|||
|
disable: disabledDay(vm.calendar, i, isLimitYM)
|
|||
|
}
|
|||
|
}
|
|||
|
vm.calendar.list.push(day)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//判断当前年/月是否超出限制
|
|||
|
function isLimited(calendar, year, month){
|
|||
|
var limit = {
|
|||
|
Y: +calendar.minYear,
|
|||
|
M: +calendar.minMonth,
|
|||
|
mY: +calendar.maxYear,
|
|||
|
mM: +calendar.maxMonth,
|
|||
|
},
|
|||
|
res = '';
|
|||
|
|
|||
|
if((!limit.Y && !limit.mY) || (!limit.M && !limit.mM) || !year){
|
|||
|
return false
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
if((limit.Y && year < limit.Y) || (limit.mY && year > limit.mY)){
|
|||
|
return true
|
|||
|
}
|
|||
|
|
|||
|
if(month){
|
|||
|
if(year === limit.Y){
|
|||
|
if(limit.M && month < limit.M)
|
|||
|
return true
|
|||
|
|
|||
|
if(month == limit.M)
|
|||
|
res += '-'
|
|||
|
}
|
|||
|
|
|||
|
if(year === limit.mY){
|
|||
|
if(limit.mM && month > limit.mM)
|
|||
|
return true
|
|||
|
|
|||
|
if(month == limit.mM)
|
|||
|
res += '+'
|
|||
|
}
|
|||
|
}
|
|||
|
return res
|
|||
|
}
|
|||
|
|
|||
|
//判断指定天数是否有效
|
|||
|
function disabledDay(calendar, day, limitedYM){
|
|||
|
var minD = calendar.minDay,
|
|||
|
maxD = calendar.maxDay;
|
|||
|
|
|||
|
if(limitedYM === '-')
|
|||
|
return day < minD
|
|||
|
|
|||
|
if(limitedYM === '+')
|
|||
|
return maxD && day > maxD
|
|||
|
|
|||
|
if(limitedYM === '-+')
|
|||
|
return day < minD || (maxD && day > maxD)
|
|||
|
|
|||
|
return limitedYM
|
|||
|
}
|
|||
|
|
|||
|
//判断指定天数是否被选中
|
|||
|
function isSelected(calendar, last, day){
|
|||
|
var year = +calendar.year,
|
|||
|
month = +calendar.month;
|
|||
|
|
|||
|
return !(last.year !== year || last.month !== month || last.day !== day)
|
|||
|
}
|
|||
|
|
|||
|
//修改当前选中日期的样式
|
|||
|
function changeStyle(calendar, day){
|
|||
|
calendar.list.forEach(function(item){
|
|||
|
if(item.day != day){
|
|||
|
item.selected = !1
|
|||
|
}else{
|
|||
|
item.selected = !0
|
|||
|
}
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
//更新时间
|
|||
|
function updateTime(vm, last){
|
|||
|
var hour = minute = second = 0;
|
|||
|
last = {
|
|||
|
year: +vm.calendar.year,
|
|||
|
month: +vm.calendar.month,
|
|||
|
day: +vm.calendar.day
|
|||
|
}
|
|||
|
|
|||
|
if(vm.showTime){
|
|||
|
hour = vm.calendar.hour
|
|||
|
minute = vm.calendar.minute
|
|||
|
second = vm.calendar.second
|
|||
|
}
|
|||
|
vm.value = new Date(last.year, last.month - 1, last.day, hour, minute, second).format(vm.format)
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//获取今年的年份/月份,返回的是数组
|
|||
|
function getThisYearMonth(){
|
|||
|
var oDate = new Date()
|
|||
|
return [oDate.getFullYear(), oDate.getMonth() + 1]
|
|||
|
}
|
|||
|
|
|||
|
//根据年份获取指定月份天数
|
|||
|
function getTotalDays(year, month){
|
|||
|
return new Date(year, month, 0).getDate()
|
|||
|
}
|
|||
|
|
|||
|
//判断指定年月第一天是星期几
|
|||
|
function getFirstDay(year, month, day){
|
|||
|
return new Date(year, month - 1, day || 1).getDay()
|
|||
|
}
|
|||
|
//数字长度补全(前面加0)
|
|||
|
function numberFormat(num, len){
|
|||
|
num += ''
|
|||
|
if(num.length === len)
|
|||
|
return num
|
|||
|
|
|||
|
while(num.length < len)
|
|||
|
num = '0' + num
|
|||
|
return num
|
|||
|
}
|
|||
|
|
|||
|
return yua
|
|||
|
})
|