1function initNewsFeedInstance(feed, scrollContainer) { 2 3 if (!feed) return; 4 5 const list = feed.querySelector('.news-feed__list') 6 if (!list) return; 7 8 const app = { 9 init() { 10 11 this.page = 1 12 this.feed = feed 13 this.list = list 14 15 this.scrollContainer = scrollContainer || window 16 17 this.isLoading = false 18 this.hasMore = true 19 this.page = 2 20 this.maxPages = 20 21 this.ajaxUrl = window.feed_ajax_path + '/include_component.php' 22 this.isMobile = window.matchMedia('(max-width: 767px)').matches 23 24 this.bindLoadMoreButton() 25 26 if (!this.isMobile) { 27 this.createSentinel() 28 this.initObserver() 29 } 30 this.handleResize = () => { 31 const isMobileNow = window.matchMedia('(max-width: 767px)').matches 32 33 if (isMobileNow !== this.isMobile) { 34 this.isMobile = isMobileNow 35 36 if (this.isMobile) { 37 // вÑклÑÑаем infinite scroll 38 if (this.observer && this.sentinel) { 39 this.observer.unobserve(this.sentinel) 40 this.observer.disconnect() 41 } 42 } else { 43 // вклÑÑаем обÑаÑно 44 this.createSentinel() 45 this.initObserver() 46 } 47 } 48 } 49 50 window.addEventListener('resize', this.handleResize) 51 }, 52 53 createSentinel() { 54 const existing = this.list.querySelector('.news-feed__sentinel') 55 if (existing) { 56 this.sentinel = existing 57 return 58 } 59 60 const sentinel = document.createElement('div') 61 sentinel.className = 'news-feed__sentinel' 62 this.list.appendChild(sentinel) 63 this.sentinel = sentinel 64 }, 65 66 initObserver() { 67 68 const root = 69 this.scrollContainer && this.scrollContainer !== window 70 ? this.scrollContainer 71 : null 72 73 console.log('root',root) 74 75 this.observer = new IntersectionObserver( 76 (entries) => { 77 entries.forEach((entry) => { 78 if (entry.isIntersecting) { 79 this.loadMore() 80 } 81 }) 82 }, 83 { 84 root, 85 rootMargin: '200px', 86 threshold: 0, 87 } 88 ) 89 90 this.observer.observe(this.sentinel) 91 }, 92 93 bindLoadMoreButton() { 94 const btn = this.feed.querySelector('.news-feed__more a') 95 if (!btn) return 96 97 this.loadMoreBtn = btn 98 99 this.loadMoreHandler = (e) => { 100 e.preventDefault() 101 this.loadMore() 102 } 103 104 btn.addEventListener('click', this.loadMoreHandler) 105 }, 106 executeScripts(item) { 107 // ÐÐ°Ñ Ð¾Ð´Ð¸Ð¼ вÑе ÑкÑипÑÑ Ð²Ð½ÑÑÑи добавленной каÑÑоÑки 108 const scripts = item.querySelectorAll('script'); 109 110 scripts.forEach((oldScript) => { 111 const newScript = document.createElement('script'); 112 113 // ÐопиÑÑем ÑодеÑжимое ÑкÑипÑа 114 if (oldScript.innerHTML) { 115 newScript.innerHTML = oldScript.innerHTML; 116 } 117 118 // ÐопиÑÑем аÑÑибÑÑÑ (src, async и Ñ.д.), еÑли они еÑÑÑ 119 Array.from(oldScript.attributes).forEach((attr) => { 120 newScript.setAttribute(attr.name, attr.value); 121 }); 122 123 // ÐаменÑем ÑÑаÑÑй ÑкÑÐ¸Ð¿Ñ Ð½Ð° новÑй, ÑÑÐ¾Ð±Ñ Ð±ÑаÑÐ·ÐµÑ ÐµÐ³Ð¾ вÑполнил 124 oldScript.parentNode.replaceChild(newScript, oldScript); 125 }); 126 }, 127 128 async loadMore() { 129 if (this.isLoading || !this.hasMore) { 130 return 131 } 132 133 if (this.page > this.maxPages) { 134 this.hasMore = false 135 this.destroy() 136 return 137 } 138 139 this.isLoading = true 140 this.feed.classList.add('news-feed--loading') 141 142 try { 143 const url = `${this.ajaxUrl}?PAGEN=${this.page}` 144 145 const response = await fetch(url, { 146 headers: { 147 'X-Requested-With': 'XMLHttpRequest', 148 }, 149 cache: 'no-cache', 150 }) 151 152 if (!response.ok) { 153 throw new Error('Failed to load news feed') 154 } 155 156 const html = await response.text() 157 158 const wrapper = document.createElement('div') 159 wrapper.innerHTML = html 160 161 const ajaxList = wrapper.querySelector('.news-feed__list') 162 const source = 163 ajaxList && ajaxList.children.length 164 ? ajaxList 165 : wrapper 166 167 const items = Array.from( 168 source.querySelectorAll('.feed-card') 169 ) 170
171 items.forEach((item) => { 172 this.list.insertBefore(item, this.sentinel); 173 this.executeScripts(item); 174 }) 175 176 this.page++ 177 } catch (e) { 178 console.error(e) 179 this.hasMore = false 180 this.destroy() 181 } finally { 182 this.isLoading = false 183 this.feed.classList.remove('news-feed--loading') 184 } 185 }, 186 187 destroy() { 188 if (this.observer && this.sentinel) { 189 this.observer.unobserve(this.sentinel) 190 this.observer.disconnect() 191 } 192 193 if (this.scrollHandler && this.scrollTarget) { 194 this.scrollTarget.removeEventListener('scroll', this.scrollHandler) 195 } 196 197 if (this.sentinel && this.sentinel.parentNode) { 198 this.sentinel.parentNode.removeChild(this.sentinel) 199 } 200 201 if (this.loadMoreBtn && this.loadMoreHandler) { 202 this.loadMoreBtn.removeEventListener('click', this.loadMoreHandler) 203 } 204 205 if (this.handleResize) { 206 window.removeEventListener('resize', this.handleResize) 207 } 208 }, 209 } 210 211 app.init() 212} 213 214function NewsFeedScript() { 215 const feeds = document.querySelectorAll('.js-news-feed:not(.no-auto-load)') 216 if (!feeds.length) return 217 218 feeds.forEach((feed) => 219 initNewsFeedInstance(feed) 220 ) 221} 222 223if (typeof window !== 'undefined') { 224 if (!window.slam) { 225 window.slam = {} 226 } 227 228 window.slam.NewsFeedScriptInit = function (feed) { 229 const container = document.querySelector( 230 '.js-news-feed-target .news-feed__list:not(.no-auto-load)' 231 ) 232 233 initNewsFeedInstance(feed, container) 234 } 235 window.addEventListener('ReactContentLoaded', NewsFeedScript) 236 document.addEventListener('DOMContentLoaded', NewsFeedScript) 237} 238
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.