Month.js 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. import { createNamespace, addUnit } from '../../utils';
  2. import { setScrollTop } from '../../utils/dom/scroll';
  3. import { t, bem, compareDay, getPrevDay, getNextDay, formatMonthTitle } from '../utils';
  4. import { getMonthEndDay } from '../../datetime-picker/utils';
  5. var _createNamespace = createNamespace('calendar-month'),
  6. createComponent = _createNamespace[0];
  7. export default createComponent({
  8. props: {
  9. date: Date,
  10. type: String,
  11. color: String,
  12. minDate: Date,
  13. maxDate: Date,
  14. showMark: Boolean,
  15. rowHeight: [Number, String],
  16. formatter: Function,
  17. lazyRender: Boolean,
  18. currentDate: [Date, Array],
  19. allowSameDay: Boolean,
  20. showSubtitle: Boolean,
  21. showMonthTitle: Boolean,
  22. firstDayOfWeek: Number
  23. },
  24. data: function data() {
  25. return {
  26. visible: false
  27. };
  28. },
  29. computed: {
  30. title: function title() {
  31. return formatMonthTitle(this.date);
  32. },
  33. rowHeightWithUnit: function rowHeightWithUnit() {
  34. return addUnit(this.rowHeight);
  35. },
  36. offset: function offset() {
  37. var firstDayOfWeek = this.firstDayOfWeek;
  38. var realDay = this.date.getDay();
  39. if (!firstDayOfWeek) {
  40. return realDay;
  41. }
  42. return (realDay + 7 - this.firstDayOfWeek) % 7;
  43. },
  44. totalDay: function totalDay() {
  45. return getMonthEndDay(this.date.getFullYear(), this.date.getMonth() + 1);
  46. },
  47. shouldRender: function shouldRender() {
  48. return this.visible || !this.lazyRender;
  49. },
  50. placeholders: function placeholders() {
  51. var rows = [];
  52. var count = Math.ceil((this.totalDay + this.offset) / 7);
  53. for (var day = 1; day <= count; day++) {
  54. rows.push({
  55. type: 'placeholder'
  56. });
  57. }
  58. return rows;
  59. },
  60. days: function days() {
  61. var days = [];
  62. var year = this.date.getFullYear();
  63. var month = this.date.getMonth();
  64. for (var day = 1; day <= this.totalDay; day++) {
  65. var date = new Date(year, month, day);
  66. var type = this.getDayType(date);
  67. var config = {
  68. date: date,
  69. type: type,
  70. text: day,
  71. bottomInfo: this.getBottomInfo(type)
  72. };
  73. if (this.formatter) {
  74. config = this.formatter(config);
  75. }
  76. days.push(config);
  77. }
  78. return days;
  79. }
  80. },
  81. methods: {
  82. getHeight: function getHeight() {
  83. if (!this.height) {
  84. this.height = this.$el.getBoundingClientRect().height;
  85. }
  86. return this.height;
  87. },
  88. scrollIntoView: function scrollIntoView(body) {
  89. var _this$$refs = this.$refs,
  90. days = _this$$refs.days,
  91. month = _this$$refs.month;
  92. var el = this.showSubtitle ? days : month;
  93. var scrollTop = el.getBoundingClientRect().top - body.getBoundingClientRect().top + body.scrollTop;
  94. setScrollTop(body, scrollTop);
  95. },
  96. getMultipleDayType: function getMultipleDayType(day) {
  97. var _this = this;
  98. var isSelected = function isSelected(date) {
  99. return _this.currentDate.some(function (item) {
  100. return compareDay(item, date) === 0;
  101. });
  102. };
  103. if (isSelected(day)) {
  104. var prevDay = getPrevDay(day);
  105. var nextDay = getNextDay(day);
  106. var prevSelected = isSelected(prevDay);
  107. var nextSelected = isSelected(nextDay);
  108. if (prevSelected && nextSelected) {
  109. return 'multiple-middle';
  110. }
  111. if (prevSelected) {
  112. return 'end';
  113. }
  114. return nextSelected ? 'start' : 'multiple-selected';
  115. }
  116. return '';
  117. },
  118. getRangeDayType: function getRangeDayType(day) {
  119. var _this$currentDate = this.currentDate,
  120. startDay = _this$currentDate[0],
  121. endDay = _this$currentDate[1];
  122. if (!startDay) {
  123. return '';
  124. }
  125. var compareToStart = compareDay(day, startDay);
  126. if (!endDay) {
  127. return compareToStart === 0 ? 'start' : '';
  128. }
  129. var compareToEnd = compareDay(day, endDay);
  130. if (compareToStart === 0 && compareToEnd === 0 && this.allowSameDay) {
  131. return 'start-end';
  132. }
  133. if (compareToStart === 0) {
  134. return 'start';
  135. }
  136. if (compareToEnd === 0) {
  137. return 'end';
  138. }
  139. if (compareToStart > 0 && compareToEnd < 0) {
  140. return 'middle';
  141. }
  142. },
  143. getDayType: function getDayType(day) {
  144. var type = this.type,
  145. minDate = this.minDate,
  146. maxDate = this.maxDate,
  147. currentDate = this.currentDate;
  148. if (compareDay(day, minDate) < 0 || compareDay(day, maxDate) > 0) {
  149. return 'disabled';
  150. }
  151. if (currentDate === null) {
  152. return;
  153. }
  154. if (type === 'single') {
  155. return compareDay(day, currentDate) === 0 ? 'selected' : '';
  156. }
  157. if (type === 'multiple') {
  158. return this.getMultipleDayType(day);
  159. }
  160. /* istanbul ignore else */
  161. if (type === 'range') {
  162. return this.getRangeDayType(day);
  163. }
  164. },
  165. getBottomInfo: function getBottomInfo(type) {
  166. if (this.type === 'range') {
  167. if (type === 'start' || type === 'end') {
  168. return t(type);
  169. }
  170. if (type === 'start-end') {
  171. return t('startEnd');
  172. }
  173. }
  174. },
  175. getDayStyle: function getDayStyle(type, index) {
  176. var style = {
  177. height: this.rowHeightWithUnit
  178. };
  179. if (type === 'placeholder') {
  180. style.width = '100%';
  181. return style;
  182. }
  183. if (index === 0) {
  184. style.marginLeft = 100 * this.offset / 7 + "%";
  185. }
  186. if (this.color) {
  187. if (type === 'start' || type === 'end' || type === 'start-end' || type === 'multiple-selected' || type === 'multiple-middle') {
  188. style.background = this.color;
  189. } else if (type === 'middle') {
  190. style.color = this.color;
  191. }
  192. }
  193. return style;
  194. },
  195. genTitle: function genTitle() {
  196. var h = this.$createElement;
  197. if (this.showMonthTitle) {
  198. return h("div", {
  199. "class": bem('month-title')
  200. }, [this.title]);
  201. }
  202. },
  203. genMark: function genMark() {
  204. var h = this.$createElement;
  205. if (this.showMark && this.shouldRender) {
  206. return h("div", {
  207. "class": bem('month-mark')
  208. }, [this.date.getMonth() + 1]);
  209. }
  210. },
  211. genDays: function genDays() {
  212. var h = this.$createElement;
  213. var days = this.shouldRender ? this.days : this.placeholders;
  214. return h("div", {
  215. "ref": "days",
  216. "attrs": {
  217. "role": "grid"
  218. },
  219. "class": bem('days')
  220. }, [this.genMark(), days.map(this.genDay)]);
  221. },
  222. genDay: function genDay(item, index) {
  223. var _this2 = this;
  224. var h = this.$createElement;
  225. var type = item.type,
  226. topInfo = item.topInfo,
  227. bottomInfo = item.bottomInfo;
  228. var style = this.getDayStyle(type, index);
  229. var disabled = type === 'disabled';
  230. var onClick = function onClick() {
  231. if (!disabled) {
  232. _this2.$emit('click', item);
  233. }
  234. };
  235. var TopInfo = topInfo && h("div", {
  236. "class": bem('top-info')
  237. }, [topInfo]);
  238. var BottomInfo = bottomInfo && h("div", {
  239. "class": bem('bottom-info')
  240. }, [bottomInfo]);
  241. if (type === 'selected') {
  242. return h("div", {
  243. "attrs": {
  244. "role": "gridcell",
  245. "tabindex": -1
  246. },
  247. "style": style,
  248. "class": [bem('day'), item.className],
  249. "on": {
  250. "click": onClick
  251. }
  252. }, [h("div", {
  253. "class": bem('selected-day'),
  254. "style": {
  255. width: this.rowHeightWithUnit,
  256. height: this.rowHeightWithUnit,
  257. background: this.color
  258. }
  259. }, [TopInfo, item.text, BottomInfo])]);
  260. }
  261. return h("div", {
  262. "attrs": {
  263. "role": "gridcell",
  264. "tabindex": disabled ? null : -1
  265. },
  266. "style": style,
  267. "class": [bem('day', type), item.className],
  268. "on": {
  269. "click": onClick
  270. }
  271. }, [TopInfo, item.text, BottomInfo]);
  272. }
  273. },
  274. render: function render() {
  275. var h = arguments[0];
  276. return h("div", {
  277. "class": bem('month'),
  278. "ref": "month"
  279. }, [this.genTitle(), this.genDays()]);
  280. }
  281. });