關於用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程式碼,看的我一臉懵逼。這地方始終不是太明白。