1class InfiniTE { 2 constructor(options) { 3 this.urls = []; 4 this.isLoading = false; 5 this.currentUrlIndex = 0; 6 this.contentContainer = $(options.contentContainer || '.infinite'); 7 this.loadingDiv = $(options.loadingDiv || '.infinite_loader'); 8 this.jsonUrl = options.jsonUrl || null; 9 this.itemSelector = options.itemSelector || '.infinite-item'; 10 this.galleryPageSelector = options.galleryPageSelector || '[data-gallery-page]'; 11 this.paginationSelector = options.paginationSelector || 'a.pagination__next'; 12 this.threshold = options.threshold || 100; 13 this.onLoadSuccess = options.onLoadSuccess || null; 14 this.scrollPages = []; 15 this.windowHeight = window.innerHeight; 16 this.lastScrollPosition = 0; 17 18 if (this.contentContainer.length === 0) { 19 return; 20 } 21 22 this.scrollPages.push({ 23 top: 0, 24 url: window.location.pathname, 25 title: document.title 26 }); 27 28 this.appendLoader(); 29 this.init(); 30 } 31 32 appendLoader() { 33 const loaderHtml = ` 34 <div class="infinite_loader container d-flex justify-content-center mb-3 bg-white p-3 d-none"> 35 <div class="infinite_animation"></div> 36 </div>`; 37 this.contentContainer.after(loaderHtml); 38 this.loadingDiv = this.contentContainer.next('.infinite_loader'); 39 } 40 41 async fetchUrlList() { 42 const customJsonUrl = this.contentContainer.find(this.itemSelector).data('json-url'); 43 if (customJsonUrl) { 44 this.jsonUrl = customJsonUrl; 45 } 46 47 if (this.jsonUrl) { 48 try { 49 const response = await $.getJSON(this.jsonUrl); 50 if (!response.error && Array.isArray(response.data) && response.data.length > 0) { 51 this.urls = response.data; 52 } else { 53 console.warn('JSON response boÅ veya geçersiz, fallback çalıÅtırılıyor.'); 54 this.fallbackToNextLink(); 55 } 56 } catch (error) { 57 console.error('URL listesi alınırken hata oluÅtu, fallback çalıÅtırılıyor:', error); 58 this.fallbackToNextLink(); 59 } 60 } else { 61 this.fallbackToNextLink(); 62 } 63 } 64 65 fallbackToNextLink() { 66 const nextLink = this.contentContainer.find(this.paginationSelector).attr('href'); 67 if (nextLink) { 68 this.urls = [nextLink]; 69 } else { 70 console.error(`${this.paginationSelector} içinde geçerli bir href bulunamadı.`); 71 } 72 } 73 74 async loadContent() { 75 if (this.isLoading || this.currentUrlIndex >= this.urls.length) return; 76 77 this.isLoading = true; 78 this.loadingDiv.removeClass('d-none'); 79 80 const currentUrl = this.urls[this.currentUrlIndex]; 81 82 try { 83 const data = await $.get(currentUrl); 84 const newItems = $(data).find(this.itemSelector); 85 this.contentContainer.append(newItems); 86 87 const newTitle = $(data).filter('title').text() || 'Yeni Sayfa'; 88 const newItemTop = newItems.first().offset().top; 89 90 this.scrollPages.push({ 91 top: newItemTop, 92 url: new URL(currentUrl, window.location.origin).pathname, 93 title: newTitle 94 }); 95 96 this.scrollPages.sort((a, b) => a.top - b.top); 97 98 const nextLink = $(data).find(this.paginationSelector).attr('href'); 99 if (nextLink) this.urls.push(nextLink); 100 101 this.currentUrlIndex++; 102 103 if (typeof this.onLoadSuccess === 'function') { 104 this.onLoadSuccess(newItems); 105 } 106 } catch (error) { 107 console.error('İçerik yüklenirken hata oluÅtu:', currentUrl, error); 108 } finally { 109 this.isLoading = false; 110 this.loadingDiv.addClass('d-none'); 111 } 112 } 113 114 updateUrlHistory(url, title, replace = false) { 115 // Sadece URL gerçekten deÄiÅmiÅse History API kullan 116 if (window.location.pathname + window.location.search !== url) { 117 document.title = title; 118 if (replace) { 119 window.history.replaceState({ path: url }, title, url); 120 } else { 121 window.history.pushState({ path: url }, title, url); 122 } 123 } else { 124 // Sadece title güncelle 125 document.title = title; 126 } 127 } 128 129 updateScrollHistory() { 130 const scrollY = window.scrollY; 131 const viewportMiddle = scrollY + (this.windowHeight / 2); 132 let currentPage = null; 133 134 for (let i = 0; i < this.scrollPages.length; i++) { 135 const page = this.scrollPages[i]; 136 if (page.top <= viewportMiddle) { 137 currentPage = page; 138 } else { 139 break; 140 } 141 } 142 143 const gallerySelector = this.galleryPageSelector; 144 if (this.contentContainer.find(gallerySelector).length > 0) { 145 this.contentContainer.find(gallerySelector).each((_, element) => { 146 const $element = $(element); 147 const elementTop = $element.offset().top; 148 const elementBottom = elementTop + $element.outerHeight(); 149 150 if (elementTop <= viewportMiddle && viewportMiddle <= elementBottom) { 151 const pageNumber = $element.data('gallery-page'); 152 153 if (currentPage) { 154 const url = new URL(currentPage.url, window.location.origin); 155 156 if (pageNumber === 1) { 157 url.searchParams.delete('page'); 158 } else { 159 url.searchParams.set('page', pageNumber); 160 } 161 162 currentPage.url = url.pathname + url.search; 163 } 164 return false;
165 } 166 }); 167 } 168 169 if (currentPage && window.location.href !== currentPage.url) { 170 this.updateUrlHistory(currentPage.url, currentPage.title, true); 171 } 172 } 173 174 startScrollListener() { 175 let scrollTimeout; 176 177 $(window).on('scroll', () => { 178 const currentScroll = window.scrollY; 179 const scrollingDown = currentScroll > this.lastScrollPosition; 180 this.lastScrollPosition = currentScroll; 181 182 // Son içerik yüklenmeden önce kontrol et 183 const lastItem = this.contentContainer.find(this.itemSelector).last(); 184 if (lastItem.length) { 185 const lastItemOffset = lastItem.offset().top; 186 const lastItemHeight = lastItem.outerHeight(); 187 const scrollTriggerPoint = lastItemOffset + lastItemHeight - (this.windowHeight * 0.8); 188 189 if (scrollY >= scrollTriggerPoint && scrollingDown) { 190 this.loadContent(); 191 } 192 } 193 194 clearTimeout(scrollTimeout); 195 scrollTimeout = setTimeout(() => { 196 this.updateScrollHistory(); 197 }, 100); 198 }); 199 200 $(document).ready(() => { 201 this.updateScrollHistory(); 202 }); 203 } 204 205 async init() { 206 await this.fetchUrlList(); 207 this.startScrollListener(); 208 } 209}
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.