diff --git a/.babelrc b/.babelrc
index 43af0e1..6df924f 100644
--- a/.babelrc
+++ b/.babelrc
@@ -1,7 +1,4 @@
{
"presets": [ [ "env" ], "stage-1" ],
- "retainLines": true,
- "plugins": [
- [ "transform-react-jsx", { "pragma": "preact.h" } ]
- ]
+ "plugins": [ [ "transform-react-jsx" ] ]
}
diff --git a/CalendarInput.js b/CalendarInput.js
index 4c13784..a6a3064 100644
--- a/CalendarInput.js
+++ b/CalendarInput.js
@@ -1,7 +1,8 @@
// Input with calendar hint based on Calendar and Picker
-// Version 2021-09-19
-// License: LGPLv3.0+
// (c) Vitaliy Filippov 2021+
+// Repository: http://yourcmc.ru/git/vitalif-js/calendar
+// Version: 2021-09-19
+// License: Dual-license MPL 2.0+ or GNU LGPL 3.0+
import React from 'react';
import PropTypes from 'prop-types';
diff --git a/calendar-material.css b/calendar-material.css
index 786c30f..65b2cff 100644
--- a/calendar-material.css
+++ b/calendar-material.css
@@ -60,6 +60,9 @@
cursor: pointer;
transition: background 0.35s cubic-bezier(0.4, 0, 0.2, 1) !important;
}
+.calendar-box a {
+ cursor: pointer;
+}
.calendar-box .clear {
clear: right;
}
@@ -108,7 +111,7 @@
color: #777;
transition: all 0.35s cubic-bezier(0.4, 0, 0.2, 1) !important;
}
-.calendar-box td a:hover {
+.calendar-box td:not(.disabled) a:hover {
background: rgba(3, 169, 244, 0.3);
}
.calendar-box td.selected a {
@@ -124,6 +127,9 @@
.calendar-box td.disabled {
background: #ddd;
}
+.calendar-box td.disabled a {
+ cursor: default;
+}
.calendar-box tr.header td {
color: #aaa;
text-transform: uppercase;
diff --git a/calendar-preact.js b/calendar-preact.js
index 4b1da60..a51c645 100644
--- a/calendar-preact.js
+++ b/calendar-preact.js
@@ -2,9 +2,10 @@
* Calendar Script
* Creates a calendar widget which can be used to select the date more easily than using just a text box
*
- * Modified: http://yourcmc.ru/git/vitalif-js/calendar
- * Version: 2019-07-18
- * License: MIT-like, http://www.openjs.com/license.php
+ * (c) Vitaliy Filippov 2018+
+ * Repository: http://yourcmc.ru/git/vitalif-js/calendar
+ * Version: 2021-09-19
+ * License: Dual-license MPL 2.0+ or GNU LGPL 3.0+
*
* Example:
*
@@ -13,44 +14,16 @@
*
*/
+import ReactCalendar from './calendar-react.js';
+
import preact from 'preact';
/** @jsx preact.h */
-export class Calendar extends preact.Component
+export class Calendar extends ReactCalendar
{
- // Configuration
- static defaultProps = {
- month_names: ["Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"],
- close_label: 'Закрыть',
- weekdays: ["Пн","Вт","Ср","Чт","Пт","Сб","Вс"],
- weekdayIds: ['Mon','Tue','Wed','Thu','Fri','Sat','Sun'],
- sunday: 6,
- selectboxes: false, // true: use selectboxes for year and month, false: show months and years in table
- years: { min: -70, max: 10 }, // range of displayed years if selectboxes==true
- format: 'd.m.Y', // either d.m.Y or Y-m-d, other formats are not supported
- // Today's date
- today: new Date(),
- start: 'days',
- }
-
- render(props, state)
- {
- return (
- {props.mode == 'months' ? this.renderMonths(props) : null}
- {props.mode == 'years' ? this.renderYears(props) : null}
- {props.mode == 'days' ? this.renderDays(props) : null}
-
Calendar.hideCalendar()}>{props.close_label}
-
);
- }
-
componentDidMount()
{
this.componentDidUpdate();
- this.props.input.addEventListener('blur', () =>
- {
- if (!Calendar.stopBlur || Calendar.stopBlur < Date.now()-200)
- Calendar.hideCalendar();
- });
}
componentDidUpdate()
@@ -58,6 +31,7 @@ export class Calendar extends preact.Component
// Position the div in the correct location...
var input = this.props.input;
var div = Calendar.box;
+ div.style.position = "absolute";
var xy = getOffset(input);
var height = input.clientHeight||input.offsetHeight;
var ww = document.body.clientWidth||document.documentElement.clientWidth;
@@ -73,258 +47,37 @@ export class Calendar extends preact.Component
div.style.top = (xy.top+height-1)+"px";
}
- /// Called when the user clicks on a date in the calendar.
- selectDate(year, month, day)
+ static onBlur()
{
- var i = this.props.input;
- var t = i.value.split(/\s+/, 2)[1]||'';
- month = Number(month)+1;
- if (this.props.callback)
+ if (!Calendar.stopBlur || Calendar.stopBlur < Date.now()-200)
+ Calendar.hideCalendar();
+ }
+
+ /// Called when the user clicks on a date in the calendar.
+ static onChange(i, date)
+ {
+ i.value = date;
+ if ("Event" in window)
{
- // Safari does not understand new Date('YYYY-MM-DD HH:MM:SS')
- t = t ? t.split(/:/) : [ 0, 0, 0 ];
- t = new Date(year-0, month-1, day-0, t[0]-0, t[1]-0, t[2]-0);
- var c = this.props.callback;
- c(new Date(t));
+ var evt = document.createEvent('Event');
+ evt.initEvent('change', true, true);
+ i.dispatchEvent(evt);
}
else
- {
- if (month < 10)
- month = '0'+month;
- if (day < 10)
- day = '0'+day;
- t = (this.format == 'Y-m-d' ? year + '-' + month + '-' + day : day + '.' + month + '.' + year) + (t ? ' '+t : '');
- i.value = t;
- if ("Event" in window)
- {
- var evt = document.createEvent('Event');
- evt.initEvent('change', true, true);
- i.dispatchEvent(evt);
- }
- else
- i.fireEvent("onchange");
- }
+ i.fireEvent("onchange");
Calendar.hideCalendar();
}
- showMonths(year)
- {
- this.props.onChangeProps({ year, mode: 'months' });
- }
-
- showYears(year)
- {
- this.props.onChangeProps({ year, mode: 'years' });
- }
-
- showDays(year, month)
- {
- this.props.onChangeProps({ year, month, mode: 'days' });
- }
-
- renderMonths(props)
- {
- var year = props.year;
- var cur_y = props.today.getFullYear();
- var cur_m = props.today.getMonth();
- var sel_m = props.selected.getFullYear() == year ? props.selected.getMonth() : -1;
- var months = [ [ 0, 1, 2 ], [ 3, 4, 5 ], [ 6, 7, 8 ], [ 9, 10, 11 ] ];
- return ();
- }
-
- renderYears({ selected, today, year })
- {
- var beg = year & ~15;
- var cur_y = today.getFullYear();
- var sel_y = selected.getFullYear();
- return ();
- }
-
- _yearOptions(min, max, year)
- {
- var r = [];
- for (var i = min; i < max; i++)
- r.push();
- return r;
- }
-
- /// Creates a calendar with the date given in the argument as the selected date.
- renderDays(props)
- {
- var { year, month, selected, selectboxes, sunday, today, month_names } = props;
-
- // Display the table
- var next_month = month+1;
- var next_month_year = year;
- if (next_month >= 12)
- {
- next_month = 0;
- next_month_year++;
- }
-
- var previous_month = month-1;
- var previous_month_year = year;
- if (previous_month < 0)
- {
- previous_month = 11;
- previous_month_year--;
- }
-
- var current_year = today.getFullYear();
-
- // Get the first day of this month
- var first_day = new Date(year, month, 1);
- var start_day = (first_day.getDay()+sunday)%7;
-
- var d = 1;
- var flag = 0;
-
- // Leap year support
- var days_in_this_month = (month == 2
- ? (!(year % 4) && ((year % 100) || !(year % 400)) ? 29 : 28)
- : ((month < 7) == !(month & 1) ? 31 : 30));
-
- var yea = today.getFullYear();
- var all_diff = (year - yea) || (month - today.getMonth());
- var sel_day = selected && year == selected.getFullYear() && month == selected.getMonth() ? selected.getDate() : -1;
-
- return (
-
- this.showDays(previous_month_year, previous_month)}
- title={month_names[previous_month]+" "+previous_month_year} class='prev'>
- {!selectboxes ?
- [
- this.showMonths(year, month)}>{month_names[month]},
- this.showYears(year)}>{year}
- ] : [
- ,
-
- ]
- }
- this.showDays(next_month_year,next_month)}
- title={props.month_names[next_month]+" "+next_month_year} class='next'>
- |
-
- {[0, 1, 2, 3, 4].map(i => (
- (i*7 < days_in_this_month+start_day ?
- {[0, 1, 2, 3, 4, 5, 6].map(j =>
- {
- var d = i*7+j+1-start_day;
- var visible = (i > 0 || j >= start_day) && (d <= days_in_this_month);
- if (visible)
- {
- var class_name = 'days';
- var diff = all_diff || (d - today.getDate());
- if (diff < 0)
- class_name += ' past';
- else if (!diff)
- class_name += ' today';
- else
- class_name += ' future';
- if (d == sel_day)
- class_name += ' selected';
- class_name += ' ' + props.weekdayIds[j].toLowerCase();
- return (
- this.selectDate(year, month, d)}>{d}
- | );
- }
- else
- return ( | );
- })}
-
: null)
- ))}
-
);
- }
-
/// Display the calendar - if a date exists in the input box, that will be selected in the calendar.
static showCalendar(input, options)
{
// Show the calendar with the date in the input as the selected date
- var props = { ...Calendar.defaultProps, ...options };
- props.selected = new Date();
- var date_in_input = input.value.replace(/\s+.*$/, ''); // Remove time
- if (date_in_input)
- {
- // date format is HARDCODE
- var selected_date = false;
- var date_parts = date_in_input.split("-");
- if (date_parts.length == 3)
- {
- // Y-m-d
- date_parts[1]--; // Month starts with 0
- selected_date = new Date(date_parts[0], date_parts[1], date_parts[2]);
- }
- else if (date_parts.length == 1)
- {
- date_parts = date_in_input.split('.');
- if (date_parts.length == 3)
- {
- // d.m.Y
- date_parts[1]--; // Month starts with 0
- selected_date = new Date(date_parts[2], date_parts[1], date_parts[0]);
- }
- }
- if (selected_date && !isNaN(selected_date.getFullYear()))
- {
- // Valid date.
- props.selected = selected_date;
- }
- }
- props.today = new Date();
- props.year = props.selected.getFullYear();
- props.month = props.selected.getMonth();
- props.mode = props.start;
- props.input = input;
- props.onChangeProps = (h) =>
- {
- props = { ...props, ...h };
- preact.render(, Calendar.box.parentNode, Calendar.box);
+ const props = {
+ ...options,
+ input,
+ value: input.value,
+ hide: Calendar.hideCalendar,
+ onChange: date => Calendar.onChange(input, date),
};
Calendar.init();
Calendar.box.style.display = "block";
@@ -332,7 +85,7 @@ export class Calendar extends preact.Component
preact.render(, Calendar.box.parentNode, Calendar.box);
}
- /// Hides the currently show calendar.
+ /// Hides the currently shown calendar.
static hideCalendar()
{
if (!Calendar.box)
@@ -351,6 +104,7 @@ export class Calendar extends preact.Component
{
return; // If the input field is not there, exit.
}
+ input_or_id.addEventListener('blur', Calendar.onBlur);
input_or_id.addEventListener('focus', function(ev)
{
Calendar.showCalendar(input_or_id, options);
diff --git a/calendar-react.js b/calendar-react.js
index 654380c..48a3d46 100644
--- a/calendar-react.js
+++ b/calendar-react.js
@@ -4,9 +4,10 @@
* Can be paired with Picker (https://yourcmc.ru/git/vitalif-js/selectbox/)
* to create a Calendar-based text input
*
- * Modified: http://yourcmc.ru/git/vitalif-js/calendar
+ * (c) Vitaliy Filippov 2011+
+ * Repository: http://yourcmc.ru/git/vitalif-js/calendar
* Version: 2021-09-19
- * License: MIT
+ * License: Dual-license MPL 2.0+ or GNU LGPL 3.0+
*/
import React from 'react';
@@ -267,12 +268,12 @@ export default class Calendar extends React.PureComponent
this.showMonths(year, month)}>{monthNames[month]},
this.showYears(year)}>{year}
] : [
-