js移動端日曆,可標記點,選範圍

說明:依賴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');

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章