js日历控件

核心思路参考了群里的MK桑的,在此谢过。

(function(){

	var db = document.body;

	var Calendar = function(opts){

		return new Calendar.prototype.init(opts);

	};

	Calendar.prototype = {

		constructor:Calendar,

		init:function(opts){

			this.opts = extend({

				target:'',

				initial:'2012/09/27',

				format:'YYYY-MM-DD',

				callback:function(){}

			},opts||{});

			var _this = this;

			this.target = $(this.opts.target);

			addEvent(this.target,'click',function(){_this.create();});

		},

		create:function(){

			var de = this.target.getAttribute('data-date');

			this.defaultValue = this.defaultValue || (de && new Date(de)) || (this.initial ? new Date(this.initial) : new Date());

			var year = this.defaultValue.getFullYear(),month = this.defaultValue.getMonth(),date =this.defaultValue.getDate(), _this = this;

			var days = this.calculateDays(year,month),fragment = document.createDocumentFragment(),ul = document.createElement('ul');

			this.close();

			this.wrapper = createEl('<div id="date_wrapper"><div id="date_header"><div id="yearBox"><span id="prevYear">«</span><em>'+year+'</em><span id="nextYear">»</span></div><div id="monthBox"><span id="prevMonth">«</span><em>'+(month+1)+'</em><span id="nextMonth">»</span></div></div><div id="date_weekBox"><ul><li>日</li><li>一</li><li>二</li><li>三</li><li>四</li><li>五</li><li>六</li></ul></div><div id="date_dateBox"></div></div>',db);

			

			for(var i=0,len=days.length;i<len;i++){

				var li = document.createElement('li');

				var y = days[i].getFullYear(),m = days[i].getMonth(),d = days[i].getDate();

				var f = m == month;

				var fl = year == y && month == m && date == d;

				li.setAttribute('data-date',days[i]);

				li.innerHTML = d;

				addClass(li,f ? 'black' : 'gray');

				fl && addClass(li,'current');

				fragment.appendChild(li);

			}

			ul.appendChild(fragment);

			$('date_dateBox').appendChild(ul);

			

			setPosition(this.wrapper,this.target);

			

			addEvent($('prevYear'),'click',function(){

				_this.defaultValue.setMonth(_this.defaultValue.getMonth()-12,date);

				_this.create();

			});

			addEvent($('nextYear'),'click',function(){

				_this.defaultValue.setMonth(_this.defaultValue.getMonth()+12,date);

				_this.create();

			});

			addEvent($('prevMonth'),'click',function(){

				_this.defaultValue.setMonth(_this.defaultValue.getMonth()-1,date);

				_this.create();

			});

			addEvent($('nextMonth'),'click',function(){

				_this.defaultValue.setMonth(_this.defaultValue.getMonth()+1,date);

				_this.create();

			});

			addEvent(ul,'click',function(e){

				e = e || window.event;

				var target = e.target || e.srcElement;

				if(hasClass(target,'black')){

					var date = target.getAttribute('data-date');

					_this.target.setAttribute('data-date',date);

					_this.defaultValue = new Date(date);

					if(_this.target.type == 'text') _this.target.value = formatDate(date,_this.opts.format);

					_this.opts.callback && _this.opts.callback(date);

					_this.close();

				};

			});			

		},

		set:function(d){

			this.defaultValue = d ? new Date(d) : new Date();

			this.create();

		},

		get:function(){

			return this.defaultValue;

		},

		close:function(){

			if(!this.wrapper) return;

			this.wrapper.parentNode.removeChild(this.wrapper);

			this.wrapper = null;

		},

		trigger:function(){

			this.create();

		},

		calculateDays:function(y,m){

			var offset, dFirstDay = new Date(y, m, 1), dLastDay = new Date(y, m + 1, 0), arr = [];

			dFirstDay.setMonth(m, 1 - dFirstDay.getDay());

			dLastDay.setMonth(m, dLastDay.getDate() + 6 - dLastDay.getDay());

			offset = parseInt((dLastDay - dFirstDay) / (1000*60*60*24)) + 1;

			var _y = dFirstDay.getFullYear(), _m = dFirstDay.getMonth(), _d = dFirstDay.getDate();

			for(var i=0; i<offset; i++){

				var d = new Date(_y, _m, _d + i);

				arr.push(d);

			}

			return arr;

		}

	};

	Calendar.prototype.init.prototype = Calendar.prototype;

	window.Calendar = Calendar;

	

	

	function $(id){

		return typeof id == 'string' ? document.getElementById(id) : id;

	};

	function createEl(str,parent){

		var div = document.createElement('div'),el;

		div.innerHTML = str;

		el = div.firstChild;

		parent && parent.appendChild(el);

		return el;

	};

	function extend(t,s){

		for(var i in s ) t[i] = s[i];

		return t;

	};

	function getElementPos(el){

		var x = 0,y=0;

		if(el.getBoundingClientRect){

			var pos = el.getBoundingClientRect();

			var d_root = document.documentElement,db = document.body;

			x = pos.left + Math.max(d_root.scrollLeft,db.scrollLeft) - d_root.clientLeft;

			y = pos.top + Math.max(d_root.scrollTop,db.scrollTop) - d_root.clientTop;

		}else{

			while(el != db){

				x += el.offsetLeft;

				y += el.offsetTop;

				el = el.offsetParent;

			};

		};

		return {

			x:x,

			y:y

		};

	};

	function setPosition(target,reference){

		var pos = getElementPos(reference);

		var left = pos.x,top = pos.y;

		var width = reference.offsetWidth,height = reference.offsetHeight;

		var w = target.offsetWidth,h = target.offsetHeight;

		var st = Math.max(document.documentElement.scrollTop,document.body.scrollTop),sl = Math.max(document.documentElement.scrollLeft,document.body.scrollLeft);

		var cw =  document.documentElement.clientWidth,ch = document.documentElement.clientHeight;

		if(ch+st-top-height-1 > h ){

			target.style.top = top + height + 1 + 'px';

		}else{

			target.style.top = top - h - 1 + 'px';

		};

		if(cw+sl-left-width > w){

			target.style.left = left + 'px';

		}else{

			target.style.left = left + width - w + 'px';

		};

	};

	function addEvent(el,type,fn){

		if(typeof el.addEventListener != 'undefined'){

			el.addEventListener(type,fn,false);

		}else if(typeof el.attachEvent != 'undefined'){

			el.attachEvent('on'+type,fn);

		}else{

			el['on'+type] = fn;

		};

	};

	function formatDate(t,tpl){

		var strs=[], w, keys, year, val,t= t ? new Date(t) : new Date();

		w = 'FullYear,Month,Date'.split(',');

		keys = [/YYYY/g, /YY/g, /MM/g, /M/g, /DD/g, /D/g];

		for (var i = 0; i < 3; i++) {

			val = t['get' + w[i]]() + (w[i] === 'Month' ? 1 : 0);

			strs.push(('0' + val).slice( - 2), val)

		};

		year = [strs[1], strs[0]].concat(strs.slice(2));

		for (var i = 0; i < 6; i++) {

			tpl = tpl.replace(keys[i], year[i])

		};

		return tpl;

	};

	function clear(str){

		return str.replace(/^\s+|\s+$/g,'').replace(/\s+/,' ');

	};

	function hasClass(el,oClass){

		return (' '+el.className+' ').indexOf(' '+oClass+' ') > -1;

	};

	function addClass(el,oClass){

		if(hasClass(el,oClass)) return;

		var c = el.className;

		el.className = clear(c? c + ' '+oClass : oClass);

	};

	function removeClass(el,oClass){

		if(!hasClass(el,oClass)) return;

		var c = el.className;

		el.className = clear((' '+c+' ').replace(' '+oClass+' ',''));

	};

})();

