Implement touch handling for modals in Certifications, Education, and Skills components
- Introduced touch event listeners to enhance mobile interactivity for certification, education, and skills cards. - Refactored modal display logic to improve user experience by allowing smooth scrolling and restoring scroll position after modal closure. - Updated event handling to prevent default actions and ensure modals function correctly across devices.
This commit is contained in:
@@ -226,60 +226,140 @@ const getImageSrc = (imagePath: string) => {
|
||||
</style>
|
||||
|
||||
<script is:inline>
|
||||
function showCertModal(element) {
|
||||
const title = element.dataset.certTitle;
|
||||
const date = element.dataset.certDate;
|
||||
const description = element.dataset.certDescription;
|
||||
const url = element.dataset.certUrl;
|
||||
|
||||
document.getElementById('certModalTitle').textContent = title;
|
||||
document.getElementById('certModalDate').textContent = date;
|
||||
document.getElementById('certModalDescription').textContent = description;
|
||||
document.getElementById('certModalLink').href = url;
|
||||
|
||||
const modal = document.getElementById('certModal');
|
||||
modal.classList.add('active');
|
||||
// Don't disable body scroll - let modal content be scrollable
|
||||
}
|
||||
// Certifications widget touch handling - namespaced to avoid conflicts
|
||||
(function() {
|
||||
let certTouchStart = { x: 0, y: 0, time: 0 };
|
||||
let certIsScrolling = false;
|
||||
let certOriginalScrollPosition = 0;
|
||||
let certClickedElement = null;
|
||||
|
||||
function closeCertModal() {
|
||||
const modal = document.getElementById('certModal');
|
||||
modal.classList.remove('active');
|
||||
// No need to restore body scroll since we didn't disable it
|
||||
}
|
||||
function certHandleTouchStart(e) {
|
||||
const touch = e.touches[0];
|
||||
certTouchStart = {
|
||||
x: touch.clientX,
|
||||
y: touch.clientY,
|
||||
time: Date.now()
|
||||
};
|
||||
certIsScrolling = false;
|
||||
}
|
||||
|
||||
// Initialize when DOM is loaded
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Add click listeners to cert cards
|
||||
const certCards = document.querySelectorAll('.cert-card');
|
||||
certCards.forEach(card => {
|
||||
// Add both click and touchend for mobile compatibility
|
||||
card.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
showCertModal(this);
|
||||
});
|
||||
function certHandleTouchMove(e) {
|
||||
const touch = e.touches[0];
|
||||
const deltaX = Math.abs(touch.clientX - certTouchStart.x);
|
||||
const deltaY = Math.abs(touch.clientY - certTouchStart.y);
|
||||
|
||||
card.addEventListener('touchend', function(e) {
|
||||
e.preventDefault();
|
||||
showCertModal(this);
|
||||
});
|
||||
});
|
||||
if (deltaX > 10 || deltaY > 10) {
|
||||
certIsScrolling = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Close modal when clicking outside
|
||||
const certModal = document.getElementById('certModal');
|
||||
if (certModal) {
|
||||
certModal.addEventListener('click', function(e) {
|
||||
if (e.target === this) {
|
||||
function certHandleTouchEnd(e, element) {
|
||||
const touch = e.changedTouches[0];
|
||||
const touchEndTime = Date.now();
|
||||
|
||||
if (certIsScrolling) return;
|
||||
|
||||
const touchDuration = touchEndTime - certTouchStart.time;
|
||||
if (touchDuration > 300) return;
|
||||
|
||||
const deltaX = Math.abs(touch.clientX - certTouchStart.x);
|
||||
const deltaY = Math.abs(touch.clientY - certTouchStart.y);
|
||||
if (deltaX > 15 || deltaY > 15) return;
|
||||
|
||||
e.preventDefault();
|
||||
showCertModal(element);
|
||||
}
|
||||
|
||||
window.showCertModal = function(element) {
|
||||
// Store the clicked element and current scroll position
|
||||
certClickedElement = element;
|
||||
certOriginalScrollPosition = window.pageYOffset || document.documentElement.scrollTop;
|
||||
|
||||
const title = element.dataset.certTitle;
|
||||
const date = element.dataset.certDate;
|
||||
const description = element.dataset.certDescription;
|
||||
const url = element.dataset.certUrl;
|
||||
|
||||
document.getElementById('certModalTitle').textContent = title;
|
||||
document.getElementById('certModalDate').textContent = date;
|
||||
document.getElementById('certModalDescription').textContent = description;
|
||||
document.getElementById('certModalLink').href = url;
|
||||
|
||||
const modal = document.getElementById('certModal');
|
||||
modal.classList.add('active');
|
||||
|
||||
setTimeout(() => {
|
||||
const modalContent = modal.querySelector('.modal-content');
|
||||
if (modalContent) {
|
||||
modalContent.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
}
|
||||
}, 100);
|
||||
};
|
||||
|
||||
window.closeCertModal = function() {
|
||||
const modal = document.getElementById('certModal');
|
||||
modal.classList.remove('active');
|
||||
|
||||
// Restore scroll position to the original card
|
||||
if (certClickedElement) {
|
||||
setTimeout(() => {
|
||||
// First, scroll to the original position
|
||||
window.scrollTo({
|
||||
top: certOriginalScrollPosition,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
|
||||
// Then, ensure the clicked card is visible with a slight offset
|
||||
setTimeout(() => {
|
||||
const elementRect = certClickedElement.getBoundingClientRect();
|
||||
const isElementVisible = elementRect.top >= 0 && elementRect.bottom <= window.innerHeight;
|
||||
|
||||
if (!isElementVisible) {
|
||||
certClickedElement.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'center'
|
||||
});
|
||||
}
|
||||
}, 300);
|
||||
}, 100);
|
||||
}
|
||||
|
||||
// Clear the reference
|
||||
certClickedElement = null;
|
||||
};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const certCards = document.querySelectorAll('.cert-card');
|
||||
|
||||
certCards.forEach(card => {
|
||||
card.addEventListener('click', function(e) {
|
||||
if (!('ontouchstart' in window)) {
|
||||
e.preventDefault();
|
||||
showCertModal(this);
|
||||
}
|
||||
});
|
||||
|
||||
card.addEventListener('touchstart', certHandleTouchStart, { passive: true });
|
||||
card.addEventListener('touchmove', certHandleTouchMove, { passive: true });
|
||||
card.addEventListener('touchend', function(e) {
|
||||
certHandleTouchEnd(e, this);
|
||||
}, { passive: false });
|
||||
});
|
||||
|
||||
const certModal = document.getElementById('certModal');
|
||||
if (certModal) {
|
||||
certModal.addEventListener('click', function(e) {
|
||||
if (e.target === this) {
|
||||
closeCertModal();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Escape') {
|
||||
closeCertModal();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Close modal with Escape key
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Escape') {
|
||||
closeCertModal();
|
||||
}
|
||||
});
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
Reference in New Issue
Block a user