Files
com2care_website/static/js/main.js
T
2026-05-20 16:21:04 +03:30

250 lines
7.3 KiB
JavaScript

'use strict';
const SELECTORS = {
navbar: '#navbar',
navbarToggle: '#navbarToggle',
navbarMenu: '#navbarMenu',
productsNavItem: '#productsNavItem',
faqItems: '.faq-item',
faqQuestion: '.faq-question',
faqAnswer: '.faq-answer',
fadeInElements: '.fade-in',
citationCopy: '.citation-copy',
};
function initNavbarScroll() {
const navbar = document.querySelector(SELECTORS.navbar);
if (!navbar) return;
const onScroll = () => {
if (window.scrollY > 20) {
navbar.classList.add('scrolled');
} else {
navbar.classList.remove('scrolled');
}
};
window.addEventListener('scroll', onScroll, { passive: true });
onScroll();
}
function initMobileMenu() {
const toggle = document.querySelector(SELECTORS.navbarToggle);
const menu = document.querySelector(SELECTORS.navbarMenu);
if (!toggle || !menu) return;
toggle.addEventListener('click', () => {
const isOpen = menu.classList.toggle('open');
toggle.classList.toggle('open', isOpen);
toggle.setAttribute('aria-expanded', String(isOpen));
});
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && menu.classList.contains('open')) {
menu.classList.remove('open');
toggle.classList.remove('open');
toggle.setAttribute('aria-expanded', 'false');
toggle.focus();
}
});
document.addEventListener('click', (e) => {
if (!menu.contains(e.target) && !toggle.contains(e.target)) {
menu.classList.remove('open');
toggle.classList.remove('open');
toggle.setAttribute('aria-expanded', 'false');
}
});
}
function initMegaMenu() {
const productsItem = document.querySelector(SELECTORS.productsNavItem);
if (!productsItem) return;
const trigger = productsItem.querySelector('.nav-link');
const megamenu = productsItem.querySelector('.megamenu');
if (!trigger || !megamenu) return;
let hideTimer = null;
function openMenu() {
clearTimeout(hideTimer);
productsItem.classList.add('open');
trigger.setAttribute('aria-expanded', 'true');
}
function scheduleClose() {
hideTimer = setTimeout(() => {
productsItem.classList.remove('open');
trigger.setAttribute('aria-expanded', 'false');
}, 180);
}
productsItem.addEventListener('mouseenter', openMenu);
productsItem.addEventListener('mouseleave', scheduleClose);
megamenu.addEventListener('mouseenter', openMenu);
megamenu.addEventListener('mouseleave', scheduleClose);
trigger.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
const isOpen = productsItem.classList.toggle('open');
trigger.setAttribute('aria-expanded', String(isOpen));
}
if (e.key === 'Escape') {
productsItem.classList.remove('open');
trigger.setAttribute('aria-expanded', 'false');
}
});
}
function initFAQAccordion() {
const faqItems = document.querySelectorAll(SELECTORS.faqItems);
faqItems.forEach((item) => {
const question = item.querySelector(SELECTORS.faqQuestion);
const answer = item.querySelector(SELECTORS.faqAnswer);
if (!question || !answer) return;
question.addEventListener('click', () => {
const isOpen = item.classList.contains('open');
faqItems.forEach((other) => {
if (other !== item) {
other.classList.remove('open');
const otherQuestion = other.querySelector(SELECTORS.faqQuestion);
const otherAnswer = other.querySelector(SELECTORS.faqAnswer);
if (otherQuestion) otherQuestion.setAttribute('aria-expanded', 'false');
if (otherAnswer) otherAnswer.hidden = true;
}
});
item.classList.toggle('open', !isOpen);
question.setAttribute('aria-expanded', String(!isOpen));
answer.hidden = isOpen;
});
});
}
function initIntersectionObserver() {
const elements = document.querySelectorAll(SELECTORS.fadeInElements);
if (!elements.length) return;
if (!('IntersectionObserver' in window)) {
elements.forEach((el) => el.classList.add('visible'));
return;
}
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
observer.unobserve(entry.target);
}
});
},
{ threshold: 0.12, rootMargin: '0px 0px -40px 0px' }
);
elements.forEach((el, index) => {
el.style.transitionDelay = `${index * 0.06}s`;
observer.observe(el);
});
}
function initReadMore() {
var chevronSVG = '<svg width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true"><path d="M2 4L6 8L10 4" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg>';
document.querySelectorAll('[data-readmore]').forEach(function (el) {
var threshold = parseInt(el.getAttribute('data-readmore'), 10) || 120;
var fullHeight = el.scrollHeight;
if (fullHeight <= threshold + 12) return;
var storedHeight = fullHeight;
el.classList.add('readmore-wrap', 'is-clamped');
el.style.maxHeight = threshold + 'px';
var btn = document.createElement('button');
btn.type = 'button';
btn.className = 'readmore-btn';
btn.setAttribute('aria-expanded', 'false');
btn.innerHTML = 'Read more ' + chevronSVG;
el.insertAdjacentElement('afterend', btn);
btn.addEventListener('click', function () {
var collapsed = el.classList.toggle('is-clamped');
if (collapsed) {
el.style.maxHeight = threshold + 'px';
btn.innerHTML = 'Read more ' + chevronSVG;
btn.setAttribute('aria-expanded', 'false');
btn.classList.remove('is-open');
} else {
el.style.maxHeight = storedHeight + 'px';
btn.innerHTML = 'Read less ' + chevronSVG;
btn.setAttribute('aria-expanded', 'true');
btn.classList.add('is-open');
}
});
});
}
function initCitationCopy() {
const copyButtons = document.querySelectorAll(SELECTORS.citationCopy);
if (!copyButtons.length) return;
copyButtons.forEach((btn) => {
const url = btn.getAttribute('data-citation-url');
const feedback = btn.querySelector('.citation-copy-feedback');
if (!url || !feedback) return;
let resetTimer = null;
btn.addEventListener('click', async () => {
clearTimeout(resetTimer);
try {
await navigator.clipboard.writeText(url);
} catch {
const textarea = document.createElement('textarea');
textarea.value = url;
textarea.setAttribute('readonly', '');
textarea.style.position = 'fixed';
textarea.style.left = '-9999px';
document.body.appendChild(textarea);
textarea.select();
document.execCommand('copy');
document.body.removeChild(textarea);
}
feedback.hidden = false;
btn.classList.add('is-copied');
btn.setAttribute('aria-label', 'Link copied');
resetTimer = setTimeout(() => {
feedback.hidden = true;
btn.classList.remove('is-copied');
btn.setAttribute('aria-label', 'Copy citation link');
}, 2000);
});
});
}
function init() {
initNavbarScroll();
initMobileMenu();
initMegaMenu();
initFAQAccordion();
initIntersectionObserver();
initReadMore();
initCitationCopy();
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}