This repository has been archived by the owner. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjquery.ejDate.js
377 lines (286 loc) · 12.8 KB
/
jquery.ejDate.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
/*!
* ejDate 1.0.1 alpha
* https://github.com/stackjie/ejDate.js
* @license MIT licensed
*
* A project by StackJIE
*/
(function ($) {
'use strict';
$.fn.ejDate = function (cfg) {
// 保存this
var that = this;
// 私有的属性
var
// 保存jquery DOM对象的集合
elems = {},
// 当前时间对象
nowDate = new Date(),
// 当前的年
nowYear = nowDate.getFullYear(),
// 当前的月
nowMonth = nowDate.getMonth() + 1,
// 被选中的日期
checkedDate,
// 默认参数对象
defaults = {
yearULV: nowDate.getFullYear(), // 年上限值
yearDLV: 1970, // 年下限值
};
// 将配置对象初始化覆盖默认参数对象的初始值
if (typeof cfg !== 'undefined') {
defaults.yearULV = cfg.yearULV || defaults.yearULV;
defaults.yearDLV = cfg.yearDLV || defaults.yearDLV;
defaults.disabledDateReg = cfg.disabledDateReg || defaults.disabledDateReg; // 筛选禁用日期的正则表达式
defaults.checkedDateFunc = cfg.checkedDateFunc || defaults.checkedDateFunc; // 选日期后调用的回调方法
}
// 私有的方法
var
init = function () {
// 生成dom节点
elems.mainElem = $('<div class="ejdate-main">').html(
'<table><caption>\
<span class="btn-cut before-date"></span>\
<select class="select-year"></select>\
<select class="select-month"></select>\
<span class="btn-cut after-date"></span></caption>\
<thead><tr><th>一</th><th>二</th><th>三</th><th>四</th><th>五</th><th>六</th><th>七</th></tr></thead>\
<tbody></tbody></table>'
);
// 将text表单用div元素包裹,以便使组件绝对定位
that.wrap('<div class="ejdate-wrap">');
that.after(elems.mainElem);
// 获取将要操作的dom元素
elems.targetInput = that;
elems.selectYear = elems.mainElem.find('.select-year'),
elems.selectMonth = elems.mainElem.find('.select-month'),
elems.btnBefore = elems.mainElem.find('.before-date'),
elems.btnAfterDate = elems.mainElem.find('.after-date'),
elems.tbody = elems.mainElem.find('table tbody');
// 将目标text表单设置为只读状态
elems.targetInput.attr('readonly','readonly');
// 渲染Select表单
initRenderSelect();
renderDate();
// 初始化表单绑定事件
elems.btnBefore.click(function(){
// 调用setNowDate函数并传入新的Date对象(当前月份-1)
setNowDate(new Date(nowYear,nowMonth - 1 - 1));
updateSelected();
});
elems.btnAfterDate.click(function(){
// 调用setNowDate函数并传入新的Date对象(当前月份-1)
setNowDate(new Date(nowYear,nowMonth - 1 + 1));
updateSelected();
});
// 绑定select的change事件
elems.selectYear.change(function () {
setNowDate(new Date(this.value,nowMonth - 1));
});
elems.selectMonth.change(function () {
setNowDate(new Date(nowYear,this.value - 1));
});
// 日期选中事件委托
elems.tbody.on('click','.day-normal',function(ev){
that.setDate(nowYear,nowMonth,$(this).html());
$(this).addClass('active');
// 将日期写入text表单
var dateStr = nowYear + '-' + nowMonth + '-' + $(this).html();
elems.targetInput.val(dateStr);
// 执行当用户选择日期后的回调处理函数
if (typeof defaults.checkedDateFunc === 'function') {
defaults.checkedDateFunc(checkedDate);
}
// 选择好日期后主体元素默认隐藏
elems.mainElem.hide();
});
// 点击目标表单显示,点击组件主体以外隐藏
elems.targetInput.click(function(ev){
elems.mainElem.show();
ev.stopPropagation();
});
$(document).click(function(){
elems.mainElem.hide();
});
elems.mainElem.click(function(ev){
ev.stopPropagation();
});
// 主体元素默认隐藏
elems.mainElem.hide();
},
// 初始化渲染Select表单
initRenderSelect = function () {
var option,i;
// 循环输出年份option
for(i = defaults.yearULV; i >= defaults.yearDLV; i--){
option = $('<option>' + i + '年</option>').val(i);
// 如果为当前年设置为选中状态
if(i === nowYear){
option[0].selected = true;
}
elems.selectYear.append(option);
}
// 循环输出月份option
for(i = 1; i <= 12; i++){
option = $('<option>' + i + '月</option>').val(i);
// 如果为当前月设置为选中状态
if(i === nowMonth){
option[0].selected = true;
}
elems.selectMonth.append(option);
}
},
// 渲染日期数据
renderDate = function () {
// 重置tbody
elems.tbody.html('');
var
daysData = createDaysData(nowDate),
tr,td,i,j,dateText;
// 初始化第一行tr
tr = $('<tr></tr>');
for (i = 0; i < daysData.length; i++) {
dateText = daysData[i].substring(daysData[i].indexOf('-') + 1);
td = $('<td></td>').html(dateText);
tr.append(td);
var isDimmed = daysData[i].indexOf('dimmed') !== -1;
// 添加class做不同日期的样式区分
if (isDimmed || isDisabledDate(dateText)) {
td.addClass('day-dimmed');
}else {
td.addClass('day-normal');
}
// 判断当前渲染的天数是不是被选中的天数
if (isCheckedDate(dateText) && !isDimmed) {
td.addClass('active');
}
// 如果当前循环到的日期能被7整除(一个星期)并且又不是最后一个日期就换行
if ( (i + 1) % 7 === 0) {
elems.tbody.append(tr);
// 只要不是最后一个日期就重置tr
if (i !== 41) {
tr = $('<tr></tr>');
}
}
}
},
// 设置当前时间对象并渲染
setNowDate = function (parNowDate) {
var tempYear = parNowDate.getFullYear();
// 如果新传入的nowDate对象年份大于指定的上限值或小于指定的下限值该函数不执行
if (tempYear > defaults.yearULV || tempYear < defaults.yearDLV) {
return false;
}
nowDate = parNowDate;
nowYear = tempYear;
nowMonth = nowDate.getMonth() + 1;
// 调用渲染函数
renderDate();
},
// 生成月份天数数据数组
createDaysData = function (dateObj) {
var
// 当月的天数
nowDays = getDays(nowYear,nowMonth),
// 上个月的天数
lastDays = getDays(nowYear,nowMonth - 1),
// 保存这个月第一天是星期几
whatDay = new Date(nowYear,nowMonth - 1,1).getDay(),
// 保存上月末尾的天数总和
lastDaysEnd = 6 - (7 - whatDay),
// 生成的天数数据数组
daysArray = [],
// 保存上个月末尾天数的起始天数
startLastDaysEnd = lastDays - lastDaysEnd,
i;
// 产生上月末尾的天数
// 日期数据格式 ['dimmed-28',dimmed-29,...,'normal-1','normal-2',...,'dimmed-1','dimmed-2']
// 末尾会添加对应的标识以便渲染时应用不同的class样式区分
// dimmed: 表示上月以及下月不可用的日期 normal: 当月的日期
for (i = 0; i < lastDaysEnd; i++) {
daysArray[i] ='dimmed-' + (startLastDaysEnd + i + 1);
}
// 产生本月的天数
for (i = 1; i <= nowDays; i++) {
daysArray.push('normal-' + i);
}
// 产生余下的下月天数
for (i = 1; daysArray.length < 42; i++) {
daysArray.push('dimmed-' + i);
}
return daysArray;
},
// 获取某个月共有几天
getDays = function (year,month) {
var days;
// 当月份为二月时,根据闰年还是非闰年判断天数
if (month === 2) {
days = year % 4 === 0 ? 29 : 28;
} else if (month === 1 || month === 3 || month === 5 || month === 7 || month === 8 || month === 10 || month === 12) {
// 月份为:1,3,5,7,8,10,12 时,为大月.则天数为31;
days = 31;
}
else {
// 其他月份,天数为:30.
days = 30;
}
return days;
},
// 更新Selec表单选中项
updateSelected = function () {
elems.selectYear.find('option').each(function(){
if($(this).text() == nowYear + '年'){
$(this)[0].selected = true;
}
});
elems.selectMonth.find('option').each(function(){
if($(this).text() == nowMonth + '月'){
$(this)[0].selected = true;
}
});
},
// 判断日期是否被禁用
isDisabledDate = function (day) {
if (defaults.disabledDateReg) {
var dateStr = nowYear + 'y' + nowMonth + 'm' + day + 'd',flag;
flag = defaults.disabledDateReg.test(dateStr);
return flag;
}
},
// 判断是否是被选中的日期
isCheckedDate = function (day) {
if (checkedDate) {
var
flagYear = checkedDate.getFullYear() === nowYear,
flagMonth = checkedDate.getMonth() + 1 === nowMonth,
flagDay = checkedDate.getDate() == day,
flag = flagYear && flagMonth && flagDay;
return flag;
}
};
// 对外提供的api
$.extend(this, {
/**
* 获取选中的日期
* @return {object}
*/
getDate: function () {
return checkedDate;
},
/**
* 设置选中的日期
* @param {int} parYear 年
* @param {int} parMonth 月
* @param {int} parDay 日
*/
setDate: function (parYear,parMonth,parDay) {
// 清空已被选中日期的选中样式
elems.tbody.find('.active').removeClass('active');
checkedDate = new Date(parYear,parMonth - 1,parDay);
}
});
// 执行初始化函数
init();
return this;
}
})(jQuery);