原生Js日历控件-多种状态可选

早就想自己写个日历控件练练手了,可惜一直没时间。

项目里一直都在用Jquery的日期控件,慢慢的需求增多了,不想改别人的,但是网站上放2个以上同功能的控件又不和谐,所以决定自己写一个。

照着淘宝的样式做了一个,目前实现了几种形态:

1.单月/双月的显示

2.年月是否可选

3.今日以前的日期是否可选

支持多个input 兼容ie/ff/chrome

在线预览地址:http://jsfiddle.net/dtdxrk/MA4x5/embedded/result/

压缩好的文件打包下载:http://files.cnblogs.com/dtdxrk/Calendar.rar

  1 <!DOCTYPE HTML>
  2   <html lang="en">
  3   <head>
  4   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5   <title>原生Js日历控件-多种状态</title>
  6   <style type="text/css">
  7   *{margin:0;padding: 0; }
  8 
  9   #txt {background-color: green;padding: 5px;line-height: 1.5;color: #fff;}
 10 
 11   /*日历控件*/
 12   input.input_Calendar, .div_Calendar button{ background: url(http://images.cnblogs.com/cnblogs_com/dtdxrk/485636/o_Calendar_bg.gif) no-repeat;}
 13   
 14   .div_Calendar{display:none;z-index: 9999; overflow: hidden; font-size: 13px;padding:0 25px;_padding-bottom:15px;width:auto;box-shadow: 2px 2px 3px rgba(0,0,0,0.3);font-family: Arial; position: absolute;border:1px solid #ccc; background-color: #fff;}
 15   .div_Calendar div.div_Month{margin:15px;float: left;_display:inline;}
 16   .div_Calendar div.double{margin-left: 0;}
 17   .div_Calendar div.div_Month h1{text-align: center;font-size: 13px;line-height: 1;margin-bottom: 5px;}
 18   .div_Calendar div.div_Month table, .div_Calendar div.div_Month table th,.div_Calendar div.div_Month table td{border-collapse: collapse;}
 19   .div_Calendar div.div_Month table{border-top:1px solid #DCDCDC;text-align: center;}
 20   .div_Calendar div.div_Month table th{font-weight: normal;padding: 2px 5px;}
 21   .div_Calendar div.div_Month table td{border:1px solid #DCDCDC;}
 22   .div_Calendar div.div_Month table td span{padding: 2px 5px;color: #ccc; cursor:default ;display: block;}
 23   .div_Calendar div.div_Month table td a{ text-decoration: none;color: #000; display: block;padding: 2px 5px;font-weight: bold;cursor: pointer;}
 24   .div_Calendar div.div_Month table td a:hover{color: #fff;background-color: #5792dc; }
 25   .div_Calendar div.div_Month table td a.active,.div_Calendar div.div_Month table td a.on{background-color:#5792dc;color: #fff;}
 26   .div_Calendar button{position: absolute;padding: 5px 2px;border:0;cursor: pointer;text-indent: -9999px; }
 27   .div_Calendar button.m_prev{left:10px;top:75px;width: 20px;height: 38px;}
 28   .div_Calendar button.m_next{right: 10px;top:75px;background-position: -20px 0;width: 20px;height: 38px;}
 29   .div_Calendar button.c_close{ right: 5px;top: 5px;width: 17px;height: 17px;background-position: -40px 0;}
 30 
 31   input.input_Calendar{
 32     cursor: pointer;
 33     border: 1px solid #ccc;
 34     padding: 4px;
 35     background-position: 95% -122px;
 36     vertical-align: middle;
 37     width: 100px;
 38   }
 39 
 40   </style>
 41   
 42   <body>
 43   <ul id="txt">
 44     <li>以前一直在用Jquery的日期控件,慢慢的需求增多了,修改别人的很头疼,但是网站上放2个以上同功能的控件又不和谐,所以决定自己写一个。
 45 照着淘宝的样式做了一个,目前实现了几种形态:</li>
 46     <li>1.单月/双月的显示</li>
 47     <li>2.年月是否可选</li>
 48     <li>3.今日以前的日期是否可选</li>
 49     <li>4.兼容ie/ff/chrome</li>
 50   </ul>
 51 
 52 
 53 <div style="margin-top:200px;margin-left:400px;">
 54 入住时间<input type="text" class="input_Calendar" id="inDate" name="inDate" readOnly="true" value=""><br><br>
 55 离店时间<input type="text" class="input_Calendar" id="outDate" name="outDate" readOnly="true" value="">
 56 <p>
 57 <br>
 58 <select name="IE6">
 59     <option>测试IE6</option>
 60     <option>2</option>
 61     <option>3</option>
 62 </select>
 63 <select name="IE6">
 64     <option>测试IE6</option>
 65     <option>2</option>
 66     <option>3</option>
 67 </select>
 68 <select name="IE6">
 69     <option>测试IE6</option>
 70     <option>2</option>
 71     <option>3</option>
 72 </select>
 73 <select name="IE6">
 74     <option>测试IE6</option>
 75     <option>2</option>
 76     <option>3</option>
 77 </select>
 78 <select name="IE6">
 79     <option>测试IE6</option>
 80     <option>2</option>
 81     <option>3</option>
 82 </select>
 83 <select name="IE6">
 84     <option>测试IE6</option>
 85     <option>2</option>
 86     <option>3</option>
 87 </select></p>
 88 </div>
 89 
 90 其他时间<input type="text" class="input_Calendar" id="Date" name="Date" readOnly="true" value="">
 91 
 92 
 93 
 94 <script type="text/javascript">
 95 
 96 var _CalF = {
 97   $ : function(object){//选择器
 98     if(object === undefined ) return;
 99     var getArr = function(name,tagName,attr){
100           var tagName = tagName || '*',
101               eles = document.getElementsByTagName(tagName),
102               clas = (typeof document.body.style.maxHeight === "undefined") ? "className" : "class";//ie6
103               attr = attr || clas,
104               Arr = [];
105           for(var i=0;i<eles.length;i++){
106             if(eles[i].getAttribute(attr)==name){
107               Arr.push(eles[i]);
108             }
109           }
110           return Arr;
111         };
112   
113     if(object.indexOf('#') === 0){  //#id 
114       return document.getElementById(object.substring(1));
115     }else if(object.indexOf('.') === 0){  //.class
116       return getArr(object.substring(1));
117     }else if(object.match(/=/g)){  //attr=name
118       return getArr(object.substring(object.search(/=/g)+1),null,object.substring(0,object.search(/=/g)));
119     }else if(object.match(/./g)){ //tagName.className
120       return getArr(object.split('.')[1],object.split('.')[0]);
121     }
122   },
123   addHandler:function(node, type, handler){
124       node.addEventListener ? node.addEventListener(type, handler, false) : node.attachEvent('on'+ type, handler);
125   },
126   removeHandler: function (node, type, handler) {
127       node.removeEventListener ? node.removeEventListener(type, handler, false) : node.detachEvent("on" + type, handler);
128   },
129   getPosition : function(obj) { //获取元素在页面里的位置和宽高
130      var top = 0,
131          left = 0,
132          width = obj.offsetWidth,
133          height = obj.offsetHeight;
134  
135      while(obj.offsetParent){
136          top += obj.offsetTop;
137          left += obj.offsetLeft;
138          obj = obj.offsetParent;
139      }
140  
141      return {"top":top,"left":left,"width":width,"height":height};
142   },
143   addClass:function(c,node){  // 添加样式名
144       node.className = node.className + ' ' + c;
145   },
146   removeClass:function(c,node){ // 移除样式名
147       var reg = new RegExp("(^|\\s+)" + c + "(\\s+|$)","g");
148       node.className = node.className.replace(reg, '');
149   },
150   stopPropagation:function(event){  // 阻止冒泡
151       var event = event || window.event;
152       event.stopPropagation ? event.stopPropagation() : event.cancelBubble = true;
153   },
154   ie6 : function(){
155      return !!window.ActiveXObject && !window.XMLHttpRequest;
156   }
157 
158 };
159 
160 
161 function Calender() {
162     this.init.apply(this, arguments);
163 }
164 
165 Calender.prototype = {
166     _temp : [ //table数组模板
167       '<table>',
168       '<tr><th>日</th><th>一</th><th>二</th><th>三</th><th>四</th><th>五</th><th>六</th></tr>'
169     ],
170     _tempButton :[
171       '<button class="c_close" title="关闭" >关闭</button>',
172       '<button class="m_prev" title="上一月" >上一月</button>',
173       '<button class="m_next" title="下一月" >下一月</button>'
174     ],
175     init :function(options){
176         this.id = options.id; //input id
177         this.input = _CalF.$("#"+this.id);  //input
178         this.past = options.past; //以前的日期能不能选择
179         this.select = options.select; //日月选择
180         this.doubleMonths = options.doubleMonths; //显示两个月
181         this.createCalendar();
182         this.inputEvent();
183     },
184     inputEvent : function(){   //input事件
185         var that = this;
186          _CalF.addHandler(this.input, 'click',function(){
187             that.createMon(new Date());
188         });
189     },
190     createCalendar : function(){//创建日历div并且定位
191         var div = this.CalendarDiv = document.createElement('div'),
192             input = _CalF.getPosition(this.input),
193             top = input.top,
194             left = input.left,
195             height = input.height;
196             divHtml = this._tempButton.concat(); //复制一个新数组
197 
198         div.id = "Calendar_"+this.id;
199         div.className= "div_Calendar";
200         div.innerHTML = divHtml.join("");
201         div.style.top = (top+height) +"px";
202         div.style.left = left +"px";
203         _CalF.addHandler(div,"click", _CalF.stopPropagation); //阻止事件冒泡
204         document.body.appendChild(div);
205         this.btnEvent();  //按钮事件
206     },
207     createIframe : function(){  //ie6创建iframe遮罩
208       var myIframe =  document.createElement('iframe');
209         myIframe.style.position = 'absolute';
210         myIframe.style.zIndex = '-1';
211         myIframe.style.left = '-1px';
212         myIframe.style.top = 0;
213         myIframe.style.border = 0;
214         myIframe.style.filter = 'alpha(opacity= 0 )';
215         myIframe.style.width = this.CalendarDiv.offsetWidth + 'px';
216         myIframe.style.height = this.CalendarDiv.offsetHeight + 'px';
217         return myIframe;
218     },
219     del_Mon:function(){ //删除月节点
220         var that = this,
221             divs = that.CalendarDiv.getElementsByTagName("div");
222         if(divs.length !== 0){
223           that.CalendarDiv.removeChild(divs[0]);
224           if(this.doubleMonths)that.CalendarDiv.removeChild(divs[0]);
225         }
226     },
227     createMon : function(idate){//创建div_Month
228       this.del_Mon();
229 
230       var now = new Date(),
231           now_year = now.getFullYear(),
232           now_month = now.getMonth(),
233           now_taday = now.getDate(),
234           i=1,  //每月从1号开始
235           trs,  //行数
236           h1, //h1 html
237           div_Month,  //月div
238           year,month,date,time,
239           firstDay, //当月第一天星期几
240           ifTaday ,
241           is_leap = function(year){return (year%400==0) ? 1 : 0},//是否为闰年 能够被400整除的闰年2月29天 不能被整除的是平年2月28天
242           months = [31,28+is_leap(this.year),31,30,31,31,30,31,30,31,30,31], //月天数
243           divHmtl = this._temp.concat(); //复制一个新数组
244 
245       this.year = year = idate.getFullYear();
246       this.month = month = idate.getMonth();
247       this.date = date = idate.getDate();
248 
249       ifTaday = (year==now_year && month==now_month) ? true : false;//判断是不是今年今月
250 
251       div_Month = document.createElement("div");
252       div_Month.className = "div_Month";
253 
254       this.select ? h1 = this.isSelect(year,month) : h1 = "<h1>"+year+""+(month+1)+"月</h1>";
255 
256       firstDay = new Date(year,month,1).getDay();   
257       trs = Math.ceil((months[month]+firstDay)/7);//行数
258 
259       for(var a =0;a<trs;a++){
260         divHmtl.push("<tr>")
261           for(var b=0;b<7;b++){
262             divHmtl.push("<td>");
263                  if (b >= firstDay) {
264                      firstDay = 0;
265                      if (i <= months[month]){  //循环当前月日期
266                         if(ifTaday && i==now_taday){
267                             divHmtl.push("<a class='live active' date="+year+"-"+(month+1)+"-"+i+">"+i+"</a>")
268                         }else if(this.past){  //今天以前的日期不可选
269                                var old = new Date(this.year, this.month, i).getTime(),
270                                    taday = new Date(now_year, now_month, now_taday).getTime();
271                                (old<taday) ? divHmtl.push("<span>"+i+"</span>") : divHmtl.push("<a class='live' date="+year+"-"+(month+1)+"-"+i+">"+i+"</a>");
272                         }else{
273                             divHmtl.push("<a class='live' date="+year+"-"+(month+1)+"-"+i+">"+i+"</a>");  
274                         }         
275                         i++;
276                      }
277                  }           
278             divHmtl.push("</td>");      
279           }
280         divHmtl.push("</tr>")
281       }
282 
283       divHmtl.unshift(h1);
284       div_Month.innerHTML = divHmtl.join("");
285       this.CalendarDiv.appendChild(div_Month);
286 
287       //显示两个月
288       if(this.doubleMonths) this.CalendarDiv.appendChild(this.creatdbMonths(idate));
289 
290       this.CalendarDiv.style.display = "block";
291       
292       this.aClick();
293       this.outClick();  //body点击事件
294       if(this.select) this.selectChange();  //邦定事件
295       if(_CalF.ie6()){this.CalendarDiv.appendChild(this.createIframe())};
296     },
297     isSelect :function(year,month){ //返回select h1
298       var h1_html=[];
299       h1_html.push('<h1><select id=yearSelect>');
300 
301       for(var y=2030;y>1941;y--){
302         if(y==year){
303           h1_html.push('<option value ="'+ y +'" selected>'+ y +'</option>');
304         }else{
305           h1_html.push('<option value ="'+ y +'">'+ y +'</option>');
306         }
307       }
308 
309       h1_html.push('</select>');
310       h1_html.push('');
311       h1_html.push('<select id=monthSelect>');
312 
313       for(var m=1;m<13;m++){
314         if(m==(month+1)){
315           h1_html.push('<option value ="'+ m +'" selected>'+ m +'</option>');
316         }else{
317           h1_html.push('<option value ="'+ m +'">'+ m +'</option>');
318         }
319       }
320 
321       h1_html.push('</select>');
322       h1_html.push(' 月</h1>');
323 
324       return h1_html.join("");
325     },
326     creatdbMonths : function(idate){
327       var now = new Date(),
328           now_year = now.getFullYear(),
329           now_month = now.getMonth(),
330           now_taday = now.getDate(),
331           i=1,  //每月从1号开始
332           trs,  //行数
333           h1, //h1 html
334           div_Month,  //月div
335           year,month,date,time,
336           firstDay, //当月第一天星期几
337           ifTaday ,  //
338           is_leap = function(year){return (year%400==0) ? 1 : 0},//是否为闰年 能够被400整除的闰年2月29天 不能被整除的是平年2月28天
339           months = [31,28+is_leap(this.year),31,30,31,31,30,31,30,31,30,31], //月天数
340           divHmtl = this._temp.concat(); //复制一个新数组
341 
342       year = idate.getFullYear();
343       month = idate.getMonth()+1;
344       if(month>=12){
345         month=0;
346         year+=1;
347       }
348       date = idate.getDate();
349 
350       ifTaday = (year==now_year && month==now_month) ? true : false;//判断是不是今年今月
351 
352       div_Month = document.createElement("div");
353       div_Month.className = "div_Month double";
354 
355       this.select ? h1 = this.isSelect(year,month) : h1 = "<h1>"+year+""+(month+1)+"月</h1>";
356 
357       firstDay = new Date(year,month,1).getDay();   
358       trs = Math.ceil((months[month]+firstDay)/7);//行数
359 
360       for(var a =0;a<trs;a++){
361         divHmtl.push("<tr>")
362           for(var b=0;b<7;b++){
363             divHmtl.push("<td>");
364                  if (b >= firstDay) {
365                      firstDay = 0;
366                      if (i <= months[month]){  //循环当前月日期
367                         if(ifTaday && i==now_taday){
368                             divHmtl.push("<a class='live active' date="+year+"-"+(month+1)+"-"+i+">"+i+"</a>")
369                         }else if(this.past){  //今天以前的日期不可选
370                                var old = new Date(year, month, i).getTime(),
371                                    taday = new Date(now_year, now_month, now_taday).getTime();
372                                (old<taday) ? divHmtl.push("<span>"+i+"</span>") : divHmtl.push("<a class='live' date="+year+"-"+(month+1)+"-"+i+">"+i+"</a>");
373                         }else{
374                             divHmtl.push("<a class='live' date="+year+"-"+(month+1)+"-"+i+">"+i+"</a>");  
375                         }         
376                         i++;
377                      }
378                  }           
379             divHmtl.push("</td>");      
380           }
381         divHmtl.push("</tr>")
382       }
383 
384       divHmtl.unshift(h1);
385       div_Month.innerHTML = divHmtl.join("");
386       return div_Month;
387     },
388     selectChange : function(){  //select邦定事件
389 
390         var that = this,
391             selects = that.CalendarDiv.getElementsByTagName("select"),
392             year,month,
393             yearSelect = selects[0],
394             monthSelect = selects[1];
395         if(selects.length==4){
396             var yearSelect2 = selects[2],
397                 monthSelect2 = selects[3];
398             _CalF.addHandler(yearSelect2, 'change',function(){
399                 year = yearSelect2.value;
400                 month = monthSelect2.value;
401                 that.createMon(new Date(year, month-1, that.date));
402             });
403             _CalF.addHandler(monthSelect2, 'change',function(){
404                 year = yearSelect2.value;
405                 month = monthSelect2.value;
406                 that.createMon(new Date(year, month-1, that.date));
407             });
408         }
409 
410         _CalF.addHandler(yearSelect, 'change',function(){
411             year = yearSelect.value;
412             month = monthSelect.value;
413             that.createMon(new Date(year, month-1, that.date));
414         });
415         _CalF.addHandler(monthSelect, 'change',function(){
416             year = yearSelect.value;
417             month = monthSelect.value;
418             that.createMon(new Date(year, month-1, that.date));
419         });
420     },
421     aClick : function(){  //a邦定事件
422       var that = this,
423           input = that.input,
424           links = _CalF.$("a.live"),
425           date,_temp=[];
426 
427       for(var i in links){
428         links[i].onclick = function(){
429             date = this.getAttribute("date");
430             _temp = date.split("-");
431             _temp[1] = (parseInt(_temp[1])<10) ? "0"+_temp[1] : _temp[1];
432             _temp[2] = (parseInt(_temp[2])<10) ? "0"+_temp[2] : _temp[2];
433             date = _temp.join("-");
434             input.value = date;
435             that.removeCalender();
436         };
437         if(_CalF.ie6()){
438           links[i].onmouseover  = function(){
439               _CalF.addClass("on",this);
440           };
441           links[i].onmouseout  = function(){
442               _CalF.removeClass("on",this);
443           };
444         }
445       }
446     },
447     btnEvent:function(){  // 上一下一月年 按钮事件
448         var that = this,
449             bts = that.CalendarDiv.getElementsByTagName("button");
450         bts[0].onclick = function(){
451             that.removeCalender();
452         };
453         bts[1].onclick = function(){
454             var idate = new Date(that.year, that.month-1, that.date);
455             that.createMon(idate);
456         };
457         bts[2].onclick = function(){
458             var idate = new Date(that.year, that.month+1, that.date);
459             that.createMon(idate);
460         };
461     },
462     removeCalender : function(){  //删除body点击事件 删除节点
463       this.CalendarDiv.style.display = "none";
464     },
465     outClick:function(){  // 鼠标在对象区域外点击,移除日期层
466         var that = this;
467         _CalF.addHandler(document.body, 'click',function(event){
468             var event = event || window.event,
469                 target = event.target || event.srcElement;
470             if(target == that.input || target==that.CalendarDiv) return;
471             that.removeCalender();
472         });
473     }
474 
475 } 
476 
477 var input1 = new Calender({id:"inDate",past:true,select:true,doubleMonths:true}),
478     input2 = new Calender({id:"outDate",past:true,doubleMonths:true}),
479     input3 = new Calender({id:"Date",past:false,select:true});
480 </script>
481   
482 </body>
483 </html>

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Js日历控件,在一个网页上同时显示两个日期选择器,写成了封装类,方便使用者调用。同时美化的相当不错。   包括了以下函数:   1、2012——2020年节假日信息(包括节假日前1~3天/后1~3天)   2、格式化数字,不足两位前面补0   3、将日期对象/日期字会串格式化为指定日期字符串   4、将日期字符串格式化为数字   5、获取目标元素针对于文档的位置   6、元素选择器   7、查找元素位置   8、判断目标元素是否包含指定的className      关于一些日历调用的参数说明:Calendar({    id: "#J_date_1", //触发显示日历元素ID    isPopup: !0, //弹出式日历    isPrevBtn: !0, //显示按钮    isNextBtn: !0, //显示按钮    isCloseBtn: !0, //显示关闭按钮    isHoliday: !0, //节假日特殊显示    isHolidayTips: !0, //显示节假日1~3天/后1~3天信息    isDateInfo: !0, //显示日期信息    isMessage: !0, //有日历提示信息    isCalStart: !0, //标记为开始时间    dateInfoClass: "date-info-start", //开始时间icon样式    range: {mindate: "2011-09-01", maxdate: "2020-12-31"},//限制范围(当天——2020-12-31)    count: 2, //日历个数    monthStep: 1, //切换上下日历步长    onSelectDate: fnSelectDate, //选择日期回调方法    onClose: fnClose //关闭日历回调方法

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值