核心思路参考了群里的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定义到浏览器的四个角上试下