JavaScript 创建日历

基本思路

  • 创建6*7表格

创建表格

  • table 的构成 <table>,<tr>, <td>
  • javasript modify methods: document.createElement("table")同理tr,td。table .insertRow(),table.insertCell(), table.remove(),td.innerHTML = "foo"
  • javascript traverse methods ````,document.getElementByTagName(table),同理tr,td。document.getElementByTagName(td)returns an array of <tr><\tr> elements。或者使用document.getElementByID(id)
  • table.rows对象: rows.item, rows.length 菜鸟教程
    构建简单表格
		// 1. create a table and set attributes
		var _table = document.createElement("table");
		_table.setAttribute("border","1");
		_table.setAttribute("borderColor","black");
		_table.setAttribute("width","200");
		
		// 1.1 set row
		for(var i=0;i<6;i++){
			var _tr=_table.insertRow(i);
			// 1.2 set col
			for(var j=0;j<7;j++){
				var _td=_tr.insertCell(j);	
			}	
		}

		// 1.3 get container and append the table
		var container = document.getElementById("datepicker1");
		container.appendChild(_table);

完成createCalender()

以上的创建表格只是最简单的空表格, 这里我们的表格是一个可以互动的calendar
其中的for loop遍历了这个表格并且调用addDay(), addHead(), addWeek() 来个每个空赋值

createCalendar (date) {
		// 1. create a table and set attributes
		var table = document.createElement("table");
		table.setAttribute("id", "table");
		// 1.1 set content
		// I must add 'this' here, I don't know why 
		this.addHead(table, date); 
		let flag = {value : 0}; // check if there is row7;

		for(var i=1;i<8;i++){
			// row
			var _tr = table.insertRow(i);	
			for(var j=0;j<7;j++){
				// column
				var _td=_tr.insertCell(j);	
				if(i === 1){
					this.addWeek(j, _td);
				} else {
					this.addDay(i, j, date, _td, flag);
				}
			}
		}
		// if there isn't row7, delete it
		if(flag.value !== 1) {
			table.deleteRow(7);
			if(table.rows[6].cells[0].innerHTML === "1"){
				table.deleteRow(6);
			}
		}
		
		// 1.2 get container and append the table
		// we do it in render()
		// var container = document.getElementById("datepicker1");
		// container.appendChild(table);
		

		return table;
	}

完成addHead(), addDay(), addWeek()

addHead()

就是加入month, year和左右箭头,点击左右箭头有功能

addHead (table, date) {
	// month and year
	var head = table.createTHead();
	var headRow = head.insertRow(0);

	var leftArrowCell = headRow.insertCell(0);
	leftArrowCell.innerHTML = "<";
	leftArrowCell.setAttribute("id", "LeftArrow");
	
	var monthCell = headRow.insertCell(1);
	monthCell.innerHTML = this.months[date.getMonth()] + "   " + date.getFullYear();
	monthCell.colSpan = "5";

	var rightArrowCell = headRow.insertCell(2);
	rightArrowCell.innerHTML = ">";
	rightArrowCell.setAttribute("id", "RightArrow");
	
	// event handler.
	leftArrowCell.addEventListener("click", () => {
		table.remove();
		date.setMonth(date.getMonth() - 1);
		console.log(date);
		this.render(date);
	});

	rightArrowCell.addEventListener("click", () => {
		table.remove();
		date.setMonth(date.getMonth() + 1);
		console.log(date);	
		this.render(date);
	});
}

addWeek()

addWeek(j, _td) {
	// var _tn = document.createTextNode(weekName[j]);
	var _tn = this.weekName[j];
	_td.innerHTML = _tn;
}

addDay()

屁事比较多,我需要判断这个月的第一天是哪一天,应该从哪个空开始填。我在填的时候分为三个部分,这个月,下个月和上个月

addDay(i, j, date, _td, flag) {
	// row = i; col = j
	// _td is this cell 
	var my_year = date.getFullYear();
	var my_month = date.getMonth();
	var my_day = date.getDate();
	// calculate the start day of a month
	function dayStart(month, year) {
		var tmpDate = new Date(year, month, 1);
		return (tmpDate.getDay());
	}
	// calculate leap year
	var self = this; // cannot call this.month_normal in the daysMonth function
	function daysMonth(month, year) {
		var leap = (year%4===0 && year%100!==0 || year%400 ===0);
		if (leap) {
			return (self.month_olympic[month]);
		} else {
			return (self.month_normal[month]);
		}
	}
	var firstDay = dayStart(my_month, my_year); 
	var totalDay = daysMonth(my_month, my_year);
	var lastDate = new Date(date);
	lastDate.setMonth(lastDate.getMonth()-1);
	var nextDate = new Date(date);
	nextDate.setMonth(nextDate.getMonth()+1);
	var _tn;
	
	if(i === 2 && j < firstDay) {
		// last month
		_tn = daysMonth(lastDate.getMonth(), lastDate.getFullYear()) + (j-firstDay+1);
		_td.innerHTML = _tn;
		_td.setAttribute("id" , "other");
		// this.hintClick(_td, lastDate, _tn);
	} else if((i-2)*7+j-firstDay+1 <= totalDay){
		// date: (i-2)*7+j-firstDay+1
		_tn = (i-2)*7+j-firstDay+1;
		_td.setAttribute("id" , "this");
		_td.innerHTML = _tn;
		this.hintClick(_td, date,_tn);
		if(i === 7) {
			flag.value = 1;
		}
	} else {
		// next month
		if(flag.value === 1 || i < 7) {
			_td.setAttribute("id" , "other");
			_tn = (i-2)*7+j-firstDay+1-totalDay;
			_td.innerHTML = _tn;
			// this.hintClick(_td, nextDate, _tn);
		}
	}
}
// click这个月的日子控制台会返回其信息
hintClick(_td, date,_tn) {
	let property = {
		month: this.months[date.getMonth()],
		day: _tn,
		year: date.getFullYear()
	};
	_td.addEventListener("click", () => {
		this.callback(this.id, property);
	});
}

类的构造

以上全部作为方法放到类里面,类包括一些需要调用的常量,并且画出表格(之前知识定义了,但是没有添加到HTML文件里面)

class DatePicker {
	
	constructor(id, callback) {
		this.id = id;
		this.callback = callback;
		this.weekName = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
		this.months = ["January","February","March","April","May","June",
		"July","August","September","October","November","December"];
		this.month_normal = [31,28,31,30,31,30,31,31,30,31,30,31];
		this.month_olympic = [31,29,31,30,31,30,31,31,30,31,30,31];
	}
	
	render(date) {
		// argument consisting of a Date object
		// selects a particular month (the object can refer to any time within the month). 
		// When render is invoked it replaces the contents of the 
		// date picker's div with HTML that displays a small one-month calendar 
		var parent = document.getElementById(this.id);
		parent.appendChild(this.createCalendar(date));
	}
}

HTML文件

创建一个对象

datePicker1 = new DatePicker("datepicker1", function (id, fixedDate) {
          console.log("DatePicker with id", id,
                  "selected date:", fixedDate.month + "/" + fixedDate.day + "/" + fixedDate.year);
});
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值