123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- import {hasProperty, pushUnique, createTagRepeat} from '../../lib/utils.js';
- import {dateValue, startOfYearPeriod} from '../../lib/date.js';
- import {parseHTML} from '../../lib/dom.js';
- import View from './View.js';
- function toTitleCase(word) {
- return [...word].reduce((str, ch, ix) => str += ix ? ch : ch.toUpperCase(), '');
- }
- // Class representing the years and decades view elements
- export default class YearsView extends View {
- constructor(picker, config) {
- super(picker, config);
- }
- init(options, onConstruction = true) {
- if (onConstruction) {
- this.navStep = this.step * 10;
- this.beforeShowOption = `beforeShow${toTitleCase(this.cellClass)}`;
- this.grid = this.element;
- this.element.classList.add(this.name, 'datepicker-grid');
- this.grid.appendChild(parseHTML(createTagRepeat('span', 12)));
- }
- super.init(options);
- }
- setOptions(options) {
- if (hasProperty(options, 'minDate')) {
- if (options.minDate === undefined) {
- this.minYear = this.minDate = undefined;
- } else {
- this.minYear = startOfYearPeriod(options.minDate, this.step);
- this.minDate = dateValue(this.minYear, 0, 1);
- }
- }
- if (hasProperty(options, 'maxDate')) {
- if (options.maxDate === undefined) {
- this.maxYear = this.maxDate = undefined;
- } else {
- this.maxYear = startOfYearPeriod(options.maxDate, this.step);
- this.maxDate = dateValue(this.maxYear, 11, 31);
- }
- }
- if (options[this.beforeShowOption] !== undefined) {
- const beforeShow = options[this.beforeShowOption];
- this.beforeShow = typeof beforeShow === 'function' ? beforeShow : undefined;
- }
- }
- // Update view's settings to reflect the viewDate set on the picker
- updateFocus() {
- const viewDate = new Date(this.picker.viewDate);
- const first = startOfYearPeriod(viewDate, this.navStep);
- const last = first + 9 * this.step;
- this.first = first;
- this.last = last;
- this.start = first - this.step;
- this.focused = startOfYearPeriod(viewDate, this.step);
- }
- // Update view's settings to reflect the selected dates
- updateSelection() {
- const {dates, rangepicker} = this.picker.datepicker;
- this.selected = dates.reduce((years, timeValue) => {
- return pushUnique(years, startOfYearPeriod(timeValue, this.step));
- }, []);
- if (rangepicker && rangepicker.dates) {
- this.range = rangepicker.dates.map(timeValue => {
- if (timeValue !== undefined) {
- return startOfYearPeriod(timeValue, this.step);
- }
- });
- }
- }
- // Update the entire view UI
- render() {
- // refresh disabled years on every render in order to clear the ones added
- // by beforeShow hook at previous render
- this.disabled = [];
- this.picker.setViewSwitchLabel(`${this.first}-${this.last}`);
- this.picker.setPrevBtnDisabled(this.first <= this.minYear);
- this.picker.setNextBtnDisabled(this.last >= this.maxYear);
- Array.from(this.grid.children).forEach((el, index) => {
- const classList = el.classList;
- const current = this.start + (index * this.step);
- const date = dateValue(current, 0, 1);
- el.className = `datepicker-cell ${this.cellClass}`;
- if (this.isMinView) {
- el.dataset.date = date;
- }
- el.textContent = el.dataset.year = current;
- if (index === 0) {
- classList.add('prev');
- } else if (index === 11) {
- classList.add('next');
- }
- if (current < this.minYear || current > this.maxYear) {
- classList.add('disabled');
- }
- 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, date);
- }
- });
- }
- // 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.textContent);
- 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) / this.step);
- this.grid.querySelectorAll('.focused').forEach((el) => {
- el.classList.remove('focused');
- });
- this.grid.children[index].classList.add('focused');
- }
- }
|