HTML:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<html lang="en">

<head>

	<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">

	<title></title>

	<style type="text/css">

		* {padding:0;margin:0;}

		body { font-family:Arial, Helvetica, sans-serif; font-size:12px;}

		ul { list-style:none;}

		#date_wrapper { width:287px; position:absolute; overflow:hidden; background:#fff;}

		#date_header {height:35px;overflow:hidden;}

		#date_header span {display:inline-block;*display:inline;*zoom:1; width:20px;height:20px;line-height:20px;text-align:center;margin:0 5px;vertical-align: 2px; cursor:pointer;font-size:15px;font-weight:bold; color:#fff;}

		#date_header em {font-style: normal; font-weight;bold; font-size:18px; color:#fff;}

		#yearBox { background:#254b7c;float:left;width:204px;height:35px; line-height:35px; text-align:center;}

		#monthBox { background:#436ca5;float:left;width:82px;height:35px; line-height:35px; text-align:center;}

		#date_weekBox li { display:inline-block;*display:inline;*zoom:1;  width:40px; height:30px; margin-right:1px; line-height:30px; text-align:center; background:#c2d7ec; color:#254b7c;}

		#date_dateBox li { display:inline-block;*display:inline;*zoom:1;  width:40px; height:40px; line-height:40px; text-align:center; background:#eaf3fa;margin-right:1px; margin-bottom:1px; font-size:15px; cursor:pointer; color:#254b7c;}

		#date_dateBox li.gray { color:#a6c0d7;}

		#date_dateBox li.current { background:#254b7c; color:#fff;font-weight:bold; }

		input[type="button"] { padding:3px 10px;}

		#calendar {position:absolute;top:400px;left:500px;width:274px;height:30px;line-height:30px;padding:0 5px;border:1px solid #C2D7EC; color:#254b7c;}

	</style>

</head>

<body>

	<input type="text" id="calendar"/>

	<input type="button" id="trigger" value=" trigger" />

	<input type="button" id="set" value="set" />

	<input type="button" id="get" value="get" />

	<input type="button" id="close" value="close" />

	<div style="height:1500px;"></div>

	<script type="text/javascript" src="calendar.js"></script>

	<script type="text/javascript">

		var trigger = document.getElementById('trigger');

		var set = document.getElementById('set');

		var get = document.getElementById('get');

		var close = document.getElementById('close');

		var a = Calendar({

			target:'calendar'

		});

		trigger.onclick = function(){

			a.trigger();

		};

		set.onclick = function(){

			a.set();

			a.trigger();

		};

		get.onclick = function(){

			alert(a.get());

		};

		close.onclick = function(){

			a.close();

		}

	</script>

</body>

</html>

测试时可以将input定义到浏览器的四个角上试下

js日历控件

你可能感兴趣的:(日历控件)