1jQuery(function() { 2 if (!is_touch_device()) { 3 jQuery(".draggableimage").draggable({ 4 appendTo: "body", 5 helper: "clone" 6 }); 7 } 8}); 9 10 11 12if (window.opener) { 13 if (typeof window.opener.addToCartWithPrice == "function") { 14 addToCartWithPrice = window.opener.addToCartWithPrice; 15 } 16 if (typeof window.opener.logon == "function") { 17 logon = window.opener.logon; 18 } 19} 20 21function goBack() { 22 if (history.state && history.state.fromSearchUrl) { 23 history.back(); 24 } else { 25 location.href = sessionStorage.getItem('lastSearchUrl') || SEARCHPAGE_URL; 26 } 27} 28 29function clampToTwoRows(container) { 30 const items = [...container.querySelectorAll(".image_wrapper")]; 31 if (!items.length) return; 32 33 function getClampThreshold() { 34 // Group items into rows by their vertical position 35 const rowSizes = [0]; 36 let currentTop = items[0].offsetTop; 37 for (let i = 1; i < items.length; i++) { 38 const top = items[i].offsetTop; 39 if (top !== currentTop) { 40 rowSizes.push(0); 41 currentTop = top; 42 } 43 rowSizes[rowSizes.length - 1]++; 44 } 45 rowSizes[0]++; 46 47 // If exactly 2 rows and the second row isn't full, clamp to 1 row 48 if (rowSizes.length === 2 && rowSizes[1] < rowSizes[0]) { 49 return 1; 50 } 51 return 2; 52 } 53 54 const clampRows = getClampThreshold(); 55 let row = 1; 56 let currentTop = items[0].offsetTop; 57 let hasHidden = false; 58 59 for (let i = 1; i < items.length; i++) { 60 const top = items[i].offsetTop; 61 62 if (top !== currentTop) { 63 row++; 64 currentTop = top; 65 } 66 67 if (row > clampRows) { 68 items[i].classList.add('series-clamped-hidden'); 69 hasHidden = true; 70 } 71 } 72 73 const btns = container.querySelectorAll(".show_all_in_series_btn"); 74 75 btns.forEach(btn => { 76 if (!hasHidden) { 77 btn.style.display = 'none'; 78 } else { 79 btn.addEventListener('click', function() { 80 const collapsed = container.querySelectorAll('.series-clamped-hidden').length > 0; 81 container.querySelectorAll('.series-clamped-hidden').forEach(el => el.classList.remove('series-clamped-hidden')); 82 if (!collapsed) { 83 const r = getClampThreshold(); 84 let row = 1; 85 let curTop = items[0].offsetTop; 86 for (let i = 1; i < items.length; i++) { 87 const top = items[i].offsetTop; 88 if (top !== curTop) { 89 row++; 90 curTop = top; 91 } 92 if (row > r) items[i].classList.add('series-clamped-hidden'); 93 } 94 btns.forEach(b => b.textContent = i18nVisaAlla); 95 } else { 96 btns.forEach(b => b.textContent = i18nVisaFarre); 97 } 98 }); 99 } 100 }); 101} 102 103function fetchSeriesMosaic(type) { 104 const params = new URLSearchParams({ 105 imageNumber: imageNumber, 106 series: imageSeries, 107 photoshoot: imagePhotoshoot, 108 type: type 109 }); 110 111 return fetch("/ajax.php?mode=RENDERSERIESMOSAIC&" + params.toString()) 112 .then(r => r.text()) 113 .catch(() => ""); 114} 115 116function loadSearchwords() { 117 const container = document.getElementById("searchwords_section"); 118 119 const params = new URLSearchParams({ 120 imageNumber: imageNumber, 121 name: imageName, 122 pcode: imagePcode, 123 search_lang: searchLang, 124 seriesMode: seriesMode, 125 }); 126 127 fetch("/ajax.php?mode=RENDERSEARCHWORDS&" + params.toString()) 128 .then(r => r.text()) 129 .then(html => { 130 if (container) container.innerHTML = html; 131 }); 132} 133 134function loadSearchwordsSection() { 135 var section = jQuery('#searchwords_section'); 136 if (section.data('loaded')) return; 137 section.data('loaded', true); 138 loadSearchwords(); 139} 140 141function initSearchwordsObserver() { 142 const section = document.getElementById('searchwords_section'); 143 if (!section) return; 144 145 const observer = new IntersectionObserver(entries => { //liten marginal: börja hämta strax innan sektionen syns, men inte så tidigt att det laddas i onödan för den som aldrig skrollar dit 146 if (entries[0].isIntersecting) { 147 loadSearchwordsSection(); 148 observer.disconnect(); 149 } 150 }, { 151 rootMargin: '200px 0px' 152 });
153 154 observer.observe(section); 155} 156 157function toggleSearchwords() { 158 document.getElementById('searchwords_section').scrollIntoView({ behavior: 'smooth' }); 159} 160 161function loadSeriesSection() { 162 var section = jQuery('#series_section'); 163 if (section.data('loaded')) return; 164 section.data('loaded', true); 165 166 const types = []; 167 if (imageSeries) types.push("seriesslides", "moviesslides"); 168 if (imagePhotoshoot) types.push("psslides", "psmoviesslides"); 169 170 // Hämta alla delar först och rendera dem i ett enda svep. Tidigare fylldes varje behållare 171 // med shimmer-platshållare och byttes ut var för sig när svaret kom, vilket fick sektionen 172 // att hoppa till och krympa flera gånger i rad medan de fyra delarna trillade in. 173 Promise.all(types.map(fetchSeriesMosaic)).then(htmls => { 174 types.forEach((type, i) => { 175 const container = document.getElementById(type); 176 if (container) container.innerHTML = htmls[i]; 177 }); 178 types.forEach((type, i) => { 179 const container = document.getElementById(type); 180 if (container && htmls[i].trim()) { 181 clampToTwoRows(container); 182 initHoverVideo(container); 183 container.animate([{ opacity: 0 }, { opacity: 1 }], { duration: 200, easing: 'ease' }); 184 } 185 }); 186 }); 187} 188 189function initSeriesObserver() { 190 const section = document.getElementById('series_section'); 191 if (!section || (!imageSeries && !imagePhotoshoot)) return; 192 193 const observer = new IntersectionObserver(entries => { //liten marginal: börja hämta strax innan sektionen syns så innehållet hinner falla på plats innan man skrollat fram, men inte så tidigt att det laddas i onödan för den som aldrig skrollar dit 194 if (entries[0].isIntersecting) { 195 loadSeriesSection(); 196 observer.disconnect(); 197 } 198 }, { 199 rootMargin: '200px 0px' 200 }); 201 202 observer.observe(section); 203} 204 205function toggleSeries() { 206 document.getElementById('series_section').scrollIntoView({ behavior: 'smooth' }); 207} 208 209var image_number = imageNumber; 210 211function swToggleSearchId(swid, checked, word) { 212 if (checked) { 213 window.opener.addGetParam("searchid[]", swid); 214 } else { 215 window.opener.removeGetParam("searchid[]", swid); 216 } 217 console.log("sw", swid, checked, word); 218} 219 220function swToggleOrSearchId(swid, checked, word) { 221 if (checked) { 222 window.opener.addGetParam("orsearchid[]", swid); 223 } else { 224 window.opener.removeGetParam("orsearchid[]", swid); 225 } 226 console.log("sw", swid, checked, word); 227} 228 229function swSearch(form, openInNewTab) { 230 const terms = []; 231 const ids = []; 232 233 form.querySelectorAll('.sw-check:checked').forEach(function(ch) { 234 if (ch.dataset.type === 'id') { 235 ids.push(ch.value); 236 } else { 237 const label = form.querySelector('label[for="' + ch.id + '"]'); 238 const term = label && label.dataset.term ? label.dataset.term.trim() : ''; 239 if (term) terms.push(term); 240 } 241 }); 242 243 var url = SEARCHPAGE_URL + '?mode=search'; 244 if (terms.length > 0) url += '&freetext=' + encodeURIComponent(terms.join(' ')); 245 ids.forEach(function(id) { url += '&searchid[]=' + encodeURIComponent(id); }); 246 247 if (openInNewTab) { 248 window.open(url, '_blank'); 249 } else { 250 window.location.href = url; 251 } 252} 253 254 255function initImagePage() { 256 const el = document.getElementById('image-page-content'); 257 if (!el) return; 258 const config = JSON.parse(el.dataset.config); 259 console.log("init image page with config", config); 260 261 lang = config.lang; 262 userId = config.userId; 263 companyId = config.companyId; 264 countryId = config.countryId; 265 priceListId = config.priceListId; 266 imageNumber = config.imageNumber; 267 levelZero = config.levelZero; 268 currency = config.currency; 269 VAT = config.VAT; 270 imageSeries = config.imageSeries; 271 imagePhotoshoot = config.imagePhotoshoot; 272 imageName = config.imageName; 273 imagePcode = config.imagePcode; 274 searchLang = config.searchLang; 275 seriesMode = config.seriesMode; 276 277 if (config.caption) document.title = config.caption; 278 279 if (document.getElementById('price-plan-card')) {
280 loadPricePlan(config.imageNumber, config.levelZero); 281 } 282 283 initSeriesObserver(); 284 initSearchwordsObserver(); 285} 286
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.