HTML+JavaScript自己动手做日历
当我们需要在页面中显示某月的事项,或是选择某一段日期时,常常要使用到日历组件。这一组件同样有着许多现成的类库,然而亲自动手开发一个日历,从中了解其实现原理也是非常必要的。在本例中我们就将制作一款非常经典的日历组件。
更多精彩内容欢迎访问我的个人博客皮皮猪:http://www.zhsh666.xyz或者http://www.zh66.club期待您的光临哦!我是皮皮猪,感谢各位光临,能为您排忧解难小站深感荣幸!祝您生活愉快!
1. 创建DOM代码
本例的HTML代码如下:
<div class="calendar">
<div class="title">
<h1 class="green" id="calendar-title">Month</h1>
<h2 class="green small" id="calendar-year">Year</h2>
<a href="" id="prev">Prev Month</a>
<a href="" id="next">Next Month</a>
</div>
<div class="body">
<div class="lightgrey body-list">
<ul>
<li>MON</li>
<li>TUE</li>
<li>WED</li>
<li>THU</li>
<li>FRI</li>
<li>SAT</li>
<li>SUN</li>
</ul>
</div>
<div class="darkgrey body-list">
<ul id="days">
</ul>
</div>
</div>
</div>
由以上代码可见,日历的最外层是一个类名为calendar的div元素,其内部包含了两大部分,分别是日历顶部的标题区域,其类名为title,以及其下方的日期区域,其类名为body。
在title中包含了当前所选日期的月份、年份,其id分别为calendar-title和calendar-year,此外该元素还包括了prev和next两个按钮,分别用于切换选择上一月和下一月。
在body中首先包含了一个周一到周日的英文表头,它们放在一个ul元素中。在表头之后是另一个div元素,用于显示日历主体。其中,日历所选月份的每一天都将显示在该元素内部的days列表中。
2. CSS样式
本例中大部分的基础CSS样式省略介绍,在此仅介绍其中的body-list类。该类用于设置日历表头和日期数据的栅格显示。我们将整个ul元素的宽度设置为100%,并将其除以7,就可以得到每一个li元素的宽度,即14.28%,将这些元素左浮动显示,就可以得到日期的7列显示,样式代码如下:
.calendar{
width:450px;
height:350px;
background:#fff;
box-shadow:0px 1px 1px rgba(0,0,0,0.1);
}
.body-list ul{
width:100%;
font-family:arial;
font-weight:bold;
font-size:14px;
}
.body-list ul li{
width:14.28%;
height:36px;
line-height:36px;
list-style-type:none;
display:block;
box-sizing:border-box;
float:left;
text-align:center;
}
此外,我们为今天、今天之前及今天之后的日期分别创建了不同的类。其中,用浅灰色来显示过去的日期,深灰色来显示将来的日期,日期当天则使用浅绿色背景、绿色文字加以显示,样式代码如下:
.lightgrey{
color:#a8a8a8; /*浅灰色*/
}
.darkgrey{
color:#565656; /*深灰色*/
}
.green{
color:#6ac13c; /*绿色*/
}
.greenbox{
border:1px solid #6ac13c;
background:#e9f8df; /*浅绿色背景*/
}
日历组件的初始显示效果如下图所示。
3. JavaScript生成日历
接着使用JavaScript来动态生成日历信息。首先,我们要做一些前期的准备工作。由于闰年和非闰年的二月天数是不一样的,在此我们为这两种年份分别创建数组,以便于获取每个月的天数,同时为每个月份的英文名创建相应的数组变量,代码如下:
var month_olympic = [31,29,31,30,31,30,31,31,30,31,30,31];
var month_normal = [31,28,31,30,31,30,31,31,30,31,30,31];
var month_name = ["January","Febrary","March","April","May","June","July","Auguest","September","October","November","December"];
然后,为页面中的各种元素创建变量,以便于后续的引用,代码如下:
var holder = document.getElementById("days");
var prev = document.getElementById("prev");
var next = document.getElementById("next");
var ctitle = document.getElementById("calendar-title");
var cyear = document.getElementById("calendar-year");
创建一个Date对象来获取当前的日期时间,并通过getFullYear()方法来获取当前年份,getMonth()方法来获取月份,getDate()方法来获取当前日期。代码如下:
var my_date = new Date();
var my_year = my_date.getFullYear();
var my_month = my_date.getMonth();
var my_day = my_date.getDate();
我们要实现日历的排布,最关键的问题是要知道某一月第一天究竟是星期几,然后才可以根据当月的天数来依次排列其后的日期。在此,专门为该功能创建一个函数,代码如下:
//获取某年某月第一天是星期几
function dayStart(month, year) {
var tmpDate = new Date(year, month, 1);
return (tmpDate.getDay());
}
此外,我们也创建一个相应的函数来获取某月的总天数,代码如下:
//计算某年是不是闰年,通过求年份除以4的余数即可
function daysMonth(month, year) {
var tmp = year % 4;
if (tmp == 0) {
return (month_olympic[month]);
} else {
return (month_normal[month]);
}
}
然后,创建一个refreshDate函数来生成月份显示,代码如下:
function refreshDate(){
var str = "";
var totalDay = daysMonth(my_month, my_year); //获取该月总天数
var firstDay = dayStart(my_month, my_year); //获取该月第一天是星期几
var myclass;
for(var i=1; i<firstDay; i++){
str += "<li></li>"; //为起始日之前的日期创建空白节点
}
for(var i=1; i<=totalDay; i++){
if((i<my_day && my_year==my_date.getFullYear() && my_month==my_date.getMonth()) || my_year<my_date.getFullYear() || ( my_year==my_date.getFullYear() && my_month<my_date.getMonth())){
myclass = " class='lightgrey'"; //当该日期在今天之前时,以浅灰色字体显示
}else if (i==my_day && my_year==my_date.getFullYear() && my_month==my_date.getMonth()){
myclass = " class='green greenbox'"; //当天日期以绿色背景突出显示
}else{
myclass = " class='darkgrey'"; //当该日期在今天之后时,以深灰字体显示
}
str += "<li"+myclass+">"+i+"</li>"; //创建日期节点
}
holder.innerHTML = str; //设置日期显示
ctitle.innerHTML = month_name[my_month]; //设置英文月份显示
cyear.innerHTML = my_year; //设置年份显示
}
refreshDate(); //执行该函数
测试页面,日历显示效果如下图所示。
4. 添加交互动作
最后,我们为prev和next元素分别创建onclick事件函数,使得每点击一次prev,则将当前月份减去1,并调用refreshDate函数刷新日历显示。当月份数值小于0时,则使年份减去1,并使月份变为11,使日历显示为前一年的12月。next的功能与其恰好相反。代码如下:
prev.onclick = function(e){
e.preventDefault();
my_month--;
if(my_month<0){
my_year--;
my_month = 11;
}
refreshDate();
}
next.onclick = function(e){
e.preventDefault();
my_month++;
if(my_month>11){
my_year++;
my_month = 0;
}
refreshDate();
}
测试页面,日历中前一月、后一月的切换效果如下图所示。
下载源文件:https://cloud.ecnu.edu.cn/p/DVF08RwQGRi6Aw
最后,希望这篇文章对大家自定义开发页面中的日历组件有所帮助!
HTML+JavaScript自己动手做日历的更多相关文章
- 动手做第一个Chrome插件
Chrome插件是令人惊讶的简单,一旦你弄懂它的工作和实现原理.它是由一部分HTML,一部分Js,然后混合了一个叫做manifest.json的Json文件组合而成的整体.这意味着你可以使用你最擅长的 ...
- 「雕爷学编程」Arduino动手做(29)——DS1302时钟模块
37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的.鉴于本人手头积累了一些传感器和模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里 ...
- IP工具类-自己动手做个ip解析器
IP工具类-自己动手做个ip解析器 一.资料准备 导入依赖包:
- 从.net复制源代码中国农历阵列,必要做日历
从.net复制源代码中国农历阵列,必要做日历 const { 闰月的月份.春节的阳历日期(农历正月初一).农历的每一个月天数 } c_arrLunarInfo: array [1900 .. 2100 ...
- 自己动手做AI:Google AIY开发工具包解析
2018年国际消费性电子展(CES)上,最明显的一个趋势是Amazon与Google的语音技术进驻战,如AmazonAlexa进驻到Acer笔电内,Google Assist进驻到KIA汽车内,其他如 ...
- 线程安全使用(四) [.NET] 简单接入微信公众号开发:实现自动回复 [C#]C#中字符串的操作 自行实现比dotcore/dotnet更方便更高性能的对象二进制序列化 自已动手做高性能消息队列 自行实现高性能MVC WebAPI 面试题随笔 字符串反转
线程安全使用(四) 这是时隔多年第四篇,主要是因为身在东软受内网限制,好多文章就只好发到东软内部网站,懒的发到外面,现在一点点把在东软写的文章给转移出来. 这里主要讲解下CancellationT ...
- 生活娱乐 WIFI机器人(某机器发烧友自己动手做一台)
某机器发烧友自己动手做一台WIFI机器人,以下是这位发烧友的自述!让我们一起来分享他的劳动成果-- 在经历了十多天的疯狂淘宝.组装.调试.拆卸.再组装.再调试的过程后,俺的Wifi Robot终于于2 ...
- 「雕爷学编程」Arduino动手做(9)——火焰传感器模块
37款传感器和模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的.鉴于本人手头积累了一些传感器与模块,依照实践出真知(动手试试)的理念,以学习和交流为目的,这里准备 ...
- 「雕爷学编程」Arduino动手做(10)——敲击传感器模块
37款传感器和模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的.鉴于本人手头积累了一些传感器与模块,依照实践出真知(动手试试)的理念,以学习和交流为目的,这里准备 ...
随机推荐
- 我造了个好大的"轮子",居然还不是"圆"的!
我造的这个"轮子"指的是集低代码开发与运维为一体的平台,为什么说它不是"圆"的,因为它有些与众不同,甚至可以说是有些另类.至于为什么造这个"轮子& ...
- Git学习(二):Git的初步使用
一.Git的最小配置 1.使用如下命令创建Git的用户名和邮箱,如下所示: $git config --global user.name 'your_name' $git config --globa ...
- 华三F100 系列防火墙 - 浮动路由联动NQA 实现双线路自动切换
公司 有两条公网线路,一条移动作为日常主用线路,一条联通作为备用线路. 为了实现主备线路自动切换,配置了浮动路由 但浮动路由只能在 主用接口为down状态时才能浮出接管默认路由.如果故障为非物理链路故 ...
- Python解释器安装教程和环境变量配置
Python解释器安装教程和环境变量配置 Python解释器安装 登录Python的官方网站 https://www.python.org/ 进行相应版本的下载. 第一步:根据电脑系统选择软件适 ...
- 【MySQL】导出长数字到 Excel 避免转为科学计数法方法
MySQL 导出比较长的数字到 Excel 时,最后几位会变成 0,解决方法如下: 如果只需要导出展示.打印:可使用 CONCAT("\t",str) 如果需要后续处理,引用,最好 ...
- MySQL5.7运行CPU达百分之400处理方案
用户在使用 MySQL 实例时,会遇到 CPU 使用率过高甚至达到 100% 的情况.本文将介绍造成该状况的常见原因以及解决方法,并通过 CPU 使用率为 100% 的典型场景,来分析引起该状况的原因 ...
- Java基础之二十 并发
20.1 并发得多面性 并发编程令人困惑的一个主要原因:使用并发时需要解决的问题有多个,而实现并发的方法也有多种,并且在这两者之间没有明显的映射关系. 20.1.1 更快的执行 速度问题初听起来很简单 ...
- vue-cli3.0创建项目报npm install --loglevel error 踩坑的那把辛酸泪
创建项目 vue create vue-pro 然后如下图 一开始以为是npm的问题,卸载了Mac的node ,安装nvm,然后再安装node (可参考: Mac中nvm的安装和使用 https: ...
- python异常处理-异常捕获-抛出异常-断言-自定义异常-UDP通信-socketserver模块应用-3
异常捕获 异常:程序在运行过程中出现了不可预知的错误,并且该错误没有对应的处理机制,那么就会以异常的形式表现出来 影响:整个程序无法再正常运行 异常的结构 异常的类型 NameError 异常的信息 ...
- 主成分分析 Principle Component Analysis
一.主要思想 利用正交变换把可能线性相关变量表示的观测数据,转换为由少数几个线性无关变量(主成分)表示的数据.(重构原始特征空间:线性降维) 要尽可能保留原始数据中的信息,两个思路:最大投影方差.最小 ...