码迷,mamicode.com
首页 > 编程语言 > 详细

javascript动手写日历组件(1)——构建日历逻辑 (by vczero)

时间:2014-08-09 21:24:19      阅读:375      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   java   使用   io   strong   

一、分析日历的组成部分和交互要素

(1)组成部分:选择年月部分、星期显示、包含本月(或者有前月和下一个月部分日子)

(2)根据选择的年和月份,动态绘制日历面板。

(3)一个日历 7(天) * 5(周) = 35格表格。

(4)一个月份是统一的一个面板;一个月的头一天一定在日历面板的第一行,根据该天的“星期几”确定位置。

(5)第一格子是星期一,最后一个格子是星期日,为5周的日历面板。

二、确定逻辑设计

bubuko.com,布布扣

日历上面的日历,8月1号建军节为什么会出现在这一格?因为一个月的天数是小于5周(35天)的,因此,在第一行肯定包含了一个月份的第一天,而这一天的位置是根据该天的星期几来确定的,比如7月的1号是星期二,那么7月1号在第一行的星期二的位置上,然后依次类推,计算前一个月在面板上显示的日期,下一个月在面板上显示的日期。

可以将每一个表格看成是一个日期对象,那么下一步的目的就是根据传入不同年份和月份,计算出面板上显示的日期对象数组。

三、构建日历类

(1)首先,构建一个可以传入DOM DIV的日历类。

1 var Calendar = function(div){
2     this.div = document.getElementById(div);
3 };
4 
5 Calendar.week = [‘星期一‘, ‘星期二‘,‘星期三‘, ‘星期四‘,‘星期五‘, ‘星期六‘, ‘星期日‘];
6 Calendar.month = [‘1月‘,‘2月‘,‘3月‘,‘4月‘,‘5月‘,‘6月‘,‘7月‘,‘8月‘,‘9月‘,‘10月‘,‘11月‘,‘12月‘];

(2)日历面板逻辑实现。

一个日历面板包含3个日期对象数组,第一个是preMonth,因为,也许该日历面板上会显示前一个月的一些日期;第二个是本月的日期currentMonth;第三个是下一个月的日期数组,nextMonth。定义一个函数monthPanel代表一个日历面板,返回值是三个数组合并的对象。

如何计算前一个月会显示多少日期?首先计算选择的月份的第一天在第一行(从0开始计算)占据着第几个位置(4),然后上一个月的总天数(31)减去该位置向上索取,即31-4,31-3,31-2,31-1,31.,那么结果就是31-4,31-3,31-2,31-1,31, 1。

如何计算下一个月会显示多少日期?很好办,总共35个格子,那么35 - 当前月份的天数 - 当前月份占据的位置n+1 就是要显示的下一个的日期格子数。

综合后的代码如下:

 1 Calendar.prototype.monthPanel = function(date){
 2     //如果传递了Date对象,则按Date对象进行计算月份面板
 3     //否则,按照当前月份计算面板
 4     var date = date || new Date(),
 5         year = date.getFullYear(),
 6         month = date.getMonth(),
 7         day = date.getDate(),
 8         week = date.getDay(),
 9         currentDays = new Date(year, month + 1, 0).getDate(),
10         preDays = new Date(year, month, 0).getDate(),
11         firstDay = new Date(year, month, 1),
12         firstCell = firstDay.getDay() === 0 ? 6 : firstDay.getDay() - 1,
13         bottomCell =  35 - currentDays - firstCell;
14     //前一个月该显示多少天
15     var preMonth = [];
16     for(var p = firstCell; p > 0; p--){
17         preMonth.push(new Date(year, month - 1, preDays - p + 1));
18     }
19     //本月
20     var currentMonth = [];
21     for(var c = 0; c < currentDays; c++){
22         currentMonth.push(new Date(year, month, c + 1));
23     }
24     //下一个月
25     var nextMonth = [];
26     for(var n = 0; n < bottomCell; n++){
27         nextMonth.push(new Date(year, month + 1, n + 1));
28     }
29 
30     preMonth = preMonth.concat(currentMonth, nextMonth);
31     return preMonth;
32 };

(3)检测代码逻辑是否正确,正好在使用node cmd,所以索性在node下运行了(当如放到Chrome console也可以),不过需要先注释掉this.div = document.getElementById(div);这一行。var c = new Calendar();console.log(c.monthPanel(new Date(2014, 6, 1))); 其实不传递参数,就是显示当前月份的日历面板。如下图。

bubuko.com,布布扣

三、构建最基础的UI

(1)动态绘制35个表格

 1     for(var i = 0; i < 35; i++){
 2         var cellDOM = document.createElement(‘div‘);
 3         cellDOM.style.width = cell.width + ‘px‘;
 4         cellDOM.style.height = cell.height + ‘px‘;
 5         cellDOM.style.display = ‘inline-block‘;
 6         cellDOM.style.float = ‘left‘;
 7         cellDOM.style.border = ‘1px solid blue‘;
 8         cellDOM.style.cursor = ‘pointer‘;           this.div.appendChild(cellDOM);
11     }

bubuko.com,布布扣

