js前端日历控件(悬浮、拖拽、自由变形)


Posted in Javascript onMarch 02, 2017

很少发现网上有简洁好用的自定义前端控件的贴子,最近项目中需要,自己YY开始写前端控件,在此给大家分享

控件是基于jQuery.UI的Widget写的,写起来就方便很多,使用起来跟普通jQuery控件一样$(#id).control(option),看着眼熟吧,下面就开始了。

首先说下控件的依赖包,加载控件的时候必须先加载jQuery, jQuqery.UI, 另外jquery-ui.css

这个包也需要引用,此包主要应用了jQuery拖拽和放缩的样式,控件样式方面大家自由发挥,给了个自己写的默认样式包 (献丑了)。 

控件本身支持颜色自定义,可根据日期自定义日历上某日的颜色,另外可悬浮,拖拽,自由变形算是卖点吧,哈哈 

控件包加载是这样的:

<link href="../../Content/themes/base/jquery-ui.css" rel="stylesheet" />
<link href="../../Content/datePrinter.css" rel="stylesheet" />

<script src="../../Scripts/default/jquery-ui-1.8.20.min.js"></script>
<script src="../../Scripts/control/datePrinter.js"></script>

控件中的核心部分就是打印选中月的日历,是参考网上的代码,偷懒嘛,欢迎认领

例如页面代码如下:

<input type="text" id="datepickerInput"/>

调用的写法:

var dpCon = $("#datepickerInput").datePrinter({
   initDate: "2017-4-5", //初始化日期
   language: "EN", //语言
   resizable: true, //可自由变形
   draggable: true, //可悬浮拖拽
   showYearAndMonth: true, //是否显示年月下拉框
   getColor: getColor, //自定义颜色接口
   chooseDone: chooseDone //选中日历某日执行事件接口
  });

  //选中日期时让日历消失 当然此处可以执行比较复杂的业务,如服务器数据请求
  function chooseDone(date) {
   dpCon.datePrinter("dpHide");
  }

  //自定义日期颜色
  function getColor(day){
   if(day == 3 || day==7 || day==15)
    return "dpdisabled";
   else if(day== 5 || day==18 || day==23)
    return "dpyellow";
   else
    return "dpenable";
  }

  //获取当前选中的日期 调用控件提供的API getSelectDate
  dpCon.datePrinter("getSelectDate");

这样子就给上面的input text控件注册了一个日历控件,在点击input时,日历就会浮出,效果如下

js前端日历控件(悬浮、拖拽、自由变形)

你可能注意到右下角的小三角了,鼠标放上去之后可以随意变化日历的长宽,另外在日历上按住鼠标左键可以随意移动日期控件的位置,不挤占页面位置

js前端日历控件(悬浮、拖拽、自由变形)

 下面这段是打印日历的代码,供参考:

//默认获取当前日期
  var today = option.initDate ? option.initDate : new Date();
  this.options.initDate = today;
  //获取日期中的年份
  var y = today.getFullYear(),
  //获取日期中的月份(需要注意的是:月份是从0开始计算,获取的值比正常月份的值少1)
  m = today.getMonth(),
  //获取日期中的日(方便在建立日期表格时高亮显示当天)
  d = today.getDate(),
  //获取当月的第一天
  firstday = new Date(y, m, 1),
  //判断第一天是星期几(返回[0-6]中的一个,0代表星期天,1代表星期一,以此类推)
  dayOfWeek = firstday.getDay() == 0 ? 7 : firstday.getDay(),
  //创建月份数组
  days_per_month = new Array(31, 28 + self._isLeap(y), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31),
  //确定日期表格所需的行数
  str_nums = Math.ceil((dayOfWeek + days_per_month[m] - 1) / 7);
  //二维数组创建日期表格
  for (i = 0; i < str_nums; i += 1) {
   var tr = '<tr>';
   for (k = 0; k < 7; k++) {
    //为每个表格创建索引,从0开始
    var idx = 7 * i + k;
    //将当月的1号与星期进行匹配
    var day = idx - dayOfWeek +2;
    var styleName = self._getColor(day);
    if (option.getColor && typeof (option.getColor) == 'function')
     styleName = option.getColor(day);
    styleName += " dateTD";

    (day <= 0 || day > days_per_month[m]) ?
    //索引小于等于0或者大于月份最大值就用空表格代替
    (day = ' ', styleName = "dpBlank") : (day = idx - dayOfWeek + 2);
    day == d ? tr += '<td class="' + styleName + ' today">' + day + '</td>' :
    //高亮显示当天
    tr += '<td class="' + styleName + '">' + day + '</td>';
   }
   tr += '</tr>';
   self._dpTable.append(tr);
   tr = "";
  }

以前都是写后台,玩前端的时间不长,有不对的地方欢迎指正

datePrinter.js的全部代码如下:

var _datePrinter_tmpl_CN = "<tr><th>一</th><th>二</th><th>三</th><th>四</th><th>五</th><th>六</th><th>日</th></tr>";
var _datePrinter_tmpl_EN = "<tr><th>Mon</th><th>Tue</th><th>Wed</th><th>Thu</th><th>Fri</th><th>Sat</th><th>Sun</th></tr>";

Date.prototype.Format = function (fmt) { //author: meizz 
 var o = {
 "M+": this.getMonth() + 1,   //月份 
 "d+": this.getDate(),   //日 
 "h+": this.getHours(),   //小时 
 "m+": this.getMinutes(),   //分 
 "s+": this.getSeconds(),   //秒 
 "q+": Math.floor((this.getMonth() + 3) / 3), //季度 
 "S": this.getMilliseconds()  //毫秒 
 };
 if (/(y+)/.test(fmt))
 fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
 for (var k in o)
 if (new RegExp("(" + k + ")").test(fmt))
  fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
 return fmt;
}

$.widget("ui.datePrinter", {
 options: {
 initDate: null,
 language: null, // CN,EN
 resizable: false,
 draggable: false,
 width: "240px",
 dateFormat:'yyyy/MM/dd',
 getColor: null, //自定义颜色
 showYearAndMonth: false,
 chooseDone: function (selectDate) { return selectDate }, //选中日期后执行的自定义事件
 autoId:null //控件Id
 },
 _dpTable: null,
 _dpRoot:null,
 _selectDate:null, //选中日期
 _create: function () {
 var self = this, option = this.options, ele = this.element;
 $(ele).after("<div class='dpRoot'></div>");
 self._dpRoot = $(ele).parent().find('div.dpRoot');
 self._dpRoot.empty();

 self._dpRoot.append("<div class='dpTitle' style='text-align:right;background-color:#e8edf4; width:" + option.width +
  "'><select class='selYear'></select><select class='selMonth'></select><a style='color:#000;text-decoration:none;font-size:18px;padding-left:10px; padding-right:10px;width:10px;' href='javascript:void(0);'>x</a></div>");
 self._dpRoot.append("<table style='width:" + option.width + "' cellspacing='0'></table>");
 option.autoId = self._newGuid();
 },
 _init: function () {
 var self = this, option = this.options, ele = this.element;
 if (option.initDate && typeof option.initDate == 'string')
  option.initDate = new Date(option.initDate.replace("-", "/"));

 //初始化日历
 self._initDate();

 //点击事件
 self._dpTable.delegate("td", "click", function () {
  if (!$(this).hasClass("dpBlank")) {
  self._dpTable.find("td").removeClass("today");
  $(this).addClass("today");
  //控件设置值
  $.proxy(self._setDate($(this).text()), self);

  if (option.chooseDone && typeof (option.chooseDone) == 'function')
   $.proxy(option.chooseDone(self._selectDate), self);
  }
 });

 if (option.resizable)
  self._dpRoot.resizable({
  minHeight: self._dpRoot.css("height").replace("px",''),
  minWidth:option.width.replace("px",''),
  resize: function (event, ui) {
   var titleHeight = self._dpRoot.find("div.dpTitle").css("height").replace("px", "");

   //最小值时不再缩小
   if (ui.size.width >= Number(option.width.replace("px",''))) {
   $(ui.element).find("table").css({ "width": ui.size.width, "height": ui.size.height - titleHeight, "text-align": "center" });
   $(ui.element).find("div.dpTitle").css({ "width": ui.size.width });
   }
  }
  });

 if(option.draggable)
  self._dpRoot.draggable();

 //关闭按钮事件
 self._dpRoot.find("div.dpTitle > a").bind("click", function () {
  $.proxy(self.dpHide(), self);
 });

 if (option.showYearAndMonth) {
  self._initSelYear();
  self._initSelMonth();
 }

 $(ele).focus(function () {
  self.dpShow();
 });

 $(ele).click(function () {
  self.dpShow();
 });

 //$(ele).blur(function (e) {
 // if ($(e.target).closest('div.dpRoot').length == 0) {
 // self.dpHide();
 // }
 //});
 },

 _destroy: function () {
 var self = this, option = this.options, ele = this.element;
 self._dpRoot.empty();
 this._prototype._destroy.call(self);
 },

 _getColor: function (date) {
 var styleName = null;
 if (date == 3 || date == 5 || date == 12)
  styleName = "dpdisabled";
 else if (date == 20 || date == 23 || date == 27)
  styleName = "dpyellow";
 else
  styleName = "dpenable";

 return styleName;
 },

 _initSelYear: function () {
 var self = this, option = this.options, ele = this.element;
 //根据初始化设置时间计算
 var today = option.initDate ? option.initDate : new Date();
 this.options.initDate = today;
 var y = today.getFullYear(),
 m = today.getMonth();

 //打印年 + - 10
 for (var i = 0; i < 20; i++) {
  var varSel = (y == (y + i - 10)) ? "selected='selected'" : "";
  self._dpRoot.find("select.selYear").show().append("<option value='" + (y + i - 10) + "' " + varSel + ">" + (y + i - 10) + "</option");
 }

 //年事件
 self._dpRoot.find("select.selYear").bind("change", function () {
  option.initDate = new Date(option.initDate.setYear($(this).val()));
  self._initDate();
 });
 },

 _initSelMonth: function () {
 var self = this, option = this.options, ele = this.element;
 //根据初始化设置时间计算
 var today = option.initDate ? option.initDate : new Date();
 this.options.initDate = today;
 var y = today.getFullYear(),
 m = today.getMonth();
 //打印月
 for (var i = 0; i < 12; i++) {
  var varSel = (m == i) ? "selected='selected'" : "";
  self._dpRoot.find("select.selMonth").show().append("<option value='" + (i + 1) + "' " + varSel + ">" + (i + 1) + "</option");
 }

 //月事件
 self._dpRoot.find("select.selMonth").bind("change", function () {
  var selMon = Number($(this).val()) - 1;
  option.initDate = new Date(option.initDate.setMonth(selMon));
  self._initDate();
 });
 },

 _initDate: function () {
 var self = this, option = this.options, ele = this.element;

 self._dpTable = self._dpRoot.find("table");
 self._dpTable.empty();
 if (option.language == "EN") {
  self._dpTable.wrapInner(_datePrinter_tmpl_EN);
 }

 //默认获取当前日期
 var today = option.initDate ? option.initDate : new Date();
 this.options.initDate = today;
 //获取日期中的年份
 var y = today.getFullYear(),
 //获取日期中的月份(需要注意的是:月份是从0开始计算,获取的值比正常月份的值少1)
 m = today.getMonth(),
 //获取日期中的日(方便在建立日期表格时高亮显示当天)
 d = today.getDate(),
 //获取当月的第一天
 firstday = new Date(y, m, 1),
 //判断第一天是星期几(返回[0-6]中的一个,0代表星期天,1代表星期一,以此类推)
 dayOfWeek = firstday.getDay() == 0 ? 7 : firstday.getDay(),
 //创建月份数组
 days_per_month = new Array(31, 28 + self._isLeap(y), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31),
 //确定日期表格所需的行数
 str_nums = Math.ceil((dayOfWeek + days_per_month[m] - 1) / 7);
 //二维数组创建日期表格
 for (i = 0; i < str_nums; i += 1) {
  var tr = '<tr>';
  for (k = 0; k < 7; k++) {
  //为每个表格创建索引,从0开始
  var idx = 7 * i + k;
  //将当月的1号与星期进行匹配
  var day = idx - dayOfWeek +2;
  var styleName = self._getColor(day);
  if (option.getColor && typeof (option.getColor) == 'function')
   styleName = option.getColor(day);
  styleName += " dateTD";

  (day <= 0 || day > days_per_month[m]) ?
  //索引小于等于0或者大于月份最大值就用空表格代替
  (day = ' ', styleName = "dpBlank") : (day = idx - dayOfWeek + 2);
  day == d ? tr += '<td class="' + styleName + ' today">' + day + '</td>' :
  //高亮显示当天
  tr += '<td class="' + styleName + '">' + day + '</td>';
  }
  tr += '</tr>';
  self._dpTable.append(tr);
  tr = "";
 }
 },

 _isLeap: function (year) {
 var self = this, option = this.options, ele = this.element;
 return year % 4 == 0 ? (year % 100 != 0 ? 1 : (year % 400 == 0 ? 1 : 0)) : 0;
 },

 //选中日期时设置选中值 day为currentDate当月的第几日
 _setDate: function (day) {
 var self = this, option = this.options, ele = this.element;
 self._selectDate = new Date(option.initDate.getFullYear() + '/' + (option.initDate.getMonth() + 1) + '/' + day);
 //设置输入框值
 $(ele).val(self.getSelectDate(), self);
 },

 //获取所选日期
 getSelectDate: function () {
 var self = this, option = this.options, ele = this.element;
 return self._selectDate.Format(option.dateFormat);
 },

 //显示
 dpShow: function () {
 var self = this, option = this.options, ele = this.element;
 self._dpRoot.show();
 },
 
 //隐藏
 dpHide: function () {
 var self = this, option = this.options, ele = this.element;
 self._dpRoot.hide();
 },

 //new Guid
 _newGuid: function () {
 var guid = "";
 for (var i = 1; i <= 32; i++) {
  var n = Math.floor(Math.random() * 16.0).toString(16);
  guid += n;
  if ((i == 8) || (i == 12) || (i == 16) || (i == 20)) {
  //guid += "-";
  }
 }
 return guid;
 }

});

样式本人是业余的,勉强看看吧,由于datePrinter.js有依赖css的class名称,贴出来datePrinter.css文件代码如下

.dpBlank {
 background-color: white;
 cursor: not-allowed;
}


.dpRoot {
 width: 240px;
 position:absolute;
 display:none;
}

.today {
 border: 2px double #FF9900 !important;
}

.dpenable {
 background-color: #AABBFF;
}

.dpyellow {
 background-color: #FFC266;
}

.dpdisabled {
 background-color: #B0AEA4;
}

.dpRoot table {
 font-size: 13px;
 width: inherit;
}

.dpRoot table th {
 font-size: 12px;
 border: solid 2px #e8eef4;
 padding: 2px 3px;
 background-color: #e8eef4;
 border-collapse:initial;
 text-align: center;
 width: 22px;
}

.dpRoot table td {
 color: white;
 padding: 4px 5px;
 border: solid 2px #e8eef4;
}

.dpTitle {
 padding: 3px 0 0 0;
}

.dateTD {
 cursor: pointer;
}

.selYear {
 margin-right: 5%;
 display: none;
 font-size:14px;
}

.selMonth {
 margin-right: 5%;
 display: none;
 font-size:14px;
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
如何取得中文输入的真实长度?
Jun 24 Javascript
广告显示判断
Aug 31 Javascript
JavaScript日历实现代码
Sep 12 Javascript
JavaScript中的apply和call函数详解
Jul 20 Javascript
js中使用使用原型(prototype)定义方法的好处详解
Jul 04 Javascript
ion content 滚动到底部会遮住一部分视图的快速解决方法
Sep 06 Javascript
基于百度地图实现产品销售的单位位置查看功能设计与实现
Oct 21 Javascript
Html5+jQuery+CSS制作相册小记录
Dec 30 Javascript
JSON 数据格式详解
Sep 13 Javascript
Webpack优化配置缩小文件搜索范围
Dec 25 Javascript
解决vue多个路由共用一个页面的问题
Mar 12 Javascript
微信小程序实现列表滚动头部吸顶的示例代码
Jul 12 Javascript
JS操作input标签属性checkbox全选的实现代码
Mar 02 #Javascript
JavaScript正则获取地址栏中参数的方法
Mar 02 #Javascript
原生js仿浏览器滚动条效果
Mar 02 #Javascript
使用grunt合并压缩js和css文件的方法
Mar 02 #Javascript
Angular-Ui-Router+ocLazyLoad动态加载脚本示例
Mar 02 #Javascript
浅谈Vue.js
Mar 02 #Javascript
利用imgareaselect辅助后台实现图片上传裁剪
Mar 02 #Javascript
You might like
php 301转向实现代码
2008/09/18 PHP
PHP程序61条面向对象分析设计的经验小结
2008/11/12 PHP
php中adodbzip类实例
2014/12/08 PHP
PHP概率计算函数汇总
2015/09/13 PHP
微信公众号支付之坑:调用支付jsapi缺少参数 timeStamp等错误解决方法
2016/01/12 PHP
javascript-TreeView父子联动效果保持节点状态一致
2007/08/12 Javascript
比较简单的一个符合web标准的JS调用flash方法
2007/11/29 Javascript
jQuery的一些特性和用法整理小结
2010/01/13 Javascript
学习从实践开始之jQuery插件开发 对话框插件开发
2012/04/26 Javascript
javascript实现文字图片上下滚动的具体实例
2013/06/28 Javascript
jQuery大于号(&gt;)选择器的作用解释
2015/01/13 Javascript
JavaSciprt中处理字符串之sup()方法的使用教程
2015/06/08 Javascript
jQuery操作动态生成的内容的方法
2016/05/28 Javascript
深入对Vue.js $watch方法的理解
2017/03/20 Javascript
jQuery+ajax实现局部刷新的两种方法
2017/06/08 jQuery
如何使用python爬取csdn博客访问量
2016/02/14 Python
Python排序搜索基本算法之选择排序实例分析
2017/12/09 Python
Python 3.x 判断 dict 是否包含某键值的实例讲解
2018/07/06 Python
Python 操作 ElasticSearch的完整代码
2019/08/04 Python
关于Python形参打包与解包小技巧分享
2019/08/24 Python
Python遍历字典方式就实例详解
2019/12/28 Python
python输入一个水仙花数(三位数) 输出百位十位个位实例
2020/05/03 Python
Python 读取位于包中的数据文件
2020/08/07 Python
PyCharm安装PyQt5及其工具(Qt Designer、PyUIC、PyRcc)的步骤详解
2020/11/02 Python
Foot Locker加拿大官网:美国知名运动产品零售商
2019/07/21 全球购物
全球工业:Global Industrial
2020/02/01 全球购物
实习生单位鉴定意见
2013/12/04 职场文书
暑期研修感言
2014/02/17 职场文书
三八妇女节活动主持词
2014/03/17 职场文书
模特大赛策划方案
2014/05/28 职场文书
护士年终考核评语
2014/12/31 职场文书
大学升旗仪式主持词
2015/07/04 职场文书
小学运动会通讯稿
2015/07/18 职场文书
个人售房合同协议书
2016/03/21 职场文书
2016年教师师德师风承诺书
2016/03/25 职场文书
python数字类型和占位符详情
2022/03/13 Python