带你开发一个日历控件_第1页
带你开发一个日历控件_第2页
带你开发一个日历控件_第3页
带你开发一个日历控件_第4页
带你开发一个日历控件_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

日历控件多的不胜枚举,为什么我们还要再造一个轮子呢?

因为大多数日历控件都是用于选择日期的,有种需求是要在日历上展示各种各样

的内容,这样的日历控件较少,而且试用下来并不满意。

因此就再造一个轮子,现在带你一起基于使用之前完成的组件机制来开发一个日

历控件。

需求

简单把需求整理如下:

・月视图

・支持在日历中每一天中插入任意的内容

・相关点击事件

・获取日历当前视图的开始和结束日期

・获取设置选中的日期

实现分析

首先我们拿系统中自带的日历观察一下,看看日历的特征到底是怎么样的。

2017年11月/XXZ

—三四五六B

303112345

-4--十三十四十五

6789101112

十八立冬二十廿一廿二甘三廿四

13141516171819

廿五Wx廿七廿八WL十月初二

20212223242526

初三初四小雪毗初八

27282930123

+—十二十三十四十五-11__/i\~-

45678910

十七I"/\丁儿tt—廿二廿三

一个月中有28到31天不等,但是为了保证完整的结构,日历中会有部分上

一月和下一月的日期,总结下来,一个月中显示的必定是整整6周的日期。

那么只要得到当月的开始日期就可以绘制日历了。

如何计算当月日历视图中的开始日期呢?前面已经分析了,为了保证完整,它

显示了上一月的部分天数,那么只用从当月的1号开始往前推算就可以了。

开始日期=当月1号的日期-当月工号的星期

结束日期=开始日期+42天

这个问题搞清楚了,感觉实现这么一个日历就没什么大阻碍了,开始动工吧!

必要结构准备

首先构建如下所示的基本结构

<divclass="ep-calendar">

<divclass="ep-calendar-header**>

<divclass=Mep-calendar-header-left"x/div>

<divclasss^ep-calendar-header-center">•••

</div>

<divclass="ep-calendar-header-right"></div>

</div>

<tableclass="ep-calendar-bodyn>

<thead>…

</thead>

<tbodyclass=Mep-calendar-days">…

</tbody>

</table>

<divclass="ep-calendar-footer1'></div>

<divclass="ep-calendar-menuMx/div>

</div>

其中:

・头部左右为个性化区域,用于实际使用时放置任意内容。中间用于显示当

前月份和切换按钮

主体区域中用绘制整个日历

Othead中绘制周一至周日或周日至周一的星期,这段内容是不会

随月份切换而改变的,可以直接准备好

otbody中用于绘制可变的日期,准备好容器留空即可。

・脚部区域用于实际使用时放置任意各项化内容

•menu区域用于切换日期时弹出的面板

绘制日历

在初始化好日历结构后就可以开始绘制日历了。

计算一个月中的开始日期和结束日期

首先完成开始和结束时间的计算

(

//初始化当前月份的开始日期和结束日期

J^itStartEiad:F认八ction0{

//当月1号

vavcurrMoiath=

//当月1号是周几the.ISOdayoftheweekwith工beingMondayav\d.7

beingSunday.

=currMoiath.isoWeekdayOj

sta七DateOFMoct几

eiadD〃teOfM。八仍;

if(!this.dayStartFroi^Su^.day){

//开始为周一则向前减少周几的天数-工即为开始的日期

startDateOfMo八th=currMoi^thsubtract(fi^tDay_weekday-工Jd砌);

}eke(

//开始为周日则直接向前周几的天数即可

staHDatcOfMonth=currMo^thsubtract(firstsayjA/eekdayj'day');

]

cudD温。fM。八历=staHDateOfMcmth.do八eO.add(41」4ag);

this.startDateOfMo八th=startDateOfMonth;

this.endDateOfMonth=e八dD〃±cOfMon/;

)

)

由于要处理很多日期,而JavaScript中关于日期处理时,不同浏览器下差异较大,

因此直接使用momentjs来对日期进行统一处理。

由于使用习惯不同,一周的开始到底是周一还是周日是不确定的,因此直接作为

配置即可。

绘制一月中的日期

上面已经计算得到了一个月的开始日期和结束日期,那么只用遍历进行绘制即可。

由于我们使用了表格实现,因此需要按行绘制。

实现如下:

(

//日历可变部分的渲染

.renderfuMtioia(){

this.JnitStartEi^d();

vavweeks=6,

days-7,

curtate=tkisstartDateOfMoiatkcloMOj

tr;

,,

vafstart=thisstartPateOfMoi^th.forkv\at(YYYY-MM-PP)J

eiad=this.e八WDateOfMo八tk.fo/MatCYYYY-MM-DD);

//清空并开始新的渲染

this._clearPays();

this..e八"erTitle。;

for(vari=O;/<weeks;+(

tr=doc〃MC八t.createE/enAeW*);

tr.classNa^e='ep-calendar-week';

tkis._day$Body.appeiadCkild.(tr);

for(varj=<9;j<dags;+琰{

//渲染一天并递增

ndcKD〃9(c“KDate,tr);

curDate.add^j'day1);

]

]

L

//每天的渲染

jc八derDag:function(date,cixrrTr){

r,,

vavtd=docui^eiat.CieateElei^\e^.t(td)J

thinner=docui^eyxt.createElei^e^tCdiv1),

text=docNkc八t.c「e〃土eE他MAC八t('s?〃八'),

day=date.isoVJeekdayOj

//返回的月份是。-11

month=date,HA。八协0+1;

tdlnMr.appci^dCkild(text);

±4.appe八dChil*tdl八八er);

td.dassNaMe=*ep-calendar-date1}

