忙里偷闲,终于有点时间写博客了。今天我要说的这款插件,是我自己在项目中开发的。前段时间花了好多心思Google,找了很多的插件,但是没有一款符合项目要求。想想自己虽然不是什么技术大牛,但是写个拙劣的插件应该还是可行的。于是花了一天时间把流程及基础功能做好了,又继续花了一天时间完善了下,现在看来,也没有白费心思。至少这个东西没有走向灭亡,而是继续在项目中实现它的价值。好了,废话不多说,上菜!
日历开源,已经放在github上面了。git@github.com:BGOnline-CN/BGOCalender.git
博客中有什么不对的地方,希望大家能帮我指出来,冰果在这里先谢过了!
1.买房子,一定得隔音!
;(function($) {
// 这里是我们的插件代码
})(jQuery);
2.打扫卫生
;(function($) {
$.fn.extend({ // 这里是我们的插件代码
'BGOCalender': function(options) { // 开始写插件,BGOCalender就是我们的插件名
}
});
})(jQuery);
3.通水电,哥们以前通下水道的,这个难不倒我。嘿嘿嘿~
;(function($) {
$.fn.extend({ // 这里是我们的插件代码
'BGOCalender': function(options) { // 开始写插件,BGOCalender就是我们的插件名
// 既然是日历插件,那少不了的东西就是 Date() 方法啦
var date = new Date(); // 实例化 日期函数
// 1.好了,房子打扫干净了,咋们把水电通通吧。(默认参数配置)
var defaultOpts = {
today: date.getDate(), // 当天
month: date.getMonth(), // 当月
year: date.getFullYear(), // 当年
data: [], // 接收服务器数据
language: cn, // 语言
callback: function() {} //回调函数
}
// 接收用户自定义参数 options 如果有则覆盖默认参数,否则使用默认参数
var opts = $.extend(defaultOpts, options || {});
var monthDays = [31, 30, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; // 一年中,每月的天数,这里你可能会发现2月有点奇怪,不是还有闰月吗?好的,不急,咋们后面会处理。
var cn = {
weekLang: ['\u4e00', '\u4e8c', '\u4e09', '\u56db', '\u4e94', '\u516d', '\u65e5'], // 周一到周日,中文语言包
//monthLang: ['\u4e00\u6708', '\u4e8c\u6708', '\u4e09\u6708', '\u56db\u6708', '\u4e94\u6708', '\u516d\u6708', '\u4e03\u6708', '\u516b\u6708', '\u4e5d\u6708', '\u5341\u6708', '\u5341\u4e00\u6708', '\u5341\u4e8c\u6708'] // 月份的语言包,我没做,因为项目中并没有用到
}
// 好了,接下来,处理我们的平年闰年了
var isLeapYear = function(y, m) { // 前面的开发规范我有说过,只包含一条语句的代码块,我们可以再一行内显示
if(m < 0) { m = 11; } // 这里的作用是,JS返回给我们的月份是从0开始的,也就是说,我们想要得到1月,必须得告诉他我们要的是0月,所以我们要做个判断,以便我们切换年份时使用
if(m > 11) { m = 0; }
if(m == 1) { // 判断是否为闰年,并返回该月天数
return ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0) ? 29 : 28;
}else { return monthDays[m]; }
}
// 返回上一个月天数
var preMonthDays = function(y, m) {
return isLeapYear(y, m-1);
}
// 返回该月第一天是星期几
var firstDayWeek = function(y, m) {
return new Date(y, m, 1).getDay() == 0 ? 7 : new Date(y, m, 1).getDay();
}
// 日历表头
for(var i = 0; i < cn.weekLang.length; i++) {
$('> .calender > table > thead > tr > th', this).eq(i).html(opts.language.weekLang[i]);
}
}
});
})(jQuery);
到这里,结合我们的html,一个简单的日历就出来了。
这个日历的html我是直接分开来写的,没有用js生成。为了扩展性和方便项目,你们有需要可以自行修改。
4.实现上一个月与下一个月功能
// 载入今天和当月,在项目中用不上,所以我注释掉了
// // 载入今天
// $('.cur').click(function() {
// opts.month = date.getMonth();
// opts.year = date.getFullYear();
// opts.today = date.getDate();
// td.removeClass('selectDate');
// initCalender(opts.year, opts.month);
// });
// // 载入当月
// $('.cur').click(function() {
// opts.month = date.getMonth();
// opts.year = date.getFullYear();
// initCalender(opts.year, opts.month);
// });
// 载入上一个月
$('.preClass').click(function() {
opts.month--;
if(opts.month < 0) {
opts.month = 11;
opts.year--;
}
initCalender(opts.year, opts.month);
});
// 载入下一个月
$('.nextClass').click(function() {
opts.month++;
if(opts.month > 11) {
opts.month = 0;
opts.year++;
}
initCalender(opts.year, opts.month);
});
5.载入日历
cData = [];
sData = [];
var showSelectInfo = function(totalData) {
var removeRepeat = function(index,array) { // 根据指定下标删除数组 供过滤时调用
if(index >= 0 && index < array.length) {
for(var i = index; i < array.length; i++) {
array[i] = array[i+1];
}
array.length = array.length - 1;
}
return array;
}
var filterArray = function(arr) { // 过滤数组中重复数据并返回新数组
for(var i=0; i< arr.length; i++) {
for(var j = i + 1; j < arr.length; j++) {
if(arr[i] == arr[j]) {
arr = removeRepeat(j,arr);
i = -1;
break;
}
}
}
return arr;
}
var bubbling = function(arr) { // 排序
var flag = false;
var temp;
for(var i = 0; i < arr.length - 1; i++) {
for(var j = 0; j < arr.length-1-i; j++) {
if(arr[j] > arr[j+1]) {
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
flag = true;
}
}
if(flag) {
flag = false;
}else {
break;
}
}
}
totalData = filterArray(totalData);
bubbling(totalData);
// 右侧显示数值
switch(opts.pattern) {
case 1:
$('.startClass > span.dateTitle').html('开班日期');
$('.endClass > span.dateTitle').html('结班日期');
break;
case 2:
$('.startClass > span.dateTitle').html('上课日期');
$('.endClass > span.dateTitle').html('结课日期');
break;
}
if(totalData.length < 1) {
$('.startClass > span.dateCon').html(''); // 开课日期
$('.endClass > span.dateCon').html(''); // 结课日期
}else {
$('.startClass > span.dateCon').html(totalData[0]); // 开课日期
$('.endClass > span.dateCon').html(totalData[totalData.length-1]); // 结课日期
}
$('.totalClass > p > span').html(totalData.length); // 总上课天数
// 剩余上课天数
var count = 0;
var fullToday;
if(date.getMonth() < 10 && date.getDate() < 10) {
fullToday = date.getFullYear() + '-' + '0' + (date.getMonth() + 1) + '-' + '0' + date.getDate();
}else if(date.getMonth() < 10 && date.getDate() > 10) {
fullToday = date.getFullYear() + '-' + '0' + (date.getMonth() + 1) + '-' + date.getDate();
}else if(date.getMonth() > 10 && date.getDate() < 10) {
fullToday = date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + '0' + date.getDate();
}else if(date.getMonth() > 10 && date.getDate() > 10) {
fullToday = date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate();
}
for(var i = 0; i < totalData.length; i++) {
if(totalData[i] >= fullToday) {
count++;
}
}
$('.onlyClass > p > span').html(count);
}
var addTotalData = function(e, totalData) { // 载入totalData
if(e.text() < 10) {
totalData.push($('.year').text()+'-'+$('.month').text()+'-'+'0'+e.text());
}else {
totalData.push($('.year').text()+'-'+$('.month').text()+'-'+e.text());
}
}
var removeTotalData = function(e, totalData) { // 删除totalData
if(e.text() < 10) {
totalData.splice($.inArray($('.year').text()+'-'+$('.month').text()+'-'+'0'+e.text(), totalData),1);
}else {
totalData.splice($.inArray($('.year').text()+'-'+$('.month').text()+'-'+e.text(), totalData),1);
}
}
var generateCalendar = function(y, m) {
// 当前所在日期
$('.year').html(y);
if(m+1 < 10) {
$('.month').html('0'+parseInt(m+1));
}else {
$('.month').html(parseInt(m+1));
}
var data = [];
// 用上月号数补齐当月1号前空余号数
for(var i = firstDayWeek(y, m) - 2; i >= 0; i--) {
data.push('<span class="notMonthly">' + (preMonthDays(y, m)-i) + '</span>');
}
// if($('.month').text() < 10) { // 拼装参数
// var holiday = $('.year').text()+'0'+$('.month').text();
// }else {
// var holiday = $('.year').text()+$('.month').text();
// }
// $.ajax({ // 获取节假日数据
// type: "GET",
// url: "http://apis.baidu.com/xiaogg/holiday/holiday",
// data: {d: holiday, apikey: '22ccbd220dba0561bbe2177d84d501cf'},
// headers : {'apikey':''},
// dataType: "json",
// success: function(response) {
// var res = response[holiday];
// for(var k = 0; k <= res.length; k++) {
// for(var i = 1; i <= 31; i++) {
// if(i == res[k].slice(2)) {
// // if(td.eq(i).text() == i) {
// // //td.eq(i).addClass('holiday')
// // alert(td.eq(i).text())
// // }
// }
// }
// }
// }
// });
// 获得当月号数
for(var i = 1; i <= isLeapYear(y, m); i++) {
data.push(i);
}
// 用下月号数补齐当月最后空余号数
var lackNum = td.length - data.length;
for(var i = 1; i <= lackNum; i++) {
data.push('<span class="notMonthly">' + i + '</span>');
}
// 载入日历
for(var i = 0; i < data.length; i++) {
td.eq(i).html(data[i]);
if(data[i] < 10) {
td.eq(i).attr({name:$('.year').text() + '-' + $('.month').text() + '-' + '0' + data[i]});
}else {
td.eq(i).attr({name:$('.year').text() + '-' + $('.month').text() + '-' + data[i]});
}
for(var k = 0; k < cData.length; k++) {
if(td.eq(i).attr('name') == cData[k]) {
td.eq(i).addClass('selectDate');
}
}
for(var j = 0; j < sData.length; j++) {
if(td.eq(i).attr('name') == sData[j]) {
td.eq(i).addClass('selectStuDate');
}
}
}
// 周末特别标识
for(var i = firstDayWeek(y, m) - 1; i <= isLeapYear(y, m) + firstDayWeek(y, m) - 2; i++) {
if(new Date(y, m, parseInt(td.eq(i).text())).getDay() == 0 || new Date(y, m, parseInt(td.eq(i).text())).getDay() == 6) {
td.eq(i).addClass('holiday');
}
}
}
6.日历初始化
switch(opts.pattern) {
case 1: // 开课日历
// 初始化日历
var initCalender = function(y, m) {
showSelectInfo(cData);
// 复位checkbox
$('.selectWeekend').removeAttr('checked');
$('.selectAll').removeAttr('checked');
td.removeClass('selectDate');
generateCalendar(y, m);
}
cData = [];
// 用户参数 data 与 历史cData 并集
var mergeArray = function(arr1, arr2) {
for (var i = 0, j = 0, ci, r = {}, c = []; ci = arr1[i++] || arr2[j++]; ) {
if (r[ci]) continue;
r[ci] = 1;
c.push(ci);
}
return c;
}
cData = mergeArray(opts.classData, cData);
// 全选周末
$('.selectWeekend').click(function() {
var y = opts.year;
var m = opts.month;
if($(this).is(':checked')) {
for(var i = firstDayWeek(y, m) - 1; i <= isLeapYear(y, m) + firstDayWeek(y, m) - 2; i++) {
if(new Date(y, m, parseInt(td.eq(i).text())).getDay() == 0 || new Date(y, m, parseInt(td.eq(i).text())).getDay() == 6) {
td.eq(i).addClass('selectDate');
addTotalData(td.eq(i), cData);
}
}
}else {
for(var i = firstDayWeek(y, m) - 1; i <= isLeapYear(y, m) + firstDayWeek(y, m) - 2; i++) {
if(new Date(y, m, parseInt(td.eq(i).text())).getDay() == 0 || new Date(y, m, parseInt(td.eq(i).text())).getDay() == 6) {
td.eq(i).removeClass('selectDate');
removeTotalData(td.eq(i), cData);
}
}
}
});
// 全选当月
$('.selectAll').click(function() {
if($(this).is(':checked')) {
td.removeClass('selectDate');
for(var i = firstDayWeek(opts.year, opts.month) - 1; i <= isLeapYear(opts.year, opts.month) + firstDayWeek(opts.year, opts.month) - 2; i++) {
td.eq(i).addClass('selectDate');
addTotalData(td.eq(i), cData);
}
$('.selectWeekend').prop("checked",'true');
}else {
for(var i = firstDayWeek(opts.year, opts.month) - 1; i <= isLeapYear(opts.year, opts.month) + firstDayWeek(opts.year, opts.month) - 2; i++) {
td.eq(i).removeClass('selectDate');
removeTotalData(td.eq(i), cData);
}
$('.selectWeekend').removeAttr("checked");
}
});
// 点选号数
td.click(function() {
if($(this).children().hasClass('notMonthly')) {
// 这里处理如果点击了上一个月的号数的逻辑
}else {
if($(this).hasClass('selectDate')) {
removeTotalData($(this), cData);
$(this).removeClass('selectDate');
}else {
$(this).addClass('selectDate');
addTotalData($(this), cData);
}
}
})
break;
case 2: // 学生日历
// 初始化日历
var initCalender = function(y, m) {
showSelectInfo(sData);
// 复位checkbox
$('.selectWeekend').removeAttr('checked');
$('.selectAll').removeAttr('checked');
td.removeClass('selectDate');
td.removeClass('selectStuDate');
generateCalendar(y, m);
}
// 用户参数 stuData 与 历史sData 并集
var mergeArray = function(arr1, arr2) {
for (var i = 0, j = 0, ci, r = {}, c = []; ci = arr1[i++] || arr2[j++]; ) {
if (r[ci]) continue;
r[ci] = 1;
c.push(ci);
}
return c;
}
cData = opts.classData;
sData = mergeArray(opts.stuData, sData);
// 全选周末
$('.selectWeekend').click(function() {
var y = opts.year;
var m = opts.month;
if($(this).is(':checked')) {
for(var i = firstDayWeek(y, m) - 1; i <= isLeapYear(y, m) + firstDayWeek(y, m) - 2; i++) {
if((new Date(y, m, parseInt(td.eq(i).text())).getDay() == 0 || new Date(y, m, parseInt(td.eq(i).text())).getDay() == 6) && td.eq(i).hasClass('selectDate')) {
td.eq(i).addClass('selectStuDate');
addTotalData(td.eq(i), sData);
}
}
}else {
for(var i = firstDayWeek(y, m) - 1; i <= isLeapYear(y, m) + firstDayWeek(y, m) - 2; i++) {
if(new Date(y, m, parseInt(td.eq(i).text())).getDay() == 0 || new Date(y, m, parseInt(td.eq(i).text())).getDay() == 6) {
if(td.eq(i).hasClass('selectDate')) {
td.eq(i).removeClass('selectStuDate');
removeTotalData(td.eq(i), sData);
}
}
}
}
});
// 全选当月
$('.selectAll').click(function() {
if($(this).is(':checked')) {
td.removeClass('selectStuDate');
for(var i = firstDayWeek(opts.year, opts.month) - 1; i <= isLeapYear(opts.year, opts.month) + firstDayWeek(opts.year, opts.month) - 2; i++) {
if(td.eq(i).hasClass('selectDate')) {
td.eq(i).addClass('selectStuDate');
addTotalData(td.eq(i), sData);
}
}
$('.selectWeekend').prop("checked",'true');
}else {
for(var i = firstDayWeek(opts.year, opts.month) - 1; i <= isLeapYear(opts.year, opts.month) + firstDayWeek(opts.year, opts.month) - 2; i++) {
if(td.eq(i).hasClass('selectDate')) {
td.eq(i).removeClass('selectStuDate');
removeTotalData(td.eq(i), sData);
}
}
$('.selectWeekend').removeAttr("checked");
}
});
// 点选号数
td.click(function() {
if($(this).children().hasClass('notMonthly')) {
// 这里处理如果点击了上一个月的号数的逻辑
}else {
if($(this).hasClass('selectDate')) {
if($(this).hasClass('selectStuDate')) {
removeTotalData($(this), sData);
$(this).removeClass('selectStuDate');
}
else {
$(this).addClass('selectStuDate');
addTotalData($(this), sData);
}
}
}
})
break;
}
// 执行初始化
initCalender(opts.year, opts.month);
7.回调函数
// 回调函数
opts.callback(function() {
switch(opts.pattern) {
case 1:
showSelectInfo(cData); // 处理cData及展示数据
if(cData.length > 0) { // 返回数据
return cData;
}
break;
case 2:
showSelectInfo(sData);
if(sData.length > 0) { // 返回数据
return sData;
}
break;
}
});
8.调用日历
<script>
/**
* 参数列表:
* year: 年份 int/string
* month: 月份 int/string 默认从0开始 如传入1将获得 2月数据
* today: 号数 int/string
* classData: 用于接收服务器传过来的班级课表数据 并在日历上标注 array
* stuData: 用于接收服务器传过来的学生课表数据 并在日历上标注 array
* language: 语言 默认中文
* patternNum: 切换日历模式 默认1班级课表 可以接收参数1,2
* callback: 回调函数 返回日历选中的值 返回值类型array
*/
if(parseInt(sessionStorage.editOrAdd)) {
var classData = window.parent.class_tableData; // 获取服务器数据
var stuData = window.parent.stuData;
}
var patternNum = window.parent.patternNum;
$('.BGOC').BGOCalender({
pattern: patternNum,
classData: classData,
stuData: stuData,
callback: function(data) {
calenderData = data();
$('.calenderTable > tbody > tr > td, .selectAll, .selectWeekend').click(function() {
calenderData = data();
console.log(calenderData);
});
}
});
</script>