calendar.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793
  1. (function (root, factory) {
  2. if (typeof define === 'function' && define.amd) {
  3. define('calendar', ['jquery'], factory);
  4. } else if (typeof exports === 'object') {
  5. module.exports = factory(require('jquery'));
  6. } else {
  7. factory(root.jQuery);
  8. }
  9. }(this, function ($) {
  10. // default config
  11. var defaults = {
  12. // 宽度
  13. width: 280,
  14. // 高度, 不包含头部,头部固定高度
  15. height: 280,
  16. zIndex: 1,
  17. // selector or element
  18. // 设置触发显示的元素,为null时默认显示
  19. trigger: null,
  20. // 偏移位置,可设正负值
  21. // trigger 设置时生效
  22. offset: [0, 1],
  23. // 自定义类,用于重写样式
  24. customClass: '',
  25. // 显示视图
  26. // 可选:date, month
  27. view: 'date',
  28. // 默认日期为当前日期
  29. date: new Date(),
  30. format: 'yyyy年mm月dd',
  31. // 一周的第一天
  32. // 0表示周日,依次类推
  33. startWeek: 0,
  34. // 星期格式
  35. weekArray: ['日', '一', '二', '三', '四', '五', '六'],
  36. // 设置选择范围
  37. // 格式:[开始日期, 结束日期]
  38. // 开始日期为空,则无上限;结束日期为空,则无下限
  39. // 如设置2015年11月23日以前不可选:[new Date(), null] or ['2015/11/23']
  40. selectedRang: null,
  41. // 日期关联数据 [{ date: string, value: object }, ... ]
  42. // 日期格式与 format 一致
  43. // 如 [ {date: '2015/11/23', value: '面试'} ]
  44. data: null,
  45. // 展示关联数据
  46. // 格式化参数:{m}视图,{d}日期,{v}value
  47. // 设置 false 表示不显示
  48. label: '{d}\n{v}',
  49. // 切换字符
  50. prev: '<',
  51. next: '>',
  52. // 切换视图
  53. // 参数:view, y, m
  54. viewChange: $.noop,
  55. // view: 视图
  56. // date: 不同视图返回不同的值
  57. // value: 日期关联数据
  58. onSelected: function (view, date, value) {
  59. // body...
  60. },
  61. // 参数同上
  62. onMouseenter: $.noop,
  63. onClose: $.noop
  64. },
  65. // static variable
  66. ACTION_NAMESPACE = 'data-calendar-',
  67. DISPLAY_VD = '[' + ACTION_NAMESPACE + 'display-date]',
  68. DISPLAY_VM = '[' + ACTION_NAMESPACE + 'display-month]',
  69. ARROW_DATE = '[' + ACTION_NAMESPACE + 'arrow-date]',
  70. ARROW_MONTH = '[' + ACTION_NAMESPACE + 'arrow-month]',
  71. ITEM_DAY = ACTION_NAMESPACE + 'day',
  72. ITEM_MONTH = ACTION_NAMESPACE + 'month',
  73. DISABLED = 'disabled',
  74. MARK_DATA = 'markData',
  75. VIEW_CLASS = {
  76. date: 'calendar-d',
  77. month: 'calendar-m'
  78. },
  79. OLD_DAY_CLASS = 'old',
  80. NEW_DAY_CLASS = 'new-day',
  81. TODAY_CLASS = 'now',
  82. SELECT_CLASS = 'selected',
  83. MARK_DAY_HTML = '<i class="dot"></i>',
  84. DATE_DIS_TPL = '{year}年<span class="m">{month}月</span>',
  85. ITEM_STYLE = 'style="width:{w}px;height:{h}px;line-height:{h}px"',
  86. WEEK_ITEM_TPL = '<li ' + ITEM_STYLE + '>{wk}</li>',
  87. DAY_ITEM_TPL = '<li ' + ITEM_STYLE + ' class="{class}" {action}>{value}</li>',
  88. MONTH_ITEM_TPL = '<li ' + ITEM_STYLE + ' ' + ITEM_MONTH + '>{m}月</li>',
  89. TEMPLATE = [
  90. '<div class="calendar-inner">',
  91. '<div class="calendar-views">',
  92. '<div class="view view-date">',
  93. '<div class="calendar-hd">',
  94. '<div class="calendar-arrow calendar-arrow-left">',
  95. '<span class="prev" title="上一月" data-calendar-arrow-date>{prev}</span>',
  96. /* '<span class="next" title="下一月" data-calendar-arrow-date>{next}</span>',*/
  97. '</div>',
  98. '<a href="javascript:;" data-calendar-display-date class="calendar-display calendar-display-center">',
  99. '{yyyy}-年<span class="m">{mm}月</span>',
  100. '</a>',
  101. '<div class="calendar-arrow calendar-arrow-right">',
  102. /* '<span class="prev" title="上一月" data-calendar-arrow-date>{prev}</span>',*/
  103. '<span class="next" title="下一月" data-calendar-arrow-date>{next}</span>',
  104. '</div>',
  105. '</div>',
  106. '<div class="calendar-ct">',
  107. '<ol class="week">{week}</ol>',
  108. '<ul class="date-items"></ul>',
  109. '</div>',
  110. '</div>',
  111. '<div class="view view-month">',
  112. '<div class="calendar-hd">',
  113. '<div class="calendar-arrow calendar-arrow-left">',
  114. '<span class="prev" title="上一年" data-calendar-arrow-month>{prev}</span>',
  115. /* '<span class="next" title="下一年" data-calendar-arrow-month>{next}</span>',*/
  116. '</div>',
  117. '<a href="javascript:;" data-calendar-display-month class="calendar-display calendar-display-center">{yyyy}</a>',
  118. '<div class="calendar-arrow calendar-arrow-right">',
  119. /* '<span class="prev" title="上一年" data-calendar-arrow-month>{prev}</span>',*/
  120. '<span class="next" title="下一年" data-calendar-arrow-month>{next}</span>',
  121. '</div>',
  122. '</div>',
  123. '<ol class="calendar-ct month-items">{month}</ol>',
  124. '</div>',
  125. '</div>',
  126. '</div>',
  127. '<div class="calendar-label"><p>HelloWorld</p><i></i></div>'
  128. ],
  129. OS = Object.prototype.toString;
  130. // utils
  131. function isDate(obj) {
  132. return OS.call(obj) === '[object Date]';
  133. }
  134. function isString(obj) {
  135. return OS.call(obj) === '[object String]';
  136. }
  137. function getClass(el) {
  138. return el.getAttribute('class') || el.getAttribute('className');
  139. }
  140. // extension methods
  141. String.prototype.repeat = function (data) {
  142. return this.replace(/\{\w+\}/g, function (str) {
  143. var prop = str.replace(/\{|\}/g, '');
  144. return data[prop] || '';
  145. });
  146. }
  147. String.prototype.toDate = function () {
  148. var dt = new Date(),
  149. dot = this.replace(/\d/g, '').charAt(0),
  150. arr = this.split(dot);
  151. dt.setFullYear(arr[0]);
  152. dt.setMonth(arr[1] - 1);
  153. dt.setDate(arr[2]);
  154. return dt;
  155. }
  156. Date.prototype.format = function (exp) {
  157. var y = this.getFullYear(),
  158. m = this.getMonth() + 1,
  159. d = this.getDate();
  160. return exp.replace('yyyy', y).replace('mm', m).replace('dd', d);
  161. }
  162. Date.prototype.isSame = function (y, m, d) {
  163. if (isDate(y)) {
  164. var dt = y;
  165. y = dt.getFullYear();
  166. m = dt.getMonth() + 1;
  167. d = dt.getDate();
  168. }
  169. return this.getFullYear() === y && this.getMonth() + 1 === m && this.getDate() === d;
  170. }
  171. Date.prototype.add = function (n) {
  172. this.setDate(this.getDate() + n);
  173. }
  174. Date.prototype.minus = function (n) {
  175. this.setDate(this.getDate() - n);
  176. }
  177. Date.prototype.clearTime = function (n) {
  178. this.setHours(0);
  179. this.setSeconds(0);
  180. this.setMinutes(0);
  181. this.setMilliseconds(0);
  182. return this;
  183. }
  184. Date.isLeap = function (y) {
  185. return (y % 100 !== 0 && y % 4 === 0) || (y % 400 === 0);
  186. }
  187. Date.getDaysNum = function (y, m) {
  188. var num = 31;
  189. switch (m) {
  190. case 2:
  191. num = this.isLeap(y) ? 29 : 28;
  192. break;
  193. case 4:
  194. case 6:
  195. case 9:
  196. case 11:
  197. num = 30;
  198. break;
  199. }
  200. return num;
  201. }
  202. Date.getSiblingsMonth = function (y, m, n) {
  203. var d = new Date(y, m - 1);
  204. d.setMonth(m - 1 + n);
  205. return {
  206. y: d.getFullYear(),
  207. m: d.getMonth() + 1
  208. };
  209. }
  210. Date.getPrevMonth = function (y, m, n) {
  211. return this.getSiblingsMonth(y, m, 0 - (n || 1));
  212. }
  213. Date.getNextMonth = function (y, m, n) {
  214. return this.getSiblingsMonth(y, m, n || 1);
  215. }
  216. Date.tryParse = function (obj) {
  217. if (!obj) {
  218. return obj;
  219. }
  220. return isDate(obj) ? obj : obj.toDate();
  221. }
  222. // Calendar class
  223. function Calendar(element, options) {
  224. this.$element = $(element);
  225. this.options = $.extend({}, $.fn.calendar.defaults, options);
  226. this.$element.addClass('calendar ' + this.options.customClass);
  227. this.width = this.options.width;
  228. this.height = this.options.height;
  229. this.date = this.options.date;
  230. this.selectedRang = this.options.selectedRang;
  231. this.data = this.options.data;
  232. this.init();
  233. }
  234. Calendar.prototype = {
  235. constructor: Calendar,
  236. getDayAction: function (day) {
  237. var action = ITEM_DAY;
  238. if (this.selectedRang) {
  239. var start = Date.tryParse(this.selectedRang[0]),
  240. end = Date.tryParse(this.selectedRang[1]);
  241. if ((start && day < start.clearTime()) || (end && day > end.clearTime())) {
  242. action = DISABLED;
  243. }
  244. }
  245. return action;
  246. },
  247. getDayData: function (day) {
  248. var ret, data = this.data;
  249. if (data) {
  250. for (var i = 0, len = data.length; i < len; i++) {
  251. var item = data[i];
  252. if (day.isSame(item.date.toDate())) {
  253. ret = item.value;
  254. }
  255. }
  256. }
  257. return ret;
  258. },
  259. getDayItem: function (y, m, d, f) {
  260. var dt = this.date,
  261. idt = new Date(y, m - 1, d),
  262. data = {
  263. w: this.width / 7,
  264. h: this.height / 7,
  265. value: d
  266. },
  267. markData,
  268. $item;
  269. var selected = dt.isSame(y, m, d) ? SELECT_CLASS : '';
  270. if (f === 1) {
  271. data['class'] = OLD_DAY_CLASS;
  272. } else if (f === 3) {
  273. data['class'] = NEW_DAY_CLASS;
  274. } else {
  275. data['class'] = '';
  276. }
  277. if (dt.isSame(y, m, d)) {
  278. data['class'] += ' ' + TODAY_CLASS;
  279. }
  280. data.action = this.getDayAction(idt);
  281. markData = this.getDayData(idt);
  282. $item = $(DAY_ITEM_TPL.repeat(data));
  283. if (markData) {
  284. $item.data(MARK_DATA, markData);
  285. $item.html(d + MARK_DAY_HTML);
  286. $item.addClass("markDay");
  287. }
  288. return $item;
  289. },
  290. getDaysHtml: function (y, m) {
  291. var year, month, firstWeek, daysNum, prevM, prevDiff,
  292. dt = this.date,
  293. $days = $('<ol class="days"></ol>');
  294. if (isDate(y)) {
  295. year = y.getFullYear();
  296. month = y.getMonth() + 1;
  297. } else {
  298. year = Number(y);
  299. month = Number(m);
  300. }
  301. firstWeek = new Date(year, month - 1, 1).getDay() || 7;
  302. prevDiff = firstWeek - this.options.startWeek;
  303. daysNum = Date.getDaysNum(year, month);
  304. prevM = Date.getPrevMonth(year, month);
  305. prevDaysNum = Date.getDaysNum(year, prevM.m);
  306. nextM = Date.getNextMonth(year, month);
  307. // month flag
  308. var PREV_FLAG = 1,
  309. CURR_FLAG = 2,
  310. NEXT_FLAG = 3,
  311. count = 0;
  312. for (var p = prevDaysNum - prevDiff + 1; p <= prevDaysNum; p++, count++) {
  313. $days.append(this.getDayItem(prevM.y, prevM.m, p, PREV_FLAG));
  314. }
  315. for (var c = 1; c <= daysNum; c++, count++) {
  316. $days.append(this.getDayItem(year, month, c, CURR_FLAG));
  317. }
  318. for (var n = 1, nl = 42 - count; n <= nl; n++) {
  319. $days.append(this.getDayItem(nextM.y, nextM.m, n, NEXT_FLAG));
  320. }
  321. return $('<li></li>').width(this.options.width).append($days);
  322. },
  323. getWeekHtml: function () {
  324. var week = [],
  325. weekArray = this.options.weekArray,
  326. start = this.options.startWeek,
  327. len = weekArray.length,
  328. w = this.width / 7,
  329. h = this.height / 7;
  330. for (var i = start; i < len; i++) {
  331. week.push(WEEK_ITEM_TPL.repeat({
  332. w: w,
  333. h: h,
  334. wk: weekArray[i]
  335. }));
  336. }
  337. for (var j = 0; j < start; j++) {
  338. week.push(WEEK_ITEM_TPL.repeat({
  339. w: w,
  340. h: h,
  341. wk: weekArray[j]
  342. }));
  343. }
  344. return week.join('');
  345. },
  346. getMonthHtml: function () {
  347. var month = [],
  348. w = this.width / 4,
  349. h = this.height / 4,
  350. i = 1;
  351. for (; i < 13; i++) {
  352. month.push(MONTH_ITEM_TPL.repeat({
  353. w: w,
  354. h: h,
  355. m: i
  356. }));
  357. }
  358. return month.join('');
  359. },
  360. setMonthAction: function (y) {
  361. var m = this.date.getMonth() + 1;
  362. this.$monthItems.children().removeClass(TODAY_CLASS);
  363. if (y === this.date.getFullYear()) {
  364. this.$monthItems.children().eq(m - 1).addClass(TODAY_CLASS);
  365. }
  366. },
  367. fillStatic: function () {
  368. var staticData = {
  369. prev: this.options.prev,
  370. next: this.options.next,
  371. week: this.getWeekHtml(),
  372. month: this.getMonthHtml()
  373. };
  374. this.$element.html(TEMPLATE.join('').repeat(staticData));
  375. },
  376. updateDisDate: function (y, m) {
  377. this.$disDate.html(DATE_DIS_TPL.repeat({
  378. year: y,
  379. month: m
  380. }));
  381. },
  382. updateDisMonth: function (y) {
  383. this.$disMonth.html(y);
  384. },
  385. fillDateItems: function (y, m) {
  386. var ma = [
  387. Date.getPrevMonth(y, m), {
  388. y: y,
  389. m: m
  390. },
  391. Date.getNextMonth(y, m)
  392. ];
  393. this.$dateItems.html('');
  394. for (var i = 0; i < 3; i++) {
  395. var $item = this.getDaysHtml(ma[i].y, ma[i].m);
  396. this.$dateItems.append($item);
  397. }
  398. },
  399. hide: function (view, date, data) {
  400. this.$trigger.val(date.format(this.options.format));
  401. this.options.onClose.call(this, view, date, data);
  402. this.$element.hide();
  403. },
  404. trigger: function () {
  405. this.$trigger = this.options.trigger instanceof $ ? this.options.trigger : $(this.options.trigger);
  406. var _this = this,
  407. $this = _this.$element,
  408. post = _this.$trigger.offset(),
  409. offs = _this.options.offset;
  410. $this.addClass('calendar-modal').css({
  411. left: (post.left + offs[0]) + 'px',
  412. top: (post.top + _this.$trigger.outerHeight() + offs[1]) + 'px',
  413. zIndex: _this.options.zIndex
  414. });
  415. _this.$trigger.click(function () {
  416. $this.show();
  417. });
  418. $(document).click(function (e) {
  419. if (_this.$trigger[0] != e.target && !$.contains($this[0], e.target)) {
  420. $this.hide();
  421. }
  422. });
  423. },
  424. render: function () {
  425. this.$week = this.$element.find('.week');
  426. this.$dateItems = this.$element.find('.date-items');
  427. this.$monthItems = this.$element.find('.month-items');
  428. this.$label = this.$element.find('.calendar-label');
  429. this.$disDate = this.$element.find(DISPLAY_VD);
  430. this.$disMonth = this.$element.find(DISPLAY_VM);
  431. var y = this.date.getFullYear(),
  432. m = this.date.getMonth() + 1;
  433. this.updateDisDate(y, m);
  434. this.updateMonthView(y);
  435. this.fillDateItems(y, m);
  436. this.options.trigger && this.trigger();
  437. },
  438. setView: function (view) {
  439. this.$element.removeClass(VIEW_CLASS.date + ' ' + VIEW_CLASS.month)
  440. .addClass(VIEW_CLASS[view]);
  441. this.view = view;
  442. },
  443. updateDateView: function (y, m, dirc, cb) {
  444. m = m || this.date.getMonth() + 1;
  445. var _this = this,
  446. $dis = this.$dateItems,
  447. exec = {
  448. prev: function () {
  449. var pm = Date.getPrevMonth(y, m),
  450. ppm = Date.getPrevMonth(y, m, 2),
  451. $prevItem = _this.getDaysHtml(ppm.y, ppm.m);
  452. m = pm.m;
  453. y = pm.y;
  454. $dis.animate({
  455. marginLeft: 0
  456. }, 300, 'swing', function () {
  457. $dis.children(':last').remove();
  458. $dis.prepend($prevItem).css('margin-left', '-100%');
  459. $.isFunction(cb) && cb.call(_this);
  460. });
  461. },
  462. next: function () {
  463. var nm = Date.getNextMonth(y, m),
  464. nnm = Date.getNextMonth(y, m, 2),
  465. $nextItem = _this.getDaysHtml(nnm.y, nnm.m);
  466. m = nm.m;
  467. y = nm.y;
  468. $dis.animate({
  469. marginLeft: '-200%'
  470. }, 300, 'swing', function () {
  471. $dis.children(':first').remove();
  472. $dis.append($nextItem).css('margin-left', '-100%');
  473. $.isFunction(cb) && cb.call(_this);
  474. });
  475. }
  476. };
  477. if (dirc) {
  478. exec[dirc]();
  479. } else {
  480. this.fillDateItems(y, m);
  481. }
  482. this.updateDisDate(y, m);
  483. this.setView('date');
  484. return {
  485. y: y,
  486. m: m
  487. };
  488. },
  489. updateMonthView: function (y) {
  490. this.updateDisMonth(y);
  491. this.setMonthAction(y);
  492. this.setView('month');
  493. },
  494. getDisDateValue: function () {
  495. var arr = this.$disDate.html().split('年'),
  496. y = Number(arr[0]),
  497. m = Number(arr[1].match(/\d{1,2}/)[0]);
  498. return [y, m];
  499. },
  500. selectedDay: function (d, type) {
  501. var arr = this.getDisDateValue(),
  502. y = arr[0],
  503. m = arr[1],
  504. toggleClass = function () {
  505. this.$dateItems.children(':eq(1)')
  506. .find('[' + ITEM_DAY + ']:not(.' + NEW_DAY_CLASS + ', .' + OLD_DAY_CLASS + ')')
  507. .removeClass(SELECT_CLASS)
  508. .filter(function (index) {
  509. return parseInt(this.innerHTML) === d;
  510. }).addClass(SELECT_CLASS);
  511. };
  512. if (type) {
  513. var ret = this.updateDateView(y, m, {
  514. 'old': 'prev',
  515. 'new': 'next'
  516. }[type], toggleClass);
  517. y = ret.y;
  518. m = ret.m;
  519. this.options.viewChange('date', y, m);
  520. } else {
  521. toggleClass.call(this);
  522. }
  523. return new Date(y, m - 1, d);
  524. },
  525. showLabel: function (event, view, date, data) {
  526. var $lbl = this.$label;
  527. $lbl.find('p').html(this.options.label.repeat({
  528. m: view,
  529. d: date.format(this.options.format),
  530. v: data
  531. }).replace(/\n/g, '<br>'));
  532. var w = $lbl.outerWidth(),
  533. h = $lbl.outerHeight();
  534. $lbl.css({
  535. left: (event.pageX - w / 2) + 'px',
  536. top: (event.pageY - h - 20) + 'px'
  537. }).show();
  538. },
  539. hasLabel: function () {
  540. if (this.options.label) {
  541. $('body').append(this.$label);
  542. return true;
  543. }
  544. return false;
  545. },
  546. event: function () {
  547. var _this = this,
  548. vc = _this.options.viewChange;
  549. // view change
  550. _this.$element.on('click', DISPLAY_VD, function () {
  551. var arr = _this.getDisDateValue();
  552. _this.updateMonthView(arr[0], arr[1]);
  553. vc('month', arr[0], arr[1]);
  554. }).on('click', DISPLAY_VM, function () {
  555. var y = this.innerHTML;
  556. _this.updateDateView(y);
  557. vc('date', y);
  558. });
  559. // arrow
  560. _this.$element.on('click', ARROW_DATE, function () {
  561. var arr = _this.getDisDateValue(),
  562. type = getClass(this),
  563. y = arr[0],
  564. m = arr[1];
  565. var d = _this.updateDateView(y, m, type, function () {
  566. vc('date', d.y, d.m);
  567. });
  568. }).on('click', ARROW_MONTH, function () {
  569. var y = Number(_this.$disMonth.html()),
  570. type = getClass(this);
  571. y = type === 'prev' ? y - 1 : y + 1;
  572. _this.updateMonthView(y);
  573. vc('month', y);
  574. });
  575. // selected
  576. _this.$element.on('click', '[' + ITEM_DAY + ']', function () {
  577. var d = parseInt(this.innerHTML),
  578. cls = getClass(this),
  579. type = /new|old/.test(cls) ? cls.match(/new|old/)[0] : '';
  580. var day = _this.selectedDay(d, type);
  581. _this.options.onSelected.call(this, 'date', day, $(this).data(MARK_DATA));
  582. _this.$trigger && _this.hide('date', day, $(this).data(MARK_DATA));
  583. }).on('click', '[' + ITEM_MONTH + ']', function () {
  584. var y = Number(_this.$disMonth.html()),
  585. m = parseInt(this.innerHTML);
  586. _this.updateDateView(y, m);
  587. vc('date', y, m);
  588. _this.options.onSelected.call(this, 'month', new Date(y, m - 1));
  589. });
  590. // hover
  591. _this.$element.on('mouseenter', '[' + ITEM_DAY + ']', function (e) {
  592. var arr = _this.getDisDateValue(),
  593. day = new Date(arr[0], arr[1] - 1, parseInt(this.innerHTML));
  594. if (_this.hasLabel && $(this).data(MARK_DATA)) {
  595. $('body').append(_this.$label);
  596. _this.showLabel(e, 'date', day, $(this).data(MARK_DATA));
  597. }
  598. _this.options.onMouseenter.call(this, 'date', day, $(this).data(MARK_DATA));
  599. }).on('mouseleave', '[' + ITEM_DAY + ']', function () {
  600. _this.$label.hide();
  601. });
  602. },
  603. resize: function () {
  604. var w = this.width,
  605. h = this.height,
  606. hdH = this.$element.find('.calendar-hd').outerHeight();
  607. this.$element.width(w).height(h + hdH)
  608. .find('.calendar-inner, .view')
  609. .css('width', w + 'px');
  610. this.$element.find('.calendar-ct').width(w).height(h);
  611. },
  612. init: function () {
  613. this.fillStatic();
  614. this.resize();
  615. this.render();
  616. this.view = this.options.view;
  617. this.setView(this.view);
  618. this.event();
  619. },
  620. setData: function (data) {
  621. this.data = data;
  622. if (this.view === 'date') {
  623. var d = this.getDisDateValue();
  624. this.fillDateItems(d[0], d[1]);
  625. } else if (this.view === 'month') {
  626. this.updateMonthView(this.$disMonth.html());
  627. }
  628. },
  629. methods: function (name, args) {
  630. if (OS.call(this[name]) === '[object Function]') {
  631. return this[name].apply(this, args);
  632. }
  633. }
  634. };
  635. $.fn.calendar = function (options) {
  636. var calendar = this.data('calendar'),
  637. fn,
  638. args = [].slice.call(arguments);
  639. if (!calendar) {
  640. return this.each(function () {
  641. return $(this).data('calendar', new Calendar(this, options));
  642. });
  643. }
  644. if (isString(options)) {
  645. fn = options;
  646. args.shift();
  647. return calendar.methods(fn, args);
  648. }
  649. return this;
  650. }
  651. $.fn.calendar.defaults = defaults;
  652. }));