UNPKG

ahmedeltatawe

Version:

Project Initializer

257 lines (239 loc) 10.5 kB
let overlay = document.getElementById("overLay") as HTMLDivElement function calcMaxHeight(items: NodeListOf<HTMLLIElement> | HTMLLIElement[]): number { let maxHeight: number = 0; // mobileResponsive.classList.add("open") items.forEach((link: any) => { maxHeight += link.clientHeight }) return maxHeight; } const animationSlide = (dir: 'up' | 'down', totalHeight: NodeListOf<HTMLLIElement> | any, targetEL: HTMLUListElement | any) => { let height = dir === "down" ? 0 : calcMaxHeight(totalHeight); let targetHeight = dir === 'down' ? calcMaxHeight(totalHeight) : 0; let speed = dir === 'down' ? (targetHeight / (targetHeight * 0.05)) : (height / (height * 0.05)); function animate() { if ((height <= 0 && dir === 'up') || (height >= targetHeight && dir === 'down')) { if (dir === 'up') { targetEL.style.height = "0"; } return; // Exit animation loop } height += dir === "down" ? speed : -speed; if (height > targetHeight && dir === 'down') { height = targetHeight; } targetEL.style.height = `${height}px`; // Request next animation frame requestAnimationFrame(animate); } // Start the animation loop requestAnimationFrame(animate); } // ===============debounce================= function debounce<F extends (...args: any[]) => any>(func: F, delay: number) { let timeoutId: ReturnType<typeof setTimeout> | null = null; return (...args: Parameters<F>) => { if (timeoutId) { clearTimeout(timeoutId); } timeoutId = setTimeout(() => { func(...args); }, delay); }; } // =====aria expanded============= const setAriaExpanded = (btn: HTMLButtonElement | null, EX: boolean) => { btn?.setAttribute('aria-expanded', EX.toString()) }; // =====toggle classes ======== const toggleClass: (Element: HTMLElement | null, Classes: string[], action: 'add' | 'remove' | 'toggle') => void = (Element, Classes, action) => { if (!Element) return console.log("no element"); Classes.forEach(cls => { if (action === 'add') { if (cls) Element.classList.add(cls); } else if (action === 'remove') { if (cls) Element.classList.remove(cls); } else if (action === 'toggle') { if (cls) Element.classList.toggle(cls); } }); } // =======toggleAsideMenu with two button========= const toggleAsideMenu = (action: 'open' | 'close', asideEl: HTMLUListElement | HTMLDivElement | HTMLFormElement, ClassName: string | null, RemoveClass: string, openBtn: HTMLButtonElement | null, closeBtn: HTMLButtonElement | null, isOverlay: boolean, isEffectLink: boolean) => { if (!asideEl || !openBtn ) return; if (action === 'open') { toggleClass(asideEl, [RemoveClass], 'remove'); if (ClassName) toggleClass(asideEl, [ClassName], 'add'); setAriaExpanded(openBtn, true); setAriaExpanded(closeBtn, true); isOverlay && toggleClass(overlay, ['active'], 'add'); if (isEffectLink) { let allLinkEffect = asideEl.querySelectorAll('li .navLink') as NodeListOf<HTMLLinkElement>; allLinkEffect.forEach((link: HTMLLinkElement, index: number) => { link.style.setProperty('--i', `${index + 1}`) }) } requestAnimationFrame(() => { toggleClass(asideEl, ['open'], 'add'); }) } else { toggleClass(asideEl, ['open'], 'remove'); setAriaExpanded(openBtn, false); setAriaExpanded(closeBtn, false); isOverlay && toggleClass(overlay, ['active'], 'remove'); setTimeout(() => { toggleClass(asideEl, [RemoveClass], 'add'); if (ClassName) toggleClass(asideEl, [ClassName], 'remove'); }, 500) } } // ========toggle aside menu with same button========== const toggleAsideMenuSameBtn = (action: 'toggle' | 'remove',asideEl: HTMLUListElement | HTMLDivElement | HTMLFormElement, ClassName: string | null, RemoveClass: string, Btn: HTMLButtonElement | null, isOverlay: boolean, isEffectLink: boolean)=>{ if (!asideEl || !Btn) return; toggleClass(Btn , ['active'], action); if(Btn.classList.contains('active')){ toggleClass(asideEl ,[RemoveClass] ,'remove'); if (ClassName) toggleClass(asideEl, [ClassName], 'add'); isOverlay && toggleClass(overlay, ['active'], 'add'); setAriaExpanded(Btn, true); if (isEffectLink) { let allLinkEffect = asideEl.querySelectorAll('li .navLink') as NodeListOf<HTMLLinkElement>; allLinkEffect.forEach((link: HTMLLinkElement, index: number) => { link.style.setProperty('--i', `${index + 1}`) }) } requestAnimationFrame(() => { toggleClass(asideEl, ['open'], 'add'); }) const handleClickOutside = (e: Event) => { const target = e.target as HTMLElement; if (!Btn.contains(target) && !asideEl.contains(target)) { toggleAsideMenuSameBtn('remove',asideEl ,'responsiveLink' , 'lg-max:d-none', Btn, true, true) } }; document.addEventListener('click', handleClickOutside, { capture: true }); (Btn as any).__outsideClickHandler = handleClickOutside; }else{ toggleClass(asideEl, ['open'], 'remove'); setAriaExpanded(Btn, false); isOverlay && toggleClass(overlay, ['active'], 'remove'); setTimeout(() => { toggleClass(asideEl, [RemoveClass], 'add'); if (ClassName) toggleClass(asideEl, [ClassName], 'remove'); }, 500) const handleClickOutside = (Btn as any).__outsideClickHandler; if (handleClickOutside) { document.removeEventListener('click', handleClickOutside, { capture: true }); delete (Btn as any).__outsideClickHandler; } } } // ========toggle dropDown menu========== const toggleDropDownMenu = (action: 'toggle' | 'remove', dropList: HTMLUListElement, Btn: HTMLButtonElement | null) => { if (!dropList || !Btn) return; toggleClass(Btn, ['active'], action); if (Btn.classList.contains('active')) { toggleClass(dropList, ['d-none'], 'remove'); setAriaExpanded(Btn, true); requestAnimationFrame(() => { toggleClass(dropList, ['open'], 'add'); }); const handleClickOutside = (e: Event) => { const target = e.target as HTMLElement; if (!Btn.contains(target) && !dropList.contains(target)) { toggleDropDownMenu('remove', dropList, Btn); console.log('y') } }; document.addEventListener('click', handleClickOutside, { capture: true }); (Btn as any).__outsideClickHandler = handleClickOutside; } else { toggleClass(dropList, ['open'], 'remove'); setAriaExpanded(Btn, false); setTimeout(() => { toggleClass(dropList, ['d-none'], 'add'); }, 300); const handleClickOutside = (Btn as any).__outsideClickHandler; if (handleClickOutside) { document.removeEventListener('click', handleClickOutside, { capture: true }); delete (Btn as any).__outsideClickHandler; } } }; // =====model======= const toggleModel = (action: 'open' | 'close' , Model:HTMLDivElement , openBtn:HTMLButtonElement | null , closeBtn:HTMLButtonElement | null ,IsOverlay:boolean)=>{ if(!openBtn || !closeBtn) return; if(action === 'open'){ toggleClass(Model , ['d-none'] , 'remove'); setAriaExpanded(openBtn , true); setAriaExpanded(closeBtn , true); requestAnimationFrame(()=>{ toggleClass(Model , ['open'] , 'add'); }) IsOverlay && toggleClass(overlay, ['active'], 'add'); const handleClickOutside = (e: Event) => { const target = e.target as HTMLElement; if (!openBtn.contains(target) && !Model.contains(target) && !closeBtn.contains(target)) { toggleModel('close',Model ,openBtn , closeBtn, true) } }; document.addEventListener('click', handleClickOutside, { capture: true }); (openBtn as any).__outsideClickHandler = handleClickOutside; }else{ setAriaExpanded(openBtn , false); setAriaExpanded(closeBtn , false); toggleClass(Model , ['open'] , 'remove'); IsOverlay && toggleClass(overlay, ['active'], 'remove'); setTimeout(()=>{ toggleClass(Model , ['d-none'] , 'add'); },500) const handleClickOutside = (openBtn as any).__outsideClickHandler; if (handleClickOutside) { document.removeEventListener('click', handleClickOutside, { capture: true }); delete (openBtn as any).__outsideClickHandler; } } } // auth // ====show password===== const togglePassword = (action: 'show' | 'hide',input:HTMLInputElement, openEye:HTMLElement , closeEye:HTMLElement)=>{ if(action === 'show'){ input.type = 'text'; openEye.classList.remove('d-none') closeEye.classList.add('d-none') }else{ input.type = 'password'; openEye.classList.add('d-none') closeEye.classList.remove('d-none') } } // ====accordion======= const accordion = document.querySelectorAll(".accordion button") as NodeListOf<HTMLButtonElement>; const toggleAccordion = ( Btn:HTMLButtonElement)=>{ let acc = Btn.nextElementSibling as HTMLDivElement; if(Btn.getAttribute('aria-controls') === acc.id){ acc.classList.toggle('show'); if(acc.classList.contains('show')){ Btn.setAttribute('aria-expanded' , 'true'); toggleClass(Btn , ['open'] , 'add') }else{ Btn.setAttribute('aria-expanded' , 'false'); toggleClass(Btn , ['open'] , 'remove') } } } const accordionWork = ()=>{ accordion.forEach((btn:HTMLButtonElement)=>{ btn.addEventListener('click' , ()=>toggleAccordion(btn)) }) } accordionWork(); // header scrolling let header = document.querySelector("header") as HTMLDivElement window.addEventListener('scroll',()=>{ if(window.scrollY >= 150){ header.classList.add('scroll') }else{ header.classList.remove('scroll') } })