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 ( - - {months.map(g => ( - {g.map(i => ( - - ))} - ))} -
- this.showMonths(year-1)} title={(year-1)} class='prev'> - this.showYears(year)}>{year} - this.showMonths(year+1)} title={(year+1)} class='next'> -
cur_y || year == cur_y && i > cur_m ? 'future' : 'today')) - + (i == sel_m ? ' selected' : '')}> - this.showDays(year, i)}> - {props.month_names[i]} - -
); - } - - renderYears({ selected, today, year }) - { - var beg = year & ~15; - var cur_y = today.getFullYear(); - var sel_y = selected.getFullYear(); - return ( - - {[0, 1, 2, 3].map(r => ( - - {[0, 1, 2, 3].map(j => { - var i = beg + j + r*4; - var class_name = (i < cur_y ? 'past' : (i > cur_y ? 'future' : 'today')) - + (i == sel_y ? ' selected' : ''); - return (); - })} - - ))} -
- this.showYears(year-16)} title={(beg-16)+" - "+(beg-1)} class='prev'> - {beg+' - '+(beg+15)} - this.showYears(year+16)} title={(beg+16)+" - "+(beg+31)} class='next'> -
- this.showMonths(i)}>{i} -
); - } - - _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 ( - - - {props.weekdays.map(name => ())} - - {[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 (); - } - else - return (); - })} - : null) - ))} -
- 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'> -
{name}
- this.selectDate(year, month, d)}>{d} -  
); - } - /// 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} ] : [ - this.showDays(year, e.target.value)}> {monthNames.map((name, i) => ( ))} , - this.showDays(e.target.value, month)}> {this._yearOptions(current_year+this.props.minYear, current_year+this.props.maxYear, year)} ] diff --git a/calendar.css b/calendar.css index d038c85..e64db77 100644 --- a/calendar.css +++ b/calendar.css @@ -1,13 +1,12 @@ -/* Standard style CSS for calendar.js, version: 2018-03-17 */ +/* Standard style CSS for calendar.js, version: 2021-09-19 */ .calendar-box { - display: none; background: #fff; - position: absolute; - padding: 5px; + padding: 0; z-index: 100; box-shadow: 0 0 4px #aaa; } +.calendar-box a { cursor: pointer; } .calendar-box .calendar-cancel { cursor: pointer; height: 2.2em; @@ -40,10 +39,12 @@ .calendar-box a:hover { background: #e8ffd0; } .calendar-box tr.header td { font-weight: bold; padding: 5px; } .calendar-box td { background: #f4f6f8; } -.calendar-box td.future { color: #606060; } +.calendar-box td.disabled { background: #ddd; color: #555; } +.calendar-box td.disabled a { cursor: default; } +.calendar-box td.disabled a:hover { background: none; } .calendar-box .today { background-color: #ffe9c6; } .calendar-box .selected { background-color: #c9ff8b; } -.calendar-box .calendar-title { text-align: center; white-space: nowrap; } -.calendar-box .calendar-title a, .calendar-box .calendar-title select { display: inline-block; padding: 3px 7px; border: 1px solid #d0d2d4; background: #eef0f2; } +.calendar-box .calendar-title { text-align: center; white-space: nowrap; background: #dddfe2; height: 2.2em; } +.calendar-box .calendar-title a, .calendar-box .calendar-title select { display: inline-block; padding: 3px 7px; } .calendar-box .calendar-title a.prev:before { content: "<"; } .calendar-box .calendar-title a.next:before { content: ">"; } diff --git a/calendar.js b/calendar.js deleted file mode 100644 index 3575da0..0000000 --- a/calendar.js +++ /dev/null @@ -1,407 +0,0 @@ -/** - * Calendar Script - * Creates a calendar widget which can be used to select the date more easily than using just a text box - * - * Original: http://www.openjs.com/scripts/ui/calendar/ - * Modified: http://yourcmc.ru/git/vitalif-js/calendar - * Version: 2019-07-16 - * License: MIT-like, http://www.openjs.com/license.php - * - * Example: - * - * - */ -export class Calendar -{ - // Configuration - static defaultOptions = { - month_names: ["Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"], - close_label: 'Закрыть', - weekdays: ["Пн","Вт","Ср","Чт","Пт","Сб","Вс"], - 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 - month_days: [31,28,31,30,31,30,31,31,30,31,30,31], - // Today's date - today: new Date(), - callback: null, - start: 'days', - } - - // State variables - static instance = null; - static box = null; - static addedListener = false; - - setHTML(html) - { - html += ""+this.close_label+""; - Calendar.box.innerHTML = html; - if (this.position) - { - this.calcPosition(); - } - } - - calcPosition() - { - // Position the div in the correct location... - var input = this.input; - var div = Calendar.box; - var xy = getOffset(input); - var height = input.clientHeight||input.offsetHeight; - var ww = document.documentElement.clientWidth||document.body.clientWidth; - div.style.display = "block"; - if (div.offsetWidth + xy.left-1 > ww) - div.style.left = (ww-div.offsetWidth-1)+"px"; - else - div.style.left = (xy.left-1)+"px"; - if (div.offsetHeight + xy.top+height-1 >= (document.documentElement.clientHeight||document.body.clientHeight) && - xy.top-div.offsetHeight >= 0) - { - this.position = 'top'; - div.style.top = (xy.top-div.offsetHeight)+'px'; - } - else - { - this.position = 'bottom'; - div.style.top = (xy.top+height-1)+"px"; - } - } - - isVisible() - { - return Calendar.instance == this && Calendar.box.style.display == 'block'; - } - - /// Called when the user clicks on a date in the calendar. - selectDate(year, month, day) - { - var i = this.input; - var t = i.value.split(/\s+/, 2)[1]||''; - if (this.callback) - { - // 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.callback; - c(t); - } - else - { - 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"); - } - Calendar.instance.hideCalendar(); - } - - showMonths(year) - { - var cur_y = this.today.getFullYear(); - var cur_m = this.today.getMonth(); - var sel_m = this.selected.getFullYear() == year ? this.selected.getMonth() : -1; - var html = ''; - html += ""; - html += ""; - html += ""; - for (var i in this.month_names) { - if (i && !(i % 3)) - html += ""; - var class_name = (year < cur_y || year == cur_y && i < cur_m ? 'past' : - (year > cur_y || year == cur_y && i > cur_m ? 'future' : 'today')) - + (i == sel_m ? ' selected' : ''); - html += ""; - } - html += ""; - html += "
"; - html += " "+year+""; - html += "
"+this.month_names[i]+"
"; - this.setHTML(html); - } - - showYears(year) - { - var beg = year & ~15; - var cur_y = this.today.getFullYear(); - var sel_y = this.selected.getFullYear(); - var html = ''; - html += ""; - html += ""; - html += ""; - for (var i = 0; i < 16; i++) { - if (i && !(i % 4)) - html += ""; - var class_name = (beg+i < cur_y ? 'past' : (beg+i > cur_y ? 'future' : 'today')) - + (beg+i == sel_y ? ' selected' : ''); - html += ""; - } - html += ""; - html += "
"; - html += " "; - html += " "+beg+" - "+(beg+15)+""; - html += " "; - html += "
"+(beg+i)+"
"; - this.setHTML(html); - } - - /// Creates a calendar with the date given in the argument as the selected date. - makeCalendar(year, month) - { - // 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 = this.today.getFullYear(); - - var html = ''; - html += ""; - html += ""; - html += ""; - for (var weekday = 0; weekday < 7; weekday++) - html += ""; - html += ""; - - // Get the first day of this month - var first_day = new Date(year,month,1); - var start_day = (first_day.getDay()+this.sunday)%7; - - var d = 1; - var flag = 0; - - // Leap year support - if (!(year % 4) && ((year % 100) || !(year % 400))) - this.month_days[1] = 29; - else - this.month_days[1] = 28; - - var days_in_this_month = this.month_days[month]; - - // Create the calendar - var yea = this.today.getFullYear(); - var all_diff = (year - yea) || (month - this.today.getMonth()); - var sel_day = year == this.selected.getFullYear() && month == this.selected.getMonth() ? this.selected.getDate() : -1; - for (var i = 0; i <= 5; i++) { - if (w >= days_in_this_month) - break; - html += ""; - for (var j = 0; j < 7; j++) { - if (d > days_in_this_month) - flag = 0; // If the days has overshooted the number of days in this month, stop writing - else if (j >= start_day && !flag) - flag = 1; // If the first day of this month has come, start the date writing - - if (flag) { - var w = d, mon = month+1; - if (w < 10) - w = "0" + w; - if (mon < 10) - mon = "0" + mon; - - // Is it today? - var class_name = ''; - - var diff = all_diff || (d - this.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 += " " + this.weekdays[j].toLowerCase(); - - html += ""; - d++; - } - else - html += ""; - } - html += ""; - } - html += "
"; - if (!this.selectboxes) { - html += " "+this.month_names[month]+""; - html += " "+year+""; - } else { - html += " "; - html += ""; - } - html += "
"+this.weekdays[weekday]+"
"+d+" 
"; - this.setHTML(html); - } - - /// Display the calendar - if a date exists in the input box, that will be selected in the calendar. - showCalendar() - { - Calendar.instance = this; - var input = this.input; - - // Show the calendar with the date in the input as the selected date - this.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. - this.selected = selected_date; - } - } - - this.position = ''; - - if (this.start == 'years') - this.showYears(this.selected.getFullYear()); - else if (this.start == 'months') - this.showMonths(this.selected.getFullYear()); - else - this.makeCalendar(this.selected.getFullYear(), this.selected.getMonth()); - - // Position the div in the correct location... - this.calcPosition(); - }; - - /// Hides the currently show calendar. - hideCalendar() - { - Calendar.box.style.display = "none"; - } - - /// Setup a text input box to be a calendar box. - static set(input_or_id, options) - { - if (typeof input_or_id == 'string') - input_or_id = document.getElementById(input_or_id); - if (!input_or_id) - return; // If the input field is not there, exit. - options = options||{}; - var instance = new Calendar(); - for (var i in Calendar.defaultOptions) - instance[i] = options[i] || Calendar.defaultOptions[i]; - instance.input = input_or_id; - Calendar.init(); - input_or_id.addEventListener('focus', function(ev) { - instance.showCalendar(); - }); - input_or_id.addEventListener('blur', function(ev) { - if (!instance.stopBlur || instance.stopBlur < Date.now()-200) { - instance.hideCalendar(); - } - }); - return instance; - } - - /// Will be called once when the first input is set. - static init() - { - if (!Calendar.box || !Calendar.box.parentNode) { - var div = document.createElement('div'); - if (!Calendar.box) - Calendar.box = div; - div.className = "calendar-box"; - div.addEventListener("mousedown", function(ev) { - ev = ev || window.event; - if (ev.stopPropagation) - ev.stopPropagation(); - else - ev.cancelBubble = true; - if (Calendar.instance) - Calendar.instance.stopBlur = Date.now(); - return true; - }); - document.getElementsByTagName("body")[0].insertBefore(div,document.getElementsByTagName("body")[0].firstChild); - if (!Calendar.addedListener) { - document.addEventListener("mousedown", function() { Calendar.instance && Calendar.instance.hideCalendar(); }); - Calendar.addedListener = true; - } - } - } -} - -window.Calendar = Calendar; - -function getOffsetRect(elem) -{ - var box = elem.getBoundingClientRect(); - - var body = document.body; - var docElem = document.documentElement; - - var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop; - var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft; - var clientTop = docElem.clientTop || body.clientTop || 0; - var clientLeft = docElem.clientLeft || body.clientLeft || 0; - var top = box.top + scrollTop - clientTop; - var left = box.left + scrollLeft - clientLeft; - - return { top: Math.round(top), left: Math.round(left) }; -} - -function getOffsetSum(elem) -{ - var top = 0, left = 0; - while(elem) - { - top = top + parseInt(elem.offsetTop); - left = left + parseInt(elem.offsetLeft); - elem = elem.offsetParent; - } - return { top: top, left: left }; -} - -function getOffset(elem) -{ - if (elem.getBoundingClientRect) - return getOffsetRect(elem); - else - return getOffsetSum(elem); -} diff --git a/package.json b/package.json index 2e2a7b1..67b1a4c 100644 --- a/package.json +++ b/package.json @@ -15,12 +15,11 @@ "babel-preset-react": "^6.24.1", "babel-preset-stage-1": "^6.24.1", "preact": "^8.2.9", - "uglify-js": "^3.4.9", "webpack": "^4.26.1", "webpack-cli": "^3.0.8" }, "scripts": { - "compile": "node_modules/.bin/webpack", - "compile-old": "node_modules/.bin/babel calendar.js | node_modules/.bin/uglifyjs > calendar.min.js" + "build": "node_modules/.bin/webpack", + "watch-dev": "node_modules/.bin/webpack --mode=development -w" } } diff --git a/preact-react.js b/preact-react.js new file mode 100644 index 0000000..922f5f1 --- /dev/null +++ b/preact-react.js @@ -0,0 +1,38 @@ +// Thin Preact-React shim for Calendar +// (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 preact from 'preact'; + +function createElement(type, props, ...children) +{ + if (props) + { + if (props.onClick) + { + props.onclick = props.onClick; + delete props.onClick; + } + if (props.onChange) + { + props.onchange = props.onChange; + delete props.onChange; + } + if (props.className) + { + props['class'] = props.className; + delete props.className; + } + } + return preact.h(type, props, ...children); +} + +const React = { + createElement, + Component: preact.Component, + PureComponent: preact.Component, +}; + +export default React; diff --git a/test.htm b/test.htm index 1c8f502..f4e52c8 100644 --- a/test.htm +++ b/test.htm @@ -1,6 +1,5 @@
- @@ -11,6 +10,6 @@ Calendar.set(document.getElementById('x'));
diff --git a/webpack.config.js b/webpack.config.js index a79bdd0..3db6e48 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -8,6 +8,11 @@ module.exports = { path: __dirname, filename: './[name].min.js' }, + resolve: { + alias: { + react: './preact-react.js' + } + }, devtool: 'source-map', module: { rules: [