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>
|
</style>
|
||||||
|
|
||||||
<script is:inline>
|
<script is:inline>
|
||||||
function showCertModal(element) {
|
// Certifications widget touch handling - namespaced to avoid conflicts
|
||||||
const title = element.dataset.certTitle;
|
(function() {
|
||||||
const date = element.dataset.certDate;
|
let certTouchStart = { x: 0, y: 0, time: 0 };
|
||||||
const description = element.dataset.certDescription;
|
let certIsScrolling = false;
|
||||||
const url = element.dataset.certUrl;
|
let certOriginalScrollPosition = 0;
|
||||||
|
let certClickedElement = null;
|
||||||
|
|
||||||
document.getElementById('certModalTitle').textContent = title;
|
function certHandleTouchStart(e) {
|
||||||
document.getElementById('certModalDate').textContent = date;
|
const touch = e.touches[0];
|
||||||
document.getElementById('certModalDescription').textContent = description;
|
certTouchStart = {
|
||||||
document.getElementById('certModalLink').href = url;
|
x: touch.clientX,
|
||||||
|
y: touch.clientY,
|
||||||
|
time: Date.now()
|
||||||
|
};
|
||||||
|
certIsScrolling = false;
|
||||||
|
}
|
||||||
|
|
||||||
const modal = document.getElementById('certModal');
|
function certHandleTouchMove(e) {
|
||||||
modal.classList.add('active');
|
const touch = e.touches[0];
|
||||||
// Don't disable body scroll - let modal content be scrollable
|
const deltaX = Math.abs(touch.clientX - certTouchStart.x);
|
||||||
}
|
const deltaY = Math.abs(touch.clientY - certTouchStart.y);
|
||||||
|
|
||||||
function closeCertModal() {
|
if (deltaX > 10 || deltaY > 10) {
|
||||||
const modal = document.getElementById('certModal');
|
certIsScrolling = true;
|
||||||
modal.classList.remove('active');
|
}
|
||||||
// No need to restore body scroll since we didn't disable it
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize when DOM is loaded
|
function certHandleTouchEnd(e, element) {
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
const touch = e.changedTouches[0];
|
||||||
// Add click listeners to cert cards
|
const touchEndTime = Date.now();
|
||||||
const certCards = document.querySelectorAll('.cert-card');
|
|
||||||
certCards.forEach(card => {
|
if (certIsScrolling) return;
|
||||||
// Add both click and touchend for mobile compatibility
|
|
||||||
card.addEventListener('click', function(e) {
|
const touchDuration = touchEndTime - certTouchStart.time;
|
||||||
e.preventDefault();
|
if (touchDuration > 300) return;
|
||||||
showCertModal(this);
|
|
||||||
|
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 });
|
||||||
});
|
});
|
||||||
|
|
||||||
card.addEventListener('touchend', function(e) {
|
const certModal = document.getElementById('certModal');
|
||||||
e.preventDefault();
|
if (certModal) {
|
||||||
showCertModal(this);
|
certModal.addEventListener('click', function(e) {
|
||||||
});
|
if (e.target === this) {
|
||||||
});
|
closeCertModal();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Close modal when clicking outside
|
document.addEventListener('keydown', function(e) {
|
||||||
const certModal = document.getElementById('certModal');
|
if (e.key === 'Escape') {
|
||||||
if (certModal) {
|
|
||||||
certModal.addEventListener('click', function(e) {
|
|
||||||
if (e.target === this) {
|
|
||||||
closeCertModal();
|
closeCertModal();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
// Close modal with Escape key
|
|
||||||
document.addEventListener('keydown', function(e) {
|
|
||||||
if (e.key === 'Escape') {
|
|
||||||
closeCertModal();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
})();
|
||||||
</script>
|
</script>
|
@@ -188,80 +188,157 @@ const getEducationStyle = (title: string) => {
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script is:inline>
|
<script is:inline>
|
||||||
function showEducationModal(element) {
|
// Education widget touch handling - namespaced to avoid conflicts
|
||||||
const title = element.dataset.educationTitle;
|
(function() {
|
||||||
const description = element.dataset.educationDescription;
|
let eduTouchStart = { x: 0, y: 0, time: 0 };
|
||||||
|
let eduIsScrolling = false;
|
||||||
|
let eduOriginalScrollPosition = 0;
|
||||||
|
let eduClickedElement = null;
|
||||||
|
|
||||||
// Parse the title to extract clean degree name
|
function eduHandleTouchStart(e) {
|
||||||
const tempDiv = document.createElement('div');
|
const touch = e.touches[0];
|
||||||
tempDiv.innerHTML = title;
|
eduTouchStart = {
|
||||||
const cleanTitle = tempDiv.textContent || tempDiv.innerText || title;
|
x: touch.clientX,
|
||||||
|
y: touch.clientY,
|
||||||
// Extract degree type for styling
|
time: Date.now()
|
||||||
const titleLower = cleanTitle.toLowerCase();
|
};
|
||||||
let statusText = '';
|
eduIsScrolling = false;
|
||||||
let statusClass = '';
|
|
||||||
|
|
||||||
if (titleLower.includes('bachelor')) {
|
|
||||||
statusText = 'Studies Undertaken';
|
|
||||||
statusClass = 'text-blue-600 dark:text-blue-400';
|
|
||||||
} else if (titleLower.includes('associate')) {
|
|
||||||
statusText = 'Completed';
|
|
||||||
statusClass = 'text-green-600 dark:text-green-400';
|
|
||||||
} else {
|
|
||||||
statusText = 'Completed';
|
|
||||||
statusClass = 'text-purple-600 dark:text-purple-400';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update modal content
|
function eduHandleTouchMove(e) {
|
||||||
document.getElementById('educationModalTitle').innerHTML = title;
|
const touch = e.touches[0];
|
||||||
document.getElementById('educationModalDescription').textContent = description || 'No additional information available.';
|
const deltaX = Math.abs(touch.clientX - eduTouchStart.x);
|
||||||
document.getElementById('educationModalStatus').textContent = statusText;
|
const deltaY = Math.abs(touch.clientY - eduTouchStart.y);
|
||||||
document.getElementById('educationModalStatus').className = `text-sm font-medium ${statusClass}`;
|
|
||||||
|
|
||||||
const modal = document.getElementById('educationModal');
|
if (deltaX > 10 || deltaY > 10) {
|
||||||
modal.classList.add('active');
|
eduIsScrolling = true;
|
||||||
// Don't disable body scroll - let modal content be scrollable
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeEducationModal() {
|
function eduHandleTouchEnd(e, element) {
|
||||||
const modal = document.getElementById('educationModal');
|
const touch = e.changedTouches[0];
|
||||||
modal.classList.remove('active');
|
const touchEndTime = Date.now();
|
||||||
// No need to restore body scroll since we didn't disable it
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize when DOM is loaded
|
if (eduIsScrolling) return;
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
// Add click listeners to education cards
|
const touchDuration = touchEndTime - eduTouchStart.time;
|
||||||
const educationCards = document.querySelectorAll('.education-card');
|
if (touchDuration > 300) return;
|
||||||
educationCards.forEach(card => {
|
|
||||||
// Add both click and touchend for mobile compatibility
|
const deltaX = Math.abs(touch.clientX - eduTouchStart.x);
|
||||||
card.addEventListener('click', function(e) {
|
const deltaY = Math.abs(touch.clientY - eduTouchStart.y);
|
||||||
e.preventDefault();
|
if (deltaX > 15 || deltaY > 15) return;
|
||||||
showEducationModal(this);
|
|
||||||
|
e.preventDefault();
|
||||||
|
showEducationModal(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.showEducationModal = function(element) {
|
||||||
|
// Store the clicked element and current scroll position
|
||||||
|
eduClickedElement = element;
|
||||||
|
eduOriginalScrollPosition = window.pageYOffset || document.documentElement.scrollTop;
|
||||||
|
|
||||||
|
const title = element.dataset.educationTitle;
|
||||||
|
const description = element.dataset.educationDescription;
|
||||||
|
|
||||||
|
const tempDiv = document.createElement('div');
|
||||||
|
tempDiv.innerHTML = title;
|
||||||
|
const cleanTitle = tempDiv.textContent || tempDiv.innerText || title;
|
||||||
|
|
||||||
|
const titleLower = cleanTitle.toLowerCase();
|
||||||
|
let statusText = '';
|
||||||
|
let statusClass = '';
|
||||||
|
|
||||||
|
if (titleLower.includes('bachelor')) {
|
||||||
|
statusText = 'Studies Undertaken';
|
||||||
|
statusClass = 'text-blue-600 dark:text-blue-400';
|
||||||
|
} else if (titleLower.includes('associate')) {
|
||||||
|
statusText = 'Completed';
|
||||||
|
statusClass = 'text-green-600 dark:text-green-400';
|
||||||
|
} else {
|
||||||
|
statusText = 'Completed';
|
||||||
|
statusClass = 'text-purple-600 dark:text-purple-400';
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('educationModalTitle').innerHTML = title;
|
||||||
|
document.getElementById('educationModalDescription').textContent = description || 'No additional information available.';
|
||||||
|
document.getElementById('educationModalStatus').textContent = statusText;
|
||||||
|
document.getElementById('educationModalStatus').className = `text-sm font-medium ${statusClass}`;
|
||||||
|
|
||||||
|
const modal = document.getElementById('educationModal');
|
||||||
|
modal.classList.add('active');
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
const modalContent = modal.querySelector('.modal-content');
|
||||||
|
if (modalContent) {
|
||||||
|
modalContent.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
};
|
||||||
|
|
||||||
|
window.closeEducationModal = function() {
|
||||||
|
const modal = document.getElementById('educationModal');
|
||||||
|
modal.classList.remove('active');
|
||||||
|
|
||||||
|
// Restore scroll position to the original card
|
||||||
|
if (eduClickedElement) {
|
||||||
|
setTimeout(() => {
|
||||||
|
// First, scroll to the original position
|
||||||
|
window.scrollTo({
|
||||||
|
top: eduOriginalScrollPosition,
|
||||||
|
behavior: 'smooth'
|
||||||
|
});
|
||||||
|
|
||||||
|
// Then, ensure the clicked card is visible with a slight offset
|
||||||
|
setTimeout(() => {
|
||||||
|
const elementRect = eduClickedElement.getBoundingClientRect();
|
||||||
|
const isElementVisible = elementRect.top >= 0 && elementRect.bottom <= window.innerHeight;
|
||||||
|
|
||||||
|
if (!isElementVisible) {
|
||||||
|
eduClickedElement.scrollIntoView({
|
||||||
|
behavior: 'smooth',
|
||||||
|
block: 'center'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, 300);
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the reference
|
||||||
|
eduClickedElement = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const educationCards = document.querySelectorAll('.education-card');
|
||||||
|
|
||||||
|
educationCards.forEach(card => {
|
||||||
|
card.addEventListener('click', function(e) {
|
||||||
|
if (!('ontouchstart' in window)) {
|
||||||
|
e.preventDefault();
|
||||||
|
showEducationModal(this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
card.addEventListener('touchstart', eduHandleTouchStart, { passive: true });
|
||||||
|
card.addEventListener('touchmove', eduHandleTouchMove, { passive: true });
|
||||||
|
card.addEventListener('touchend', function(e) {
|
||||||
|
eduHandleTouchEnd(e, this);
|
||||||
|
}, { passive: false });
|
||||||
});
|
});
|
||||||
|
|
||||||
card.addEventListener('touchend', function(e) {
|
const educationModal = document.getElementById('educationModal');
|
||||||
e.preventDefault();
|
if (educationModal) {
|
||||||
showEducationModal(this);
|
educationModal.addEventListener('click', function(e) {
|
||||||
});
|
if (e.target === this) {
|
||||||
});
|
closeEducationModal();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Close modal when clicking outside
|
document.addEventListener('keydown', function(e) {
|
||||||
const educationModal = document.getElementById('educationModal');
|
if (e.key === 'Escape') {
|
||||||
if (educationModal) {
|
|
||||||
educationModal.addEventListener('click', function(e) {
|
|
||||||
if (e.target === this) {
|
|
||||||
closeEducationModal();
|
closeEducationModal();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
// Close modal with Escape key
|
|
||||||
document.addEventListener('keydown', function(e) {
|
|
||||||
if (e.key === 'Escape') {
|
|
||||||
closeEducationModal();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
})();
|
||||||
</script>
|
</script>
|
@@ -187,56 +187,136 @@ if (uncategorizedSkills.length > 0) {
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script is:inline>
|
<script is:inline>
|
||||||
function showSkillModal(element) {
|
// Skills widget touch handling - namespaced to avoid conflicts
|
||||||
const title = element.dataset.skillTitle;
|
(function() {
|
||||||
const description = element.dataset.skillDescription;
|
let skillTouchStart = { x: 0, y: 0, time: 0 };
|
||||||
|
let skillIsScrolling = false;
|
||||||
|
let skillOriginalScrollPosition = 0;
|
||||||
|
let skillClickedElement = null;
|
||||||
|
|
||||||
document.getElementById('skillModalTitle').textContent = title;
|
function skillHandleTouchStart(e) {
|
||||||
document.getElementById('skillModalDescription').textContent = description;
|
const touch = e.touches[0];
|
||||||
|
skillTouchStart = {
|
||||||
|
x: touch.clientX,
|
||||||
|
y: touch.clientY,
|
||||||
|
time: Date.now()
|
||||||
|
};
|
||||||
|
skillIsScrolling = false;
|
||||||
|
}
|
||||||
|
|
||||||
const modal = document.getElementById('skillModal');
|
function skillHandleTouchMove(e) {
|
||||||
modal.classList.add('active');
|
const touch = e.touches[0];
|
||||||
// Don't disable body scroll - let modal content be scrollable
|
const deltaX = Math.abs(touch.clientX - skillTouchStart.x);
|
||||||
}
|
const deltaY = Math.abs(touch.clientY - skillTouchStart.y);
|
||||||
|
|
||||||
function closeSkillModal() {
|
if (deltaX > 10 || deltaY > 10) {
|
||||||
const modal = document.getElementById('skillModal');
|
skillIsScrolling = true;
|
||||||
modal.classList.remove('active');
|
}
|
||||||
// No need to restore body scroll since we didn't disable it
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize when DOM is loaded
|
function skillHandleTouchEnd(e, element) {
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
const touch = e.changedTouches[0];
|
||||||
// Add click listeners to skill pills
|
const touchEndTime = Date.now();
|
||||||
const skillPills = document.querySelectorAll('.skill-pill');
|
|
||||||
skillPills.forEach(pill => {
|
if (skillIsScrolling) return;
|
||||||
// Add both click and touchend for mobile compatibility
|
|
||||||
pill.addEventListener('click', function(e) {
|
const touchDuration = touchEndTime - skillTouchStart.time;
|
||||||
e.preventDefault();
|
if (touchDuration > 300) return;
|
||||||
showSkillModal(this);
|
|
||||||
|
const deltaX = Math.abs(touch.clientX - skillTouchStart.x);
|
||||||
|
const deltaY = Math.abs(touch.clientY - skillTouchStart.y);
|
||||||
|
if (deltaX > 15 || deltaY > 15) return;
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
showSkillModal(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.showSkillModal = function(element) {
|
||||||
|
// Store the clicked element and current scroll position
|
||||||
|
skillClickedElement = element;
|
||||||
|
skillOriginalScrollPosition = window.pageYOffset || document.documentElement.scrollTop;
|
||||||
|
|
||||||
|
const title = element.dataset.skillTitle;
|
||||||
|
const description = element.dataset.skillDescription;
|
||||||
|
|
||||||
|
document.getElementById('skillModalTitle').textContent = title;
|
||||||
|
document.getElementById('skillModalDescription').textContent = description;
|
||||||
|
|
||||||
|
const modal = document.getElementById('skillModal');
|
||||||
|
modal.classList.add('active');
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
const modalContent = modal.querySelector('.modal-content');
|
||||||
|
if (modalContent) {
|
||||||
|
modalContent.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
};
|
||||||
|
|
||||||
|
window.closeSkillModal = function() {
|
||||||
|
const modal = document.getElementById('skillModal');
|
||||||
|
modal.classList.remove('active');
|
||||||
|
|
||||||
|
// Restore scroll position to the original skill pill
|
||||||
|
if (skillClickedElement) {
|
||||||
|
setTimeout(() => {
|
||||||
|
// First, scroll to the original position
|
||||||
|
window.scrollTo({
|
||||||
|
top: skillOriginalScrollPosition,
|
||||||
|
behavior: 'smooth'
|
||||||
|
});
|
||||||
|
|
||||||
|
// Then, ensure the clicked skill pill is visible with a slight offset
|
||||||
|
setTimeout(() => {
|
||||||
|
const elementRect = skillClickedElement.getBoundingClientRect();
|
||||||
|
const isElementVisible = elementRect.top >= 0 && elementRect.bottom <= window.innerHeight;
|
||||||
|
|
||||||
|
if (!isElementVisible) {
|
||||||
|
skillClickedElement.scrollIntoView({
|
||||||
|
behavior: 'smooth',
|
||||||
|
block: 'center'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, 300);
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the reference
|
||||||
|
skillClickedElement = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const skillPills = document.querySelectorAll('.skill-pill');
|
||||||
|
|
||||||
|
skillPills.forEach(pill => {
|
||||||
|
pill.addEventListener('click', function(e) {
|
||||||
|
if (!('ontouchstart' in window)) {
|
||||||
|
e.preventDefault();
|
||||||
|
showSkillModal(this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
pill.addEventListener('touchstart', skillHandleTouchStart, { passive: true });
|
||||||
|
pill.addEventListener('touchmove', skillHandleTouchMove, { passive: true });
|
||||||
|
pill.addEventListener('touchend', function(e) {
|
||||||
|
skillHandleTouchEnd(e, this);
|
||||||
|
}, { passive: false });
|
||||||
});
|
});
|
||||||
|
|
||||||
pill.addEventListener('touchend', function(e) {
|
const skillModal = document.getElementById('skillModal');
|
||||||
e.preventDefault();
|
if (skillModal) {
|
||||||
showSkillModal(this);
|
skillModal.addEventListener('click', function(e) {
|
||||||
});
|
if (e.target === this) {
|
||||||
});
|
closeSkillModal();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Close modal when clicking outside
|
document.addEventListener('keydown', function(e) {
|
||||||
const skillModal = document.getElementById('skillModal');
|
if (e.key === 'Escape') {
|
||||||
if (skillModal) {
|
|
||||||
skillModal.addEventListener('click', function(e) {
|
|
||||||
if (e.target === this) {
|
|
||||||
closeSkillModal();
|
closeSkillModal();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
// Close modal with Escape key
|
|
||||||
document.addEventListener('keydown', function(e) {
|
|
||||||
if (e.key === 'Escape') {
|
|
||||||
closeSkillModal();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
})();
|
||||||
</script>
|
</script>
|
Reference in New Issue
Block a user