td/nncH.c/〃ssNahAe=fep-calendar-date-inMr1;

//完整日期

tdsetA.ttribute('data-date1,date.fori^a^'YYYY-MM一DD'));

//对应的《。星期

tctsetAttribute^data-isoweekday1jday);

//周末标记text.cSssAMkwe

if(day=====6||day===7){

td.classNai^e+=1ep-calei^day-weekend1;

)

//非本月标记

//sufestr在ies下有问题

//if(moHth!=parse伍t(tkis.c〃"Mo八协.s〃Ost«-2))){

if(MO八物!=parse伉t(协is.c〃々M。八物suSsty(5),X6>)){

td.classNa^v\e+=1ep-calendar-other^oi^tk1;

]

//今天标记

if(tkis.today==date.fon^a^'YYYY-MM-PP*)){

td.classNai^e+-=1ep-calendar-today';

]

//每天渲染时发生还未插入页面

var%八derEue八七=tkis.fi/eCcellRe八He—,{

//当天的完整日期

date:date.fori^,at('YYYY-MM-PPr)>

//当天的is。星期

isoWeekdag:day,

//日历dow\

d:this"

//当前单元格

tdEl:tdj

//日期文本

datcText:date.dateOj

//日期cbss

dateCk:lep-calendar-date-text',

//需要注入的额外的9以1

extraHtml:11,

isHeader:false

!);

//处理对dagTcxt内容和样式的更改

text.mHcrText=匕。八WeHEve八t.dateText;

text.className=re^dcrEvei^t.dateCls;

//添加新增内容

if(ren^erEv/ent.extraHtmO{

jQ(Aery(re^.derEve^t.extraHt^l).appe^.dTo(tdi^.Mr);

)

CMnTr.appe八HChiia(七八derEve八t.tdEl);

//每天渲染后发生插入到页面

this.fi砥%ftwCeHRe八4e『){

date:date.fori^atCYYYY-MM-DD^j

is。Weekday:day,

el:this"

tdEl:td,

dateText:teKt.innWText,

dateCIs:text.dassNaMC,

%八dcrEvent.extRHtiM。

isHeade仁false

!);

}

直接从开始日期往后依次画出42天即可。

为了灵活性,在绘制的不同时机触发了不同的事件,在使用时可绑定相应的事件,

在其中进行个性化操作。

也为了使用了方便和灵活性,直接在绘制日期时,在相应的dom上加入了所对

应的日期和星期属性。

在此过程中需要对日期是否周末、是否本月、是否是选中的、是否是今天等进行

相应的标记处理。

绘制其他内容

除了上面所述之外此外还要绘制出年月选择、标题等,这些实际就是给已经有的

dom元素中更改内容而已,就不再展开了。

切换月份的实现

上面已经基本绘制出了一个日历,切换月份实际就更简单了,只用根据新的月份

重新计算开始日期,清空原来的内容,重新进行绘制即可。

(

//设置月份

setMo八th:function(ym){

vardate-

if(date.isValid()){

varo/dM。八亡k=七〃is.c〃rrM。八th,

N'MM。八协=date.fori^at('YYYY-MM1);

//月份变动前

this.fiKeCbefoReMo八thCha八g*{

el:this.eL

oldMo^th:o/dM。八M

八ewM。八协:

));

th/s.eurrMoHth=〃沁Month;

加MHCn

//月份变动后

this.fireCaftwMo八thCha八g*{

cl:this.eL

oldMo八th:o/dM。八M

MwMontk:

}else{

throwMWErrorfym+,是一个不合法的日期,);

)

)

)

事件的处理

要处理的事件较多,此处仅仅以日期的点击作为示意。

(

//初始化事件

J^itEveiat:function0{

vavmy=this;

jQuerg(加k.ef)

//日期单元格

缶八cti。八(e){

vardate=tkis.getA.ttribute(,data-date'),

cv=i^y.fireCdayClick'j{

ev.e,

date:date,

day:tkis.getA.ttribute(,data-isoweekday1),

d:my.eL

tdEl:this

});

//如果修改事件对象的amcH为tme后则不进行后续的选中操作

if(lev.caMel){

i^ysetSelected(date);

}

})

)

)

由于日期所对应的dom元素始终会添加和移除,直接把事件绑定在日期的dom

元素上,则必须在每次新增后重新绑定事件,十分麻烦。

直接使用事件代理机制,将事件绑定在整个日历的dom上即可,这样事件只用

在创建时初始化一次即可,简单、高效、省内存。

使用

我们新增这个控件的主要目的就是要支持在日历中绘制任意内容,怎么使用呢?

vartestCale^dar=epctrl.iiaitCCale^d.ar1,(

el:^date',

//资源加载过程中的事件需要直接在这里指定

events:{

beforeSourceLoad:fuMtiovx(e){

//资源加载前,在加入

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论