修复框架子对象中数组无法监听的bug;日期选择组件完成适配;
parent
3f925843ad
commit
10d5df4dad
|
@ -1,46 +1,6 @@
|
|||
# 日历组件文档
|
||||
## 更新日志
|
||||
|
||||
## 配置说明
|
||||
v1.0.0 (2017-09-11)
|
||||
============
|
||||
|
||||
```json
|
||||
{
|
||||
showTime: false, //对话框上显示时间
|
||||
showCalendar: false, //显示日历对话框
|
||||
disabled: false, //是否禁用
|
||||
exclass: '', //输入框拓展样式, 用于外部调整输入框样式以适配各种场景
|
||||
duplex: '',
|
||||
format: '', // 日期显示格式
|
||||
radius: 0, //日历输入框边框圆角半径
|
||||
border: 1, //日历输入框边框大小
|
||||
btns: { //切换年份/月份的按钮上的字符
|
||||
prevYear: '<<',
|
||||
nextYear: '>>',
|
||||
prevMonth: '<',
|
||||
nextMonth: '>'
|
||||
},
|
||||
callback: function(date){/*...*/}, //日期被修改后的回调,参数是被修改后的值
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## 用法
|
||||
|
||||
```html
|
||||
<!-- 把do:datepicker 标签放到想要放的地方即可 -->
|
||||
<section>
|
||||
<span class="label">示例1:</span>
|
||||
<do:datepicker config="dp" duplex="ex1" border="1" class="date" radius="3"></do:datepicker>
|
||||
</section>
|
||||
<!--
|
||||
其中config属性是指定日历组件的配置,会自动从上一层controller里找,如果该属性为空,则自动从上层controller中找与组件同名的属性(找不到则使用组件默认配置);
|
||||
其他的属性(除$id, config, id, class, tabindex, style, ms-*属性,data-*属性外,也可以用以配置组件,且优先级最高);
|
||||
$id或identifier属性可以设定组件的$id值,方便各模块之间进行通讯
|
||||
-->
|
||||
<!-- 引入分页组件 -->
|
||||
<script>
|
||||
require(['存放路径/doui.datepicker'], function(){
|
||||
|
||||
})
|
||||
</script>
|
||||
```
|
||||
First Release.
|
|
@ -1,40 +0,0 @@
|
|||
@charset "UTF-8";
|
||||
/**
|
||||
*
|
||||
* @authors yutent (yutent@doui.cc)
|
||||
* @date 2016-02-14 14:00:06
|
||||
*
|
||||
*/
|
||||
.do-ui-datepicker {position:relative;z-index:65534;width:100%;height:100%;}
|
||||
.do-ui-datepicker a {text-decoration:none;}
|
||||
.do-ui-datepicker .date-input {float:left;width:100%;height:100%;border:1px solid #ddd;line-height:18px;padding:0 5px;}
|
||||
|
||||
.do-ui-datepicker .calendar {position:absolute;z-index:65534;left:0;top:98%;width:230px;height:auto;min-height:60px;padding:10px;border:1px solid #ddd;background:#fff;font-size:13px;box-shadow:0 0 5px rgba(0,0,0,.1)}
|
||||
|
||||
.do-ui-datepicker .calendar-hd {width:100%;height:30px;line-height:30px;background:#f3f3f3;color:#666;text-align:center;}
|
||||
.do-ui-datepicker .calendar-contrl {position:relative;width:90%;height:30px;margin:0 5%;line-height:30px;border-bottom:1px solid #eee;color:#09f;text-align:center;}
|
||||
.do-ui-datepicker .calendar-contrl a {position:absolute;top:0;left:0;width:30px;color:#09f;}
|
||||
.do-ui-datepicker .calendar-contrl .prev-month {left:30px;}
|
||||
.do-ui-datepicker .calendar-contrl .next-month {left:auto;right:30px;}
|
||||
.do-ui-datepicker .calendar-contrl .next-year {left:auto;right:0;}
|
||||
|
||||
.do-ui-datepicker .calendar-table {position:relative;width:90%;height:auto;margin:0 5%;line-height:25px;color:#888;text-align:center;}
|
||||
.do-ui-datepicker .calendar-table .tr {width:100%;height:auto;min-height:25px;}
|
||||
.do-ui-datepicker .calendar-table .tr.tr-hd {border-bottom:1px solid #eee;margin-bottom:3px;}
|
||||
.do-ui-datepicker .calendar-table .tr .td {float:left;width:14.28%;height:25px;}
|
||||
.do-ui-datepicker .calendar-table .tr .do-st-hand:hover {background:#b6def9;}
|
||||
.do-ui-datepicker .calendar-table .tr .td.weeken {color:#f30;}
|
||||
.do-ui-datepicker .calendar-table .tr .td.selected {background:#09f;color:#fff;}
|
||||
.do-ui-datepicker .calendar-table .tr .td.disabled {color:#ddd;cursor:default;}
|
||||
|
||||
.do-ui-datepicker .time-contrl {position:relative;width:90%;height:30px;margin:5px 5%;line-height:30px;border-top:1px solid #eee;color:#888;}
|
||||
.do-ui-datepicker .time-contrl label {float:left;height:20px;margin:5px 5px 5px 0;}
|
||||
.do-ui-datepicker .time-contrl input {float:left;width:25px;height:20px;padding:0 3px;line-height:17px;outline:none;}
|
||||
.do-ui-datepicker .time-contrl label:after {float:right;height:20px;line-height:20px;font-size:12px;}
|
||||
.do-ui-datepicker .time-contrl .hours:after {content:"时"}
|
||||
.do-ui-datepicker .time-contrl .minutes:after {content:"分"}
|
||||
.do-ui-datepicker .time-contrl .seconds:after {content:"秒"}
|
||||
.do-ui-datepicker .time-contrl .now {float:right;width:40px;height:20px;margin:5px;border:1px solid #ddd;border-radius:3px;line-height:20px;background:#f7f7f7;color:#888;text-align:center;}
|
||||
.do-ui-datepicker .time-contrl .now:hover {background:#eee;}
|
||||
.do-ui-datepicker .time-contrl .now:active {background:#e7e7e7;}
|
||||
.do-ui-datepicker .calendar-tips {position:absolute;z-index:65535;left:25%;top:40%;width:50%;height:30px;line-height:30px;background:rgba(0,0,0,.7);color:#fff;font-size:12px;text-align:center;}
|
|
@ -1,375 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* @authors yutent (yutent@doui.cc)
|
||||
* @date 2016-02-14 13:58:39
|
||||
*
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
define(['avalon',
|
||||
'css!./doui.datepicker.min'
|
||||
],
|
||||
function(av){
|
||||
//父级vm
|
||||
var parentVm = null
|
||||
|
||||
av.component('do:datepicker', {
|
||||
$replace: true,
|
||||
$template: '<div class="do-ui-datepicker do-fn-noselect"><input class="date-input" type="text" ms-duplex="dateVal" ms-on-focus="$focus" ms-click="$cancelBubble" ms-attr-disabled="disabled" ms-css="{borderWidth: border, borderRadius: radius}"><div class="calendar" ms-if="showCalendar" ms-click="$cancelBubble"><div class="calendar-hd">请选择日期</div><div class="calendar-contrl"><a href="javascript:;" ms-click="$turn(1, -1)" class="prev-year">{{btns.prevYear}}</a><a href="javascript:;" ms-click="$turn(0, -1)" class="prev-month">{{btns.prevMonth}}</a><a href="javascript:;" ms-click="$turn(0, 1)" class="next-month">{{btns.nextMonth}}</a><a href="javascript:;" ms-click="$turn(1, 1)" class="next-year">{{btns.nextYear}}</a><span class="date-display">{{calendar.year + \'-\' + calendar.month}}</span></div><ul class="calendar-table"><li class="tr tr-hd"><span class="td">日</span><span class="td">一</span><span class="td">二</span><span class="td">三</span><span class="td">四</span><span class="td">五</span><span class="td">六</span></li><li class="tr list do-fn-cl"><span class="td" ms-class="{weeken:el.weeken, \'do-st-hand\': !el.disable, disabled: el.disable, selected: el.selected}" ms-repeat="calendar.list" ms-click="$getDate(el.disable, el.day)">{{el.day}}</span></li></ul><div class="time-contrl" ms-if="showTime"><label class="hours"><input type="text" ms-duplex-time="calendar.hour" data-format="hour"></label><label class="minutes"><input type="text" ms-duplex-time="calendar.minute" data-format="minute"></label><label class="seconds"><input type="text" ms-duplex-time="calendar.second" data-format="second"></label><a href="javascript:;" class="now" ms-click="$now">现在</a></div><span class="calendar-tips" ms-if="tips">{{tips}}</span></div></div>',
|
||||
$construct: function(opts, b, c){
|
||||
var vm = av.mix(b, c)
|
||||
/********** 获取上一级vm ***********/
|
||||
var pctrl = vm.duplex.slice(0, vm.duplex.indexOf('.'))
|
||||
parentVm = av.vmodels[pctrl]
|
||||
/**********************************/
|
||||
//获取初始值
|
||||
vm.duplex = vm.duplex.slice(vm.duplex.indexOf('.') + 1)
|
||||
var defaultVal = (new Function('v', 'return v.' + vm.duplex))(parentVm)
|
||||
|
||||
//日期格式化, 默认会调用过滤器的格式'Y-m-d H:i:s'
|
||||
if(!vm.showTime && !vm.format){
|
||||
vm.format = 'Y-m-d';
|
||||
}
|
||||
|
||||
if(defaultVal === undefined){
|
||||
if(vm.minDate){
|
||||
defaultVal = vm.minDate, vm.format;
|
||||
}else if(opts.maxDate){
|
||||
defaultVal = vm.maxDate, vm.format;
|
||||
}
|
||||
}
|
||||
opts.dateVal = defaultVal && av.filters.date(defaultVal, vm.format)
|
||||
opts.calendar = {
|
||||
list: [],
|
||||
year: av.filters.date(opts.dateVal, 'Y'),
|
||||
month: av.filters.date(opts.dateVal, 'm'),
|
||||
day: av.filters.date(opts.dateVal, 'd') || 0,
|
||||
hour: av.filters.date(opts.dateVal, 'H') || 0,
|
||||
minute: av.filters.date(opts.dateVal, 'i') || 0,
|
||||
second: av.filters.date(opts.dateVal, 's') || 0,
|
||||
minYear: vm.minDate && av.filters.date(vm.minDate, 'Y') >> 0,
|
||||
minMonth: vm.minDate && av.filters.date(vm.minDate, 'm') >> 0,
|
||||
minDay: vm.minDate && av.filters.date(vm.minDate, 'd') >> 0 || 1,
|
||||
maxYear: vm.maxDate && av.filters.date(vm.maxDate, 'Y') >> 0,
|
||||
maxMonth: vm.maxDate && av.filters.date(vm.maxDate, 'm') >> 0,
|
||||
maxDay: vm.maxDate && av.filters.date(vm.maxDate, 'd') >> 0
|
||||
}
|
||||
//移除部分属性
|
||||
delete vm.minDate;
|
||||
delete vm.maxDate;
|
||||
|
||||
return av.mix(opts, vm)
|
||||
},
|
||||
$init: function(vm, ele){
|
||||
// av.log(vm)
|
||||
var lastDate = {
|
||||
year: vm.calendar.year >> 0,
|
||||
month: vm.calendar.month >> 0,
|
||||
day: vm.calendar.day >> 0
|
||||
}
|
||||
var timer
|
||||
|
||||
getCalendar() //初始化日历显示
|
||||
|
||||
//日历按钮,未超出限制时切换日历
|
||||
vm.$turn = function(type, step){
|
||||
var year = vm.calendar.year >> 0,
|
||||
month = vm.calendar.month >> 0;
|
||||
|
||||
if(type === 1){
|
||||
year += step;
|
||||
}else{
|
||||
month += step;
|
||||
if(month < 1){
|
||||
month = 12;
|
||||
year--
|
||||
}
|
||||
if(month > 12){
|
||||
month = 1;
|
||||
year++
|
||||
}
|
||||
}
|
||||
if(isLimited(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(day);
|
||||
updateTime();
|
||||
vm.showCalendar = !1;
|
||||
}
|
||||
|
||||
//输入框获取焦点时,显示日历
|
||||
vm.$focus = function(){
|
||||
vm.showCalendar = !0;
|
||||
}
|
||||
|
||||
//获取当前时间
|
||||
vm.$now = function(){
|
||||
var year = av.filters.date(null, 'Y') >> 0,
|
||||
month = av.filters.date(null, 'm') >> 0,
|
||||
day = av.filters.date(null, 'd') >> 0;
|
||||
|
||||
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 = av.filters.date(null, 'H');
|
||||
vm.calendar.minute = av.filters.date(null, 'i');
|
||||
vm.calendar.second = av.filters.date(null, 's');
|
||||
|
||||
changeStyle(day);
|
||||
updateTime();
|
||||
|
||||
vm.showCalendar = !1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
//计算日历数组
|
||||
function getCalendar(){
|
||||
var year = vm.calendar.year >> 0
|
||||
var month = vm.calendar.month >> 0
|
||||
var nums = getNumsOfYearMonth(year, month)
|
||||
var numsFixed = -getDayByYearMonth(year, month) + 1
|
||||
var isLimitYM = isLimited(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 = getDayByYearMonth(year, month, i)
|
||||
day = {
|
||||
weeken: d == 0 || d == 6,
|
||||
day: i,
|
||||
selected: isSelected(i),
|
||||
disable: disabledDay(i, isLimitYM)
|
||||
}
|
||||
}
|
||||
vm.calendar.list.push(day)
|
||||
}
|
||||
}
|
||||
|
||||
//判断当前年/月是否超出限制
|
||||
function isLimited(year, month){
|
||||
var limit = {
|
||||
Y: vm.calendar.minYear,
|
||||
M: vm.calendar.minMonth,
|
||||
mY: vm.calendar.maxYear,
|
||||
mM: vm.calendar.maxMonth,
|
||||
}
|
||||
var res = ''
|
||||
|
||||
if((!limit.Y && !limit.mY) || (!limit.M && !limit.mM))
|
||||
return false
|
||||
|
||||
if(year){
|
||||
if((limit.Y && year < limit.Y) || (limit.mY && year > limit.mY))
|
||||
return true
|
||||
}else{
|
||||
return false
|
||||
}
|
||||
|
||||
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(day, limitedYM){
|
||||
var minD = vm.calendar.minDay
|
||||
var maxD = vm.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(day){
|
||||
var year = vm.calendar.year >> 0
|
||||
var month = vm.calendar.month >> 0
|
||||
|
||||
return !(lastDate.year !== year || lastDate.month !== month || lastDate.day !== day)
|
||||
}
|
||||
|
||||
//修改当前选中日期的样式
|
||||
function changeStyle(day){
|
||||
vm.calendar.list.forEach(function(item){
|
||||
if(item.day != day){
|
||||
item.selected = !1
|
||||
}else{
|
||||
item.selected = !0
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//更新时间
|
||||
function updateTime(){
|
||||
var cal = vm.calendar
|
||||
var year = cal.year
|
||||
var month = cal.month
|
||||
var day = cal.day
|
||||
var hour = cal.hour
|
||||
var minute = cal.minute
|
||||
var second = cal.second
|
||||
var date = year + '-' + month + '-' + day
|
||||
|
||||
if(vm.showTime){
|
||||
date += ' ' + hour + ':' + minute + ':' + second
|
||||
}
|
||||
lastDate = {
|
||||
year: year >> 0,
|
||||
month: month >> 0,
|
||||
day: day >> 0
|
||||
}
|
||||
vm.dateVal = av.filters.date(date, vm.format)
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
vm.$watch('calendar.year', function(){
|
||||
getCalendar();
|
||||
})
|
||||
|
||||
vm.$watch('calendar.month', function(){
|
||||
getCalendar();
|
||||
})
|
||||
vm.$watch('calendar.hour', function(v){
|
||||
vm.calendar.hour = v
|
||||
updateTime()
|
||||
})
|
||||
vm.$watch('calendar.minute', function(v){
|
||||
vm.calendar.minute = v
|
||||
updateTime()
|
||||
})
|
||||
vm.$watch('calendar.second', function(v){
|
||||
vm.calendar.second = v
|
||||
updateTime()
|
||||
})
|
||||
|
||||
vm.$watch('showCalendar', function(v){
|
||||
if(v || !vm.duplex)
|
||||
return;
|
||||
|
||||
eval('parentVm.' + vm.duplex + ' = "' + vm.dateVal + '"');
|
||||
vm.callback && vm.callback(vm.dateVal);
|
||||
})
|
||||
|
||||
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, //是否禁用
|
||||
exclass: '', //输入框拓展样式, 用于外部调整输入框样式以适配各种场景
|
||||
tips: '',
|
||||
duplex: '',
|
||||
format: '', // 日期显示格式
|
||||
dateVal: '',
|
||||
radius: 0, //日历输入框边框圆角半径
|
||||
border: 1, //日历输入框边框大小
|
||||
btns: { //切换年份/月份的按钮上的字符
|
||||
prevYear: '<<',
|
||||
nextYear: '>>',
|
||||
prevMonth: '<',
|
||||
nextMonth: '>'
|
||||
},
|
||||
$focus: av.noop,
|
||||
$turn: av.noop,
|
||||
$getDate: av.noop,
|
||||
$now: av.noop,
|
||||
$cancelBubble: function(event){
|
||||
event.stopPropagation && event.stopPropagation() || (event.cancelBubble = true);
|
||||
},
|
||||
callback: null, //日期被修改后的回调
|
||||
})
|
||||
|
||||
|
||||
//获取今年的年份/月份,返回的是数组
|
||||
function getThisYearMonth(){
|
||||
var oDate = new Date()
|
||||
return [oDate.getFullYear(), oDate.getMonth() + 1]
|
||||
}
|
||||
|
||||
//根据年份获取指定月份天数
|
||||
function getNumsOfYearMonth(year, month){
|
||||
return new Date(year, month, 0).getDate()
|
||||
}
|
||||
|
||||
//判断指定年月第一天是星期几
|
||||
function getDayByYearMonth(year, month, day){
|
||||
day = day || 1
|
||||
return new Date(year, month - 1, day).getDay()
|
||||
}
|
||||
//数字长度补全(前面加0)
|
||||
function numberFormat(num, len){
|
||||
num += ''
|
||||
if(num.length === len)
|
||||
return num
|
||||
|
||||
while(num.length < len)
|
||||
num = '0' + num
|
||||
return num
|
||||
}
|
||||
|
||||
return av
|
||||
})
|
|
@ -1 +0,0 @@
|
|||
@charset "UTF-8";.do-ui-datepicker{position:relative;z-index:65534;width:100%;height:100%}.do-ui-datepicker a{text-decoration:none}.do-ui-datepicker .date-input{float:left;width:100%;height:100%;border:1px solid #ddd;line-height:18px;padding:0 5px}.do-ui-datepicker .calendar{position:absolute;z-index:65534;left:0;top:98%;width:230px;height:auto;min-height:60px;padding:10px;border:1px solid #ddd;background:#fff;font-size:13px;box-shadow:0 0 5px rgba(0,0,0,.1)}.do-ui-datepicker .calendar-hd{width:100%;height:30px;line-height:30px;background:#f3f3f3;color:#666;text-align:center}.do-ui-datepicker .calendar-contrl{position:relative;width:90%;height:30px;margin:0 5%;line-height:30px;border-bottom:1px solid #eee;color:#09f;text-align:center}.do-ui-datepicker .calendar-contrl a{position:absolute;top:0;left:0;width:30px;color:#09f}.do-ui-datepicker .calendar-contrl .prev-month{left:30px}.do-ui-datepicker .calendar-contrl .next-month{left:auto;right:30px}.do-ui-datepicker .calendar-contrl .next-year{left:auto;right:0}.do-ui-datepicker .calendar-table{position:relative;width:90%;height:auto;margin:0 5%;line-height:25px;color:#888;text-align:center}.do-ui-datepicker .calendar-table .tr{width:100%;height:auto;min-height:25px}.do-ui-datepicker .calendar-table .tr.tr-hd{border-bottom:1px solid #eee;margin-bottom:3px}.do-ui-datepicker .calendar-table .tr .td{float:left;width:14.28%;height:25px}.do-ui-datepicker .calendar-table .tr .do-st-hand:hover{background:#b6def9}.do-ui-datepicker .calendar-table .tr .td.weeken{color:#f30}.do-ui-datepicker .calendar-table .tr .td.selected{background:#09f;color:#fff}.do-ui-datepicker .calendar-table .tr .td.disabled{color:#ddd;cursor:default}.do-ui-datepicker .time-contrl{position:relative;width:90%;height:30px;margin:5px 5%;line-height:30px;border-top:1px solid #eee;color:#888}.do-ui-datepicker .time-contrl label{float:left;height:20px;margin:5px 5px 5px 0}.do-ui-datepicker .time-contrl input{float:left;width:25px;height:20px;padding:0 3px;line-height:17px;outline:0}.do-ui-datepicker .time-contrl label:after{float:right;height:20px;line-height:20px;font-size:12px}.do-ui-datepicker .time-contrl .hours:after{content:"时"}.do-ui-datepicker .time-contrl .minutes:after{content:"分"}.do-ui-datepicker .time-contrl .seconds:after{content:"秒"}.do-ui-datepicker .time-contrl .now{float:right;width:40px;height:20px;margin:5px;border:1px solid #ddd;border-radius:3px;line-height:20px;background:#f7f7f7;color:#888;text-align:center}.do-ui-datepicker .time-contrl .now:hover{background:#eee}.do-ui-datepicker .time-contrl .now:active{background:#e7e7e7}.do-ui-datepicker .calendar-tips{position:absolute;z-index:65535;left:25%;top:40%;width:50%;height:30px;line-height:30px;background:rgba(0,0,0,.7);color:#fff;font-size:12px;text-align:center}
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,50 @@
|
|||
<div class="do-datepicker do-fn-noselect">
|
||||
<input class="date-input"
|
||||
type="text"
|
||||
:duplex="value"
|
||||
:focus="$focus"
|
||||
:click="$cancelBubble"
|
||||
:attr-disabled="disabled">
|
||||
|
||||
<dl class="calendar-box"
|
||||
:if="showCalendar"
|
||||
:click="$cancelBubble">
|
||||
|
||||
<dt class="title">请选择日期</dt>
|
||||
<dd class="contrl">
|
||||
<a href="javascript:;"
|
||||
:click="$turn(1, -1)"
|
||||
:text="btns.prevYear"></a>
|
||||
<a href="javascript:;" class="prev-month"
|
||||
:click="$turn(0, -1)" :text="btns.prevMonth"></a>
|
||||
<a href="javascript:;" class="next-month"
|
||||
:click="$turn(0, 1)" :text="btns.nextMonth"></a>
|
||||
<a href="javascript:;" class="next-year"
|
||||
:click="$turn(1, 1)" :text="btns.nextYear"></a>
|
||||
<span :text="calendar.year + '-' + calendar.month"></span>
|
||||
</dd>
|
||||
<dd class="calendar">
|
||||
<section class="week"><span class="td">日</span><span class="td">一</span><span class="td">二</span><span class="td">三</span><span class="td">四</span><span class="td">五</span><span class="td">六</span></section>
|
||||
<section class="list do-fn-cl">
|
||||
<span class="td"
|
||||
:class="{weeken:el.weeken, disabled: el.disable, selected: el.selected}"
|
||||
:repeat="calendar.list"
|
||||
:click="$getDate(el.disable, el.day)"
|
||||
:text="el.day"></span>
|
||||
</section>
|
||||
</dd>
|
||||
<dd class="time" :if="showTime">
|
||||
<label>
|
||||
<input type="text" :duplex-time="calendar.hour" data-format="hour"> 时
|
||||
</label>
|
||||
<label>
|
||||
<input type="text" :duplex-time="calendar.minute" data-format="minute"> 分
|
||||
</label>
|
||||
<label>
|
||||
<input type="text" :duplex-time="calendar.second" data-format="second"> 秒
|
||||
</label>
|
||||
<a href="javascript:;" class="now" :click="$now">现在</a>
|
||||
</dd>
|
||||
<dd class="tips" :if="tips" :text="tips"></dd>
|
||||
</dl>
|
||||
</div>
|
|
@ -0,0 +1,391 @@
|
|||
/**
|
||||
*
|
||||
* @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
|
||||
})
|
|
@ -0,0 +1 @@
|
|||
.do-datepicker{position:relative;z-index:65534;width:100%;height:100%}.do-datepicker a{text-decoration:none}.do-datepicker .date-input{display:block;width:100%;height:100%;padding:0 5px;line-height:18px;border:1px solid #e7e8eb;transition:all .1s ease-in-out}.do-datepicker .date-input:focus{border-color:#1abc9c}.do-datepicker .calendar-box{position:absolute;left:0;top:100%;width:267px;height:auto;min-height:60px;padding:10px;line-height:35px;border:1px solid #ddd;background:#fff;font-size:14px;color:#34495e;text-align:center;box-shadow:0 1px 5px rgba(0,0,0,0.1)}.do-datepicker .calendar-box dt.title{width:100%;height:35px;background:#e7e8eb}.do-datepicker .calendar-box dd.contrl{position:relative;width:90%;height:35px;margin:0 5%}.do-datepicker .calendar-box dd.contrl a{position:absolute;left:0;top:0;width:35px;height:35px;color:#34495e;font-weight:bold}.do-datepicker .calendar-box dd.contrl a:hover{color:#1abc9c}.do-datepicker .calendar-box dd.contrl a.prev-month{left:35px}.do-datepicker .calendar-box dd.contrl a.next-month{left:auto;right:35px}.do-datepicker .calendar-box dd.contrl a.next-year{left:auto;right:0}.do-datepicker .calendar-box dd.calendar{width:100%;height:auto}.do-datepicker .calendar-box dd.calendar .week{width:100%;height:35px;margin-bottom:5px;border-bottom:1px solid #eee}.do-datepicker .calendar-box dd.calendar span.td{float:left;width:35px}.do-datepicker .calendar-box dd.calendar .list span.td{height:30px;line-height:30px;cursor:pointer;transition:all .1s ease-in-out}.do-datepicker .calendar-box dd.calendar .list span.td:hover{background:#e7e8eb}.do-datepicker .calendar-box dd.calendar .list span.td.weeken{color:#e74c3c}.do-datepicker .calendar-box dd.calendar .list span.td.selected{background:#48c9b0;color:#fff}.do-datepicker .calendar-box dd.calendar .list span.td.disabled{color:#bdc3c7;cursor:default}.do-datepicker .calendar-box dd.calendar .list span.td.disabled:hover{background:none}.do-datepicker .calendar-box dd.time{position:relative;width:100%;height:41px;padding:5px 0;margin-top:5px;line-height:30px;border-top:1px solid #eee}.do-datepicker .calendar-box dd.time label{float:left;width:60px;height:30px}.do-datepicker .calendar-box dd.time label input{width:30px;height:30px;border:1px solid #e7e8eb;text-align:center}.do-datepicker .calendar-box dd.time .now{float:right;width:50px;height:30px;border-radius:3px;background:#1abc9c;color:#fff;text-align:center}.do-datepicker .calendar-box dd.time .now:hover{background:#48c9b0}.do-datepicker .calendar-box dd.time .now:active{background:#16a085}.do-datepicker .calendar-box dd.tips{position:absolute;z-index:65535;left:25%;top:40%;width:50%;height:30px;line-height:30px;background:rgba(0,0,0,0.7);color:#fff;font-size:12px;text-align:center}
|
|
@ -0,0 +1,56 @@
|
|||
@charset "UTF-8";
|
||||
/**
|
||||
*
|
||||
* @authors yutent (yutent@doui.cc)
|
||||
* @date 2016-02-14 14:00:06
|
||||
*
|
||||
*/
|
||||
@import "../../../css/var.scss";
|
||||
.do-datepicker {position:relative;z-index:65534;width:100%;height:100%;
|
||||
|
||||
a {text-decoration:none;}
|
||||
.date-input {display:block;width:100%;height:100%;padding:0 5px;line-height:18px;border:1px solid nth($cp, 1);@include ts();
|
||||
|
||||
&:focus {border-color:nth($cg, 1)}
|
||||
}
|
||||
|
||||
.calendar-box {position:absolute;left:0;top:100%;width:267px;height:auto;min-height:60px;padding:10px;line-height:35px;border:1px solid #ddd;background:#fff;font-size:14px;color:nth($cgr, 1);text-align:center;box-shadow:0 1px 5px rgba(0,0,0,.1);
|
||||
|
||||
dt.title {width:100%;height:35px;background:#e7e8eb;}
|
||||
dd.contrl {position:relative;width:90%;height:35px;margin:0 5%;
|
||||
|
||||
a {position:absolute;left:0;top:0;width:35px;height:35px;color:nth($cgr, 1);font-weight:bold;}
|
||||
a:hover {color:nth($cg, 1)}
|
||||
a.prev-month {left:35px;}
|
||||
a.next-month {left:auto;right:35px;}
|
||||
a.next-year {left:auto;right:0;}
|
||||
}
|
||||
|
||||
dd.calendar {width:100%;height:auto;
|
||||
|
||||
.week {width:100%;height:35px;margin-bottom:5px;border-bottom:1px solid #eee;}
|
||||
span.td {float:left;width:35px;}
|
||||
.list span.td {height:30px;line-height:30px;cursor:pointer;@include ts();
|
||||
|
||||
&:hover {background:nth($cp, 1);}
|
||||
&.weeken {color:nth($cr, 1)}
|
||||
&.selected {background:nth($cg, 2);color:#fff}
|
||||
&.disabled {color:nth($cp, 3);cursor:default;}
|
||||
&.disabled:hover {background:none;}
|
||||
}
|
||||
}
|
||||
dd.time {position:relative;width:100%;height:41px;padding:5px 0;margin-top:5px;line-height:30px;border-top:1px solid #eee;
|
||||
|
||||
label {float:left;width:60px;height:30px;
|
||||
input {width:30px;height:30px;border:1px solid nth($cp, 1);text-align:center;}
|
||||
}
|
||||
.now {float:right;width:50px;height:30px;border-radius:3px;background:nth($cg, 1);color:#fff;text-align:center;
|
||||
|
||||
&:hover {background:nth($cg, 2);}
|
||||
&:active {background:nth($cg, 3);}
|
||||
}
|
||||
}
|
||||
dd.tips {position:absolute;z-index:65535;left:25%;top:40%;width:50%;height:30px;line-height:30px;background:rgba(0,0,0,.7);color:#fff;font-size:12px;text-align:center;}
|
||||
}
|
||||
|
||||
}
|
|
@ -1178,7 +1178,7 @@ function $emit(key, args) {
|
|||
var path = p + "." + key;
|
||||
arr = path.split(".");
|
||||
|
||||
args = args.concat([path, key])
|
||||
args = args && args.concat([path, key]) || [path, key]
|
||||
|
||||
if (arr.indexOf("*") === -1) {
|
||||
$emit.call(parent, path, args)//以确切的值往上冒泡
|
||||
|
|
|
@ -1177,7 +1177,7 @@ function $emit(key, args) {
|
|||
var path = p + "." + key;
|
||||
arr = path.split(".");
|
||||
|
||||
args = args.concat([path, key])
|
||||
args = args && args.concat([path, key]) || [path, key]
|
||||
|
||||
if (arr.indexOf("*") === -1) {
|
||||
$emit.call(parent, path, args)//以确切的值往上冒泡
|
||||
|
@ -1711,7 +1711,6 @@ var newProto = {
|
|||
},
|
||||
clear: function () {
|
||||
this.removeAll()
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Reference in New Issue