MFCalendarPopup / 1.0 / js / mf-calendar-popup.js file last updated : 2024-05-09 |
---|
/*! methodfish package release
Project : MFCalendarPopup
Release : 1.0
Release date : 2024-05-09 18:50:52
License : {{warning}}tba
For more information please refer to https://methodfish.com/Projects/MFCalendarPopup
*/
// Calendar popup, triggered by calling:
// new MFCalendarPopup().getDate(e.target, new Date(), setDate);
//
// function setDate(dt) {
// alert('Set to '+dt);
// }
//
let _mfCalendarPopupEvents=false;
function MFCalendarPopup() {
const _today = new Date();
let _popup;
function getPopup(elem, dt, cb) {
function generateDaysGrid(year, month) {
daysContainer.innerHTML = '';
const daysInMonth = new Date(year, month + 1, 0).getDate();
const firstDayOfMonth = new Date(year, month, 1).getDay();
for (let i = 0; i < firstDayOfMonth; i++) {
const emptyCell = document.createElement('div');
emptyCell.classList.add('day');
daysContainer.appendChild(emptyCell);
}
for (let day = 1; day <= daysInMonth; day++) {
const dayCell = document.createElement('div');
dayCell.classList.add('day');
dayCell.textContent = day;
if (year === _today.getFullYear() && month === _today.getMonth() && day === _today.getDate()) {
dayCell.classList.add('today');
}
const currentDate = new Date(year, month, day);
if (currentDate.getDay() === 0 || currentDate.getDay() === 6) {
dayCell.classList.add('weekend'); // Add 'weekend' class for Saturday and Sunday
}
dayCell.addEventListener('click', () => selectDate(year, month, day));
daysContainer.appendChild(dayCell);
}
}
function selectDate(year, month, day) {
const selectedDt = new Date(year, month, day);
cb(selectedDt);
hidePopup();
}
function hidePopup() {
_popup.style.display = 'none';
}
function updateYearList(yearSelect, selectedYear) {
yearSelect.innerHTML = '';
const currentYear = selectedYear;
for (let i = currentYear - 50; i <= currentYear + 50; i++) {
const option = document.createElement('option');
option.value = i;
option.textContent = i;
if ( i === selectedYear ) {
option.selected = true;
}
yearSelect.appendChild(option);
}
}
function moveDivOnscreen(elem, container) {
// Get the dimensions of the viewport
let viewportWidth;
let containerLeft = 0;
if ( container==undefined ) container = window;
if (container === window) viewportWidth = window.innerWidth - 30;
else {
containerLeft = container.getBoundingClientRect().left;
viewportWidth = container.getBoundingClientRect().width - 30;
}
let viewportHeight;
if (container === window) viewportHeight = window.innerHeight - 30;
else viewportHeight = container.getBoundingClientRect().height - 30;
// Get the bounding rectangle of the element
const elemRect = elem.getBoundingClientRect();
// Calculate the desired position of the element relative to the viewport
let newTop = elemRect.top; // Maintain the current top position
let newLeft = elemRect.left; // Maintain the current left position
// Check if the element would exceed the viewport width
if ((elemRect.right - containerLeft) > viewportWidth) {
//console.log('moving from ' + newLeft);
// Adjust the left position to ensure the element stays within the viewport
newLeft -= (elemRect.right - containerLeft - viewportWidth);
//console.log('moved to ' + newLeft);
}
// Check if the element would exceed the viewport height
if (elemRect.bottom > viewportHeight) {
// Adjust the top position to ensure the element stays within the viewport
newTop -= (elemRect.bottom - viewportHeight);
}
// Set the new position of the element
elem.style.top = newTop + 'px';
elem.style.left = +newLeft + 'px';
if ( elem.getBoundingClientRect().left < 5 ) elem.style.left='5px';
}
// Create popup container
let daysContainer;
_popup = document.querySelector('.mf-calendar-popup');
if ( !_popup ) {
_popup = document.createElement('div');
_popup.classList.add('mf-calendar-popup');
_popup.classList.add('removeOnEscape');
// Create header container
const header = document.createElement('div');
if ( 1 ) {
header.classList.add('header');
const row1 = document.createElement('div');
// Create hide button
const hideBtn = document.createElement('i');
hideBtn.textContent = 'close';
hideBtn.classList.add('material-icons');
hideBtn.classList.add('hideBtn');
hideBtn.addEventListener('click', hidePopup);
row1.appendChild(hideBtn);
// Create previous month button
const prevMonthBtn = document.createElement('i');
prevMonthBtn.classList.add('prevMonthBtn');
prevMonthBtn.classList.add('material-icons');
prevMonthBtn.textContent = 'navigate_before';
prevMonthBtn.addEventListener('click', () => {
const selectedMonth = parseInt(monthSelect.value);
if (selectedMonth > 0) {
monthSelect.selectedIndex = selectedMonth - 1;
}
else {
monthSelect.selectedIndex = 11; // December
yearSelect.value = parseInt(yearSelect.value) - 1;
}
generateDaysGrid(parseInt(yearSelect.value), parseInt(monthSelect.value));
});
row1.appendChild(prevMonthBtn);
// Create month selector
const monthSelect = document.createElement('select');
monthSelect.classList.add('month');
const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
months.forEach((month, index) => {
const option = document.createElement('option');
option.value = index;
option.textContent = month;
monthSelect.appendChild(option);
});
monthSelect.selectedIndex = dt.getMonth();
monthSelect.addEventListener('change', () => {
generateDaysGrid(parseInt(yearSelect.value), parseInt(monthSelect.value));
});
row1.appendChild(monthSelect);
// Create year selector
const yearSelect = document.createElement('select');
yearSelect.classList.add('year');
const currentYear = new Date().getFullYear();
for (let i = currentYear - 50; i <= currentYear + 50; i++) {
const option = document.createElement('option');
option.value = i;
option.textContent = i;
yearSelect.appendChild(option);
}
yearSelect.value = dt.getFullYear();
yearSelect.addEventListener('change', () => {
generateDaysGrid(parseInt(yearSelect.value), parseInt(monthSelect.value));
});
row1.appendChild(yearSelect);
yearSelect.addEventListener('change', function() {
let selectedYear = parseInt(yearSelect.value); // Update the selected year
updateYearList(yearSelect, selectedYear);
});
// Create next month button
const nextMonthBtn = document.createElement('i');
nextMonthBtn.classList.add('nextMonthBtn');
nextMonthBtn.classList.add('material-icons');
nextMonthBtn.textContent = 'navigate_next';
nextMonthBtn.addEventListener('click', () => {
const selectedMonth = parseInt(monthSelect.value);
if (selectedMonth < 11) {
monthSelect.selectedIndex = selectedMonth + 1;
}
else {
monthSelect.selectedIndex = 0; // January
yearSelect.value = parseInt(yearSelect.value) + 1;
}
generateDaysGrid(parseInt(yearSelect.value), parseInt(monthSelect.value));
});
row1.appendChild(nextMonthBtn);
header.appendChild(row1);
// Append days of the week
let dayNamesContainer = document.createElement('div');
dayNamesContainer.classList.add('header');
const daysOfWeek = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
daysOfWeek.forEach(day => {
const dayName = document.createElement('div');
dayName.textContent = day;
console.log(day);
dayName.classList.add('day-name');
if (day == 'Sat' || day == 'Sun') dayName.classList.add('weekend');
dayNamesContainer.appendChild(dayName);
});
_popup.appendChild(header);
_popup.appendChild(dayNamesContainer);
}
daysContainer = document.createElement('div');
daysContainer.classList.add('days');
_popup.appendChild(daysContainer);
document.body.appendChild(_popup);
}
else {
_popup.style.display='';
daysContainer = _popup.querySelector('.days');
}
generateDaysGrid(parseInt(dt.getFullYear()), parseInt(dt.getMonth()));
const rect = elem.getBoundingClientRect();
_popup.style.top = `${rect.bottom}px`;
_popup.style.left = `${rect.left}px`;
moveDivOnscreen(_popup);
if ( !_mfCalendarPopupEvents ) {
_mfCalendarPopupEvents = true;
window.addEventListener('resize', function() {
_popup.style.display = 'none';
})
}
}
// Function to show the popup each time it's called
this.getDate = function(elem, dt, cb) {
if (!_popup || _popup.style.display === 'none') {
getPopup(elem, dt, cb);
} else {
_popup.style.display = 'block';
}
};
}
Also see
articles/Implementing-a-Monaco-Editorsquarearticles/iConnectionTestsquarearticles/javascript-camerasquarearticles/list-editsquarearticles/minifierssquarearticles/opayosquarearticles/table-drag-sortersquarearticles/typewatchsquareprojects/MFCalendarPopupsquareprojects/MFChartColumnsquareprojects/MFColorPickersquareprojects/MFColorPickerBasicsquareprojects/MFColumnGradientsquareprojects/MFFloatawayMsgsquareprojects/MFPanelssquareprojects/MFSelectorsquare
Comments
New Comment