@narmafzam/jalali-datepicker
Version:
just a jalali-datepicker
433 lines (404 loc) • 17.1 kB
JavaScript
let Constant = require('./constant');
let Helper = require('./helper');
let Mustache = require('mustache');
let PersianDate = require('../../bower_components/persian-date/dist/persian-date');
class View {
constructor (model) {
this.yearsViewCount = 12;
this.model = model;
this.rendered = null;
this.$container = null;
this.id = `persianDateInstance-${parseInt(Math.random(100) * 1000)}`;
let that = this;
if (this.model.state.ui.isInline) {
this.$container = $('<div id="' + this.id + '" class="ui-datepicker-inline' + (this.model.options.locale_ == 'fa' ? ' ui-datepicker-rtl' : ' ') + '"></div>').appendTo(that.model.inputElement);
}
else {
this.$container = $('<div id="' + this.id + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all' + (this.model.options.locale_ == 'fa' ? ' ui-datepicker-rtl' : ' ') + '"></div>').appendTo('body');
this.hide();
this.setPickerBoxPosition();
this.addCompatibilityClass();
}
return this;
}
addCompatibilityClass () {
if (Helper.isMobile && this.model.options.responsive) {
this.$container.addClass('pwt-mobile-view');
}
}
destroy () {
this.$container.remove();
}
setPickerBoxPosition () {
let inputPosition = this.model.input.getInputPosition(),
inputSize = this.model.input.getInputSize();
if (Helper.isMobile && this.model.options.responsive) {
return false;
}
if (this.model.options.position === 'auto') {
this.$container.css({
right: ($(window).width() - (inputPosition.left + inputSize.width))+ 'px',
top: (inputSize.height + inputPosition.top) + 'px'
});
} else {
this.$container.css({
right: (this.model.options.position[1] + inputPosition.right) + 'px',
top: (this.model.options.position[0] + inputPosition.top) + 'px'
});
}
}
show () {
this.$container.removeClass('ui-datepicker-hide');
this.$container.addClass('ui-datepicker-show');
this.setPickerBoxPosition();
}
hide () {
this.$container.removeClass('ui-datepicker-show');
this.$container.addClass('ui-datepicker-hide');
}
toggle () {
this.$container.toggleClass('ui-datepicker-hide');
}
_getNavSwitchText (data) {
let output;
if (this.model.state.viewMode == 'day') {
output = this.model.options.dayPicker.titleFormatter.call(this, data.year, data.month);
}
else if (this.model.state.viewMode == 'month') {
output = this.model.options.monthPicker.titleFormatter.call(this, data.dateObject.valueOf());
}
else if (this.model.state.viewMode == 'year') {
output = this.model.options.yearPicker.titleFormatter.call(this, data.year);
}
return output;
}
checkYearAccess (year) {
let output = true;
if (this.model.state.filetredDate) {
let startYear = this.model.state.filterDate.start.year,
endYear = this.model.state.filterDate.end.year;
if (startYear && year < startYear) {
return false;
}
else if (endYear && year > endYear) {
return false;
}
}
if (output) {
return this.model.options.checkYear(year);
}
}
_getYearViewModel (viewState) {
let isEnabled = this.model.options.yearPicker.enabled;
// Make performance better
if (!isEnabled) {
return {
enabled: false
};
}
let list = [...Array(this.yearsViewCount).keys()].map(value => value + parseInt(viewState.year / this.yearsViewCount) * this.yearsViewCount);
let yearsModel = [],
yearStr = this.model.JalaliDate.date();
for (let i of list) {
yearStr.year([i]);
yearsModel.push({
title: yearStr.format('YYYY'),
enabled: this.checkYearAccess(i),
dataYear: i,
selected: this.model.state.selected.year == i
});
}
return {
enabled: isEnabled,
viewMode: this.model.state.viewMode == 'year',
list: yearsModel
};
}
checkMonthAccess (month) {
month = month + 1;
let output = true,
y = this.model.state.view.year;
if (this.model.state.filetredDate) {
let startMonth = this.model.state.filterDate.start.month,
endMonth = this.model.state.filterDate.end.month,
startYear = this.model.state.filterDate.start.year,
endYear = this.model.state.filterDate.end.year;
if (startMonth && endMonth && ((y == endYear && month > endMonth) || y > endYear) || ((y == startYear && month < startMonth) || y < startYear)) {
return false;
}
else if (endMonth && ((y == endYear && month > endMonth) || y > endYear)) {
return false;
}
else if (startMonth && ((y == startYear && month < startMonth) || y < startYear)) {
return false;
}
}
if (output) {
return this.model.options.checkMonth(month, y);
}
}
_getMonthViewModel () {
let isEnaled = this.model.options.monthPicker.enabled;
// Make performance better
if (!isEnaled) {
return {
enabled: false
};
}
let monthModel = [], that = this;
for (let [index, month] of that.model.JalaliDate.date().rangeName().months.entries()) {
monthModel.push({
title: month,
enabled: this.checkMonthAccess(index),
year: this.model.state.view.year,
dataMonth: index + 1,
selected: (this.model.state.selected.year == this.model.state.view.year && this.model.state.selected.month == (index + 1))
});
}
return {
enabled: isEnaled,
viewMode: this.model.state.viewMode == 'month',
list: monthModel
};
}
checkDayAccess (unixtimespan) {
let self = this,
output = true;
self.minDate = this.model.options.minDate;
self.maxDate = this.model.options.maxDate;
if (self.model.state.filetredDate) {
if (self.minDate && self.maxDate) {
self.minDate = self.model.JalaliDate.date(self.minDate).startOf('day').valueOf();
self.maxDate = self.model.JalaliDate.date(self.maxDate).endOf('day').valueOf();
if (!(unixtimespan >= self.minDate && unixtimespan <= self.maxDate)) {
return false;
}
} else if (self.minDate) {
self.minDate = self.model.JalaliDate.date(self.minDate).startOf('day').valueOf();
if (unixtimespan <= self.minDate) {
return false;
}
} else if (self.maxDate) {
self.maxDate = self.model.JalaliDate.date(self.maxDate).endOf('day').valueOf();
if (unixtimespan >= self.maxDate) {
return false;
}
}
}
if (output) {
return self.model.options.checkDate(unixtimespan);
}
}
_getDayViewModel () {
if (this.model.state.viewMode != 'day') {
return [];
}
let isEnabled = this.model.options.dayPicker.enabled;
if (!isEnabled) {
return {
enabled: false
};
}
const viewMonth = this.model.state.view.month, viewYear = this.model.state.view.year;
let pdateInstance = this.model.JalaliDate.date(),
daysCount = pdateInstance.daysInMonth(viewYear, viewMonth),
firstWeekDayOfMonth = pdateInstance.getFirstWeekDayOfMonth(viewYear, viewMonth) - 1,
outputList = [],
daysListindex = 0,
nextMonthListIndex = 0,
daysMatrix = [
['null', 'null', 'null', 'null', 'null', 'null', 'null'],
['null', 'null', 'null', 'null', 'null', 'null', 'null'],
['null', 'null', 'null', 'null', 'null', 'null', 'null'],
['null', 'null', 'null', 'null', 'null', 'null', 'null'],
['null', 'null', 'null', 'null', 'null', 'null', 'null'],
['null', 'null', 'null', 'null', 'null', 'null', 'null']
];
const anotherCalendar = this._getAnotherCalendar();
let pdate = this.model.JalaliDate.date();
for (let [rowIndex, daysRow] of daysMatrix.entries()) {
outputList[rowIndex] = [];
for (let [dayIndex] of daysRow.entries()) {
let calcedDate, otherMonth;
if (rowIndex === 0 && dayIndex < firstWeekDayOfMonth) {
calcedDate = pdate.unix(this.model.state.view.dateObject.startOf('month').valueOf() / 1000).subtract('days', ((firstWeekDayOfMonth) - dayIndex ));
otherMonth = true;
}
else if ((rowIndex === 0 && dayIndex >= firstWeekDayOfMonth) || (rowIndex <= 5 && daysListindex < daysCount)) {
daysListindex += 1;
calcedDate = pdate.year(this.model.state.view.year).month(this.model.state.view.month).date(daysListindex);
otherMonth = false;
}
else {
nextMonthListIndex += 1;
calcedDate = pdate.unix(this.model.state.view.dateObject.endOf('month').valueOf() / 1000).add('days', nextMonthListIndex);
otherMonth = true;
}
outputList[rowIndex].push({
title: calcedDate.format('D'),
alterCalTitle: new PersianDate(calcedDate.valueOf()).toCalendar(anotherCalendar[0]).toLocale(anotherCalendar[1]).format('D'),
dataDate: [calcedDate.year(), calcedDate.month(), calcedDate.date()].join(','),
dataUnix: calcedDate.valueOf(),
otherMonth: otherMonth,
otherMonthDisabled: (otherMonth && this.model.options.otherMonthDisabled),
otherMonthUnselectable: (otherMonth && this.model.options.otherMonthUnselectable),
enabled: this.checkDayAccess(calcedDate.valueOf())
});
}
}
return {
enabled: isEnabled,
viewMode: this.model.state.viewMode == 'day',
list: outputList
};
}
markSelectedDay () {
const selected = this.model.state.selected;
this.$container.find('.table-days td').each(function () {
if ($(this).data('date') == [selected.year, selected.month, selected.date].join(',')) {
$(this).addClass('selected');
} else {
$(this).removeClass('selected');
}
});
}
markToday () {
const today = new PersianDate();
this.$container.find('.ui-datepicker-calendar td').each(function () {
if ($(this).data('date') == [today.year(), today.month(), today.date()].join(',')) {
$(this).addClass('ui-state-highlight');
} else {
$(this).removeClass('ui-state-highlight');
}
});
}
_getTimeViewModel () {
let isEnabled = this.model.options.timePicker.enabled;
// Make performance better
if (!isEnabled) {
return {
enabled: false
};
}
let hourTitle;
if (this.model.options.timePicker.meridian.enabled) {
hourTitle = this.model.state.view.dateObject.format('hh');
} else {
hourTitle = this.model.state.view.dateObject.format('HH');
}
return {
enabled: isEnabled,
hour: {
title: hourTitle,
enabled: this.model.options.timePicker.hour.enabled
},
minute: {
title: this.model.state.view.dateObject.format('mm'),
enabled: this.model.options.timePicker.minute.enabled
},
second: {
title: this.model.state.view.dateObject.format('ss'),
enabled: this.model.options.timePicker.second.enabled
},
meridian: {
title: this.model.state.view.dateObject.format('a'),
enabled: this.model.options.timePicker.meridian.enabled
}
};
}
_getWeekViewModel () {
return {
enabled: true,
list: this.model.JalaliDate.date().rangeName().weekdaysMin
};
}
getCssClass () {
return [
this.model.state.ui.isInline ? 'datepicker-plot-area-inline-view' : '',
!this.model.options.timePicker.meridian.enabled ? 'datepicker-state-no-meridian' : '',
this.model.options.onlyTimePicker ? 'datepicker-state-only-time' : '',
!this.model.options.timePicker.second.enabled ? 'datepicker-state-no-second' : '',
(this.model.options.calendar_ == 'gregorian') ? 'datepicker-gregorian' : 'datepicker-persian'
].join(' ');
}
getViewModel (data) {
const anotherCalendar = this._getAnotherCalendar();
return {
plotId: '',
navigator: {
enabled: this.model.options.navigator.enabled,
switch: {
enabled: true,
text: this._getNavSwitchText(data)
},
text: this.model.options.locale_ == 'fa' ? this.model.options.navigator.text.fa : this.model.options.navigator.text.en
},
selected: this.model.state.selected,
time: this._getTimeViewModel(data),
days: this._getDayViewModel(data),
weekdays: this._getWeekViewModel(data),
month: this._getMonthViewModel(data),
year: this._getYearViewModel(data),
toolbox: this.model.options.toolbox,
cssClass: this.getCssClass(),
onlyTimePicker: this.model.options.onlyTimePicker,
altCalendarShowHint: this.model.options.calendar[anotherCalendar[0]].showHint,
calendarSwitchText: this.model.state.view.dateObject.toCalendar(anotherCalendar[0]).toLocale(anotherCalendar[1]).format(this.model.options.toolbox.calendarSwitch.format),
todayButtonText: this._getButtonText().todayButtontext,
submitButtonText: this._getButtonText().submitButtonText
};
}
_getButtonText () {
let output = {};
if (this.model.options.locale_ == 'fa') {
output.todayButtontext = this.model.options.toolbox.todayButton.text.fa;
output.submitButtonText = this.model.options.toolbox.submitButton.text.fa;
}
else if (this.model.options.locale_ == 'en') {
output.todayButtontext = this.model.options.toolbox.todayButton.text.en;
output.submitButtonText = this.model.options.toolbox.submitButton.text.en;
}
return output;
}
_getAnotherCalendar () {
let that = this, cal, loc;
if (that.model.options.calendar_ == 'persian') {
cal = 'gregorian';
loc = that.model.options.calendar.gregorian.locale;
}
else {
cal = 'persian';
loc = that.model.options.calendar.persian.locale;
}
return [cal, loc];
}
renderTimePartial () {
const timeViewModel = this._getTimeViewModel(this.model.state.view);
this.$container.find('[data-time-key="hour"] input').val(timeViewModel.hour.title);
this.$container.find('[data-time-key="minute"] input').val(timeViewModel.minute.title);
this.$container.find('[data-time-key="second"] input').val(timeViewModel.second.title);
this.$container.find('[data-time-key="meridian"] input').val(timeViewModel.meridian.title);
}
render (data) {
if (!data) {
data = this.model.state.view;
}
Helper.debug(this, 'render');
Mustache.parse(Constant.TEMPLATE);
this.rendered = $(Mustache.render(this.model.options.template, this.getViewModel(data)));
this.$container.empty().append(this.rendered);
this.markSelectedDay();
this.markToday();
this.afterRender();
}
reRender () {
let data = this.model.state.view;
this.render(data);
}
afterRender () {
if (this.model.navigator) {
this.model.navigator.liveAttach();
}
}
}
module.exports = View;