jquery.calendar.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. /**
  2. * calendar - jQuery EasyUI
  3. *
  4. * Copyright (c) 2009-2013 www.jeasyui.com. All rights reserved.
  5. *
  6. * Licensed under the GPL or commercial licenses
  7. * To use it on other terms please contact us: info@jeasyui.com
  8. * http://www.gnu.org/licenses/gpl.txt
  9. * http://www.jeasyui.com/license_commercial.php
  10. *
  11. */
  12. (function($){
  13. function setSize(target){
  14. var opts = $.data(target, 'calendar').options;
  15. var t = $(target);
  16. // if (opts.fit == true){
  17. // var p = t.parent();
  18. // opts.width = p.width();
  19. // opts.height = p.height();
  20. // }
  21. opts.fit ? $.extend(opts, t._fit()) : t._fit(false);
  22. var header = t.find('.calendar-header');
  23. t._outerWidth(opts.width);
  24. t._outerHeight(opts.height);
  25. t.find('.calendar-body')._outerHeight(t.height() - header._outerHeight());
  26. }
  27. function init(target){
  28. $(target).addClass('calendar').html(
  29. '<div class="calendar-header">' +
  30. '<div class="calendar-prevmonth"></div>' +
  31. '<div class="calendar-nextmonth"></div>' +
  32. '<div class="calendar-prevyear"></div>' +
  33. '<div class="calendar-nextyear"></div>' +
  34. '<div class="calendar-title">' +
  35. '<span>Aprial 2010</span>' +
  36. '</div>' +
  37. '</div>' +
  38. '<div class="calendar-body">' +
  39. '<div class="calendar-menu">' +
  40. '<div class="calendar-menu-year-inner">' +
  41. '<span class="calendar-menu-prev"></span>' +
  42. '<span><input class="calendar-menu-year" type="text"></input></span>' +
  43. '<span class="calendar-menu-next"></span>' +
  44. '</div>' +
  45. '<div class="calendar-menu-month-inner">' +
  46. '</div>' +
  47. '</div>' +
  48. '</div>'
  49. );
  50. $(target).find('.calendar-title span').hover(
  51. function(){$(this).addClass('calendar-menu-hover');},
  52. function(){$(this).removeClass('calendar-menu-hover');}
  53. ).click(function(){
  54. var menu = $(target).find('.calendar-menu');
  55. if (menu.is(':visible')){
  56. menu.hide();
  57. } else {
  58. showSelectMenus(target);
  59. }
  60. });
  61. $('.calendar-prevmonth,.calendar-nextmonth,.calendar-prevyear,.calendar-nextyear', target).hover(
  62. function(){$(this).addClass('calendar-nav-hover');},
  63. function(){$(this).removeClass('calendar-nav-hover');}
  64. );
  65. $(target).find('.calendar-nextmonth').click(function(){
  66. showMonth(target, 1);
  67. });
  68. $(target).find('.calendar-prevmonth').click(function(){
  69. showMonth(target, -1);
  70. });
  71. $(target).find('.calendar-nextyear').click(function(){
  72. showYear(target, 1);
  73. });
  74. $(target).find('.calendar-prevyear').click(function(){
  75. showYear(target, -1);
  76. });
  77. $(target).bind('_resize', function(){
  78. var opts = $.data(target, 'calendar').options;
  79. if (opts.fit == true){
  80. setSize(target);
  81. }
  82. return false;
  83. });
  84. }
  85. /**
  86. * show the calendar corresponding to the current month.
  87. */
  88. function showMonth(target, delta){
  89. var opts = $.data(target, 'calendar').options;
  90. opts.month += delta;
  91. if (opts.month > 12){
  92. opts.year++;
  93. opts.month = 1;
  94. } else if (opts.month < 1){
  95. opts.year--;
  96. opts.month = 12;
  97. }
  98. show(target);
  99. var menu = $(target).find('.calendar-menu-month-inner');
  100. menu.find('td.calendar-selected').removeClass('calendar-selected');
  101. menu.find('td:eq(' + (opts.month-1) + ')').addClass('calendar-selected');
  102. }
  103. /**
  104. * show the calendar corresponding to the current year.
  105. */
  106. function showYear(target, delta){
  107. var opts = $.data(target, 'calendar').options;
  108. opts.year += delta;
  109. show(target);
  110. var menu = $(target).find('.calendar-menu-year');
  111. menu.val(opts.year);
  112. }
  113. /**
  114. * show the select menu that can change year or month, if the menu is not be created then create it.
  115. */
  116. function showSelectMenus(target){
  117. var opts = $.data(target, 'calendar').options;
  118. $(target).find('.calendar-menu').show();
  119. if ($(target).find('.calendar-menu-month-inner').is(':empty')){
  120. $(target).find('.calendar-menu-month-inner').empty();
  121. var t = $('<table></table>').appendTo($(target).find('.calendar-menu-month-inner'));
  122. var idx = 0;
  123. for(var i=0; i<3; i++){
  124. var tr = $('<tr></tr>').appendTo(t);
  125. for(var j=0; j<4; j++){
  126. $('<td class="calendar-menu-month"></td>').html(opts.months[idx++]).attr('abbr',idx).appendTo(tr);
  127. }
  128. }
  129. $(target).find('.calendar-menu-prev,.calendar-menu-next').hover(
  130. function(){$(this).addClass('calendar-menu-hover');},
  131. function(){$(this).removeClass('calendar-menu-hover');}
  132. );
  133. $(target).find('.calendar-menu-next').click(function(){
  134. var y = $(target).find('.calendar-menu-year');
  135. if (!isNaN(y.val())){
  136. y.val(parseInt(y.val()) + 1);
  137. }
  138. });
  139. $(target).find('.calendar-menu-prev').click(function(){
  140. var y = $(target).find('.calendar-menu-year');
  141. if (!isNaN(y.val())){
  142. y.val(parseInt(y.val() - 1));
  143. }
  144. });
  145. $(target).find('.calendar-menu-year').keypress(function(e){
  146. if (e.keyCode == 13){
  147. setDate();
  148. }
  149. });
  150. $(target).find('.calendar-menu-month').hover(
  151. function(){$(this).addClass('calendar-menu-hover');},
  152. function(){$(this).removeClass('calendar-menu-hover');}
  153. ).click(function(){
  154. var menu = $(target).find('.calendar-menu');
  155. menu.find('.calendar-selected').removeClass('calendar-selected');
  156. $(this).addClass('calendar-selected');
  157. setDate();
  158. });
  159. }
  160. function setDate(){
  161. var menu = $(target).find('.calendar-menu');
  162. var year = menu.find('.calendar-menu-year').val();
  163. var month = menu.find('.calendar-selected').attr('abbr');
  164. if (!isNaN(year)){
  165. opts.year = parseInt(year);
  166. opts.month = parseInt(month);
  167. show(target);
  168. }
  169. menu.hide();
  170. }
  171. var body = $(target).find('.calendar-body');
  172. var sele = $(target).find('.calendar-menu');
  173. var seleYear = sele.find('.calendar-menu-year-inner');
  174. var seleMonth = sele.find('.calendar-menu-month-inner');
  175. seleYear.find('input').val(opts.year).focus();
  176. seleMonth.find('td.calendar-selected').removeClass('calendar-selected');
  177. seleMonth.find('td:eq('+(opts.month-1)+')').addClass('calendar-selected');
  178. sele._outerWidth(body._outerWidth());
  179. sele._outerHeight(body._outerHeight());
  180. seleMonth._outerHeight(sele.height() - seleYear._outerHeight());
  181. }
  182. /**
  183. * get weeks data.
  184. */
  185. function getWeeks(target, year, month){
  186. var opts = $.data(target, 'calendar').options;
  187. var dates = [];
  188. var lastDay = new Date(year, month, 0).getDate();
  189. for(var i=1; i<=lastDay; i++) dates.push([year,month,i]);
  190. // group date by week
  191. var weeks = [], week = [];
  192. // var memoDay = 0;
  193. var memoDay = -1;
  194. while(dates.length > 0){
  195. var date = dates.shift();
  196. week.push(date);
  197. var day = new Date(date[0],date[1]-1,date[2]).getDay();
  198. if (memoDay == day){
  199. day = 0;
  200. } else if (day == (opts.firstDay==0 ? 7 : opts.firstDay) - 1){
  201. weeks.push(week);
  202. week = [];
  203. }
  204. memoDay = day;
  205. }
  206. if (week.length){
  207. weeks.push(week);
  208. }
  209. var firstWeek = weeks[0];
  210. if (firstWeek.length < 7){
  211. while(firstWeek.length < 7){
  212. var firstDate = firstWeek[0];
  213. var date = new Date(firstDate[0],firstDate[1]-1,firstDate[2]-1)
  214. firstWeek.unshift([date.getFullYear(), date.getMonth()+1, date.getDate()]);
  215. }
  216. } else {
  217. var firstDate = firstWeek[0];
  218. var week = [];
  219. for(var i=1; i<=7; i++){
  220. var date = new Date(firstDate[0], firstDate[1]-1, firstDate[2]-i);
  221. week.unshift([date.getFullYear(), date.getMonth()+1, date.getDate()]);
  222. }
  223. weeks.unshift(week);
  224. }
  225. var lastWeek = weeks[weeks.length-1];
  226. while(lastWeek.length < 7){
  227. var lastDate = lastWeek[lastWeek.length-1];
  228. var date = new Date(lastDate[0], lastDate[1]-1, lastDate[2]+1);
  229. lastWeek.push([date.getFullYear(), date.getMonth()+1, date.getDate()]);
  230. }
  231. if (weeks.length < 6){
  232. var lastDate = lastWeek[lastWeek.length-1];
  233. var week = [];
  234. for(var i=1; i<=7; i++){
  235. var date = new Date(lastDate[0], lastDate[1]-1, lastDate[2]+i);
  236. week.push([date.getFullYear(), date.getMonth()+1, date.getDate()]);
  237. }
  238. weeks.push(week);
  239. }
  240. return weeks;
  241. }
  242. /**
  243. * show the calendar day.
  244. */
  245. function show(target){
  246. var opts = $.data(target, 'calendar').options;
  247. $(target).find('.calendar-title span').html(opts.months[opts.month-1] + ' ' + opts.year);
  248. var body = $(target).find('div.calendar-body');
  249. body.find('>table').remove();
  250. var t = $('<table cellspacing="0" cellpadding="0" border="0"><thead></thead><tbody></tbody></table>').prependTo(body);
  251. var tr = $('<tr></tr>').appendTo(t.find('thead'));
  252. for(var i=opts.firstDay; i<opts.weeks.length; i++){
  253. tr.append('<th>'+opts.weeks[i]+'</th>');
  254. }
  255. for(var i=0; i<opts.firstDay; i++){
  256. tr.append('<th>'+opts.weeks[i]+'</th>');
  257. }
  258. var weeks = getWeeks(target, opts.year, opts.month);
  259. for(var i=0; i<weeks.length; i++){
  260. var week = weeks[i];
  261. var tr = $('<tr></tr>').appendTo(t.find('tbody'));
  262. for(var j=0; j<week.length; j++){
  263. var day = week[j];
  264. $('<td class="calendar-day calendar-other-month"></td>').attr('abbr',day[0]+','+day[1]+','+day[2]).html(day[2]).appendTo(tr);
  265. }
  266. }
  267. t.find('td[abbr^="'+opts.year+','+opts.month+'"]').removeClass('calendar-other-month');
  268. var now = new Date();
  269. var today = now.getFullYear()+','+(now.getMonth()+1)+','+now.getDate();
  270. t.find('td[abbr="'+today+'"]').addClass('calendar-today');
  271. if (opts.current){
  272. t.find('.calendar-selected').removeClass('calendar-selected');
  273. var current = opts.current.getFullYear()+','+(opts.current.getMonth()+1)+','+opts.current.getDate();
  274. t.find('td[abbr="'+current+'"]').addClass('calendar-selected');
  275. }
  276. // calulate the saturday and sunday index
  277. var saIndex = 6 - opts.firstDay;
  278. var suIndex = saIndex + 1;
  279. if (saIndex >= 7) saIndex -= 7;
  280. if (suIndex >= 7) suIndex -= 7;
  281. t.find('tr').find('td:eq('+saIndex+')').addClass('calendar-saturday');
  282. t.find('tr').find('td:eq('+suIndex+')').addClass('calendar-sunday');
  283. t.find('td').hover(
  284. function(){$(this).addClass('calendar-hover');},
  285. function(){$(this).removeClass('calendar-hover');}
  286. ).click(function(){
  287. t.find('.calendar-selected').removeClass('calendar-selected');
  288. $(this).addClass('calendar-selected');
  289. var parts = $(this).attr('abbr').split(',');
  290. opts.current = new Date(parts[0], parseInt(parts[1])-1, parts[2]);
  291. opts.onSelect.call(target, opts.current);
  292. });
  293. }
  294. $.fn.calendar = function(options, param){
  295. if (typeof options == 'string'){
  296. return $.fn.calendar.methods[options](this, param);
  297. }
  298. options = options || {};
  299. return this.each(function(){
  300. var state = $.data(this, 'calendar');
  301. if (state){
  302. $.extend(state.options, options);
  303. } else {
  304. state = $.data(this, 'calendar', {
  305. options:$.extend({}, $.fn.calendar.defaults, $.fn.calendar.parseOptions(this), options)
  306. });
  307. init(this);
  308. }
  309. if (state.options.border == false){
  310. $(this).addClass('calendar-noborder');
  311. }
  312. setSize(this);
  313. show(this);
  314. $(this).find('div.calendar-menu').hide(); // hide the calendar menu
  315. });
  316. };
  317. $.fn.calendar.methods = {
  318. options: function(jq){
  319. return $.data(jq[0], 'calendar').options;
  320. },
  321. resize: function(jq){
  322. return jq.each(function(){
  323. setSize(this);
  324. });
  325. },
  326. moveTo: function(jq, date){
  327. return jq.each(function(){
  328. $(this).calendar({
  329. year: date.getFullYear(),
  330. month: date.getMonth()+1,
  331. current: date
  332. });
  333. });
  334. }
  335. };
  336. $.fn.calendar.parseOptions = function(target){
  337. var t = $(target);
  338. return $.extend({}, $.parser.parseOptions(target, [
  339. 'width','height',{firstDay:'number',fit:'boolean',border:'boolean'}
  340. ]));
  341. };
  342. $.fn.calendar.defaults = {
  343. width:180,
  344. height:180,
  345. fit:false,
  346. border:true,
  347. firstDay:0,
  348. weeks:['S','M','T','W','T','F','S'],
  349. months:['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
  350. year:new Date().getFullYear(),
  351. month:new Date().getMonth()+1,
  352. current:new Date(),
  353. onSelect: function(date){}
  354. };
  355. })(jQuery);