-
Notifications
You must be signed in to change notification settings - Fork 53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Responsive Layout - pop-up negatively interfering #235
Comments
Hi @uvarov-frontend, I encountered an issue where the entire calendar (not just a popup) was overflowing outside the body container at a specific breakpoint (1070px). I tried fixing it with CSS initially, but wasn't successful. I then implemented a JavaScript solution that resolved the problem. See the original issue in this example: website (1070px breakpoint). Here's the fixed version for your reference: website Here is the JavaScript code I used for the fix. const options = {
input: true,
actions: {
changeToInput(e, calendar, self) {
if (!self.HTMLInputElement) return;
if (self.selectedDates[0]) {
self.HTMLInputElement.innerHTML = self.selectedDates[0];
// if you want to hide the calendar after picking a date
calendar.hide();
} else {
self.HTMLInputElement.innerHTML = "Select Date";
}
},
showCalendar(self) {
const setPositionCalendar = (
input,
calendar,
position,
css,
) => {
const getPosition = {
top: -calendar.offsetHeight,
bottom: input.offsetHeight,
left: 0,
center: input.offsetWidth / 2 - calendar.offsetWidth / 2,
right: input.offsetWidth - calendar.offsetWidth,
};
const YPosition = !Array.isArray(position)
? "bottom"
: position[0];
const XPosition = !Array.isArray(position)
? position
: position[1];
let left = input.offsetLeft;
let top = input.offsetTop;
// Calculate document dimensions
const docWidth = document.documentElement.clientWidth;
const docHeight = document.documentElement.clientHeight;
// Calculate window scroll offsets
const scrollLeft =
window.scrollX || document.documentElement.scrollLeft;
const scrollTop =
window.scrollY || document.documentElement.scrollTop;
// Calculate calendar width and set maximum width to 100%
const calendarWidth = Math.min(
calendar.offsetWidth,
docWidth,
);
// Check if there's horizontal overflow
const rightOverflow =
left + calendarWidth > docWidth + scrollLeft;
const leftOverflow = left < scrollLeft;
// Check if there's vertical overflow
const verticalOverflow =
(YPosition === "bottom" &&
top + input.offsetHeight + calendar.offsetHeight >
docHeight + scrollTop) ||
(YPosition === "top" &&
top - calendar.offsetHeight < scrollTop);
// Adjust positions accordingly
if (rightOverflow && XPosition !== "left") {
left = input.offsetLeft + input.offsetWidth - calendarWidth;
} else if (leftOverflow && XPosition !== "right") {
left = input.offsetLeft;
}
// Center the calendar if the left or right value is negative
if (left < 0 || left + calendarWidth > docWidth) {
left =
document.documentElement.offsetLeft +
(document.documentElement.offsetWidth - calendarWidth) /
2;
}
if (verticalOverflow) {
top =
YPosition === "bottom"
? input.offsetTop - calendar.offsetHeight
: input.offsetTop + input.offsetHeight;
} else {
top =
YPosition === "bottom"
? top + input.offsetHeight
: top - calendar.offsetHeight;
}
calendar.classList.add(
YPosition === "bottom"
? css.calendarToInputBottom
: css.calendarToInputTop,
);
Object.assign(calendar.style, {
left: `${left}px`,
top: `${top}px`,
maxWidth: "100%",
});
};
setPositionCalendar(
self.HTMLInputElement,
self.HTMLElement,
"auto",
self.CSSClasses,
);
const actionsInput = (self) => ({
hide() {
self.HTMLElement.classList.add(
self.CSSClasses.calendarHidden,
);
if (self.actions.hideCalendar)
self.actions.hideCalendar(self);
},
show() {
self.HTMLElement.classList.remove(
self.CSSClasses.calendarHidden,
);
if (self.actions.showCalendar)
self.actions.showCalendar(self);
},
self,
});
const documentClickEvent = (e) => {
if (
!self ||
e.target === self.HTMLInputElement ||
self.HTMLElement?.contains(e.target)
)
return;
if (self.HTMLInputElement && self.HTMLElement)
actionsInput(self).hide();
window.removeEventListener("resize", handleResize);
document.removeEventListener("click", documentClickEvent, {
capture: true,
});
};
const handleResize = () =>
setPositionCalendar(
self.HTMLInputElement,
self.HTMLElement,
"auto",
self.CSSClasses,
);
self.HTMLInputElement.addEventListener("click", () => {
window.addEventListener("resize", handleResize);
document.addEventListener("click", documentClickEvent, {
capture: true,
});
});
document.addEventListener("click", documentClickEvent, {
capture: true,
});
window.addEventListener("resize", handleResize);
window.addEventListener("scroll", handleResize);
},
}, |
Probably easier to use Floating UI for positioning. |
@tfsumon Thanks for sharing, I’ll think about making the calendar auto-position depending on the breakpoint. |
I have the code for auto-positioning in a fork, I can submit a PR for auto-positioning after all my other PRs are reviewed/merged :) I also assume that my code could help with the original issue since I have a new function that given an element, will calculate the best possible side to reposition itself (by available space depending on element's position in the viewport). Cheers |
Discussed in #176
Originally posted by pablopereira27 December 30, 2023
For small screens (Boostrap sm ceil breakpoint = 767.98px), I applied the following change to the multiple month calendar.
@media (max-width: 767.98px) { .vanilla-calendar_multiple { width: 100%; max-width: 550px; } }
If it weren't for the pop-ups that can go out the calendar, it would be great.
overflow: hidden
in the.calendar
prevents the entire site from being affected, but prevents the user from seeing pop-ups that exceed the calendar.I couldn't find a way to solve it via CSS. Could you help me with any tips or any future adjustments to the calendar javascript to avoid this leak of calendar pop-ups?
The text was updated successfully, but these errors were encountered: