1. 程式人生 > >關於用js實現的日曆記事功能

關於用js實現的日曆記事功能

博主是個java新手,目前在做的一個專案就是考勤排班系統,主要負責的模組是排班模組這一方面。需求上面要求要在顯示當月的日曆表,日曆表上同時動態生成上班時間、下班時間、是否值班、值班型別等功能。
當時在網上找了很多日曆模板,都沒有找到能夠符合自己要求的。便決定自己畫一個頁面。

樣式沒有做太多的美化 畢竟博主屬於後端開發人員

個人感覺最主要的一塊就是字串的拼接,日曆的生成,還有一些個別的屬性需要注意。

基本樣式引用:

<link rel="stylesheet" href="css/bootstrap.css" />
        <link rel="stylesheet" href="css/bootstrapValidator.css"
/>
<link rel="stylesheet" href="css/css1.css" /> <script type="text/javascript" src="js/jquery-1.10.2.js" ></script> <script type="text/javascript" src="js/bootstrap.js" ></script> <script type="text/javascript" src="js/bootstrapValidator.js" >
</script>

html程式碼:

<div class="col-xs-10 col-xs-offset-1">
            <form class="form-inline">
              <div class="form-group col-xs-offset-1">
                <label for="exampleInputName2">部門:</label>
                <select class="form-control" style
="margin-right: 50px;">
<option>==請選擇==</option> <option>產品研發部</option> <option>系統運維部</option> <option>人事管理部</option> </select> <label for="exampleInputEmail2">員工名:</label> <select class="form-control" style="margin-right: 100px;" onchange="alertdate()"> <option>==請選擇==</option> <option>張三</option> <option>李四</option> <option>王五</option> </select> <button class="btn btn-primary">儲存</button> </div> <div class='calendar' id='calendar'></div> </form> </div>

html程式碼中的下拉框都是寫死的,給第二個下拉框繫結onchange事件,觸發事件在id=’calendar’的div中生成日曆。

js部分:

var dateobj = prev();

            function prev(){
                var _date = new Date();    // 預設為當前系統時間
                return {
                  getDate : function(){
                    return _date;
                  },
                  setDate : function(date) {
                    _date = date;
                  }
                };
              }

            function alertdate(){

                renderhtml();    //對日曆div中增加表格元素
                showCalendarData();  //在表格中顯示日期
                bindEvent();   //對錶格上方的上月下月繫結事件
                $(":radio").click(function(){

                    var parentCode=$(this).parent();
                    if($(this).val()=='true'){
                        if(parentCode.children("select").length==0){
                            parentCode.children("span").show();
                            parentCode.append("<select><option>白班</option><option>夜班</option></select>");
                        }
                    }else{

                        parentCode.children("select").remove();
                        parentCode.children("span").hide();

                    }
                });

            }


            function renderhtml(){
                var calendar=document.getElementById("calendar");
                var titlebox=document.createElement("div");  //在div中設定標題區  顯示當前月份和上月下月的控制
                var bodybox=document.createElement("div");   //主體部分 用於存放日曆表格

                titlebox.className="calendar-title-box";   //給標題box繫結屬性   並向div中新增元素
                titlebox.innerHTML="<span id='prevMonth' class='prev-month'></span>"+
                "<span class='calendar-title' id='calendarTitle'></span>"+
                "<span class='next-month' id='nextMonth'></span>";

                 calendar.appendChild(titlebox);  //將標題box設為日曆容器的子節點
                 bodybox.className='calendar-body-box';   //表格部分繫結屬性
                 var headhtml="<tr>"+"<th>日</th>"+"<th>一</th>"+
                 "<th>二</th>"+"<th>三</th>"+"<th>四</th>"+
                 "<th>五</th>"+"<th>六</th>"+"</tr>";
                 var bodyhtml="";

                 for(var i=0;i<6;i++){      //一週7天 字串拼接放到bodyhtml中
                    bodyhtml+="<tr>"+"<td></td>"+"<td></td>"+"<td></td>"+
                    "<td></td>"+"<td></td>"+"<td></td>"+"<td></td>"+"</tr>";
                 }
                 bodybox.innerHTML="<table id='calendarTable' class='table table-bordered text-center'>"+
                 headhtml+bodyhtml+"</table>";  //設定表格box的內容

                 calendar.appendChild(bodybox);

            }



            function showCalendarData(){
                //alert(dateobj);
                var year=dateobj.getDate().getFullYear();   //dateobj為object物件 通過getDate得到日期 再得到年
                var month=dateobj.getDate().getMonth()+1;
                var datestr=getdatestr(dateobj.getDate());  //通過函式gatdatestr將dateobj轉換成字串格式

                //設定表格頂部的年月資訊
                var calendarTitle=document.getElementById("calendarTitle");
                var titleStr=datestr.substr(0,4)+"年"+datestr.substr(4,2)+"月";  //通過substr擷取字串  得到年的數字和月份數字
                calendarTitle.innerText=titleStr;   //將拼接後的****年**月顯示在上方

                //設定表格中的日期資料
                var table=document.getElementById("calendarTable");
                var tds=table.getElementsByTagName("td");
                var firstday=new Date(year,month-1,1);  //當前月的第一天
                //alert(firstday.getDay());

                for(var i=0;i<tds.length;i++){
                    var thisday=new Date(year,month-1,i+1-firstday.getDay());  //getDay得到第一天是周幾 從而顯示第一行上個月的資料
                    var thisdayStr=getdatestr(thisday);
                    //tds[i].innerText=thisday.getDate();
                    tds[i].innerHTML="<span style='font-size:16px; font-wight:700'>"+thisday.getDate()+"</span>"+
                    "<br/>上班時間:<input type='text' style='width:48px; height:18px; margin-top:1px' placeholder='9:00' />"+
                    "<br/>下班時間:<input type='text' style='width:48px; height:18px; margin-top:1px' placeholder='18:00' />"+
                    "<br/>是否值班:<input type='radio' name='flag"+i+"' value='true' style='margin-top:2px' />是"+
                    "<input type='radio' name='flag"+i+"' value='false' checked='checked' style='margin-top:2px' />否"+
                    "<br/><span style='display:none'>值班型別:</span>";

                    tds[i].setAttribute("data",thisdayStr);
                    if(thisdayStr==getdatestr(new Date())){
                        tds[i].className="currentDay";   //當天設定屬性
                    }else if(thisdayStr.substr(0,6)==getdatestr(firstday).substr(0,6)){
                        tds[i].className="currentMonth";  //當前月設定屬性
                    }else{
                        tds[i].className="otherMonth";      //其他月的日曆設定屬性
                    }
                }

                //alert(dateobj.getdate().getDay());

            }


            function bindEvent(){
                var prevMonth=document.getElementById("prevMonth");
                var nextMonth=document.getElementById("nextMonth");
                addEvent(prevMonth,'click',toPrevMonth);    //繫結點選事件
                addEvent(nextMonth,'click',toNextMonth);
                //addEvent($(":radio"),'click',toChooseSch);
            }

            function getdatestr(date){
                var year=date.getFullYear();
                var month=date.getMonth()+1;  //月份從0開始
                var day=date.getDate();
                month=(month>9)?(""+month):("0"+month);  //如果得到的數字小於9要在前面加'0'
                day=(day>9)?(""+day):("0"+day);

                return year+month+day;
            }

            function addEvent(dom,eType,func){
                if(dom.addEventListener){
                    dom.addEventListener(eType,function(e){
                        func(e);
                    });
                }else if(dom.attachEvent){
                    dom.attachEvent('on'+eType,function(e){
                        func(e);
                    });
                }else{
                    dom['on'+eType]=function(e){
                        func(e);
                    }
                }
            }

            function toPrevMonth(){
                var date=dateobj.getDate();
                dateobj.setDate(new Date(date.getFullYear(),date.getMonth()-1,1));
                showCalendarData();
            }

            function toNextMonth(){
                var date=dateobj.getDate();
                dateobj.setDate(new Date(date.getFullYear(),date.getMonth()+1),1)
                showCalendarData();
            }

        </script>

