用AJAX自定义日历
需求分析
在一些购物网站中,都会有促销活动,这些活动都在日历上标注出来,如何通过Ajax让日历 通过读取数据库中的信息,正确的把促销活动标注在日历上,本文通过自定义日历来实现这 个问题。
技术难点
- 日历的布局
- 日历的初始化
- 日历的动态变化
- 日历的促销定制
实现方法
1、 先创建一个固定的日历,效果如下

html代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style type="text/css">
* {margin: 0; padding: 0;}
body {font-size: 13px;}
.calendar {width: 330px; margin: 0 auto;}
.calendar .title {
position: relative;
width: 100%;
height: 30px;
line-height: 30px;
background: #17a4eb;
}
.title div {position: absolute;}
.prev {left: 10px; }
.now {left: 40%;}
.next {right: 10px;}
input {height: 30px; width: 300px; margin: 100px 475px 0px;}
table {width: 100%; border-collapse: collapse;}
table th {border: 1px solid #ccc;}
table td {text-align: center; border: 1px solid #ccc;}
</style>
</head>
<body>
<input type="text">
<div class="calendar">
<div class="title">
<div class="prev">
<span>08</span>月
</div>
<div class="now">
<span>2016</span>年
<span>09</span>月
</div>
<div class="next">
<span>10</span>月
</div>
</div>
<table>
<!--星期部分-->
<thead>
<tr>
<th>日</th>
<th>一</th>
<th>二</th>
<th>三</th>
<th>四</th>
<th>五</th>
<th>六</th>
</tr>
</thead>
<!--日期部分-->
<tbody>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
当创建固定日历后,把日历的html部分注释掉(title和table),保留css部分
2、 通过javascript动态生成日历
window.onload = function () {
var oInput = document.getElementsByTagName('input')[0];
var oCalendar = document.getElementById('calendar');
// console.log(oCalendar);
var oDate = new Date();
var year = oDate.getFullYear();
var month = oDate.getMonth()+1;
//日期td
var oTds = oCalendar.getElementsByTagName('td');
var flag = false;
oInput.onfocus = function () {
showDate(year,month);
}
//显示日历
function showDate(year,month) {
if (false == flag) {
var oTitle = document.createElement('div');
oTitle.className = 'title';
oTitle.innerHTML = '<div class="prev"> <span>'+(month-1)+'</span>月 </div> ' +
'<div class="now"> <span>'+year+'</span>年 <span>'+month+'</span>月 </div> ' +
'<div class="next"> <span>'+(month+1)+'</span>月 </div>';
oCalendar.appendChild(oTitle);
//月份span
ospans = oCalendar.getElementsByTagName('span');
// console.log(ospans);
prevMonth = ospans[0];
nextMonth = ospans[3];
nowMonth = ospans[2];
nowYear = ospans[1];
//创建星期
var otable = document.createElement('table');
var othead = document.createElement('thead');
var otr = document.createElement('tr');
var arr = ['日','一','二','三','四','五','六'];
for (var i=0; i<arr.length; i++) {
//创建th
var oth = document.createElement('th');
oth.innerHTML = arr[i];
otr.appendChild(oth);
}
othead.appendChild(otr);
otable.appendChild(othead);
oCalendar.appendChild(otable);
//先获得当前月有多少天
if (1 == month || 3 == month || 5 == month || 7 == month || 8 == month || 10 == month || 12 == month) {
var dayNum = 31;
} else if (4 == month || 6 == month || 9 == month || 11 == month) {
var dayNum = 30;
} else if (2 == month && isLeapYear(year)) {
var dayNum = 29;
} else {
var dayNum = 28;
}
//确定当前月的1号是星期几
oDate.setFullYear(year);
oDate.setMonth(month-1);
oDate.setDate(1);
//日期
var otbody = document.createElement('tbody');
for (var i=0; i<6; i++) {
var oTr = document.createElement('tr');
//每行里面有7列
for (var j=0; j<7; j++) {
var oTd = document.createElement('td');
//oTd.innerHTML = 1;
oTr.appendChild(oTd);
}
otbody.appendChild(oTr);
}
otable.appendChild(otbody);
//获得今天1号对应的是星期几
var week = oDate.getDay();
var oTds = oCalendar.getElementsByTagName('td');
//alert(week);
for (var i=0; i<dayNum; i++) {
oTds[i+week].innerHTML = i+1;
}
//如果当前月month 是12或者1
if (1 == month) {
prevMonth.innerHTML = 12;
} else if (12 == month) {
nextMonth.innerHTML = 1;
}
//让当前日期显示红色、后面的显示蓝色
showColor();
//给左右月份绑定点击事件
monthEvent();
//给所有的td绑定点击事件
tdClick();
//判断最后一行是否全为空
lastTr();
//获得促销信息
getPromotion();
flag = true;
}
}
//最后一行如果全部为空就将其隐藏
function lastTr() {
//查找最后一行的所有td
var flag = true;
for (var i=35; i<42; i++) {
if (oTds[i].innerHTML != '') {
//有任何一个td不为空就设置为false
flag = false;
}
}
//全部是空的
if (flag) {
for (var i=35; i<42; i++) {
oTds[i].style.display = 'none';
}
}
}
//给所有的td绑定点击事件
function tdClick() {
for (var i=0; i<oTds.length; i++) {
oTds[i].onclick = function() {
if ('red' == this.className ||'blue' == this.className) {
var year = nowYear.innerHTML;
var month = nowMonth.innerHTML;
var date = this.innerHTML;
oInput.value = year +'-'+month+'-'+date;
flag = false;
oCalendar.innerHTML = '';
} else {
alert('您只能选择红色或蓝色区域');
}
}
}
}
//当前日期显示红色、后面的显示蓝色
function showColor() {
//当前的日期
var oday = new Date().getDate();
for (var i=0; i<oTds.length; i++) {
if (oday == oTds[i].innerHTML) {
oTds[i].className = 'red';
var oindex = i;
}
}
for (var j=oindex+1; j<oTds.length; j++) {
oTds[j].className = 'blue';
}
}
//给左右月份绑定点击事件
function monthEvent() {
//向左的月份div
prevMonth.parentNode.onclick = function () {
//alert('向左');
flag = false;
oCalendar.innerHTML = '';
if (12 == prevMonth.innerHTML) {
showDate(year -= 1, 12);
} else {
showDate(year,parseInt(prevMonth.innerHTML));
}
}
//向左的月份div
nextMonth.parentNode.onclick = function () {
//alert('向右');
flag = false;
oCalendar.innerHTML = '';
if (1 == nextMonth.innerHTML) {
showDate(year+=1,1);
} else {
showDate(year,parseInt(nextMonth.innerHTML));
}
}
}
//判断是否是闰年
function isLeapYear(year) {
if (0 == year%100 && 0 == year%400) {
return true;
}else if (year%100 != 0 && year%4 ==0) {
return true;
} else {
return false;
}
}
}
3、 从服务器获取促销的信息并在日历中显示
//从服务器获取促销信息
function getPromotion() {
$.request({
method:"post", //获取方式
url:"promotion.php", //从哪个文件中获取
data:"", //是否传递数据
callback:function (res) {
eval("var obj="+res);
if (obj.status) {
var dates = obj.dates;
for (var i=0; i<dates.length; i++) {
for (var j=0; j<oTds.length; j++) {
if (oTds[j].innerHTML == dates[i]) {
oTds[j].innerHTML += "促销";
oTds[j].style.background = 'red';
}
}
}
}
}
});
}
$.request()是封装在js里的Ajax方法,代码如下:
var $ = {
request:function(obj){
var xhr;
try {
//主流浏览器里面的ajax对象
xhr = new XMLHttpRequest();
} catch(e) {
//IE低版本的浏览器
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
//建立和服务器的连接
if (obj.method == 'get') {
xhr.open(obj.method,obj.url+'?'+obj.data+'&'+Math.random(),true);
xhr.send();
} else if (obj.method == 'post') {
xhr.open(obj.method,obj.url,true);
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xhr.send(obj.data);
}
//监视服务器的处理状态
xhr.onreadystatechange = function(){
if (4 == xhr.readyState && 200 == xhr.status) {
//说明请求成功了,输出服务器返回的数据
obj.callback(xhr.responseText);
}
}
}
}
promotion.php
<?php
$data['status'] = 1;
//促销时间
$data['dates'] = array(28,29,30); echo json_encode($data);
最终效果图如下,样式不是很美观

用AJAX自定义日历的更多相关文章
- javascript实例学习之六—自定义日历控件
基于之前上篇博客轻量级jquery,tool.js和base.js.自定义开发的base_datePicker插件,效果类似于jquery_ui的datePicker插件 //基于Base.js以及t ...
- Springboot如何优雅的解决ajax+自定义headers的跨域请求
1.什么是跨域 由于浏览器同源策略(同源策略,它是由Netscape提出的一个著名的安全策略.现在所有支持JavaScript 的浏览器都会使用这个策略.所谓同源是指,域名,协议,端口相同.),凡是发 ...
- Android自定义日历控件(继承系统控件实现)
Android自定义日历控件(继承系统控件实现) 主要步骤 编写布局 继承LinearLayout设置子控件 设置数据 继承TextView实现有圆圈背景的TextView 添加Attribute 添 ...
- Springboot如何优雅的解决ajax+自定义headers的跨域请求[转]
1.什么是跨域 由于浏览器同源策略(同源策略,它是由Netscape提出的一个著名的安全策略.现在所有支持JavaScript 的浏览器都会使用这个策略.所谓同源是指,域名,协议,端口相同.),凡是发 ...
- ExtJS基础知识总结:自定义日历和ComboBox控件(二)
概述 1.ExtJS 5不支持日期选择框中只选择年月,为了满足ExtJs5可以实现选择年月的功能,查询网上资料,整理出来了相应的处理方式,最终实现的效果如下图: 2.ExtJS 控件丰富,如果需要实现 ...
- 用NSCalendar和UICollectionView自定义日历,并实现签到显示
前一段时间因为工作需要实现了一个可以签到的日历,来记录一下实现的思路 效果如图: 这里的基本需求是: 1,显示用户某个月的签到情况,已经签到的日子打个圈,没有签到且在某个时间范围内的可以签到,其他 ...
- IOS自定义日历控件的简单实现(附思想及过程)
因为程序要求要插入一个日历控件,该空间的要求是从当天开始及以后的六个月内的日历,上网查资料基本上都说只要获取两个条件(当月第一天周几和本月一共有多少天)就可以实现一个简单的日历,剩下的靠自己的简单逻辑 ...
- 利用 ajax自定义Form表单的提交方式
需求场景:有时候单纯的form表单无法向后端传递额外的参数 比如需要action传递js异步生成的参数 ,form表单默认的action就无法满足需求,这时就需要我们自定义form表单的提交方式. h ...
- ✅问题:Rails.ajax自定义请求
chatroom.coffee中的js代码: document.addEventListener 'turbolinks:load', -> document.getElementById(&q ...
随机推荐
- C#_ajax fileupload
@{ ViewBag.Title = "Index"; Layout = null; } <h2>Index</h2> <script src=&qu ...
- jQuery获取表单各元素的值
radio值获取 $("input[type='radio']:checked").val(); 2,设置指定的项为当前选中项 $("input[type='radio' ...
- TIANKENG’s rice shop
Problem Description TIANKENG managers a pan fried rice shop. There are n kinds of fried rice numbere ...
- dem30下载地址
http://www.gscloud.cn/listdata/listdata_new.shtml?from=&productId=311#Wzg4LFswLDEwLDEsMF0sW10sW1 ...
- find & rm
1)查找并删除3天前的历史文件 rm -rfi `find /tmp/ -ctime 3` 2)按分钟查找 find -cmin N
- The Story of self Parameter in Python, Demystified
转自:http://www.programiz.com/article/python-self-why If you have been programming in Python (in obj ...
- 使用copy再次实现Circle类,保证不能有内存泄漏问题
#import <Foundation/Foundation.h> //xieyi @protocol showOn @required -(void)printOn; @end // l ...
- 关于Override在JDK1.5和JDK1.6上子类实现接口中方法使用@Override注解编译错误.
遇到这个问题说来也怪.新开了一个path的工作空间用来打patch.该Eclipse的默认全局的编译版本是1.6.但是唯独其中的一个插件项目的版本是1.5(可能是唯一的一个,不确定,不知道为什么会是这 ...
- hdu 4571 floyd+动态规划
思路: 我们先求一遍floyd,将各点的最短距离求出,然后将点按si的升序排序.dp[i][k]表示第i个点在第j时间所获得的最大效益,那么 dp[i][k]=max(dp[ i ][ k ] , ...
- TSQL基础(四) - 日期处理
日期类型-DateTime DateTime是sql中最常用的日期类型. 存储大小为:8个字节: 日期范围:1753-01-01到9999-12-31: 精确度:3.33毫秒: 常用的日期函数 Get ...