(2)显示日期和月份的头部

 1 Calendar.prototype.showUI = function(date){
 2     var width = this.div.style.width || 800,
 3         height = this.div.style.height || (600 - 30),
 4         cell = {width: (parseInt(width) - 20)/7, height: (parseInt(height) -30 - 20)/5},
 5         monthArr = this.monthPanel(date);
 6 
 7     this.addHeader(date);
 8     for(var i = 0; i < 35; i++){
 9         var cellDOM = document.createElement(‘div‘);
10         cellDOM.style.width = cell.width + ‘px‘;
11         cellDOM.style.height = cell.height + ‘px‘;
12         cellDOM.style.display = ‘inline-block‘;
13         cellDOM.style.float = ‘left‘;
14         cellDOM.style.border = ‘1px solid blue‘;
15         cellDOM.style.cursor = ‘pointer‘;
16         cellDOM.innerHTML = monthArr[i].getDate();
17         this.div.appendChild(cellDOM);
18     }
19     
20 };
21 
22 Calendar.prototype.addHeader = function(date){
23     var header = document.createElement(‘div‘);
24     header.style.height = ‘20px‘;
25     header.style.width = this.div.style.width || ‘800px‘;
26     header.style.textAlign = ‘center‘;
27     header.style.fontWeight = ‘bold‘;
28     header.innerHTML = date.getFullYear() + ‘年‘ + (date.getMonth() + 1) + ‘月‘;
29     console.log(header);
30     this.div.appendChild(header);
31 }

(3)编写HTML和整个逻辑代码

HTML:

<!doctype html>
<html>
    <head>
        <meta charset="utf-8" />
        <script type="text/javascript" src="calendar.js"></script>
        <script type="text/javascript">
            function showCalendar(){
                var c = new Calendar(calendar);
                c.showUI(new Date());
            }
        </script>
    </head>
    <body onload="showCalendar()">
        <div id="calendar" style="width:600px; height:400px;border:1px solid red;"></div>
    </body>
</html>

javascript:

 1 var Calendar = function(div){
 2     this.div = document.getElementById(div);
 3 };
 4 
 5 Calendar.week = [‘星期一‘, ‘星期二‘,‘星期三‘, ‘星期四‘,‘星期五‘, ‘星期六‘, ‘星期日‘];
 6 Calendar.month = [‘1月‘,‘2月‘,‘3月‘,‘4月‘,‘5月‘,‘6月‘,‘7月‘,‘8月‘,‘9月‘,‘10月‘,‘11月‘,‘12月‘];
 7 
 8 Calendar.prototype.showUI = function(date){
 9     var width = this.div.style.width || 800,
10         height = this.div.style.height || (600 - 30),
11         cell = {width: (parseInt(width) - 20)/7, height: (parseInt(height) -30 - 20)/5},
12         monthArr = this.monthPanel(date);
13 
14     this.addHeader(date);
15     for(var i = 0; i < 35; i++){
16         var cellDOM = document.createElement(‘div‘);
17         cellDOM.style.width = cell.width + ‘px‘;
18         cellDOM.style.height = cell.height + ‘px‘;
19         cellDOM.style.display = ‘inline-block‘;
20         cellDOM.style.float = ‘left‘;
21         cellDOM.style.border = ‘1px solid blue‘;
22         cellDOM.style.cursor = ‘pointer‘;
23         cellDOM.innerHTML = monthArr[i].getDate();
24         this.div.appendChild(cellDOM);
25     }
26     
27 };
28 
29 Calendar.prototype.addHeader = function(date){
30     var header = document.createElement(‘div‘);
31     header.style.height = ‘20px‘;
32     header.style.width = this.div.style.width || ‘800px‘;
33     header.style.textAlign = ‘center‘;
34     header.style.fontWeight = ‘bold‘;
35     header.innerHTML = date.getFullYear() + ‘年‘ + (date.getMonth() + 1) + ‘月‘;
36     console.log(header);
37     this.div.appendChild(header);
38 }
39 
40 Calendar.prototype.monthPanel = function(date){
41     //如果传递了Date对象,则按Date对象进行计算月份面板
42     //否则,按照当前月份计算面板
43     var date = date || new Date(),
44         year = date.getFullYear(),
45         month = date.getMonth(),
46         day = date.getDate(),
47         week = date.getDay(),
48         currentDays = new Date(year, month + 1, 0).getDate(),
49         preDays = new Date(year, month, 0).getDate(),
50         firstDay = new Date(year, month, 1),
51         firstCell = firstDay.getDay() === 0 ? 6 : firstDay.getDay() - 1,
52         bottomCell =  35 - currentDays - firstCell;
53     //前一个月该显示多少天
54     var preMonth = [];
55     for(var p = firstCell; p > 0; p--){
56         preMonth.push(new Date(year, month - 1, preDays - p + 1));
57     }
58     //本月
59     var currentMonth = [];
60     for(var c = 0; c < currentDays; c++){
61         currentMonth.push(new Date(year, month, c + 1));
62     }
63     //下一个月
64     var nextMonth = [];
65     for(var n = 0; n < bottomCell; n++){
66         nextMonth.push(new Date(year, month + 1, n + 1));
67     }
68 
69     preMonth = preMonth.concat(currentMonth, nextMonth);
70     return preMonth;
71 };

基本效果,最为基本的日历逻辑已经完成,可以传入不同的月份,显示日历面板了:

bubuko.com,布布扣

 

下一篇:增加日历的UI效果 & 添加交互(根据选择,显示日历面板)

 

javascript动手写日历组件(1)——构建日历逻辑 (by vczero),布布扣,bubuko.com

javascript动手写日历组件(1)——构建日历逻辑 (by vczero)

标签:style   blog   http   color   java   使用   io   strong   

原文地址:http://www.cnblogs.com/vczero/p/js_ui_1.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!