說明:依賴jquery,設置選擇範圍,設置標記點,文字和點等,可自定義格式化文字。
各方法所需參數請查看源碼說明
效果:
源碼:
/**
* Name:calender.js
* Author:Li
* E-mail:[email protected]
* Time: 2019-8-22 10:07:56
* time:時間
* text:文本
* markPoint:true/false,是否顯示點
* pointText:右上角是否顯示爲文字
* formatText:function,格式化底部文本
*/
var calendarWidget = {
config: {},
htmlStr: "",
topSelecter: undefined,
year: undefined,
month: undefined,
day: undefined,
range:{ //標記範圍
start:undefined,
end:undefined
},
/**
* 初始化
* @param {obj} data 以下爲data的參數
* @param {string} currentTime 當前時間 yyyy-MM-dd
* @param {string} elem 綁定div的id 帶#
* @param {array} mark 標記點列表
* @param {function} change 日期改變事件回調
* @param {function} mounted 渲染完成事件回調
* @param {function} dateclick 頂頭的日期點擊回調,可以通過此回調選擇月份
* @param {function} formatText 格式化底部的文字
* @param {string} lastText 上月文字
* @param {string} nextText 下月文字
* */
initCalculate: function(data) {
calendarWidget.config = data || {
currentTime: "", //當前時間 yyyy-MM-dd
elem: undefined, //綁定div的id 帶#
mark: [], //標記點列表
change: undefined, //日期改變事件回調
mounted:undefined, //渲染完成事件回調
dateclick:undefined, //頂頭的日期點擊回調,可以通過此回調選擇月份
formatText:undefined, //格式化底部的文字
startDate:undefined, //選擇的開始時間,此時間之前爲灰色狀態 yyyy-MM-dd 未實現
endDate:undefined, //選擇的結束時間,此時間之後爲灰色狀態 yyyy-MM-dd 未實現
lastText:'〈', //上月文字
nextText:'〉', //下月文字
};
calendarWidget.config.lastText = data.lastText?data.lastText:'〈';
calendarWidget.config.nextText = data.nextText?data.nextText:'〉'
if (!calendarWidget.config.elem) {
console.error("element is not set");
return;
}
if (calendarWidget.config.currentTime == "" || calendarWidget.config.currentTime == undefined) {
calendarWidget.config.currentTime = new Date().getFullYear() + "/" + (new Date().getMonth() + 1) + "/01";
}
calendarWidget.config.currentTime = calendarWidget.config.currentTime.replace(/-/g, "/");
//設置開始時間
if(calendarWidget.config.startDate){
calendarWidget.config.startDate = new Date(calendarWidget.config.startDate.replace(/-/g, "/"));
if(calendarWidget.config.startDate == "Invalid Date"){
console.error('startDate config error');
calendarWidget.config.startDate = undefined;
}
}
//設置結束時間
if(calendarWidget.config.endDate){
calendarWidget.config.endDate = new Date(calendarWidget.config.endDate.replace(/-/g, "/"));
if(calendarWidget.config.endDate == "Invalid Date"){
console.error('endDate config error');
calendarWidget.config.endDate = undefined;
}
}
calendarWidget.renderCalendar();
},
renderCalendar: function() { //生成日曆
calendarWidget.day = "";
calendarWidget.config.currentTime = calendarWidget.config.currentTime.replace(/-/g, "/");
var tempDateWidget = new Date(calendarWidget.config.currentTime);
calendarWidget.config.currentTime = tempDateWidget.getFullYear() + "/" + (tempDateWidget.getMonth() + 1) + "/01"; //重置當前時間月份1號
var totalDay = calendarWidget.getTotalDay(calendarWidget.config.currentTime); //獲取一個月的天數
var date = new Date(calendarWidget.config.currentTime);
calendarWidget.year = date.getFullYear();
calendarWidget.month = date.getMonth() + 1;
var firstDayWeek = date.getDay(); //第一天是星期幾
var textStr = calendarWidget.year + "年" + calendarWidget.month + '月'; //頂部顯示的日期
var sum = 0;
var htmlStr = "";
//獲取上一個月的天數
var TempMonth;
var TempYear;
if (calendarWidget.month == 1) { //跨年
TempMonth = 12;
TempYear = calendarWidget.year - 1;
} else {
TempYear = calendarWidget.year;
TempMonth = calendarWidget.month - 1;
}
var TempLastMonthStr = TempYear + "/" + TempMonth + "/01";
var lastMonthTotalDay = calendarWidget.getTotalDay(TempLastMonthStr);
var lastMonthStartDay = lastMonthTotalDay - firstDayWeek;
// 創建前面的日期
for (var i = 0; i < firstDayWeek; i++) {
sum++;
lastMonthStartDay++;
htmlStr += '<div class="calendar-col aligncanter calendar-col-lastMonth">' + lastMonthStartDay + '</div>';
}
var dayStr = calendarWidget.year + "-" + calendarWidget.month;
//獲取當前時間
var currentDateTemp = new Date().getFullYear() + "-" + (new Date().getMonth() + 1) + "-" + new Date().getDate();
//生成日曆
for (var i = 1; i <= totalDay; i++) { //循環日
sum++;
var tempDay = dayStr + "-" + i; //日期字符串
var fontText = i; //日期數字
//當前日期變量
var tempCurrTime = new Date(tempDay.replace('-','/').replace('-','/'));
var tempCurrWeek = tempCurrTime.getDay();
if(tempCurrWeek == 0 || tempCurrWeek == 6) //週六和週日,特殊處理
fontText = "<span class='calendar-day-6-7'>" + fontText +"</span>";
var textTemp = "<div class='dayValue'>" + fontText + "<span class='calendar-point'></span><span class='calendar-text'></span></div>";
for (var z = 0; z < calendarWidget.config.mark.length; z++) { //判斷是否爲標記點
if (tempDay == calendarWidget.config.mark[z].time.trim()) {
var tempTextStr = calendarWidget.config.formatText == undefined? calendarWidget.config.mark[z].text
: calendarWidget.config.formatText(calendarWidget.config.mark[z].text);
textTemp = "<div class='dayValue'>" + fontText;
if (calendarWidget.config.mark[z].markPoint != false) // 是否顯示點
textTemp += calendarWidget.config.mark[z].pointText? '<span class="calendar-point">'+calendarWidget.config.mark[z].pointText+'</span>' : '<span class="calendar-point">●</span>';
if (tempTextStr != undefined && tempTextStr != "") // 是否顯示文字
textTemp += '<div class="calendar-text">' + tempTextStr + '</div>';
textTemp += "</div>";
break;
}
}
//如果設置了範圍
var calendar_range = "";
if(calendarWidget.range.start && calendarWidget.range.end){
if(calendarWidget.range.start <= tempCurrTime && tempCurrTime <= calendarWidget.range.end)
calendar_range = ' calendar-range ';
}
if (tempDay == currentDateTemp) { //當天
htmlStr += '<div class="calendar-col aligncanter currentDays calendar-today ' +calendar_range + '" data-day="' + i + '" data-date="' + tempDay + '">' + textTemp +
'</div>';
} else { //其他
htmlStr += '<div class="calendar-col aligncanter currentDays ' +calendar_range + '" data-day="' + i + '" data-date="' + tempDay + '">' + textTemp + '</div>';
}
}
if (sum < 42) { // 創建後面的空白,補夠五行
var j = 0;
for (var i = sum; i < 42; i++) {
sum++;
j++;
htmlStr += '<div class="calendar-col aligncanter calendar-col-nextMonth">' + j + '</div>';
}
}
var content = "<div class='calendar-Time-header under_line'><a class='calendar-lastMonth'>" +calendarWidget.config.lastText+ "</a><a class='calendar-TimeH'>" +
textStr + "<a><a class='calendar-nextMonth'>" +calendarWidget.config.nextText+ "</a> <a class='calendar-backToToday'>回到今天</a></div><div class='ClearBoth'></div>" +
'<div class="calendar-content">' +
'<div class="calendar-row calendar-header">' +
'<div class="calendar-col aligncanter">日</div>' +
'<div class="calendar-col aligncanter">一</div>' +
'<div class="calendar-col aligncanter">二</div>' +
'<div class="calendar-col aligncanter">三</div>' +
'<div class="calendar-col aligncanter">四</div>' +
'<div class="calendar-col aligncanter">五</div>' +
'<div class="calendar-col aligncanter">六</div>' +
'</div>' +
'<div class="calendar-row calendar-day">' + htmlStr +
'</div><div class="ClearBoth"></div> ' +
'</div>';
calendarWidget.htmlStr = content;
$(calendarWidget.config.elem).html(calendarWidget.htmlStr);
calendarWidget.bindEvent();
if (calendarWidget.config.mounted) //初始化完成
calendarWidget.config.mounted(calendarWidget.year + "/" + calendarWidget.month);
return content;
},
bindEvent: function() { //綁定事件
//點擊頂部時間回調
$(".calendar-TimeH").on('tap',function(){
if(calendarWidget.config.dateclick){
var textStr = calendarWidget.year + "-" + calendarWidget.month;
calendarWidget.config.dateclick(calendarWidget, textStr);
}
})
//每項點擊
$(".calendar-day").on('tap', '.currentDays', function() {
$(".calendar-active").removeClass("calendar-active");
$(this).addClass("calendar-active");
calendarWidget.day = $(this).attr("data-day");
calendarWidget.change();
})
//日曆中屬於上個月的日期
$(".calendar-day").on('tap', '.calendar-col-lastMonth', function() {
var screenX = window.screen.width;
calendarWidget.calendarTransform(screenX,300);
setTimeout(function(){
calendarWidget.subMonth();
},300);
})
//日曆中屬於下個月的日期
$(".calendar-day").on('tap', '.calendar-col-nextMonth', function() {
var screenX = window.screen.width;
screenX = -screenX;
calendarWidget.calendarTransform(screenX,300);
setTimeout(function(){
calendarWidget.addMonth();
},300);
})
//頭部上月按鈕
$(".calendar-nextMonth").on('tap', function() {
var screenX = window.screen.width;
screenX = -screenX;
calendarWidget.calendarTransform(screenX,300);
setTimeout(function(){
calendarWidget.addMonth();
},300);
})
//頭部下月按鈕
$(".calendar-lastMonth").on('tap', function() {
var screenX = window.screen.width;
calendarWidget.calendarTransform(screenX,300);
setTimeout(function(){
calendarWidget.subMonth();
},300);
})
//頭部回到今天按鈕
$(".calendar-backToToday").on('tap', function() {
var currDate = new Date();
var value = currDate.getFullYear() + "-" + (currDate.getMonth() + 1) + "-" + currDate.getDate();
calendarWidget.setDate(value);
})
//以下爲實現日曆左右滾動
var startPageX = 0;
var startPageY = 0;
$(".calendar-day").on("touchstart", function(e) {
startPageX = event.targetTouches[0].pageX;
startPageY = event.targetTouches[0].pageY;
})
$(".calendar-day").on("touchmove", function(e) {
var touchmovePageX = event.targetTouches[0].pageX;
var result = touchmovePageX - startPageX;
calendarWidget.calendarTransform(result,0);
})
$(".calendar-day").on("touchend", function(e) {
var endPageX = event.changedTouches[0].pageX;
var endPageY = event.changedTouches[0].pageY;
var x = Math.abs(startPageX - endPageX); //橫座標之差
var y = Math.abs(startPageY - endPageY); //縱座標之差
var screenX = window.screen.width;
var screenY = window.screen.height;
if (startPageX > endPageX) { //左滑
var a = Math.atan(y / x);
var Rate = x / screenX;
if (a < Math.PI / 6 && Rate > 0.3) {
screenX = -screenX;
calendarWidget.calendarTransform(screenX,300);
setTimeout(function(){
calendarWidget.addMonth();
},300);
}
else{
calendarWidget.calendarTransform(0,300);
}
} else {
var a = Math.atan(y / x);
var Rate = x / screenX;
if (a < Math.PI / 6 && Rate > 0.3) {
calendarWidget.calendarTransform(screenX,300);
setTimeout(function(){
calendarWidget.subMonth();
},300);
}
else{
calendarWidget.calendarTransform(0,300);
}
}
})
},
calendarTransform:function(x,time){ //日曆滑動動畫
$(".calendar-day").css("transform", 'translate3d('+x+'px, 0px, 0px) translateZ(0px)');
$(".calendar-day").css("transition-duration", time+"ms");
},
addMonth: function() { //加一個月
if (calendarWidget.month == 12) { //跨年
calendarWidget.month = 1;
calendarWidget.year += 1;
} else {
calendarWidget.month += 1;
}
var str = calendarWidget.year + "/" + calendarWidget.month + "/01";
calendarWidget.setDate(str);
},
subMonth: function() { //減一個月
if (calendarWidget.month == 1) { //跨年
calendarWidget.month = 12;
calendarWidget.year -= 1;
} else {
calendarWidget.month -= 1;
}
var str = calendarWidget.year + "/" + calendarWidget.month + "/01";
calendarWidget.setDate(str);
},
setDate:function(date){ //設置日期並重新生成日曆
calendarWidget.config.currentTime = date;
calendarWidget.renderCalendar();
},
change: function() { //改變日期
var tempd = calendarWidget.getSelectedDay();
var markPoint = undefined;
for (var z = 0; z < calendarWidget.config.mark.length; z++) { //判斷是否爲標記點
if (tempd.indexOf(calendarWidget.config.mark[z].time) > -1) {
markPoint = calendarWidget.config.mark[z];
}
}
if (calendarWidget.config.change)
calendarWidget.config.change(tempd, markPoint);
},
getSelectedDay: function() { //獲取選擇時間
return calendarWidget.year + '-' + calendarWidget.month + '-' + calendarWidget.day;
},
/**
* 設置標記點,初始化完成後可執行
* @param {array} data 標記點列表
* [{
* time:'yyyy-MM-dd', string 標記時間
* text:'標記文本', string 標記文本
* markPoint:false, boolean 是否顯示點
* pointText:'文字' string 代替點的文字,設置了則不顯示點,需要把markPoint設爲true
* }]
* @param {Boolean} cover 是否覆蓋原來的標記點
* @return none
* */
setMark:function(data,cover){
if(cover){ //如果是覆蓋標記點
calendarWidget.config.mark = data;
calendarWidget.renderCalendar();
return;
}
if(data && data.length > 0){ //填充標記點
for(var i = 0;i < data.length;i++){
if(data[i] ==undefined){
continue;
}
calendarWidget.config.mark.push(data[i])
var selectDiv = $(".calendar-day").find('div[data-date="'+data[i].time+'"]');
var tempTextStr = calendarWidget.config.formatText == undefined? data[i].text
: calendarWidget.config.formatText(data[i].text);
if (tempTextStr != undefined && tempTextStr != ""){// 是否顯示文字
$(selectDiv).find('.calendar-text').html(tempTextStr);
}
if(data[i].markPoint){// 是否顯示點
var pointTextStr = data[i].pointText? data[i].pointText : '●';
$(selectDiv).find('.calendar-point').html(pointTextStr);
}
}
}
},
/**
* 設置標記範圍,初始化完成後可執行
* @param {string} startDate 開始時間 yyyy-MM-dd
* @param {string} endDate 結束時間 yyyy-MM-dd
* */
setRange:function(startDate,endDate){
calendarWidget.range.start = undefined;
calendarWidget.range.end = undefined;
if(startDate && endDate){ //填充標記點
startDate = startDate.replace(/-/g, "/");
endDate = endDate.replace(/-/g, "/");
var start = new Date(startDate);
var end = new Date(endDate);
calendarWidget.range.start = new Date(startDate);
calendarWidget.range.end = new Date(endDate);
if(start == "Invalid Date" || end == "Invalid Date"){
console.error('setRange : error param');
return;
}
while(start <= end){
var currentTimeStr = start.getFullYear() + "-" + (start.getMonth() + 1) + "-" + start.getDate();
var selectDiv = $(".calendar-day").find('div[data-date="'+currentTimeStr+'"]');
$(selectDiv).addClass("calendar-range");
$(selectDiv).removeClass("calendar-active");
start = start.setDate(start.getDate() + 1);
start=new Date(start);
}
}
else
console.error('setRange : error param');
},
clearRange:function(){ //去掉範圍標記
calendarWidget.range.start = undefined;
calendarWidget.range.end = undefined;
$(".calendar-range").removeClass("calendar-range");
},
getTotalDay: function(time) { //獲取月日期總數
time = time.replace(/-/g, "/");
var selectedDate = new Date(time);
if(selectedDate == "Invalid Date"){
selectedDate = new Date(time + "/01");
}
var selectedMonth = selectedDate.getMonth() + 1;
selectedDate.setMonth(selectedMonth);
selectedDate.setDate(0);
var dayMany = selectedDate.getDate();
return dayMany;
},
/**
* 設置日曆的日期範圍
* @param {string} startDate 開始時間 yyyy-MM-dd
* @param {string} endDate 結束時間 yyyy-MM-dd
* */
setDateRange:function(startDate,endDate){
//設置開始時間
if(startDate){
calendarWidget.config.startDate = new Date(startDate.replace(/-/g, "/"));
if(calendarWidget.config.startDate == "Invalid Date"){
console.error('startDate config error');
calendarWidget.config.startDate = undefined;
}
}
//設置結束時間
if(endDate){
calendarWidget.config.endDate = new Date(endDate.replace(/-/g, "/"));
if(calendarWidget.config.endDate == "Invalid Date"){
console.error('endDate config error');
calendarWidget.config.endDate = undefined;
}
}
calendarWidget.renderCalendar();
}
}
樣式:
.calendar-Time-header{
/* border-top: 1px solid gainsboro; */
text-align: center;
min-height: 40px;
padding: 10px;
}
.calendar-TimeH{
}
.calendar-lastMonth{
width: 50px;
font-size: 15px;
margin-right: 10%;
padding: 0 5px;
/* float: left; */
text-align: center;
}
.calendar-nextMonth{
text-align: center;
margin-left: 10%;
font-size: 15px;
padding: 0 5px;
/* float: right; */
}
.calendar-backToToday{
text-align: center;
font-size: 12px;
position: absolute;
right: 5px;
}
.calendar-row:before,
.calendar-row:after {
display: table;
content: ' ';
}
.calendar-row:after {
clear: both;
}
.calendar-col {
border-radius: 3px;
width: 14.285714%;
position: relative;
float: left;
padding: 8px;
min-height: 40px;
}
.aligncanter {
text-align: center;
}
.calendar-header {
color: gray;
height: 40px;
font-size: 12px;
/* border-bottom: 1px solid gainsboro; */
}
.calendar-day {
height: 40px;
transform: translate3d(0px, 0px, 0px) translateZ(0px); transition-duration: 0ms; transition-timing-function: cubic-bezier(0.165, 0.84, 0.44, 1);
}
.calendar-content {
}
.calendar-today {
background-color: #43CD80;
color:white;
-moz-box-shadow: 0px 1px 5px #ABABAB;
-webkit-box-shadow: 0px 1px 5px #ABABAB;
box-shadow: 0px 1px 5px #ABABAB;
}
.calendar-active {
color:#01AAED;
background-color: #D9D9D9;
-moz-box-shadow: 0px 1px 5px #ABABAB;
-webkit-box-shadow: 0px 1px 5px #ABABAB;
box-shadow: 0px 1px 5px #ABABAB;
}
/* 範圍標記 */
.calendar-range {
/* color:#01AAED; */
border-radius: 0px;
background-color: #D9D9D9;
-moz-box-shadow: none;
-webkit-box-shadow: none;
box-shadow: none;
}
.ClearBoth {
clear: both;
/* border-top: 1px solid gainsboro; */
}
.calendar-col-nextMonth{
color:gainsboro;
}
.calendar-col-lastMonth{
color:gainsboro;
}
.calendar-point{
font-size: 8px;color: #01AAED;top:0px;right: 1px;position: absolute;
}
.calendar-text{
max-height: .25rem;
padding: .01rem;
width:100%;font-size: .14rem;color: #01AAED;top:20px;left: 0px;position: absolute;overflow:hidden;
}
.dayValue{
text-align: center;
}
.calendar-day-6-7{
color: gray;
}
/* 以下爲實現0.5px底部邊界 */
.under_line{position: relative;}
.under_line:before,
.under_line:after{position: absolute;content: " ";height: 1px;width: 100%;left: 0;transform-origin: 0 0;-webkit-transform-origin: 0 0;}
/* .fineLine:before{頂部top: 0;background: #000;} */
.under_line:after{bottom: 0;border-bottom: 1px solid gainsboro;}
@media only screen and (-webkit-min-device-pixel-ratio: 1.5){.under_line:after,.under_line:before{-webkit-transform: scaleY(.667);}}
@media only screen and (-webkit-min-device-pixel-ratio: 2){.under_line:after,.under_line:before{-webkit-transform: scaleY(.5);}}
/* 以上爲實現0.5px底部邊界 */
用法:
<div id='dateWidget' style='background-color: white;'></div>
calendarWidget.initCalculate({
elem: "#dateWidget",
currentTime: '2019-8-1',
mark: [{
time: '2019-8-5',
text: '<span style="color:red">未排</span>',
markPoint: true,
pointText: '<span style="color:red">●</span>'
}],
mounted: function(data) { //初始化完成
console.log(data)
},
change: function(selectedDate, markPoint) {
},
dateclick: function(widget, curentDate) { //點擊頂部時間回調,方便外部設置時間
}
formatText: function(text) { //格式化文本
}
});
//設置範圍
calendarWidget.setRange('2019-8-1', '2019-8-15');