其中印象比較深刻的地方有

1、每個單元格中的radio按鈕所設定的checked=’checked’屬性無效。
這個原因博主找了一會發現,因為所有的日曆部分程式碼都是通過字串拼接動態生成的,在生成radio按鈕的時候

是否值班:<input type='radio' name='flag' value='true' style='margin-top:2px' />是
        <input type='radio' name='flag' value='false' checked='checked' style='margin-top:2px' />否

這裡所繫結的name屬性是全部相同的,即整個表格中的name屬性重複,所以所生成的單選按鈕組沒有預設選中項。

後來在name屬性中加上for迴圈中的變數i,實現一個單元格中的兩個按鈕name值相同,從而解決該問題。

2、相同型別的問題還有一處:

<span id='dutyType' style='display:none'>值班型別:</span>

博主在嘗試實現選擇值班時顯示值班型別的功能時發現在js程式碼中無法找到該span。按理用jquery的id選擇器不會出現這種問題啊,仔細想想應該還是字串拼接出錯。因為博主是使用for迴圈實現每個日曆單元格都產生相應的操作,後面再根據是否屬於當前月進行判斷是進行顯示還是隱藏。

最終發現每個單元格中所產生的span id全部相同,無法使用選擇器找到。後來博主便放棄了使用id選擇器的方法。改用節點操作:

$(":radio").click(function(){

                    var parentCode=$(this).parent();
                    if($(this).val()=='true'){
                        if(parentCode.children("select").length==0){
                            parentCode.children("span").show();
                            parentCode.append("<select><option>白班</option><option>夜班</option></select>");
                        }
                    }else{

                        parentCode.children("select").remove();
                        parentCode.children("span").hide();

                    }
                });

找到所點選按鈕的父級元素,在父級元素的所有子元素中找到span的children,再通過hide或者show控制其顯示或者隱藏。同樣的select下拉框也是這樣實現的。

3、字串拼接後 radio按鈕所繫結的click事件失效。

$(":radio").click(function(){

                    var parentCode=$(this).parent();
                    if($(this).val()=='true'){
                        if(parentCode.children("select").length==0){
                            parentCode.children("span").show();
                            parentCode.append("<select><option>白班</option><option>夜班</option></select>");
                        }
                    }else{

                        parentCode.children("select").remove();
                        parentCode.children("span").hide();

                    }
                });

還是相同的程式碼塊,原先博主是用html()方法獲取所點選按鈕父級元素中所有的內容,在後面繼續字串的拼接加上select下拉框,最後再用html()將原先的內容替換,但是後面自測發現事件失效,當前單元格中的click事件無效,在Google的開發者工具中檢視頁面程式碼無問題,但是始終不能觸發事件。

後選擇是用append的方法實現。查閱相關資料應該是js部分的程式碼在頁面載入完之後,也隨之載入完,若想再次實現點選事件需要重新載入js程式碼,看的我一臉懵逼。這地方始終不是太明白。