62,040
社区成员
发帖
与我相关
我的任务
分享
/*
* 構造函數參數對象屬性:
* id: ID
* prevText: 按鈕 "上一月" 的文本或圖片(直接寫 html)
* nextText: 按鈕 "下一月" 的文本或圖片(直接寫 html)
* ymFmt: 年月的顯示格式(yyyy 為年,MM 為兩位月份,M 為實際位數月份)
* dayFmt: 日的顯示格式(dd 為兩位日期,d 為實際位數日期)
* year: 年,整型值
* month: 月,整型值
* onChange: 事件處理函數,日曆的年月發生改變後觸發,方法中的 this 已指向當前對象。
* onNextBefore: 事件處理函數,點擊上一月之前發生,方法中 this 已指向當前對象。若返回 false,終止事件。
* onPrevBefore: 事件處理函數,點擊下一月之前發生,方法中 this 已指向當前對象。若返回 false,終止事件。
* 方法:
* year(): 獲取年度
* year(val): 設置年度,val:int
* month(): 獲取月份
* month(val): 設置月份 ,val:int
* find(day): 查找 day 指定的日對應的單元格,day:int
* find(days, fn): 查找 days 指定的日對應所在的單元格集合,若指定 fn,則當查找到相應的單元格後,會執行 fn。days:int[],fn:callback,可選,fn 中 this 指向當前查找到的單元格
* foretime(): 小於當前日期的單元格集合
* 屬性:
* dom: calendar 包含的 DOM 節點,jQuery 對象
* days: 包含所有的日期單元格的 jQuery 對象
* 日期單元格對象獨有方法
* date(): 獲取日期(格式:yyyy-MM-dd)
* year(): 獲取年度
* month(): 獲取月份
* day(): 獲取日
* CSS class 說明:
* calendar: table,包含整個日曆的表格
* nav: tr,第一行,包含上一月、下一月及年月顯示
* prev: td,上一月
* ym: td,年月顯示
* next: td,下一月
* week: tr,第二行,周
* days: tr,日期所在行
* blank: td,沒有日期的單元格
* day: td,日所在單元格
* today: td,今日所在單元格
*/
function Calendar(pObj) {
pObj = pObj || {};
var $j = jQuery;
var my = this;
var obj = {};
obj.id = pObj.id || '_1';
if(Calendar[obj.id])
throw 'ID 已被使用。';
Calendar[obj.id] = this;
obj.prevText = pObj.prevText || '<<';
obj.nextText = pObj.nextText || '>>';
obj.ymFmt = pObj.ymFmt || 'yyyy 年 MM 月';
obj.dayFmt = pObj.dayFmt || 'd';
obj.onChange = pObj.onChange || function() {};
obj.onNextBefore = pObj.onNextBefore || function() { return true; };
obj.onPrevBefore = pObj.onPrevBefore || function() { return true; };
// 若數字為一位,則在左方補 0
function lpad(num) {
num = parseInt(num);
return num < 10 ? '0' + num : num;
}
var now = new Date();
obj.year = pObj.year || now.getFullYear(); // 年,int
obj.month = pObj.month || now.getMonth() + 1; // 月,int
var today;
function buildDom() {
var ymColHtml = obj.ymFmt.replace(/yyyy/, obj.year).replace(/MM/, lpad(obj.month)).replace(/M/, obj.month);
// 年月及上一月、下一月
var navRow =
'<tr class="nav">' +
'<td class="prev"><a href="javascript:">' + obj.prevText + '</a></td>' +
'<td class="ym" colspan="5">' + ymColHtml + '</td>' +
'<td class="next"><a href="javascript:">' + obj.nextText + '</a></td>' +
'</tr>';
// 周日至周六
var weekText = ['日', '一', '二', '三', '四', '五', '六'];
var weekRow = '<tr class="week">';
for(var i = 0; i != 7; ++i) {
weekRow += '<td>' + weekText[i] + '</td>';
}
weekRow += '</tr>';
var date = new Date(obj.year, obj.month, 1);
date.setDate(0);
var days = date.getDate(); // 日: 1~31,這裡獲取的是當月的天數
date.setDate(1);
var week = date.getDay(); // 周: 0~6
var rows = Math.ceil((week + days) / 7);
var html = '<table class="calendar">' + navRow + weekRow;
for(var i = 0; i != rows; ++i) {
html += '<tr class="days">';
for(j = 0; j != 7; ++j) {
var curDay = i * 7 + j - week + 1;
if((i == 0 && j < week) || curDay > days)
html += '<td class="blank"></td>';
else
html += '<td class="day" id="' + curDay + '">' + obj.dayFmt.replace(/dd/, lpad(curDay)).replace(/d/, curDay) + '</td>';
}
html += '</tr>';
}
html += '</table>';
var domNode = $j(html);
// 設置今天日期的顯示
today = null;
if(now.getFullYear() == obj.year && now.getMonth() + 1 == obj.month) {
today = domNode.find('#' + now.getDate());
today.addClass('today');
}
my.days = domNode.find('.day');
my.days.each(function() {
var elm = this;
elm.year = function() { return obj.year; };
elm.month = function() { return obj.month; };
elm.day = function() { return parseInt(elm.id); };
elm.date = function() {
return obj.year + '-' + lpad(obj.month) + '-' + lpad(elm.id);
};
});
if(my.dom) {
my.dom.replaceWith(domNode);
my.dom = domNode; // 注意,該語句必須放在 onChange 事件觸發前
obj.onChange.apply(my);
} else
my.dom = domNode;
// 上一月點擊事件
my.dom.find('.prev:first > a:first').click(function() {
if(obj.onPrevBefore.apply(my)) {
if(!--obj.month) {
--obj.year;
obj.month = 12;
}
buildDom();
}
});
// 下一月點擊事件
my.dom.find('.next:first > a:first').click(function() {
if(obj.onNextBefore.apply(my)) {
if(++obj.month > 12) {
++obj.year;
obj.month = 1;
}
buildDom();
}
});
}
buildDom();
// 下面是 public 方法
this.year = function(val) {
if(!val)
return obj.year;
obj.year = val;
buildDom();
};
this.month = function(val) {
if(!val)
return obj.month;
obj.month = val;
buildDom();
};
this.setYM = function(y, m) {
obj.year = y;
obj.month = m;
buildDom();
};
this.find = function() {
var params = arguments;
var day = arguments[0];
var type = typeof day;
if(type == 'number' || type == 'string')
return my.dom.find('#' + day);
if($j.isArray(day)) {
return my.days.filter(function() {
result = ($j.inArray(parseInt(this.id), day) != -1);
if(result && params.length > 1) {
params[1].apply(this);
}
return result;
});
}
return $j([]);
}
this.today = function() {
return today;
}
this.foretime = function() {
var curYear = now.getFullYear();
var curMonth = now.getMonth() + 1;
if(obj.year < curYear || (obj.year == curYear && obj.month < curMonth))
return my.days;
if(obj.year > curYear || (obj.year == curYear && obj.month > curMonth))
return $j([]);
var curDay = now.getDate();
return my.days.filter(function() {
return parseInt(this.id) < curDay;
});
};
obj.onChange.apply(this);
}
table.calendar {
border: 1px solid #CCC;
border-collapse:collapse;
border-spacing:0;
margin:0 0 5px 0;
padding:0;
-moz-background-clip: border;
-moz-background-origin: padding;
-moz-background-inline-policy: continuous;
}
.calendar td {
border:1px solid #CCC;
margin:2px;
padding:3px;
height:20px;
width: 50px;
}
.nav td {
text-align:center;
}
.week td {
-moz-background-clip:border;
-moz-background-inline-policy:continuous;
-moz-background-origin:padding;
background:#E6EFFA none repeat scroll 0 0;
color:#434343;
padding:3px 3px 3px 10px;
text-align:center;
}
.today {
background-color: #FFA;
}
/*
* 構造函數參數對象屬性:
* id: ID
* prevText: 按鈕 "上一月" 的文本或圖片(直接寫 html)
* nextText: 按鈕 "下一月" 的文本或圖片(直接寫 html)
* ymFmt: 年月的顯示格式(yyyy 為年,MM 為兩位月份,M 為實際位數月份)
* dayFmt: 日的顯示格式(dd 為兩位日期,d 為實際位數日期)
* year: 年,整型值
* month: 月,整型值
* onChange: 事件處理函數,日曆的年月發生改變後觸發,方法中的 this 已指向當前對象。
* onNextBefore: 事件處理函數,點擊上一月之前發生,方法中 this 已指向當前對象。若返回 false,終止事件。
* onPrevBefore: 事件處理函數,點擊下一月之前發生,方法中 this 已指向當前對象。若返回 false,終止事件。
* 方法:
* year(): 獲取年度
* year(val): 設置年度,val:int
* month(): 獲取月份
* month(val): 設置月份 ,val:int
* find(day): 查找 day 指定的日對應的單元格,day:int
* find(days, fn): 查找 days 指定的日對應所在的單元格集合,若指定 fn,則當查找到相應的單元格後,會執行 fn。days:int[],fn:callback,可選,fn 中 this 指向當前查找到的單元格
* foretime(): 小於當前日期的單元格集合
* 屬性:
* dom: calendar 包含的 DOM 節點,jQuery 對象
* days: 包含所有的日期單元格的 jQuery 對象
* 日期單元格對象獨有方法
* date(): 獲取日期(格式:yyyy-MM-dd)
* year(): 獲取年度
* month(): 獲取月份
* day(): 獲取日
* CSS class 說明:
* calendar: table,包含整個日曆的表格
* nav: tr,第一行,包含上一月、下一月及年月顯示
* prev: td,上一月
* ym: td,年月顯示
* next: td,下一月
* week: tr,第二行,周
* days: tr,日期所在行
* blank: td,沒有日期的單元格
* day: td,日所在單元格
* today: td,今日所在單元格
*/
function Calendar(pObj) {
pObj = pObj || {};
var $j = jQuery;
var my = this;
var obj = {};
obj.id = pObj.id || '_1';
if(Calendar[obj.id])
throw 'ID 已被使用。';
Calendar[obj.id] = this;
obj.prevText = pObj.prevText || '<<';
obj.nextText = pObj.nextText || '>>';
obj.ymFmt = pObj.ymFmt || 'yyyy 年 MM 月';
obj.dayFmt = pObj.dayFmt || 'd';
obj.onChange = pObj.onChange || function() {};
obj.onNextBefore = pObj.onNextBefore || function() { return true; };
obj.onPrevBefore = pObj.onPrevBefore || function() { return true; };
// 若數字為一位,則在左方補 0
function lpad(num) {
num = parseInt(num);
return num < 10 ? '0' + num : num;
}
var now = new Date();
obj.year = pObj.year || now.getFullYear(); // 年,int
obj.month = pObj.month || now.getMonth() + 1; // 月,int
var today;
function buildDom() {
var ymColHtml = obj.ymFmt.replace(/yyyy/, obj.year).replace(/MM/, lpad(obj.month)).replace(/M/, obj.month);
// 年月及上一月、下一月
var navRow =
'<tr class="nav">' +
'<td class="prev"><a href="javascript:">' + obj.prevText + '</a></td>' +
'<td class="ym" colspan="5">' + ymColHtml + '</td>' +
'<td class="next"><a href="javascript:">' + obj.nextText + '</a></td>' +
'</tr>';
// 周日至周六
var weekText = ['日', '一', '二', '三', '四', '五', '六'];
var weekRow = '<tr class="week">';
for(var i = 0; i != 7; ++i) {
weekRow += '<td>' + weekText[i] + '</td>';
}
weekRow += '</tr>';
var date = new Date(obj.year, obj.month, 1);
date.setDate(0);
var days = date.getDate(); // 日: 1~31,這裡獲取的是當月的天數
date.setDate(1);
var week = date.getDay(); // 周: 0~6
var rows = Math.ceil((week + days) / 7);
var html = '<table class="calendar">' + navRow + weekRow;
for(var i = 0; i != rows; ++i) {
html += '<tr class="days">';
for(j = 0; j != 7; ++j) {
var curDay = i * 7 + j - week + 1;
if((i == 0 && j < week) || curDay > days)
html += '<td class="blank"></td>';
else
html += '<td class="day" id="' + curDay + '">' + obj.dayFmt.replace(/dd/, lpad(curDay)).replace(/d/, curDay) + '</td>';
}
html += '</tr>';
}
html += '</table>';
var domNode = $j(html);
// 設置今天日期的顯示
today = null;
if(now.getFullYear() == obj.year && now.getMonth() + 1 == obj.month) {
today = domNode.find('#' + now.getDate());
today.addClass('today');
}
my.days = domNode.find('.day');
my.days.each(function() {
var elm = this;
elm.year = function() { return obj.year; };
elm.month = function() { return obj.month; };
elm.day = function() { return parseInt(elm.id); };
elm.date = function() {
return obj.year + '-' + lpad(obj.month) + '-' + lpad(elm.id);
};
});
if(my.dom) {
my.dom.replaceWith(domNode);
my.dom = domNode; // 注意,該語句必須放在 onChange 事件觸發前
obj.onChange.apply(my);
} else
my.dom = domNode;
// 上一月點擊事件
my.dom.find('.prev:first > a:first').click(function() {
if(obj.onPrevBefore.apply(my)) {
if(!--obj.month) {
--obj.year;
obj.month = 12;
}
buildDom();
}
});
// 下一月點擊事件
my.dom.find('.next:first > a:first').click(function() {
if(obj.onNextBefore.apply(my)) {
if(++obj.month > 12) {
++obj.year;
obj.month = 1;
}
buildDom();
}
});
}
buildDom();
// 下面是 public 方法
this.year = function(val) {
if(!val)
return obj.year;
obj.year = val;
buildDom();
};
this.month = function(val) {
if(!val)
return obj.month;
obj.month = val;
buildDom();
};
this.setYM = function(y, m) {
obj.year = y;
obj.month = m;
buildDom();
};
this.find = function() {
var params = arguments;
var day = arguments[0];
var type = typeof day;
if(type == 'number' || type == 'string')
return my.dom.find('#' + day);
if($j.isArray(day)) {
return my.days.filter(function() {
result = ($j.inArray(parseInt(this.id), day) != -1);
if(result && params.length > 1) {
params[1].apply(this);
}
return result;
});
}
return $j([]);
}
this.today = function() {
return today;
}
this.foretime = function() {
var curYear = now.getFullYear();
var curMonth = now.getMonth() + 1;
if(obj.year < curYear || (obj.year == curYear && obj.month < curMonth))
return my.days;
if(obj.year > curYear || (obj.year == curYear && obj.month > curMonth))
return $j([]);
var curDay = now.getDate();
return my.days.filter(function() {
return parseInt(this.id) < curDay;
});
};
obj.onChange.apply(this);
}
table.calendar {
border: 1px solid #CCC;
border-collapse:collapse;
border-spacing:0;
margin:0 0 5px 0;
padding:0;
-moz-background-clip: border;
-moz-background-origin: padding;
-moz-background-inline-policy: continuous;
}
.calendar td {
border:1px solid #CCC;
margin:2px;
padding:3px;
height:20px;
width: 50px;
}
.nav td {
text-align:center;
}
.week td {
-moz-background-clip:border;
-moz-background-inline-policy:continuous;
-moz-background-origin:padding;
background:#E6EFFA none repeat scroll 0 0;
color:#434343;
padding:3px 3px 3px 10px;
text-align:center;
}
.today {
background-color: #FFA;
}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript" src="jquery-1.4.4.min.js"></script>
<script type="text/javascript" src="calendar/calendar.js"></script>
<link href="calendar/calendar.css" rel="stylesheet" type="text/css" />
<script type="text/javascript">
<!--
var $j = jQuery.noConflict();
function getSelectedDate(cal) {
var dateSelect = {selected: [], unselect: []};
cal.days.each(function() {
var checkbox = $j(this).find('input');
if(checkbox.attr('checked'))
dateSelect.selected.push(this.day());
else
dateSelect.unselect.push(this.day());
});
if(dateSelect.selected.length == 0)
dateSelect.unselect = [];
return dateSelect;
}
function getYM(cal) {
var val = cal.month();
if(val < 10)
val = '0' + val;
return cal.year() + '-' + val;
}
function fillDates(cal) {
var key = getYM(cal);
var days = selected[key];
if(days && days.length) {
cal.find(days, function() {
$j(this).addClass('selected').find('input').attr('checked', true);
});
}
}
var selected = {}; // 已選擇的日期(hash,key 為年月,值為日,key 格式: 2010-03)
var unselect = {}; // 未選擇的日期(hash,key 為年月,值為日,key 格式: 2010-03)
function InitCalendar() {
var calendar = new Calendar({
// prevText: '<img src="calendar/left.gif" alt="上一月" />',
// nextText: '<img src="calendar/right.gif" alt="下一月" />',
year: 2011,
month: 7,
ymFmt: 'yyyy 年 MM 月(<input type="button" value="置為預設" style="border:solid 1px black;padding-top:2px;" />)',
dayFmt: '<input type="checkbox" />dd',
onChange: function() {
// this.foretime().each(function() {
// $j(this).find('input').attr('disabled', true);
// });
fillDates(this);
var cal = this;
cal.dom.find('.nav:first input:first').click(function(){
cal.dom.find('tr.days').each(function() {
$j(this).children().each(function(i) {
if(i != 0 && i != 6) {
$j(this).children(':enabled').attr('checked', true).parent().addClass('selected');
}
});
});
});
cal.dom.find('.day input:enabled').click(function() {
if(this.checked) {
$j(this).parent().addClass('selected');
}
else {
$j(this).parent().removeClass('selected');
}
});
},
onPrevBefore: function() {
if(this.month() == 1)
return false;
var key = getYM(this);
var dateSelect = getSelectedDate(this);
selected[key] = dateSelect.selected;
unselect[key] = dateSelect.unselect;
return true;
},
onNextBefore: function() {
if(this.month() == 12)
return false;
var key = getYM(this);
var dateSelect = getSelectedDate(this);
selected[key] = dateSelect.selected;
unselect[key] = dateSelect.unselect;
return true;
}
});
$j('#calDiv').prepend(calendar.dom);
}
$j(function() {
$j('#calYear').val('<?php echo $calYear; ?>');
var dates = '<?php echo @$selectedDates; ?>';
if(dates) {
dates = dates.split(',');
for(var i = 0, len = dates.length; i != len; ++i) {
var key = dates[i].substr(0, 7);
var val = dates[i].substr(8);
if(!selected[key])
selected[key] = [];
selected[key].push(val - 0);
}
}
dates = '<?php echo @$unselectDates; ?>';
if(dates) {
dates = dates.split(',');
for(var i = 0, len = dates.length; i != len; ++i) {
var key = dates[i].substr(0, 7);
var val = dates[i].substr(8);
if(!unselect[key])
unselect[key] = [];
unselect[key].push(val - 0);
}
}
InitCalendar();
});
function submitbutton(pressbutton) {
if(pressbutton == 'load') {
if(confirm('選擇年度後會重新載入頁面,您所做的修改將不會被儲存,是否繼續?')) {
submitform( pressbutton );
}
return;
}
var setted = [];
var cal = Calendar._1;
var key = getYM(cal);
var dateSelect = getSelectedDate(cal);
selected[key] = dateSelect.selected;
unselect[key] = dateSelect.unselect;
var dates = [];
var uDates = [];
for(var p in selected) {
var pArray = selected[p];
var pUArray = unselect[p];
if(pArray.length) {
var ym = p.split('-');
setted.push(ym[1] - 0);
}
for(var i = 0, len = pArray.length; i < len; ++i) {
var day = pArray[i];
if(day < 10)
day = '0' + day;
dates.push(p + '-' + day);
}
if(pUArray) {
for(var i = 0, len = pUArray.length; i < len; ++i) {
var day = pUArray[i];
if(day < 10)
day = '0' + day;
uDates.push(p + '-' + day);
}
}
}
var unsetted = [];
var i = <?php echo $year == $calYear ? $month : 1 ?>;
for(; i <= 12; ++i) {
if($j.inArray(i, setted) == -1) {
unsetted.push(i + ' 月');
}
}
if(unsetted.length) {
if(!confirm('尚有 ' + unsetted.join(', ') + ' 未設置上班日期,是否儲存?'))
return;
}
$j('#unselectDates').val(uDates.join());
$j('#selectedDates').val(dates.join());
submitform( pressbutton );
}
//-->
</script>
</head>
<body>
<div id="calDiv"></div>
</body>
</html>