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


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

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

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

    1.单月/双月的显示

    2.年月是否可选

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

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

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

    压缩好的文件打包下载:https://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>
  • 相关阅读:
    【SQL注入技巧拓展】————11、PostgreSQL渗透测试指南
    【SQL注入技巧拓展】————10、postgresql数据库利用方式
    【XXE技巧拓展】————3、XML实体注入漏洞攻与防
    【XXE技巧拓展】————2、未知攻焉知防之XXE漏洞攻防
    【XXE技巧拓展】————1、浅谈XXE漏洞攻击与防御
    S2-032 远程代码执行漏洞检测与利用
    S2-029 远程代码执行漏洞检测与利用
    Rendering Paths
    IOS: 模型面数控制
    IOS: 账号,证书 好文整理
  • 原文地址:https://www.cnblogs.com/dtdxrk/p/3112982.html
Copyright © 2020-2023  润新知