用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 ...
随机推荐
- discuz常用变量
帖子URL: {url}帖子标题: {title}附件图片: {pic}帖子内容: {summary}楼主: {author}楼主UID: {authorid}楼主头像: {avatar}楼主头像(中 ...
- vim中taglist使用
转载:http://www.cnblogs.com/mo-beifeng/archive/2011/11/22/2259356.html 本节所用命令的帮助入口: :help helptags :he ...
- uva 133 The Dole Queue 双向约瑟夫环 模拟实现
双向约瑟夫环. 数据规模只有20,模拟掉了.(其实公式我还是不太会推,有空得看看) 值得注意的是两个方向找值不是找到一个去掉一个,而是找到后同时去掉. 还有输出也很坑爹! 在这里不得不抱怨下Uva的o ...
- Active Session History (ASH) Performed An Emergency Flush Messages In The Alert Log
Active Session History (ASH) Performed An Emergency Flush Messages In The Alert Log (文档 ID 1385872.1 ...
- DedeCMS更新文章同步发布到新浪微博
如果在网站推广过程中能利用好微博这个工具的话,将会给网站的推广工作带来巨大的便利.下面以dede程序为例讲讲如何将网站内容自动同步到新浪微博. 在新浪微博的工具中有个自动关联博客的功能,利用好这个功能 ...
- [改善Java代码]构造代码块会想你所想
建议37: 构造代码块会想你所想 镜像博文:http://www.cnblogs.com/DreamDrive/p/5413408.html http://www.cnblogs.com/DreamD ...
- 【二分查找最优解】FZU 2056 最大正方形
题意:现在有一个n*m的矩阵A,在A中找一个H*H的正方形,使得其面积最大且该正方形元素的和不大于 limit. 分析:开始以为是DP或者二维RMQ,其实用二分就可以做出来: 在输入时构造元素和矩阵d ...
- Codevs 2307[SDOI2009]HH的项链
同题: Codevs 2307 HH的项链 BZOJ 1878 HH的项链 洛谷 1972 HH的项链 2009年省队选拔赛山东 时间限制: 1 s 空间限 ...
- jQuery对象和dom对象的辨析和相互转化
jquery对象和dom对象总是让人感觉很难分清,其实只要做到1对两者概念有明确认识2找出不同点 A DOM 1概念 DOM对象(Document Object Model,文档对象模型)可以把htm ...
- SignalR 2.0 系列:SignalR的服务器广播
英文渣水平,大伙凑合着看吧…… 这是微软官方SignalR 2.0教程Getting Started with ASP.NET SignalR 2.0系列的翻译,这里是第八篇:SignalR的服务器广 ...