博主是个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代码,看的我一脸懵逼。这地方始终不是太明白。