1(() => { 2 'use strict'; 3 4 const dropdownMenus = document.querySelectorAll('.dropdown-menu'); 5 const mobileNavTrigger = document.querySelector('.mobile-nav-trigger'); 6 const siteNavContainer = document.querySelector('.site-nav-container'); 7 const templatesShowMore = document.querySelector('.templates-show-more'); 8 const filterTriggers = document.querySelectorAll('button[data-target]'); 9 const toggleClassnameTriggers = document.querySelectorAll( '[data-lqd-toggle-class]' ); 10 const frontendLocalNav = document.querySelector('#frontend-local-navbar'); 11 const textRotators = document.querySelectorAll('.lqd-text-rotator'); 12 const setAnchors = document.querySelectorAll('[data-set-anchor=true]'); 13 let lastActiveTrigger = null; 14 let lastOpenedAccordion = null; 15 16 textRotators?.forEach(textRotator => { 17 const items = textRotator.querySelectorAll('.lqd-text-rotator-item'); 18 19 if (!items.length) return; 20 21 const timeout = 2000; 22 let activeIndex = 0; 23 24 textRotator.style.width = `${ 25 items[activeIndex].querySelector('span').clientWidth 26 }px`; 27 28 setInterval(() => { 29 // current item 30 items[activeIndex].classList.remove('lqd-is-active'); 31 32 // now next item 33 activeIndex = 34 activeIndex === items.length - 1 ? 0 : activeIndex + 1; 35 textRotator.style.width = `${ 36 items[activeIndex].querySelector('span').clientWidth 37 }px`; 38 items[activeIndex].classList.add('lqd-is-active'); 39 }, timeout); 40 }); 41 42 dropdownMenus.forEach(dd => { 43 if (document.body.classList.contains('navbar-shrinked')) { 44 dd.classList.remove('show'); 45 } 46 }); 47 48 document.addEventListener('click', ev => { 49 const { target } = ev; 50 dropdownMenus.forEach(dd => { 51 if ( 52 !document.body.classList.contains('navbar-shrinked') && 53 dd.closest('.primary-nav') 54 ) 55 return; 56 const clickedOutside = !dd.parentElement.contains(target); 57 if (clickedOutside) { 58 dd.classList.remove('show'); 59 } 60 }); 61 }); 62 63 templatesShowMore?.addEventListener('click', ev => { 64 ev.preventDefault(); 65 const list = document.querySelector('.templates-cards'); 66 const overlay = document.querySelector('.templates-cards-overlay'); 67 68 list.style.overflow = 'visible'; 69 list.style.maxHeight = 'none'; 70 71 overlay.animate([ { opacity: 0 } ], { 72 duration: 650, 73 fill: 'forwards', 74 easing: 'ease-out', 75 }); 76 const btnAnima = templatesShowMore.animate([ { opacity: 0 } ], { 77 duration: 650, 78 fill: 'forwards', 79 easing: 'ease-out', 80 }); 81 btnAnima.onfinish = () => { 82 overlay.style.visibility = 'hidden'; 83 templatesShowMore.style.visibility = 'hidden'; 84 }; 85 }); 86 87 filterTriggers?.forEach(trigger => { 88 const targetId = trigger.getAttribute('data-target'); 89 const targets = document.querySelectorAll(targetId); 90 const triggerType = 91 trigger.getAttribute('data-trigger-type') || 'toggle'; 92 93 if (targets.length <= 0) { 94 return trigger.setAttribute('disabled', true); 95 } 96 97 trigger.addEventListener('click', ev => { 98 ev?.preventDefault(); 99 100 trigger.classList.add('lqd-is-active'); 101 102 if (triggerType === 'toggle') { 103 [ ...trigger.parentElement.children ] 104 .filter(c => c.getAttribute('data-target') !== targetId) 105 .forEach(c => c.classList.remove('lqd-is-active')); 106 } else if (triggerType === 'accordion') { 107 if (lastActiveTrigger) { 108 lastActiveTrigger.classList.remove('lqd-is-active'); 109 } 110 if (lastActiveTrigger === trigger) { 111 lastActiveTrigger = null; 112 } else { 113 lastActiveTrigger = trigger; 114 } 115 } 116 117 targets?.forEach(t => { 118 t.style.display = 'block'; 119 t.animate([ { opacity: 0 }, { opacity: 1 } ], { 120 duration: 650, 121 easing: 'cubic-bezier(.48,.81,.52,.99)', 122 }); 123 }); 124 125 if (triggerType === 'toggle') { 126 [ ...targets[0]?.parentElement?.children ] 127 ?.filter(c => 128 targetId.startsWith('.') 129 ? !c.classList.contains(targetId.replace('.', '')) 130 : c.getAttribute('id') !== targetId.replace('#', '') 131 ) 132 ?.forEach(c => (c.style.display = 'none')); 133 } else if (triggerType === 'accordion') { 134 if (lastOpenedAccordion) { 135 lastOpenedAccordion.style.display = 'none'; 136 } 137 if (lastOpenedAccordion === targets[0]) { 138 lastOpenedAccordion = null; 139 } else { 140 lastOpenedAccordion = targets[0]; 141 } 142 } 143 }); 144 }); 145 146 toggleClassnameTriggers?.forEach(trigger => { 147 const target = trigger.getAttribute('data-lqd-toggle-target'); 148 let targetEls = target ? document.querySelectorAll(target) : []; 149 150 trigger.addEventListener('click', ev => { 151 ev?.preventDefault(); 152 trigger.classList.toggle('lqd-is-active');
153 targetEls.forEach(t => t.classList.toggle('lqd-is-active')); 154 }); 155 }); 156 157 if (frontendLocalNav?.querySelector('ul')) { 158 const scrollspy = VanillaScrollspy({ menu: frontendLocalNav.querySelector('ul') }); 159 scrollspy.init(); 160 } 161 162 mobileNavTrigger?.addEventListener('click', ev => { 163 ev.preventDefault(); 164 mobileNavTrigger?.classList.toggle('lqd-is-active'); 165 siteNavContainer?.classList.toggle('lqd-is-active'); 166 }); 167 168 siteNavContainer?.querySelectorAll('a')?.forEach(link => { 169 link.addEventListener('click', ev => { 170 mobileNavTrigger?.classList.remove('lqd-is-active'); 171 siteNavContainer?.classList.remove('lqd-is-active'); 172 }); 173 }); 174 175 document.addEventListener('click', ev => { 176 const clickedEl = ev.target; 177 const clipboardCopyButton = clickedEl.closest('.lqd-clipboard-copy'); 178 179 // Close mobile nav when clicked outside 180 if ( 181 siteNavContainer?.classList.contains('lqd-is-active') && 182 !siteNavContainer?.contains(clickedEl) && 183 !siteNavContainer !== clickedEl && 184 !mobileNavTrigger?.contains(clickedEl) && 185 !mobileNavTrigger !== clickedEl 186 ) { 187 mobileNavTrigger?.classList.remove('lqd-is-active'); 188 siteNavContainer?.classList.remove('lqd-is-active'); 189 } 190 191 // Copy to clipboard 192 if (clipboardCopyButton) { 193 const settings = JSON.parse( 194 clipboardCopyButton.getAttribute('data-copy-options') || '{}' 195 ); 196 let getContentFrom; 197 198 if (settings.contentIn) { 199 if (settings.contentIn.startsWith('<') && settings.content) { 200 const el = clipboardCopyButton.parentElement.closest( 201 settings.contentIn.replace('<', '') 202 ); 203 getContentFrom = el.querySelector(settings.content); 204 } 205 } else { 206 getContentFrom = settings.content 207 ? document.querySelector(settings.content) 208 : clipboardCopyButton.parentElement; 209 } 210 211 if (getContentFrom) { 212 const copyButtonsTemplate = document.querySelector('#copy-btns-template'); 213 const wrapper = clipboardCopyButton.closest('.lqd-clipboard-copy-wrap'); 214 let textContent = extractTextWithLinks(getContentFrom); 215 216 wrapper?.classList?.toggle('active'); 217 218 copyToClipboard(textContent, 'text'); 219 220 if ( wrapper && copyButtonsTemplate && !clipboardCopyButton.classList.contains('copy-buttons-appended') ) { 221 const copyButtons = copyButtonsTemplate.content.cloneNode(true); 222 const buttons = copyButtons.querySelectorAll('button'); 223 224 wrapper.appendChild(copyButtons); 225 clipboardCopyButton.classList.add('copy-buttons-appended'); 226 227 buttons.forEach(button => { 228 button.addEventListener('click', () => { 229 const copyType = button.getAttribute('data-copy-type'); 230 231 if ( copyType === 'text' ) { 232 copyToClipboard(textContent, 'text'); 233 } else if ( copyType === 'html' ) { 234 const unwrappedContent = getContentFrom.innerHTML 235 .replace(/<span[^>]*class="[^"]*animated-word[^"]*"[^>]*>(.*?)<\/span>/g, '$1') 236 .replace('[DONE]', ''); 237 copyToClipboard(unwrappedContent, 'html'); 238 } else if ( copyType === 'md' ) { 239 if ( typeof TurndownService !== 'undefined' ) { 240 const turndownService = new TurndownService(); 241 const content = getContentFrom.innerHTML.replace('[DONE]', ''); 242 copyToClipboard(turndownService.turndown(getContentFrom.innerHTML), 'md'); 243 } 244 } 245 }); 246 }); 247 } 248 } 249 } 250 }); 251 252 function copyToClipboard(content, contentType = 'text') { 253 if (typeof toastr === 'undefined') { 254 return; 255 } 256 257 navigator.clipboard.writeText(content).then(() => { 258 toastr.success( 259 magicai_localize && magicai_localize[`${contentType}_content_copied_to_clipboard`] ? 260 magicai_localize[`${contentType}_content_copied_to_clipboard`] : 261 'Content copied to clipboard' ); 262 }).catch(err => { 263 toastr.error( magicai_localize?.copy_failed || 'Failed to copy content' ); 264 }); 265 } 266 267 function extractTextWithLinks(element) { 268 let result = ''; 269 const walker = document.createTreeWalker( 270 element, 271 NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT, 272 null, 273 false 274 ); 275 276 let node; 277 while ((node = walker.nextNode())) { 278 if (node.nodeType === Node.TEXT_NODE) { 279 result += node.nodeValue; 280 } else if (node.nodeType === Node.ELEMENT_NODE) { 281 const nodeStyles = window.getComputedStyle(node); 282 283 if (node.nodeName === 'A') { 284 result += `(${node.href})`; 285 } else if (node.nodeName === 'BR') { 286 result += '\n\n'; 287 } else if ( 288 nodeStyles.display === 'block' || 289 nodeStyles.display === 'list-item' 290 ) { 291 result += '\n'; 292 } 293 } 294 } 295 return result.trim(); 296 } 297
298 setAnchors.forEach(el => { 299 const elRect = el.getBoundingClientRect(); 300 const isRtl = document.documentElement.getAttribute('dir') === 'rtl'; 301 302 if ( 303 (!isRtl && elRect.right > window.innerWidth) || 304 (isRtl && elRect.left < 0) 305 ) { 306 el.classList.add('anchor-end'); 307 } 308 }); 309})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.