PageSourceSearch

https://dibaqpetcare.com/modules/prestablog/views/js/toc.js

js dibaqpetcare.com collected 2026-09-24 13:09:44 UTC 8,436 bytes, 258 lines download raw bytes

1/**
2 * 2008 - 2024 (c) Prestablog
3 *
4 * MODULE PrestaBlog
5 *
6 * @author    Prestablog
7 * @copyright Copyright (c) permanent, Prestablog
8 * @license   Commercial
9 */
10
11// Global function for the onclick attribute in templates
12function toggleTOC(element) {
13  const toc = element.closest('.prestablog-toc');
14  if (toc) {
15    // Toggle the collapsed class
16    if (toc.classList.contains('collapsed')) {
17      toc.classList.remove('collapsed');
18      
19      // Store state in localStorage
20      if (toc.id) {
21        localStorage.setItem('prestablog_toc_' + toc.id, 'expanded');
22      }
23      
24      // Réactiver le placeholder si nécessaire
25      const tocWrapper = toc.closest('.toc-wrapper');
26      if (tocWrapper) {
27        const placeholder = tocWrapper.querySelector('.toc-placeholder');
28        if (placeholder) {
29          placeholder.style.display = 'block';
30        }
31      }
32    } else {
33      toc.classList.add('collapsed');
34      
35      // Store state in localStorage
36      if (toc.id) {
37        localStorage.setItem('prestablog_toc_' + toc.id, 'collapsed');
38      }
39      
40      // Masquer le placeholder
41      const tocWrapper = toc.closest('.toc-wrapper');
42      if (tocWrapper) {
43        const placeholder = tocWrapper.querySelector('.toc-placeholder');
44        if (placeholder) {
45          placeholder.style.display = 'none';
46        }
47      }
48    }
49  }
50}
51
52// Initialize TOC on page load
53document.addEventListener('DOMContentLoaded', function() {
54  // Restore saved state from localStorage
55  const allTocs = document.querySelectorAll('.prestablog-toc');
56  allTocs.forEach(function(toc) {
57    if (toc.id) {
58      const savedState = localStorage.getItem('prestablog_toc_' + toc.id);
59      if (savedState === 'expanded') {
60        toc.classList.remove('collapsed');
61      } else {
62        // Default is collapsed
63        toc.classList.add('collapsed');
64      }
65    }
66  });
67  
68  // Highlight active section while scrolling
69  const tocLinks = document.querySelectorAll('.prestablog-toc-link');
70  const headings = [];
71  
72  // Get all heading elements that have IDs
73  tocLinks.forEach(function(link) {
74    const targetId = link.getAttribute('href').substring(1);
75    const targetHeading = document.getElementById(targetId);
76    if (targetHeading) {
77      headings.push({
78        element: targetHeading,
79        link: link
80      });
81    }
82  });
83  
84  // Set up scroll event to highlight current section
85  if (headings.length > 0) {
86    window.addEventListener('scroll', function() {
87      const scrollPosition = window.scrollY + 100; // Offset for better UX
88      
89      // Find the current visible heading
90      let currentHeading = null;
91      for (let i = 0; i < headings.length; i++) {
92        const heading = headings[i];
93        if (heading.element.offsetTop <= scrollPosition) {
94          currentHeading = heading;
95        } else {
96          break;
97        }
98      }
99      
100      // Remove highlight from all links
101      tocLinks.forEach(function(link) {
102        link.classList.remove('active');
103      });
104      
105      // Add highlight to current link
106      if (currentHeading) {
107        currentHeading.link.classList.add('active');
108      }
109    });
110    
111    // Trigger scroll event once on page load
112    window.dispatchEvent(new Event('scroll'));
113  }
114  
115  // Add smooth scrolling to TOC links
116  tocLinks.forEach(function(link) {
117    link.addEventListener('click', function(e) {
118      e.preventDefault();
119      const targetId = this.getAttribute('href').substring(1);
120      const targetElement = document.getElementById(targetId);
121      
122      if (targetElement) {
123        // Calculer un offset dynamique basé sur la taille du TOC et une marge fixe
124        let dynamicOffset = 150; // Valeur de base
125        
126        // Obtenir le TOC et sa hauteur si possible
127        const tocElement = document.querySelector('.prestablog-toc');
128        if (tocElement) {
129          if (tocElement.classList.contains('toc-fixed')) {
130            // Si le TOC est fixe, on prend sa hauteur réelle
131            dynamicOffset = tocElement.offsetHeight + 50; // 50px de marge supplémentaire
132          } else {
133            // Sinon on utilise une valeur plus importante pour être sûr
134            dynamicOffset = Math.max(200, tocElement.offsetHeight + 50);
135          }
136        }
137        
138        // Position absolue dans le document
139        const targetPosition = targetElement.getBoundingClientRect().top + window.scrollY;
140        
141        // Défilement avec offset dynamique
142        window.scrollTo({
143          top: targetPosition - dynamicOffset,
144          behavior: 'smooth'
145        });
146      }
147    });
148  });
149  
150  // Setup sticky TOC with JavaScript (no layout shift approach)
151  function setupStickyTOC() {
152    // Get floating TOCs, but ignore those inside Swiper
153    const floatTocs = document.querySelectorAll('.prestablog-toc.float-toc');
154    const validTocs = Array.from(floatTocs).filter(toc => !toc.closest('.prestablogswip'));
155    
156    if (validTocs.length === 0) {
157      return;
158    }
159    
160    // Get content area for boundary detection
161    const contentArea = document.getElementById('prestablogfont');
162    if (!contentArea) {
163      return;
164    }
165    
166    // Process each valid TOC
167    validTocs.forEach(function(toc) {
168      // Create a wrapper that will contain both TOC and placeholder
169      const wrapper = document.createElement('div');
170      wrapper.className = 'toc-wrapper';
171      
172      // Move the TOC into the wrapper
173      toc.parentNode.insertBefore(wrapper, toc);
174      wrapper.appendChild(toc);
175      
176      // Create a placeholder - TOUJOURS visible mais transparent
177      const placeholder = document.createElement('div');
178      placeholder.className = 'toc-placeholder';
179      wrapper.appendChild(placeholder);
180      
181      // Set placeholder dimensions IMMÉDIATEMENT
182      placeholder.style.width = toc.offsetWidth + 'px';
183      placeholder.style.height = toc.offsetHeight + 'px';
184      
185      // Get initial position of the TOC
186      const tocOffsetTop = wrapper.offsetTop;
187      
188      // Handle scroll event with throttling
189      let lastScrollTime = 0;
190      let scrollTimeout = null;
191      let lastScrollY = window.scrollY;
192      let scrollDirection = 'down';
193      
194      function handleScroll() {
195        // Throttle scroll events
196        const now = Date.now();
197        if (now - lastScrollTime < 50) { // 50ms throttle
198          clearTimeout(scrollTimeout);
199          scrollTimeout = setTimeout(handleScroll, 50);
200          return;
201        }
202        lastScrollTime = now;
203        
204        const scrollY = window.scrollY;
205        
206        scrollDirection = scrollY > lastScrollY ? 'down' : 'up';
207        lastScrollY = scrollY;
208        
209        const contentBottom = contentArea.offsetTop + contentArea.offsetHeight;
210               
211        // begin: 200px after the start of the content
212        const startThreshold = tocOffsetTop + 200;
213        
214        // end: maintain visible until 100px after the end of the content
215        const endThreshold = contentBottom + 100;
216        
217        // Check if we are in the zone where the TOC should be fixed
218        const shouldBeFixed = scrollY > startThreshold && scrollY < endThreshold;
219        
220        if (shouldBeFixed) {
221          // If the TOC is not already fixed, make it fixed
222          if (!toc.classList.contains('toc-fixed')) {
223            toc.classList.add('toc-fixed');
224            toc.style.width = placeholder.style.width;
225            toc.style.left = wrapper.getBoundingClientRect().left + 'px';
226          } else {
227            toc.style.left = wrapper.getBoundingClientRect().left + 'px';
228          }
229        } else {
230          if (toc.classList.contains('toc-fixed')) {
231            toc.classList.remove('toc-fixed');
232            toc.style.width = '';
233            toc.style.left = '';
234          }
235        }
236      }
237
238      window.addEventListener('scroll', handleScroll, { passive: true });
239      
240      // Handle resize event to update dimensions
241      window.addEventListener('resize', function() {
242        placeholder.style.width = toc.offsetWidth + 'px';
243        placeholder.style.height = toc.offsetHeight + 'px';
244        
245        if (toc.classList.contains('toc-fixed')) {
246          toc.style.width = placeholder.style.width;
247          toc.style.left = wrapper.getBoundingClientRect().left + 'px';
248        }
249      });
250      
251      // Trigger initial check
252      handleScroll();
253    });
254  }
255  
256  // Initialize TOC
257  setupStickyTOC();
258});

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.