jquery.calendario.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. /**
  2. * jquery.calendario.js v1.0.0
  3. * http://www.codrops.com
  4. *
  5. * Licensed under the MIT license.
  6. * http://www.opensource.org/licenses/mit-license.php
  7. *
  8. * Copyright 2012, Codrops
  9. * http://www.codrops.com
  10. */
  11. ;( function( $, window, undefined ) {
  12. 'use strict';
  13. $.Calendario = function( options, element ) {
  14. this.$el = $( element );
  15. this._init( options );
  16. };
  17. // the options
  18. $.Calendario.defaults = {
  19. /*
  20. you can also pass:
  21. month : initialize calendar with this month (1-12). Default is today.
  22. year : initialize calendar with this year. Default is today.
  23. caldata : initial data/content for the calendar.
  24. caldata format:
  25. {
  26. 'MM-DD-YYYY' : 'HTML Content',
  27. 'MM-DD-YYYY' : 'HTML Content',
  28. 'MM-DD-YYYY' : 'HTML Content'
  29. ...
  30. }
  31. */
  32. weeks : [ '日', '一', '二', '三', '四', '五', '六' ],
  33. weekabbrs : [ '日', '一', '二', '三', '四', '五', '六'],
  34. months : [ '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12' ],
  35. monthabbrs : [ '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
  36. // choose between values in options.weeks or options.weekabbrs
  37. displayWeekAbbr : true,
  38. // choose between values in options.months or options.monthabbrs
  39. displayMonthAbbr : true,
  40. // left most day in the calendar
  41. // 0 - Sunday, 1 - Monday, ... , 6 - Saturday
  42. startIn : 0,
  43. onDayClick : function( $el, $content, dateProperties ) { return false; }
  44. };
  45. $.Calendario.prototype = {
  46. _init : function( options ) {
  47. // options
  48. this.options = $.extend( true, {}, $.Calendario.defaults, options );
  49. this.today = new Date();
  50. this.month = ( isNaN( this.options.month ) || this.options.month == null) ? this.today.getMonth() : this.options.month - 1;
  51. this.year = ( isNaN( this.options.year ) || this.options.year == null) ? this.today.getFullYear() : this.options.year;
  52. this.caldata = this.options.caldata || {};
  53. this._generateTemplate();
  54. this._initEvents();
  55. },
  56. _initEvents : function() {
  57. var self = this;
  58. this.$el.on( 'click.calendario', 'div.fc-row > div', function() {
  59. var $cell = $( this ),
  60. idx = $cell.index(),
  61. $content = $cell.children( 'div' ),
  62. dateProp = {
  63. day : $cell.children( 'span.fc-date' ).text(),
  64. month : self.month + 1,
  65. monthname : self.options.displayMonthAbbr ? self.options.monthabbrs[ self.month ] : self.options.months[ self.month ],
  66. year : self.year,
  67. weekday : idx + self.options.startIn,
  68. weekdayname : self.options.weeks[ idx + self.options.startIn ]
  69. };
  70. if( dateProp.day ) {
  71. self.options.onDayClick( $cell, $content, dateProp );
  72. }
  73. } );
  74. },
  75. // Calendar logic based on http://jszen.blogspot.pt/2007/03/how-to-build-simple-calendar-with.html
  76. _generateTemplate : function( callback ) {
  77. var head = this._getHead(),
  78. body = this._getBody(),
  79. rowClass;
  80. switch( this.rowTotal ) {
  81. case 4 : rowClass = 'fc-four-rows'; break;
  82. case 5 : rowClass = 'fc-five-rows'; break;
  83. case 6 : rowClass = 'fc-six-rows'; break;
  84. }
  85. this.$cal = $( '<div class="fc-calendar ' + rowClass + '">' ).append( head, body );
  86. this.$el.find( 'div.fc-calendar' ).remove().end().append( this.$cal );
  87. if( callback ) { callback.call(); }
  88. },
  89. _getHead : function() {
  90. var html = '<div class="fc-head">';
  91. for ( var i = 0; i <= 6; i++ ) {
  92. var pos = i + this.options.startIn,
  93. j = pos > 6 ? pos - 6 - 1 : pos;
  94. html += '<div>';
  95. html += this.options.displayWeekAbbr ? this.options.weekabbrs[ j ] : this.options.weeks[ j ];
  96. html += '</div>';
  97. }
  98. html += '</div>';
  99. return html;
  100. },
  101. _getBody : function() {
  102. var d = new Date( this.year, this.month + 1, 0 ),
  103. // number of days in the month
  104. monthLength = d.getDate(),
  105. firstDay = new Date( this.year, this.month, 1 );
  106. // day of the week
  107. this.startingDay = firstDay.getDay();
  108. var html = '<div class="fc-body"><div class="fc-row">',
  109. // fill in the days
  110. day = 1;
  111. // this loop is for weeks (rows)
  112. for ( var i = 0; i < 7; i++ ) {
  113. // this loop is for weekdays (cells)
  114. for ( var j = 0; j <= 6; j++ ) {
  115. var pos = this.startingDay - this.options.startIn,
  116. p = pos < 0 ? 6 + pos + 1 : pos,
  117. inner = '',
  118. today = this.month === this.today.getMonth() && this.year === this.today.getFullYear() && day === this.today.getDate(),
  119. content = '';
  120. if ( day <= monthLength && ( i > 0 || j >= p ) ) {
  121. inner += '<span class="fc-date">' + day + '</span><span class="fc-weekday">' + this.options.weekabbrs[ j + this.options.startIn > 6 ? j + this.options.startIn - 6 - 1 : j + this.options.startIn ] + '</span>';
  122. // this day is:
  123. var strdate = ( this.month + 1 < 10 ? '0' + ( this.month + 1 ) : this.month + 1 ) + '-' + ( day < 10 ? '0' + day : day ) + '-' + this.year,
  124. dayData = this.caldata[ strdate ];
  125. if( dayData ) {
  126. content = dayData;
  127. }
  128. if( content !== '' ) {
  129. inner += '<div style="position: absolute; top:0px;right:0px; width:16px;height:16px;background:url(My/Calendario/note.png);line-height:16px;overflow:hidden; color:#fff;text-align: center;font-size: 12px; font-weight:bold;">' + content + '</div>';
  130. }
  131. ++day;
  132. }
  133. else {
  134. today = false;
  135. }
  136. var cellClasses = today ? 'fc-today ' : '';
  137. if( content !== '' ) {
  138. cellClasses += 'fc-content';
  139. }
  140. html += cellClasses !== '' ? '<div class="' + cellClasses + '">' : '<div>';
  141. html += inner;
  142. html += '</div>';
  143. }
  144. // stop making rows if we've run out of days
  145. if (day > monthLength) {
  146. this.rowTotal = i + 1;
  147. break;
  148. }
  149. else {
  150. html += '</div><div class="fc-row">';
  151. }
  152. }
  153. html += '</div></div>';
  154. return html;
  155. },
  156. // based on http://stackoverflow.com/a/8390325/989439
  157. _isValidDate : function( date ) {
  158. date = date.replace(/-/gi,'');
  159. var month = parseInt( date.substring( 0, 2 ), 10 ),
  160. day = parseInt( date.substring( 2, 4 ), 10 ),
  161. year = parseInt( date.substring( 4, 8 ), 10 );
  162. if( ( month < 1 ) || ( month > 12 ) ) {
  163. return false;
  164. }
  165. else if( ( day < 1 ) || ( day > 31 ) ) {
  166. return false;
  167. }
  168. else if( ( ( month == 4 ) || ( month == 6 ) || ( month == 9 ) || ( month == 11 ) ) && ( day > 30 ) ) {
  169. return false;
  170. }
  171. else if( ( month == 2 ) && ( ( ( year % 400 ) == 0) || ( ( year % 4 ) == 0 ) ) && ( ( year % 100 ) != 0 ) && ( day > 29 ) ) {
  172. return false;
  173. }
  174. else if( ( month == 2 ) && ( ( year % 100 ) == 0 ) && ( day > 29 ) ) {
  175. return false;
  176. }
  177. return {
  178. day : day,
  179. month : month,
  180. year : year
  181. };
  182. },
  183. _move : function( period, dir, callback ) {
  184. if( dir === 'previous' ) {
  185. if( period === 'month' ) {
  186. this.year = this.month > 0 ? this.year : --this.year;
  187. this.month = this.month > 0 ? --this.month : 11;
  188. }
  189. else if( period === 'year' ) {
  190. this.year = --this.year;
  191. }
  192. }
  193. else if( dir === 'next' ) {
  194. if( period === 'month' ) {
  195. this.year = this.month < 11 ? this.year : ++this.year;
  196. this.month = this.month < 11 ? ++this.month : 0;
  197. }
  198. else if( period === 'year' ) {
  199. this.year = ++this.year;
  200. }
  201. }
  202. this._generateTemplate( callback );
  203. },
  204. /*************************
  205. ******PUBLIC METHODS *****
  206. **************************/
  207. getYear : function() {
  208. return this.year;
  209. },
  210. getMonth : function() {
  211. return this.month + 1;
  212. },
  213. getDay : function() {
  214. return this.today.getDate();
  215. },
  216. getWeek : function() {
  217. var weeks = [ '星期天', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六' ];
  218. return weeks[Math.floor( ( this.today.getDate() + this.startingDay - 1 - this.options.startIn ) % 7 )];
  219. },
  220. getMonthName : function() {
  221. return this.options.displayMonthAbbr ? this.options.monthabbrs[ this.month ] : this.options.months[ this.month ];
  222. },
  223. // gets the cell's content div associated to a day of the current displayed month
  224. // day : 1 - [28||29||30||31]
  225. getCell : function( day ) {
  226. var row = Math.floor( ( day + this.startingDay - this.options.startIn ) / 7 ),
  227. pos = day + this.startingDay - this.options.startIn - ( row * 7 ) - 1;
  228. return this.$cal.find( 'div.fc-body' ).children( 'div.fc-row' ).eq( row ).children( 'div' ).eq( pos ).children( 'div' );
  229. },
  230. setData : function( caldata ) {
  231. caldata = caldata || {};
  232. $.extend( this.caldata, caldata );
  233. this._generateTemplate();
  234. },
  235. // goes to today's month/year
  236. gotoNow : function( callback ) {
  237. this.month = this.today.getMonth();
  238. this.year = this.today.getFullYear();
  239. this._generateTemplate( callback );
  240. },
  241. // goes to month/year
  242. goto : function( month, year, callback ) {
  243. this.month = month;
  244. this.year = year;
  245. this._generateTemplate( callback );
  246. },
  247. gotoPreviousMonth : function( callback ) {
  248. this._move( 'month', 'previous', callback );
  249. },
  250. gotoPreviousYear : function( callback ) {
  251. this._move( 'year', 'previous', callback );
  252. },
  253. gotoNextMonth : function( callback ) {
  254. this._move( 'month', 'next', callback );
  255. },
  256. gotoNextYear : function( callback ) {
  257. this._move( 'year', 'next', callback );
  258. }
  259. };
  260. var logError = function( message ) {
  261. if ( window.console ) {
  262. window.console.error( message );
  263. }
  264. };
  265. $.fn.calendario = function( options ) {
  266. var instance = $.data( this, 'calendario' );
  267. if ( typeof options === 'string' ) {
  268. var args = Array.prototype.slice.call( arguments, 1 );
  269. this.each(function() {
  270. if ( !instance ) {
  271. logError( "cannot call methods on calendario prior to initialization; " +
  272. "attempted to call method '" + options + "'" );
  273. return;
  274. }
  275. if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) {
  276. logError( "no such method '" + options + "' for calendario instance" );
  277. return;
  278. }
  279. instance[ options ].apply( instance, args );
  280. });
  281. }
  282. else {
  283. this.each(function() {
  284. if ( instance ) {
  285. instance._init();
  286. }
  287. else {
  288. instance = $.data( this, 'calendario', new $.Calendario( options, this ) );
  289. }
  290. });
  291. }
  292. return instance;
  293. };
  294. } )( jQuery, window );