calendar.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. mbui.define(['tool'], function (exports) {
  2. let tool = mbui.tool;
  3. var settings = {
  4. mode: "month",
  5. weekMode: ["一", "二", "三", "四", "五", "六", "日"],
  6. newDate: new Date(),
  7. width: null,
  8. height: null,
  9. shwoLunar: false,
  10. showModeBtn: true,
  11. showEvent: true,
  12. success: function (today) {
  13. console.log(today);
  14. },
  15. mark: function (start_date, end_date) {
  16. console.log(start_date);
  17. console.log(end_date);
  18. }
  19. };
  20. var Calendar = {
  21. init: function () {
  22. var me = this, el = me.el, opts = me.options;
  23. el.addClass("calendar");
  24. opts.width = el.width();
  25. opts.height = el.height();
  26. typeof (opts.newDate) == "string" ? opts.newDate = me._getDateByString(opts.newDate) : "";
  27. me._createCalendar();
  28. //绑定事件
  29. //changeMode
  30. el.on("click", ".calendar-mode-select .btn", function (e) {
  31. e.stopPropagation();
  32. var modeText = $(this).text();
  33. var mode = modeText == "月" ? "month" : "year";
  34. me.changeMode(mode);
  35. })
  36. //calendar-cell日期点击事件
  37. el.on("click", ".calendar-cell", function (e) {
  38. e.stopPropagation();
  39. $(".dropdown-month").removeClass("open");
  40. $(".dropdown-year").removeClass("open");
  41. var cellDate = $(this).attr("title");
  42. var viewData = me.viewData;
  43. var year = parseInt(cellDate.split("年")[0]);
  44. var month = parseInt(cellDate.split("年")[1].split("月")[0]) - 1;
  45. var date = parseInt(cellDate.split("年")[1].split("月")[1].split("日")[0]);
  46. if (opts.mode == "year") {
  47. if (opts.cellClick) opts.cellClick(year + '-' + (month + 1))
  48. }
  49. else if (opts.mode == "month" && month == opts.newDate.getMonth()) {
  50. if (me.options.cellClick) me.options.cellClick(year + '-' + (month + 1) + '-' + date);
  51. }
  52. })
  53. //年份下拉
  54. el.on("click", ".calendar-year-select", function (e) {
  55. e.stopPropagation();
  56. $(".dropdown-month").removeClass("open");
  57. $(".dropdown-year").toggleClass("open");
  58. //创建下拉数据
  59. var yearText = opts.newDate.getFullYear();
  60. var s = '';
  61. for (var i = 0; i < 21; i++) {
  62. if (i == 10) {
  63. s += '<li class="year-item active">'
  64. }
  65. else {
  66. s += '<li class="year-item">'
  67. }
  68. s += '<span class="year-check">' + (yearText - 10 + i) + '</span>'
  69. s += '<span >年</span>'
  70. s += '</li>'
  71. }
  72. me.el.find(".dropdown-year").html(s);
  73. })
  74. //上一月
  75. el.on("click", ".calendar-pre", function (e) {
  76. e.stopPropagation();
  77. var year = opts.newDate.getFullYear(), month = opts.newDate.getMonth() + 1;
  78. month--;
  79. if (month < 1) {
  80. year = year - 1;
  81. month = 12;
  82. }
  83. opts.newDate.setFullYear(year);
  84. var beforeDate = opts.newDate.getDate();
  85. opts.newDate.setMonth(month - 1);
  86. var afterDate = opts.newDate.getDate();
  87. //处理日期30号,切换到2月不存在30号
  88. if (beforeDate != afterDate) {
  89. opts.newDate.setDate(opts.newDate.getDate() - 1);
  90. }
  91. opts.mode == "month" ? me._refreshCalendar(opts.newDate) : me._refreshYearCalendar(opts.newDate);
  92. $(".calendar-month-text").text(month + "月");
  93. $(".calendar-year-text").text(year + "年");
  94. })
  95. //下一月
  96. el.on("click", ".calendar-next", function (e) {
  97. e.stopPropagation();
  98. var year = opts.newDate.getFullYear(), month = opts.newDate.getMonth() + 1;
  99. month++;
  100. if (month > 12) {
  101. year = year + 1;
  102. month = 1;
  103. }
  104. opts.newDate.setFullYear(year);
  105. var beforeDate = opts.newDate.getDate();
  106. opts.newDate.setMonth(month - 1);
  107. var afterDate = opts.newDate.getDate();
  108. //处理日期30号,切换到2月不存在30号
  109. if (beforeDate != afterDate) {
  110. opts.newDate.setDate(opts.newDate.getDate() - 1);
  111. }
  112. opts.mode == "month" ? me._refreshCalendar(opts.newDate) : me._refreshYearCalendar(opts.newDate);
  113. $(".calendar-month-text").text(month + "月");
  114. $(".calendar-year-text").text(year + "年");
  115. })
  116. //年份改变
  117. el.on("click", ".year-item", function (e) {
  118. e.stopPropagation();
  119. $(".dropdown-year").removeClass("open");
  120. var yearText = $(this).text();
  121. var yearNum = yearText.split("年")[0];
  122. if (yearNum == opts.newDate.getFullYear()) return;
  123. opts.newDate.setFullYear(yearNum);
  124. opts.mode == "month" ? me._refreshCalendar(opts.newDate) : me._refreshYearCalendar(opts.newDate);
  125. $(".calendar-year-text").text(yearText);
  126. })
  127. //月份下拉
  128. el.on("click", ".calendar-month-select", function (e) {
  129. e.stopPropagation();
  130. $(".dropdown-year").removeClass("open");
  131. $(".dropdown-month").toggleClass("open");
  132. })
  133. //月份改变
  134. el.on("click", ".month-item", function (e) {
  135. e.stopPropagation();
  136. $(".dropdown-month").removeClass("open");
  137. var monthText = $(this).text();
  138. var monthNum = monthText.split("月")[0];
  139. if (monthNum == (opts.newDate.getMonth() + 1)) return;
  140. var beforeDate = opts.newDate.getDate();
  141. opts.newDate.setMonth(monthNum - 1);
  142. var afterDate = opts.newDate.getDate();
  143. //处理日期30号,切换到2月不存在30号
  144. if (beforeDate != afterDate) {
  145. opts.newDate.setDate(opts.newDate.getDate() - 1);
  146. }
  147. me._refreshCalendar(opts.newDate);
  148. $(".calendar-month-text").text(monthText);
  149. })
  150. $(document.body).on("click", function (e) {
  151. $(".dropdown-month").removeClass("open");
  152. $(".dropdown-year").removeClass("open");
  153. })
  154. },
  155. //公开方法
  156. changeMode: function (mode) {
  157. var me = this;
  158. if (mode == me.options.mode) return;
  159. me.options.mode = mode;
  160. me._createCalendar();
  161. },
  162. getViewDate: function (viewDate) {
  163. var me = this, opts = me.options, mode = opts.mode, data = opts.data;
  164. if (!data || data.length == 0) return [];
  165. var viewData = {}, modeYear = viewDate.getFullYear(), modeMonth = null;
  166. if (mode == "month") { modeMonth = viewDate.getMonth() };
  167. //筛选视图数据并转化未对象 要不要转化为属性
  168. for (var i = 0; i < data.length; i++) {
  169. var item = data[i];
  170. var start = me._getDateByString(item.startDate);
  171. var year = start.getFullYear();
  172. var month = start.getMonth();
  173. var date = start.getDate();
  174. if (modeMonth && year == modeYear && modeMonth == month) {
  175. if (!viewData[date]) viewData[date] = [];
  176. viewData[date].push(item);
  177. }
  178. else if (!modeMonth && year == modeYear) {
  179. if (!viewData[month]) viewData[month] = [];
  180. viewData[month].push(item);
  181. }
  182. }
  183. return viewData;
  184. },
  185. _getDateByString: function (stringDate) {
  186. var me = this;
  187. var year = stringDate.split("-")[0];
  188. var month = parseInt(stringDate.split("-")[1]) - 1;
  189. var date = stringDate.split("-")[2];
  190. return new Date(year, month, date);
  191. },
  192. //私有方法
  193. _createCalendar: function () {
  194. var me = this;
  195. var dateMode = me.options.mode;
  196. me._createView();
  197. },
  198. _createView: function () {
  199. var me = this, el = me.el, opts = me.options, mode = opts.mode, newDate = opts.newDate, html = '';
  200. html += me._createToolbar();
  201. html += '<div class="calendar-body">';
  202. html += '<table class="calendar-table" cellspacing="0">'
  203. if (mode == "month") {
  204. html += me._createHeader();
  205. }
  206. html += me._createBody();
  207. html += '</table>'
  208. html += '</div>'
  209. el.html(html);
  210. if (mode == "month") {
  211. me._refreshCalendar(newDate);
  212. }
  213. else {
  214. me._refreshYearCalendar(newDate);
  215. }
  216. if (me.options.success) me.options.success(newDate);
  217. },
  218. _createToolbar: function () {
  219. var me = this, newDare = me.options.newDate, mode = me.options.mode, showModeBtn = me.options.showModeBtn, s = '';
  220. var year = newDare.getFullYear();
  221. var month = newDare.getMonth() + 1;
  222. s += '<div class="calendar-header">'
  223. s += '<div class="calendar-select calendar-year-select" >'
  224. s += '<span class="calendar-year-text"> ' + year + '年</span >'
  225. s += '<ul id="dropdown-year" class="dropdown-year">'
  226. s += '</ul>'
  227. s += '</div> '
  228. if (mode == "month") {
  229. s += '<div class="calendar-select calendar-month-select">'
  230. s += '<span class="calendar-month-text"> ' + month + '月</span >'
  231. //创建月份下拉
  232. s += '<ul class="dropdown-month">'
  233. for (var i = 1; i <= 12; i++) {
  234. s += '<li class="month-item">'
  235. s += '<span class="month-check">' + i + '</span>'
  236. s += '<span >月</span>'
  237. s += '</li>'
  238. }
  239. s += '</ul>'
  240. s += '</div > '
  241. }
  242. if (showModeBtn) {
  243. s += '<div class="calendar-select calendar-mode-select">'
  244. s += '<div class="btn-group">'
  245. if (mode == "month") {
  246. s += '<span class="btn calendar-select-active">月</span>'
  247. s += '<span class="btn">年</span>'
  248. }
  249. else {
  250. s += '<span class="btn">月</span>'
  251. s += '<span class="btn calendar-select-active">年</span>'
  252. }
  253. s += '</div>'
  254. s += '</div>'
  255. }
  256. s += '<i class="fa-angle-left calendar-pre"></i><i class="fa-angle-right calendar-next"></i>'
  257. s += '</div>'
  258. return s;
  259. },
  260. _createHeader: function () {
  261. var me = this, opts = me.options, weekMode = opts.weekMode;
  262. var s = '<thead><tr>'
  263. weekMode.forEach(function (item) {
  264. s += ' <th class="calendar-column-header" title="周' + item + '"><span class="calendar-column-header-inner">' + item + '</span></th>'
  265. })
  266. s += '</thead></tr>'
  267. return s;
  268. },
  269. _createBody: function () {
  270. var me = this;
  271. var s = ' <tbody class="calendar-tbody">'
  272. s += '</tbody>'
  273. return s;
  274. },
  275. _refreshYearCalendar: function (newDate) {
  276. var me = this, showEvent = me.options.showEvent, s = '';
  277. //每次都重新获取会不会影响性能
  278. me.viewData = viewData = me.getViewDate(newDate);
  279. var year = newDate.getFullYear(), month = newDate.getMonth();
  280. //四行三列
  281. for (var i = 0; i < 4; i++) {
  282. s += '<tr>'
  283. for (var l = 0; l < 3; l++) {
  284. renderMonth = i * 3 + l;
  285. if (month == renderMonth) {
  286. s += '<td title="' + year + '年' + (renderMonth + 1) + '月" class="calendar-cell calendar-thisMonth">';
  287. }
  288. else {
  289. s += '<td title="' + year + '年' + (renderMonth + 1) + '月" class="calendar-cell">';
  290. }
  291. s += '<div class="calendar-date">';
  292. s += '<div class="calendar-value">' + (renderMonth + 1) + '月';
  293. if (showEvent && viewData[renderMonth]) {
  294. if (viewData[renderMonth].length > 0) {
  295. s += '<div class="calendar-event"></div>';
  296. }
  297. }
  298. s += '</div>';
  299. s += '</div></td>';
  300. }
  301. s += '</tr>'
  302. }
  303. me.el.find(".calendar-tbody").html(s);
  304. },
  305. _refreshCalendar: function (newDate) {
  306. var me = this, showEvent = me.options.showEvent, s = '';
  307. me.viewData = viewData = me.getViewDate(newDate);
  308. var _newDate = me._cloneDate(newDate);
  309. //当前date
  310. var nowNum = _newDate.getDate();
  311. //第一天周几
  312. _newDate.setDate(1);
  313. var weekDay = _newDate.getDay() == 0 ? 7 : _newDate.getDay();
  314. //视图第一天
  315. var viewDate = me._cloneDate(_newDate);
  316. viewDate.setDate(viewDate.getDate() - weekDay + 1);
  317. //当前第几周/行 (暂不处理)
  318. var spileDate = (newDate.getTime() - viewDate.getTime()) / (1000 * 60 * 60 * 24);
  319. renderDate = me._cloneDate(viewDate);
  320. var start_date, end_date;
  321. //固定六行
  322. for (var i = 0; i < 6; i++) {
  323. s += '<tr>'
  324. for (var l = 0; l < 7; l++) {
  325. var year = renderDate.getFullYear();
  326. var month = renderDate.getMonth() + 1;
  327. var date = renderDate.getDate();
  328. if (i == 0 && l == 0) {
  329. start_date = year + '-' + month + '-' + date;
  330. }
  331. end_date = year + '-' + month + '-' + date;
  332. if (renderDate.getMonth() < newDate.getMonth()) {
  333. s += '<td title="' + year + '年' + month + '月' + date + '日" class="calendar-cell calendar-last-month-cell">';
  334. }
  335. else if (renderDate.getMonth() > newDate.getMonth()) {
  336. s += '<td title="' + year + '年' + month + '月' + date + '日" class="calendar-cell calendar-next-month-cell">';
  337. }
  338. else if (date == nowNum) {
  339. s += '<td title="' + year + '年' + month + '月' + date + '日" class="calendar-cell calendar-today">';
  340. }
  341. else {
  342. s += '<td title="' + year + '年' + month + '月' + date + '日" class="calendar-cell">';
  343. }
  344. s += '<div class="calendar-date">';
  345. s += '<div class="calendar-value">' + date;
  346. if (showEvent && viewData[date] && renderDate.getMonth() == newDate.getMonth()) {
  347. if (viewData[date].length > 0) {
  348. s += '<div class="calendar-event"></div>';
  349. }
  350. }
  351. s += '</div>';
  352. s += '</div></td>';
  353. renderDate.setDate(renderDate.getDate() + 1);
  354. }
  355. s += '</tr>'
  356. }
  357. me.el.find(".calendar-tbody").html(s);
  358. if (me.options.mark) me.options.mark(start_date, end_date);
  359. },
  360. _cloneDate: function (date) {
  361. return new Date(date.getFullYear(), date.getMonth(), date.getDate());
  362. }
  363. }
  364. var calendar = function (element, options) {
  365. Calendar.el = $('#' + element);
  366. Calendar.options = $.extend(true, {}, settings, options);
  367. Calendar.init();
  368. }
  369. // 输出接口
  370. exports('calendar', calendar);
  371. });