zepto.mdater.js 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. (function($){
  2. $.fn.mdater = function(config){
  3. var defaults = {
  4. maxDate : null,
  5. minDate : new Date(1970, 0, 1)
  6. };
  7. var option = $.extend(defaults, config);
  8. //window.console && console.log(this);
  9. var input = this;
  10. //通用函数
  11. var F = {
  12. //计算某年某月有多少天
  13. getDaysInMonth : function(year, month){
  14. return new Date(year, month+1, 0).getDate();
  15. },
  16. //计算某月1号是星期几
  17. getWeekInMonth : function(year, month){
  18. return new Date(year, month, 1).getDay();
  19. },
  20. getMonth : function(m){
  21. return ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '十二'][m];
  22. },
  23. //计算年某月的最后一天日期
  24. getLastDayInMonth : function(year, month){
  25. return new Date(year, month, this.getDaysInMonth(year, month));
  26. }
  27. }
  28. //为$扩展一个方法,以配置的方式代理事件
  29. $.fn.delegates = function(configs) {//[function(){...},function(){...}]
  30. el = $(this[0]);
  31. for (var name in configs) {
  32. var value = configs[name];
  33. if (typeof value == 'function') {
  34. var obj = {};
  35. obj.click = value;
  36. value = obj; //vaule= {click:function(){...}}
  37. };
  38. for (var type in value) {
  39. el.delegate(name, type, value[type]);
  40. }
  41. }
  42. return this;
  43. }
  44. var mdater = {
  45. value : {
  46. year : '',
  47. month : '',
  48. date : ''
  49. },
  50. lastCheckedDate : '',
  51. init : function(){
  52. this.initListeners();
  53. },
  54. renderHTML : function(){
  55. var $html = $('<div class="md_mask"></div><div class="md_panel"><div class="md_head"><div class="md_selectarea"><a class="md_prev change_year" href="javascript:void(0);">&lt;</a> <a class="md_headtext yeartag" href="javascript:void(0);"></a> <a class="md_next change_year" href="javascript:void(0);">&gt;</a></div><div class="md_selectarea"><a class="md_prev change_month" href="javascript:void(0);">&lt;</a> <a class="md_headtext monthtag" href="javascript:void(0);">月</a> <a class="md_next change_month" href="javascript:void(0);">&gt;</a></div></div><div class="md_body"><ul class="md_weekarea"><li>日</li><li>一</li><li>二</li><li>三</li><li>四</li><li>五</li><li>六</li></ul><ul class="md_datearea in"></ul></div><div class="md_foot"><a href="javascript:void(0);" class="md_ok">确定</a> <a href="javascript:void(0);" class="md_cancel">取消</a></div></div>');
  56. if($('.md_mask').length==0){$(document.body).append($html);}
  57. return $html;
  58. },
  59. _showPanel : function(container){
  60. this.refreshView();
  61. $('.md_panel, .md_mask').addClass('show');
  62. },
  63. _hidePanel : function(){
  64. //$('.md_panel, .md_mask').removeClass('show');
  65. $('.md_panel, .md_mask').remove();
  66. },
  67. _changeMonth : function(add, checkDate){
  68. //先把已选择的日期保存下来
  69. this.saveCheckedDate();
  70. var monthTag = $('.md_selectarea').find('.monthtag'),
  71. num = ~~monthTag.data('month')+add;
  72. //月份变动发生了跨年
  73. if(num>11){
  74. num = 0;
  75. this.value.year++;
  76. $('.yeartag').text(this.value.year).data('year', this.value.year);
  77. }
  78. else if(num<0){
  79. num = 11;
  80. this.value.year--;
  81. $('.yeartag').text(this.value.year).data('year', this.value.year);
  82. }
  83. var nextMonth = F.getMonth(num)+'月';
  84. monthTag.text(nextMonth).data('month', num);
  85. this.value.month = num;
  86. if(checkDate){
  87. this.value.date = checkDate;
  88. }
  89. else{
  90. //如果有上次选择的数据,则进行赋值
  91. this.setCheckedDate();
  92. }
  93. this.updateDate(add);
  94. },
  95. _changeYear : function(add){
  96. //先把已选择的日期保存下来
  97. this.saveCheckedDate();
  98. var yearTag = $('.md_selectarea').find('.yeartag'),
  99. num = ~~yearTag.data('year')+add;
  100. yearTag.text(num+'年').data('year', num);
  101. this.value.year = num;
  102. this.setCheckedDate();
  103. this.updateDate(add);
  104. },
  105. //保存上一次选择的数据
  106. saveCheckedDate : function(){
  107. if(this.value.date){
  108. this.lastCheckedDate = {
  109. year : this.value.year,
  110. month : this.value.month,
  111. date : this.value.date
  112. }
  113. }
  114. },
  115. //将上一次保存的数据恢复到界面
  116. setCheckedDate : function(){
  117. if(this.lastCheckedDate && this.lastCheckedDate.year==this.value.year && this.lastCheckedDate.month==this.value.month){
  118. this.value.date = this.lastCheckedDate.date;
  119. }
  120. else{
  121. this.value.date = '';
  122. }
  123. },
  124. //根据日期得到渲染天数的显示的HTML字符串
  125. getDateStr : function(y, m, d){
  126. var dayStr = '';
  127. //计算1号是星期几,并补上上个月的末尾几天
  128. var week = F.getWeekInMonth(y, m);
  129. var lastMonthDays = F.getDaysInMonth(y, m-1);
  130. for(var j=week-1; j>=0; j--){
  131. dayStr += '<li class="prevdate" data-day="'+(lastMonthDays-j)+'">'+(lastMonthDays-j)+'</li>';
  132. }
  133. //再补上本月的所有天;
  134. var currentMonthDays = F.getDaysInMonth(y, m);
  135. //判断是否超出允许的日期范围
  136. var startDay = 1,
  137. endDay = currentMonthDays,
  138. thisDate = new Date(y, m, d),
  139. firstDate = new Date(y, m, 1);
  140. lastDate = new Date(y, m, currentMonthDays),
  141. minDateDay = option.minDate.getDate();
  142. if(option.minDate>lastDate){
  143. startDay = currentMonthDays+1;
  144. }
  145. else if(option.minDate>=firstDate && option.minDate<=lastDate){
  146. startDay = minDateDay;
  147. }
  148. if(option.maxDate){
  149. var maxDateDay = option.maxDate.getDate();
  150. if(option.maxDate<firstDate){
  151. endDay = startDay-1;
  152. }
  153. else if(option.maxDate>=firstDate && option.maxDate<=lastDate){
  154. endDay = maxDateDay;
  155. }
  156. }
  157. //将日期按允许的范围分三段拼接
  158. for(var i=1; i<startDay; i++){
  159. dayStr += '<li class="disabled" data-day="'+i+'">'+i+'</li>';
  160. }
  161. for(var j=startDay; j<=endDay; j++){
  162. var current = '';
  163. if(y==this.value.year && m==this.value.month && d==j){
  164. current = 'current';
  165. }
  166. dayStr += '<li class="'+current+'" data-day="'+j+'">'+j+'</li>';
  167. }
  168. for(var k=endDay+1; k<=currentMonthDays; k++){
  169. dayStr += '<li class="disabled" data-day="'+k+'">'+k+'</li>';
  170. }
  171. //再补上下个月的开始几天
  172. var nextMonthStartWeek = (currentMonthDays + week) % 7;
  173. if(nextMonthStartWeek!==0){
  174. for(var i=1; i<=7-nextMonthStartWeek; i++){
  175. dayStr += '<li class="nextdate" data-day="'+i+'">'+i+'</li>';
  176. }
  177. }
  178. return dayStr;
  179. },
  180. updateDate : function(add){
  181. var dateArea = $('.md_datearea.in');
  182. if(add == 1){
  183. var c1 = 'out_left';
  184. var c2 = 'out_right';
  185. }
  186. else{
  187. var c1 = 'out_right';
  188. var c2 = 'out_left';
  189. }
  190. var newDateArea = $('<ul class="md_datearea '+c2+'"></ul>');
  191. newDateArea.html(this.getDateStr(this.value.year, this.value.month, this.value.date));
  192. $('.md_body').append(newDateArea);
  193. setTimeout(function(){
  194. newDateArea.removeClass(c2).addClass('in');
  195. dateArea.removeClass('in').addClass(c1);
  196. }, 0);
  197. },
  198. //每次调出panel前,对界面进行重置
  199. refreshView : function(){
  200. var initVal = this.input.val(),
  201. date = null;
  202. if(initVal){
  203. var arr = initVal.split('-');
  204. date = new Date(arr[0], arr[1]-1 , arr[2]);
  205. }
  206. else{
  207. date = new Date();
  208. }
  209. var y = this.value.year = date.getFullYear(),
  210. m = this.value.month = date.getMonth(),
  211. d = this.value.date = date.getDate();
  212. $('.yeartag').text(y).data('year', y);
  213. $('.monthtag').text(F.getMonth(m)+'月').data('month', m);
  214. var dayStr = this.getDateStr(y, m, d);
  215. $('.md_datearea').html(dayStr);
  216. },
  217. input : null,//暂存当前指向input
  218. initListeners : function(){
  219. var _this = this;
  220. input.on('click', function(){
  221. _this.input = $(this);//暂存当前指向input
  222. if($('.md_mask').length){
  223. _this._hidePanel();
  224. }else{
  225. _this.renderHTML();
  226. var panel = $('.md_panel'),
  227. mask = $('.md_mask');
  228. _this.afterShowPanel(mask,panel);
  229. setTimeout(function () {
  230. _this._showPanel();
  231. }, 50);
  232. }
  233. });
  234. },
  235. afterShowPanel : function (mask,panel) {
  236. var _this = this;
  237. mask.on('click', function(){
  238. _this._hidePanel();
  239. });
  240. panel.delegates({
  241. '.change_month' : function(){
  242. var add = $(this).hasClass('md_next') ? 1 : -1;
  243. _this._changeMonth(add);
  244. },
  245. '.change_year' : function(){
  246. var add = $(this).hasClass('md_next') ? 1 : -1;
  247. _this._changeYear(add);
  248. },
  249. '.out_left, .out_right' : {
  250. 'webkitTransitionEnd' : function(){
  251. $(this).remove();
  252. }
  253. },
  254. '.md_datearea li' : function(){
  255. var $this = $(this);
  256. if($this.hasClass('disabled')){
  257. return;
  258. }
  259. _this.value.date = $this.data('day');
  260. //判断是否点击的是前一月或后一月的日期
  261. var add = 0;
  262. if($this.hasClass('nextdate')){
  263. add = 1;
  264. }
  265. else if($this.hasClass('prevdate')){
  266. add = -1;
  267. }
  268. if(add !== 0){
  269. _this._changeMonth(add, _this.value.date);
  270. }
  271. else{
  272. $this.addClass('current').siblings('.current').removeClass('current');
  273. }
  274. },
  275. '.md_ok' : function(){
  276. var monthValue = ~~_this.value.month + 1;
  277. if(monthValue < 10){
  278. monthValue = '0' + monthValue;
  279. }
  280. var dateValue = _this.value.date;
  281. if(dateValue === ''){
  282. dateValue = _this.value.date = 1;
  283. }
  284. if(dateValue < 10){
  285. dateValue = '0' + dateValue;
  286. }
  287. _this.input.val(_this.value.year + '-' + monthValue + '-' + dateValue);
  288. _this._hidePanel();
  289. },
  290. '.md_cancel' : function(){
  291. _this._hidePanel();
  292. }
  293. });
  294. }
  295. }
  296. mdater.init();
  297. }
  298. })(Zepto);