123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- import {hasProperty, pushUnique} from '../../lib/utils.js';
- import {today, dateValue, addDays, addWeeks, dayOfTheWeekOf, getWeek} from '../../lib/date.js';
- import {formatDate} from '../../lib/date-format.js';
- import {parseHTML, showElement, hideElement} from '../../lib/dom.js';
- import daysTemplate from '../templates/daysTemplate.js';
- import calendarWeeksTemplate from '../templates/calendarWeeksTemplate.js';
- import View from './View.js';
- export default class DaysView extends View {
- constructor(picker) {
- super(picker, {
- id: 0,
- name: 'days',
- cellClass: 'day',
- });
- }
- init(options, onConstruction = true) {
- if (onConstruction) {
- const inner = parseHTML(daysTemplate).firstChild;
- this.dow = inner.firstChild;
- this.grid = inner.lastChild;
- this.element.appendChild(inner);
- }
- super.init(options);
- }
- setOptions(options) {
- let updateDOW;
- if (hasProperty(options, 'minDate')) {
- this.minDate = options.minDate;
- }
- if (hasProperty(options, 'maxDate')) {
- this.maxDate = options.maxDate;
- }
- if (options.datesDisabled) {
- this.datesDisabled = options.datesDisabled;
- }
- if (options.daysOfWeekDisabled) {
- this.daysOfWeekDisabled = options.daysOfWeekDisabled;
- updateDOW = true;
- }
- if (options.daysOfWeekHighlighted) {
- this.daysOfWeekHighlighted = options.daysOfWeekHighlighted;
- }
- if (options.todayHighlight !== undefined) {
- this.todayHighlight = options.todayHighlight;
- }
- if (options.weekStart !== undefined) {
- this.weekStart = options.weekStart;
- this.weekEnd = options.weekEnd;
- updateDOW = true;
- }
- if (options.locale) {
- const locale = this.locale = options.locale;
- this.dayNames = locale.daysMin;
- this.switchLabelFormat = locale.titleFormat;
- updateDOW = true;
- }
- if (options.beforeShowDay !== undefined) {
- this.beforeShow = typeof options.beforeShowDay === 'function'
- ? options.beforeShowDay
- : undefined;
- }
- if (options.calendarWeeks !== undefined) {
- if (options.calendarWeeks && !this.calendarWeeks) {
- const weeksElem = parseHTML(calendarWeeksTemplate).firstChild;
- this.calendarWeeks = {
- element: weeksElem,
- dow: weeksElem.firstChild,
- weeks: weeksElem.lastChild,
- };
- this.element.insertBefore(weeksElem, this.element.firstChild);
- } else if (this.calendarWeeks && !options.calendarWeeks) {
- this.element.removeChild(this.calendarWeeks.element);
- this.calendarWeeks = null;
- }
- }
- if (options.showDaysOfWeek !== undefined) {
- if (options.showDaysOfWeek) {
- showElement(this.dow);
- if (this.calendarWeeks) {
- showElement(this.calendarWeeks.dow);
- }
- } else {
- hideElement(this.dow);
- if (this.calendarWeeks) {
- hideElement(this.calendarWeeks.dow);
- }
- }
- }
- // update days-of-week when locale, daysOfweekDisabled or weekStart is changed
- if (updateDOW) {
- Array.from(this.dow.children).forEach((el, index) => {
- const dow = (this.weekStart + index) % 7;
- el.textContent = this.dayNames[dow];
- el.className = this.daysOfWeekDisabled.includes(dow) ? 'dow disabled' : 'dow';
- });
- }
- }
- // Apply update on the focused date to view's settings
- updateFocus() {
- const viewDate = new Date(this.picker.viewDate);
- const viewYear = viewDate.getFullYear();
- const viewMonth = viewDate.getMonth();
- const firstOfMonth = dateValue(viewYear, viewMonth, 1);
- const start = dayOfTheWeekOf(firstOfMonth, this.weekStart, this.weekStart);
- this.first = firstOfMonth;
- this.last = dateValue(viewYear, viewMonth + 1, 0);
- this.start = start;
- this.focused = this.picker.viewDate;
- }
- // Apply update on the selected dates to view's settings
- updateSelection() {
- const {dates, rangepicker} = this.picker.datepicker;
- this.selected = dates;
- if (rangepicker) {
- this.range = rangepicker.dates;
- }
- }
- // Update the entire view UI
- render() {
- // update today marker on ever render
- this.today = this.todayHighlight ? today() : undefined;
- // refresh disabled dates on every render in order to clear the ones added
- // by beforeShow hook at previous render
- this.disabled = [...this.datesDisabled];
- const switchLabel = formatDate(this.focused, this.switchLabelFormat, this.locale);
- this.picker.setViewSwitchLabel(switchLabel);
- this.picker.setPrevBtnDisabled(this.first <= this.minDate);
- this.picker.setNextBtnDisabled(this.last >= this.maxDate);
- if (this.calendarWeeks) {
- // start of the UTC week (Monday) of the 1st of the month
- const startOfWeek = dayOfTheWeekOf(this.first, 1, 1);
- Array.from(this.calendarWeeks.weeks.children).forEach((el, index) => {
- el.textContent = getWeek(addWeeks(startOfWeek, index));
- });
- }
- Array.from(this.grid.children).forEach((el, index) => {
- const classList = el.classList;
- const current = addDays(this.start, index);
- const date = new Date(current);
- const day = date.getDay();
- el.className = `datepicker-cell ${this.cellClass}`;
- el.dataset.date = current;
- el.textContent = date.getDate();
- if (current < this.first) {
- classList.add('prev');
- } else if (current > this.last) {
- classList.add('next');
- }
- if (this.today === current) {
- classList.add('today');
- }
- if (current < this.minDate || current > this.maxDate || this.disabled.includes(current)) {
- classList.add('disabled');
- }
- if (this.daysOfWeekDisabled.includes(day)) {
- classList.add('disabled');
- pushUnique(this.disabled, current);
- }
- if (this.daysOfWeekHighlighted.includes(day)) {
- classList.add('highlighted');
- }
- if (this.range) {
- const [rangeStart, rangeEnd] = this.range;
- if (current > rangeStart && current < rangeEnd) {
- classList.add('range');
- }
- if (current === rangeStart) {
- classList.add('range-start');
- }
- if (current === rangeEnd) {
- classList.add('range-end');
- }
- }
- if (this.selected.includes(current)) {
- classList.add('selected');
- }
- if (current === this.focused) {
- classList.add('focused');
- }
- if (this.beforeShow) {
- this.performBeforeHook(el, current, current);
- }
- });
- }
- // Update the view UI by applying the changes of selected and focused items
- refresh() {
- const [rangeStart, rangeEnd] = this.range || [];
- this.grid
- .querySelectorAll('.range, .range-start, .range-end, .selected, .focused')
- .forEach((el) => {
- el.classList.remove('range', 'range-start', 'range-end', 'selected', 'focused');
- });
- Array.from(this.grid.children).forEach((el) => {
- const current = Number(el.dataset.date);
- const classList = el.classList;
- if (current > rangeStart && current < rangeEnd) {
- classList.add('range');
- }
- if (current === rangeStart) {
- classList.add('range-start');
- }
- if (current === rangeEnd) {
- classList.add('range-end');
- }
- if (this.selected.includes(current)) {
- classList.add('selected');
- }
- if (current === this.focused) {
- classList.add('focused');
- }
- });
- }
- // Update the view UI by applying the change of focused item
- refreshFocus() {
- const index = Math.round((this.focused - this.start) / 86400000);
- this.grid.querySelectorAll('.focused').forEach((el) => {
- el.classList.remove('focused');
- });
- this.grid.children[index].classList.add('focused');
- }
- }
|