js万年历,麻雀虽小五脏俱全,由原生js编写
对于前端来说,我们可能见到最多的就是各种各样的框架,各种各样的插件了,有各种各样的功能,比如轮播啊,日历啊,给我们提供了很大的方便,但是呢?我们在用别人这些写好的插件,框架的时候,有没有试着问一问自己?这些东西都是怎么写出来的?现在我们以一个万年历为例,介绍下怎么写出来,别人那个看似小巧的万年历,又蕴含着怎样的构思,我觉得这才是前端的魅力所在。
废话不多说了,先看看我做的效果图:
说一下具体的思路先:首先js能给我们的就只是一个日期函数date();我们只能知道当前时间是哪年哪月哪日哪时哪分哪秒,时分秒这里不用(待会再说为什么不用),那我们怎么做出来呢?
1、其实这个日历实际上是一个上头的div+下方的表格table组合而成,这是第一步
2、说第2步之前呢?我先贴下html的代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>万年历</title>
<link rel="stylesheet" href="dorseyCh.css" type="text/css">
<script src="dorseyCh.js" type="text/javascript"></script>
</head>
<body>
<div id="dsCalendar">
</div>
</body>
</html>
可以看到就是一个div指定到某个id上。跟我们插件类似,为什么先贴代码,因为这里组成万年历的div跟table是通过js创建出来的。
怎么创建呢?这里列两个关键函数:
(父元素).appendChild(子元素).添加子元素
(父元素).removeChild(子元素).删除子元素
3、创建了元素之后呢?得有内容,表格的每个单元格填什么?怎么填?
这里我说下我的思路,可能有大神会有更好的,仅供参考:
1、首先我们获取每个月的第1天,以及这一天是星期几(date(年,月,1).getDay());这部分其实应该都会。
2、我们每个月的天数是固定的,除了2月份闰年多一天之外其他是固定的,这就很容易联想到做一个数组,通过查表的方式来获取每个月的天数。
3、接下来呢?最后一天跟第一天知道了,我们怎么把这些给填进去呢?也不难,上面创建的table是一个7*6的表格,先默认把7*6的表格从1~42全部填进去,然后呢,因为我们第一天是星期几是知道的,把这42个数都去减掉星期几对应的那个数,你会发现嘿嘿在对应的星期上就填出了个0,再加1就OK了,接下来呢,把不用的都去掉,什么意思呢?因为你原来是1~42,现在变成了-x到42-x(这个x就是星期几代表的那个数),然后呢把小于0且大于对应月份天数的数全部清除掉,剩余的你会发现就是一个日历的一页了。
4、点击换页
四个按钮也很简单,只需要对应按钮点击一下,比如年-的按钮,那就把对应的年份减1,同时这里需要说的是换页,这个怎么做呢?
也很简单,把table删掉,再重新弄个table进去(这时候的table里面某个月或是某年对应的值是改变了的)
这个方法我总觉得比较耗费资源,当然应该会有更好的办法,这里仅供参考。
5、换页了,但是万年历还有一个显示细节的栏目,显示对应日期的,这个怎么搞?
也很简单,通过innerHTML写入,但写入啥呢?对应的年月日跟星期咯。
6、还有一个细节就是我们在点日历的时候,点击后,显示详情页会变成你点击的那一天,这又得怎么搞?
也不难,你忘了js本身就有获取元素标签的值的函数,把获取的值动态显示到详情页即可,接下来还有一个小问题,显示栏不是还有星期么?得怎么显示啊?嘿嘿,这个你发现没,你点击的那个小单元格它是在42个格里都有对应的位置的,比如0,7,14,21都是对应了星期一是吧?这样你会了吧,还是不会的话,这42个值是不是可以余7,剩下的数值就是跟星期一一对应了,说到一一对应,嗯又可以联想到列数组查表了哈。
基本的思路就是这样,其他小细节,小改样式的就不细说了,没意思,样式什么的各位可以自己改。
好啦!最重要的代码来啦,感谢你听了我啰嗦这么多。
css部分:(这里面我为了方便调试给外部div定义了位置,插件最好不要,不会乱,让用这个插件的人自己去调位置)
#dsCalendar{width:500px;height:396px;margin:100px auto;border-radius:20px;
border:1px solid black;box-shadow:5px 5px #222;box-sizing: border-box} #dsCalendar table{width:500px;height:336px;border:1px solid black;box-sizing:border-box;
background:url(images/calendar.jpg) 100%;font:25px Times New Roman;text-align: center;border-radius:20px;}
#dsCalendar table thead{width:500px;border-radius:20px;}
/*#dsCalendar table thead{width:500px;height:56px;background:red;}*/
#dsCalendar table thead tr td{color:black;height:80px;} #dsCalendar table tbody tr td{color:red;cursor:pointer;height:36px;border-radius:36px;}
#dsCalendar table tbody tr td:hover{background:skyblue;color:black;} #dsCalendar div{width:500px;height:60px;border-radius:60px;}
#dsCalendar div span,#dsCalendar div span img{width:40px;height:40px;border-radius:50px;}
#dsCalendar div span{float:left;box-sizing:border-box;cursor:pointer;margin-top:10px;} #dsCalendar div .yBtn,#dsCalendar div .yBtn img{width:60px;height:60px;border-radius:60px;margin-top:0;} #dsCalendar #cDetail{float:left;width:300px;height:60px;border:1px solid black;box-sizing:border-box;
font:20px Times New Roman;text-align: center;line-height:60px;}
#dsCalendar div:after{clear:both;content:'';display:block;}
js部分:(开头说了那么多插件插件,这里算是勉强可以当成个人类库使用,没有插件框架那么严谨,主要是思路)
window.onload=function(){
(function dsCalendar(){
var oCalendar=document.getElementById('dsCalendar'); /*上面控制栏所有内容*/
var oDiv=document.createElement('div');
oDiv.innerHTML='<span class="yBtn"><img src="data:images/y_left.png" alt=""></span>' +
'<span><img src="data:images/m_left.png" alt=""></span><div id="cDetail"></div>' +
'<span><img src="data:images/m_right.png" alt=""></span>'+
'<span class="yBtn"><img src="data:images/y_right.png" alt=""></span>';
oCalendar.appendChild(oDiv);
/*日历内容解析*/
var oDate=new Date();
var oYear=oDate.getYear();
var isLeap=oYear%400==0?1:((oYear%100!=0&&oYear%4==0)?1:0);
var aMouth=[31,28+isLeap,31,30,31,30,31,31,30,31,30,31];//创建月份尾数表,作为每张日历最后一个数
var aWeek=['日','一','二','三','四','五','六'];
var y=oDate.getFullYear();
var m=oDate.getMonth(),
d=oDate.getDate(),
w=oDate.getDay();
//hour=oDate.getHours(),
//min=oDate.getMinutes(),
//sec=oDate.getSeconds();
var oDetail=document.getElementById('cDetail');//显示当前日期的栏目
var oSpan=oDiv.getElementsByTagName('span'); //4个按钮 function update(){
/*table里面的所有内容*/
var cTable=document.createElement('table'); //创建table
var cTHead=document.createElement('thead'); //创建thead
var cTBody=document.createElement('tbody'); //创建tbody
/*无中生有,通过javascript创造一个table表格*/
var cTr0=document.createElement('tr');
for(var k=0;k<7;k++){
var cTd0=document.createElement('td');
cTd0.innerHTML=aWeek[k];
cTr0.appendChild(cTd0);
}
cTHead.appendChild(cTr0);
cTable.appendChild(cTHead); var firstDate=new Date(y,m,1); //获取当月第一天
var dayOfWeek=firstDate.getDay();//获取当月的第一天是星期几
for(var i=0;i<6;i++){
var ctr=document.createElement('tr');
for(var j=0;j<7;j++){
var re=i*7+j;
var re1=re-dayOfWeek+1;
var ctd=document.createElement('td');
if(re1<=0||re1>aMouth[m]){
ctd.innerHTML='';
}
else{
ctd.innerHTML=re1;
if(re1==d&&m==oDate.getMonth()&&y==oDate.getFullYear()){
ctd.style.color='black';
ctd.style.border='1px dasher black';
}
}
ctr.appendChild(ctd); //将创造出来的td插入到tr中
}
cTBody.appendChild(ctr); //将创造出来的tr插入到tbody中
}
cTable.appendChild(cTBody); //将创造出来的tbody插入到table中
oCalendar.appendChild(cTable);//将创造出来的table插入到指定id的div中,完成一个完整table的创建 /*在控制栏的中部加入当天的时间*/ oDetail.innerHTML=y+'年'+(m+1)+'月'+d+'日'+' '+'星期'+aWeek[w]; //4个按钮的功能函数
for(var a=0;a<oSpan.length;a++){
oSpan[a].index=a;
oSpan[a].onclick=function(){
for(var i=0;i<oSpan.length;i++){
oSpan[i].style.background='';
}
this.style.background='yellow';
switch(this.index){
case 0:y-=1;break;
case 1:{
m-=1;
if(m<0){
m=11;
y-=1;
}
}break;
case 2:{
m+=1;
if(m>11){
m=0;
y+=1;
}
}break;break;
case 3:y+=1;break;
}
oCalendar.removeChild(cTable);
update();
oDetail.innerHTML=y+'年'+(m+1)+'月'+d+'日'+' '+'星期'+aWeek[w];
};
} //点击任意一天的功能函数
//var ctr1=cTBody.getElementsByTagName('tr');
var ctd1=cTBody.getElementsByTagName('td');
for(var i=0;i<ctd1.length;i++){
ctd1[i].index=i;
ctd1[i].onclick=function(){
for(var i=0;i<ctd1.length;i++){
ctd1[i].style.background='';
}
ctd1[this.index].style.background='skyblue';
oDetail.innerHTML=y+'年'+(m+1)+'月'+ctd1[this.index].innerText+'日'+' '+'星期'+aWeek[(this.index%7)];
console.log(this.index);
}
}
console.log(ctd1.length); }
update();
})();
};
好了,基本的都在那,里面加了一些小资源文件(图片)就不贴了,希望对各位在javascript有所帮助。
javascript是开源的,不止js,很多都是开源的,给了我们程序员无穷无尽的的资料,我们要珍惜,分享快乐!
js万年历,麻雀虽小五脏俱全,由原生js编写的更多相关文章
- JavaScript中函数和类(以及this的使用<重点>,以及js和jquery讲解,原生js实现jquery)
1.javascript中以函数来表示类: 一般函数是小写开头:function foo() 类开头是大写:function Foo() 实例化类: obj = new Foo() 其他属性就同类是一 ...
- JS对象转URL参数(原生JS和jQuery两种方式)
转自:点击打开链接 现在的js框架将ajax请求封装得非常简单,例如下面: $.ajax({ type: "POST", url: "some.php", da ...
- js中for循环(原生js)
1,普通for循环,经常用的数组遍历 var arr = [1,2,3,4,5]; for ( var i = 0; i <arr.length; i++){ console.log(arr[i ...
- AJAX初识(原生JS版AJAX和Jquery版AJAX)
一.什么是JSON 1.介绍 JSON独立于语言,是一种与语言无关的数据格式. JSON指的是JavaScript对象表示法(JavaScript Object Notation) JSON是轻量级的 ...
- 记一次数据、逻辑、视图分离的原生JS项目实践
一切的开始源于这篇文章:一句话理解Vue核心内容. 在文章中,作者给出了这样一个思考: 假设现在有一个这样的需求,有一张图片,在被点击时,可以记录下被点击的次数. 这看起来很简单吧, 按照上面提到到开 ...
- 用原生JS写一个网页版的2048小游戏(兼容移动端)
这个游戏JS部分全都是用原生JS代码写的,加有少量的CSS3动画,并简单的兼容了一下移动端. 先看一下在线的demo:https://yuan-yiming.github.io/2048-online ...
- 关于错位动画的练习,原生js编写
最近在网上看到一个关于错位动画的文章,感觉非常有趣,便自己练习了一下,文章连接:http://www.w3cplus.com/animation/staggering-animations.html ...
- 原生js编写的安全色拾色器
<html > <head> <meta http-equiv="Content-Type" content="text/html; cha ...
- 原生JS和JQuery代码编写窗口捕捉函数和页面视觉差效果(scroll()、offsetTop、滚动监听的妙用)
想实现窗口滚动到一定位置时,部分网页的页面发生一些变化,但是手头没有合适的插件,所以就想到自己编写一个简易的方法, 想到这个方法要有很高的自由度和适应性,在这,就尽量的削减其功能,若有错误的地方或者更 ...
- 原生JS编写getByClass、addClass、removeClass、hasClass
前言: 年后换了工作,在现在的公司写交互主要使用JS原生:刚刚入门前端的时候写交互一直用的原生JS,虽然用的不怎么样.后来去之前的公司之后,leader主张把jQuery用好,JS原生自然就熟练了:一 ...
随机推荐
- 智能循迹避障小车&抢答器
智能循迹避障小车 →视频链接← 抢答器
- 分布式进阶(十六)Zookeeper入门基础
Zookeeper入门基础 前言 在Zookeeper中,znode是一个跟Unix文件系统路径相似的节点,可以往这个节点存储或获取数据.如果在创建znode时Flag设置为EPHEMERAL,那么当 ...
- iOS设备中垂直同步开启后的帧率计数
因为iOS设备的垂直同步总是开启的所以显得帧计数意义没啥意义. 帧计数给你一个多个帧中的平均数,现实中,你帧速率只能是60,30,20,15,12以及6fps等各个常数中的一个.所有这些值都是60的因 ...
- SpriteBuilder中的CCSprite9Slice是个什么鬼?
CCSprite大家都知道,但是加上后面那一串又变成了神马呢? 我们可以首先到官方的API文档网站查一下,如下: http://www.cocos2d-swift.org/docs/api/Class ...
- 【39】FlexboxLayout使用介绍
FlexboxLayout介绍: Flexbox 也称为弹性盒子模型 或伸缩盒子模型,广泛用于前端开发,做过前端 web 的都知道Bootstrap 中有一套强大的 CSS Grid网格样式.Boot ...
- PHP-MVC和Smarty初探笔记
在慕课网上学习了PHP的MVC的基础知识,记录一下笔记: 等待更新~
- 在Eclipse 中集成SVN
在项目开发的过程中,我们需要用到版本控制工具,最常见的也就是SVN了,下面就来介绍最简单的一种在Elipse中集成svn工具. 第一步:下载 svn包,如site-1.6.5.zip或者site-1. ...
- git使用中checkout生成临时br的问题(吓出一身冷汗啊)
git中几天前漫不经心的使用了git checkout ver_hash的命令,结果push到远程库都提示everything is up-to-date,实际神马都没提交上去啊!但看本地log中的确 ...
- 基于 Java Web 的毕业设计选题管理平台--选题报告与需求规格说明书
一.选题报告 目录 团队名称 团队成员 项目名称 项目描述 创新与收益 用户场景分析 真实用户调研 未来市场与竞争 项目导图 比例权重 总结 1.团队名称--指南者团队 2.团队成员 孔潭活:2015 ...
- 深入源码解析类Route
微软官网对这个类的说明是:提供用于定义路由及获取路由相关信息的属性和方法.这个说明已经很简要的说明了这个类的作用,下面我们就从源码的角度来看看这个类的内部是如何工作的. public class Ro ...