1window.contentListShowMore = function (url, trackingModule, filters = []) { 2 return { 3 filters, 4 selectedFilter: {}, 5 showMore: !!url, 6 showMoreUrl: url ?? "", 7 trackingModule, 8 lastScrollPosition: 0, 9 template: window?.template ?? "", 10 currentPage: 1, 11 selectFilter: function (item = null) { 12 this.selectedFilter = item; 13 this.currentPage = this.selectedFilter?.currentPage ?? 1; 14 15 if (this.selectedFilter?.showMore !== undefined) { 16 this.showMore = this.selectedFilter.showMore; 17 } 18 19 if (this.selectedFilter?.showMoreUrl) { 20 this.showMoreUrl = this.selectedFilter.showMoreUrl; 21 } 22 23 this.updatePaginationDisplay(); 24 25 if (this.shouldUseFullReload()) { 26 const url = new URL(window.location.href); 27 28 if (this.selectedFilter.model === "all") { 29 url.searchParams.delete("model"); 30 } else { 31 url.searchParams.set("model", this.selectedFilter.model); 32 } 33 34 if (this.selectedFilter?.id !== undefined && this.selectedFilter?.id !== null && this.selectedFilter?.id !== "") { 35 url.searchParams.set("id", this.selectedFilter.id); 36 } else { 37 url.searchParams.delete("id"); 38 } 39 40 url.searchParams.delete("type"); 41 42 url.searchParams.set("page", "1"); 43 44 // Save scroll position before reload 45 sessionStorage.setItem('contentListScrollPosition', window.scrollY.toString()); 46 47 window.location.href = url.toString(); 48 49 return; 50 } 51 52 const containerId = this.selectedFilter.slug 53 ? `${this.selectedFilter.slug}-show-more-content-${this.trackingModule}` 54 : `show-more-content-${this.trackingModule}`; 55 const container = document.getElementById(containerId); 56 57 if (container && container.children.length) { 58 return; 59 } 60 61 this.getNextPage(); 62 }, 63 shouldUseFullReload: function () { 64 return Boolean(this.selectedFilter?.requires_full_reload); 65 }, 66 updatePaginationDisplay: function () { 67 if (typeof window !== "undefined" && typeof window.dispatchEvent === "function") { 68 const detail = { 69 totalPages: this.selectedFilter?.totalPages ?? this.currentPage, 70 currentPage: this.selectedFilter?.currentPage ?? this.currentPage, 71 filterModel: this.selectedFilter?.model ?? "all", 72 }; 73 74 window.dispatchEvent(new CustomEvent("filter-changed", { detail })); 75 } 76 }, 77 getNextPage: async function () { 78 const includeId = this.selectedFilter?.id !== undefined && this.selectedFilter?.id !== null && this.selectedFilter?.id !== ""; 79 80 const updates = { 81 type: this.selectedFilter.slug, 82 model: this.selectedFilter.model, 83 ajax: "1", 84 }; 85 86 if (includeId) { 87 updates.id = this.selectedFilter.id; 88 } 89 90 const searchParams = new URLSearchParams(this.showMoreUrl.split("?")[1]); 91 Object.entries(updates).forEach(([key, value]) => searchParams.set(key, value)); 92 93 if (!includeId) { 94 searchParams.delete("id"); 95 } 96 97 // Update page parameter for the current filter 98 const nextPage = this.currentPage + 1; 99 searchParams.set("page", nextPage); 100 101 const url = `${this.showMoreUrl.split("?")[0]}?${searchParams.toString()}`; 102 try { 103 const response = await fetch(url); 104 if (!response.ok) throw { status: response.status, statusText: response.statusText, url: response.url }; 105 const { showMore, showMoreUrl, contentHubStrips, totalPages, currentPage, totalItems } = await response.json(); 106 this.showMore = showMore; 107 this.showMoreUrl = showMoreUrl; 108 this.selectedFilter.showMore = showMore; 109 this.selectedFilter.showMoreUrl = showMoreUrl; 110 111 // Update pagination info from server response 112 if (totalPages !== undefined) { 113 this.selectedFilter.totalPages = totalPages; 114 } 115 if (totalItems !== undefined) { 116 this.selectedFilter.totalItems = totalItems; 117 } 118 119 // Update current page after successful load 120 this.currentPage = currentPage || nextPage; 121 this.selectedFilter.currentPage = currentPage || nextPage; 122 123 let str = contentHubStrips; 124 const regexp = /data-id=\"([^\"]+)\"/g; 125 const matches = [...str.matchAll(regexp)]; 126
127 matches.forEach((value) => { 128 if (document.querySelectorAll(`[${value[0]}]`).length) { 129 const dataValue = `${value[1]}" class="`; 130 const position = str.indexOf(dataValue) + dataValue.length; 131 str = str.substr(0, position) + str.substr(position); 132 } 133 }); 134 135 this.lastScrollPosition = window.scrollY; 136 const showMoreContentContainerId = this.selectedFilter.slug 137 ? `${this.selectedFilter.slug}-show-more-content-${this.trackingModule}` 138 : `show-more-content-${this.trackingModule}`; 139 document.getElementById(showMoreContentContainerId).insertAdjacentHTML("beforeend", str); 140 this.$nextTick(() => { 141 window.scrollTo({ top: this.lastScrollPosition + 1, behavior: "auto" }); 142 // Update pagination display after loading new content 143 this.updatePaginationDisplay(); 144 }); 145 } catch (error) { 146 console.error("Error fetching data:", error); 147 } 148 }, 149 init: function () { 150 if (this.filters.length) { 151 // Check URL parameters to determine initial filter 152 const urlParams = new URLSearchParams(window.location.search); 153 const modelFromUrl = urlParams.get("model") || "all"; 154 const idFromUrl = urlParams.get("id"); 155 const typeFromUrl = urlParams.get("type"); 156 157 const potentialPageKeys = [typeFromUrl, modelFromUrl, "page"].filter(Boolean); 158 let pageFromUrl = "1"; 159 for (const key of potentialPageKeys) { 160 const value = urlParams.get(key); 161 if (value) { 162 pageFromUrl = value; 163 break; 164 } 165 } 166 167 // Find the filter that matches the URL parameters as closely as possible 168 const initialFilter = this.filters.find((filter) => { 169 if (filter.model !== modelFromUrl) { 170 return false; 171 } 172 173 if (idFromUrl) { 174 return String(filter.id ?? "") === idFromUrl; 175 } 176 177 if (typeFromUrl) { 178 return filter.slug === typeFromUrl; 179 } 180 181 return true; 182 }) || this.filters[0]; 183 184 this.selectedFilter = initialFilter; 185 const currentPage = parseInt(pageFromUrl, 10) || 1; 186 this.selectedFilter.currentPage = currentPage; 187 188 // Only show "Show More" if there are more pages available 189 if (this.selectedFilter.totalPages !== undefined) { 190 this.selectedFilter.showMore = !!url && (this.selectedFilter.totalPages > currentPage); 191 } 192 193 this.selectedFilter.showMoreUrl = this.selectedFilter.showMoreUrl ?? url; 194 this.currentPage = currentPage; 195 this.showMore = this.selectedFilter.showMore ?? !!url; 196 this.updatePaginationDisplay(); 197 198 // Initialize each filter with its current page if not already set 199 this.filters.forEach((filter) => { 200 if (!filter.currentPage) { 201 filter.currentPage = 1; 202 } 203 }); 204 } 205 206 // Restore scroll position after full page reload 207 const savedScrollPosition = sessionStorage.getItem('contentListScrollPosition'); 208 if (savedScrollPosition !== null) { 209 setTimeout(() => { 210 window.scrollTo({ top: parseInt(savedScrollPosition, 10), behavior: 'auto' }); 211 sessionStorage.removeItem('contentListScrollPosition'); 212 }, 100); 213 } 214 }, 215 }; 216};
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.