1$(document).ready(function(){ 2 3 if($('.category-perex .col.image img').length === 0){ 4 $('<style>@media (max-width: 767px) { .category-top::before { height: 480px; } }</style>').appendTo('head'); 5 } 6 7 function applyFlagLogic($scope){ 8 /* 9 var $root = ($scope && $scope.length) ? $scope : $(document); 10 11 $root.find('.flag.flag-discount').addBack('.flag.flag-discount').each(function(){ 12 var $flag = $(this); 13 if($flag.data('flag-processed')) return; 14 $flag.data('flag-processed', true); 15 16 var $priceStandard = $flag.find('.price-standard'); 17 if(!$priceStandard.length) return; 18 19 var $clone = $priceStandard.clone(); 20 $priceStandard.remove(); 21 22 var $target = $flag.closest('.products-block, .product').find('.p-bottom .prices').first(); 23 if($target.length) $target.prepend($clone); 24 }); 25 26 $root.find('.flag.flag-freeshipping').addBack('.flag.flag-freeshipping').each(function(){ 27 var $flag = $(this); 28 if($flag.data('flag-processed')) return; 29 $flag.data('flag-processed', true); 30 31 var $flagText = $flag.find('.flag-text'); 32 if($flagText.length) $flagText.text('Doprava zdarma'); 33 34 var $flagsDefault = $flag.closest('.products-block, .product').find('.flags-default').first(); 35 if($flagsDefault.length) $flag.appendTo($flagsDefault); 36 }); 37 */ 38 } 39 40 function getDeliveryText(){ 41 var now = new Date(); 42 var day = now.getDay(); 43 var delivery = new Date(now); 44 45 if(day === 5) delivery.setDate(now.getDate() + 3); 46 else if(day === 6) delivery.setDate(now.getDate() + 2); 47 else delivery.setDate(now.getDate() + 1); 48 49 var dateStr = delivery.getDate() + '. ' + (delivery.getMonth() + 1) + '.'; 50 var prefix = (day === 5 || day === 6) ? '' : 'již zÃtra '; 51 52 return prefix + dateStr + ' u vás'; 53 } 54 55 function applyDeliveryDate($scope){ 56 var $root = ($scope && $scope.length) ? $scope : $(document); 57 var text = getDeliveryText(); 58 59 $root.find('.availability-amount').addBack('.availability-amount').each(function(){ 60 if(this.textContent !== text){ 61 this.textContent = text; 62 } 63 }); 64 65 // Na nÄkterých shopech Shoptet .availability-amount vůbec nevykreslà (jiná 66 // konfigurace dostupnosti/skladu na tom shopu) - pak tu nenà nic k pÅepsánÃ. 67 // Proto ho do .availability doplnÃme sami, aÅ¥ termÃn dodánà jde vidÄt i tam. 68 // ZobrazenÃ/schovánà podle stavu skladem pak dál Åešà CSS 69 // (.availability:not(:has([data-original-title="Skladem."])) .availability-amount). 70 $root.find('.availability').addBack('.availability').each(function(){ 71 var $availability = $(this); 72 if($availability.find('.availability-amount').length) return; 73 74 $('<span class="availability-amount"></span>').text(text).appendTo($availability); 75 }); 76 } 77 78 function applyRatingBadges($scope){ 79 var $root = ($scope && $scope.length) ? $scope : $(document); 80 81 $root.find('.stars-wrapper[data-micro-rating-count]').addBack('.stars-wrapper[data-micro-rating-count]').each(function(){ 82 var el = this; 83 var count = el.getAttribute('data-micro-rating-count'); 84 85 $(el).find('.rating-count-badge').remove(); 86 87 if(!count || count === '0') return; 88 89 var badge = document.createElement('span'); 90 badge.className = 'rating-count-badge'; 91 badge.textContent = '(' + count + ')'; 92 badge.style.cssText = 'font-size:12px;color:#888;margin-top:2px;white-space:nowrap;'; 93 el.appendChild(badge); 94 }); 95 } 96 97 applyFlagLogic(); 98 applyDeliveryDate(); 99 applyRatingBadges(); 100 101 var progressUpdating = false; 102 var ajaxRefreshRunning = false; 103 var ajaxRefreshTimer = null; 104 var productsPerPage = 0; 105 106 function getCurrentPageFromUrl(){ 107 var match = window.location.href.match(/strana-(\d+)/); 108 return match ? parseInt(match[1], 10) : 1; 109 } 110 111 /* Kategorie (produkty) použÃvá #products .product, výpis Älánků 112 (body.type-posts-listing) použÃvá #newsWrapper .news-item. */ 113 function getListingItemsSelector(){ 114 return $('body').hasClass('type-posts-listing') ? '#newsWrapper .news-item' : '#products .product'; 115 } 116 117 /* Slovo za poÄtem v textu "Už jste vidÄli X z Y ___". U receptů/blogu 118 nedává "produktů" smysl, tak ho podle stránky pÅepneme. */ 119 function getItemsNoun(){ 120 var $body = $('body'); 121 if($body.hasClass('type-posts-listing')){ 122 return $body.hasClass('in-nase-recepty') ? 'receptů' : 'Älánků'; 123 } 124 return 'produktů'; 125 } 126 127 function fixLoadMoreButton(){ 128 var $btn = $('[data-testid="buttonMoreItems"]'); 129 if(!$btn.length) return; 130 if($btn.text() !== 'Zobrazit dalÅ¡Ã') $btn.text('Zobrazit dalÅ¡Ã'); 131 } 132 133 function updateProgressBar(){ 134 if(progressUpdating) return; 135 136 var $itemsTotal = $('.itemsTotal'); 137 if(!$itemsTotal.length) return; 138 139 var totalItems = parseInt($itemsTotal.find('strong').first().text(), 10) || 0; 140 if(!totalItems) return; 141 142 var currentPage = getCurrentPageFromUrl(); 143 var $products = $(getListingItemsSelector()); 144 145 if(productsPerPage === 0 || currentPage === 1){ 146 productsPerPage = $products.length; 147 } 148 149 if(!productsPerPage) return; 150 151 var isLastPage = !$('[data-testid="linkNextPage"]').length; 152 var seenProducts = isLastPage ? totalItems : Math.min(currentPage * productsPerPage, totalItems); 153 var percent = Math.round((seenProducts / totalItems) * 100); 154 var itemsNoun = getItemsNoun(); 155 156 progressUpdating = true; 157 158 var $existing = $('.iuv-progress-wrapper'); 159 160 if($existing.length){ 161 $existing.find('.iuv-progress-bar-fill').css('width', percent + '%'); 162 $existing.find('.iuv-progress-text').text('Už jste vidÄli ' + seenProducts + ' z ' + totalItems + ' ' + itemsNoun); 163 progressUpdating = false; 164 return; 165 } 166
167 var $wrapper = $('<div>', { class: 'iuv-progress-wrapper' }); 168 var $text = $('<p>', { class: 'iuv-progress-text', text: 'Už jste vidÄli ' + seenProducts + ' z ' + totalItems + ' ' + itemsNoun }); 169 var $barBg = $('<div>', { class: 'iuv-progress-bar-bg' }); 170 var $barFill = $('<div>', { class: 'iuv-progress-bar-fill' }); 171 172 $barFill.css('width', percent + '%'); 173 $barBg.append($barFill); 174 $wrapper.append($text).append($barBg); 175 $('.listingControls').prepend($wrapper); 176 177 progressUpdating = false; 178 } 179 180 /* Výpis receptů/Älánků nemá nativnà AJAX "Zobrazit dalÅ¡Ã" (buttonMoreItems) - 181 Shoptet tam renderuje jen klasické ÄÃslované stránkovánÃ. Tahle funkce 182 postavà vlastnà tlaÄÃtko, které natáhne dalšà stranu pÅes AJAX, pÅidá 183 nové .news-item do #newsWrapper a nahradà stránkovánà tÃm z natažené 184 stránky (aby dalšà klik Å¡el na stranu+2, pÅÃpadnÄ tlaÄÃtko zmizelo). */ 185 function initNewsLoadMore(){ 186 if(!$('body').hasClass('type-posts-listing')) return; 187 if($('.iuv-load-more').length) return; // už inicializováno 188 189 var $wrapper = $('#newsWrapper'); 190 if(!$wrapper.length) return; 191 192 var $pagination = $('.listingControls .pagination'); 193 if(!$pagination.find('[data-testid="linkNextPage"]').length) return; // poslednà strana 194 195 var $progressWrapper = $('.iuv-progress-wrapper'); 196 if(!$progressWrapper.length) return; // progress bar se vytváÅà dÅÃv (updateProgressBar()) 197 198 var loading = false; 199 200 // Shoptet má pro "Zobrazit dalÅ¡Ã" vlastnà nativnà tÅÃdy (.loadMore / .btn.loadMore__button) 201 // se stylem i flex/order rozvrženÃm uvnitÅ .listingControls - použitÃm stejných tÅÃd 202 // jako u kategorie odpadá potÅeba vlastnÃho CSS, vzhled bude automaticky sjednocený. 203 var $btnWrapper = $('<div>', { class: 'loadMore iuv-load-more' }); 204 var $btn = $('<button>', { 205 type: 'button', 206 class: 'btn loadMore__button', 207 text: 'Zobrazit dalÅ¡Ã' 208 }); 209 $btnWrapper.append($btn); 210 // Pod progress bar, nad zachované klasické stránkovánà (to zůstává vidÄt i funkÄnÃ) 211 $progressWrapper.after($btnWrapper); 212 213 // Shoptet ukazuje pÅi AJAXu (napÅ. na kategorii) celostránkový loader pÅes 214 // dvojici tÅÃd: ajax-pending (na body) + loader-wrapper (na kontejneru, 215 // jehož :before/:after Shoptet CSS vykreslà jako spinner + pÅeslech). 216 // position:relative na #content-wrapper doÄasnÄ doplnÃme pÅes JS, aÅ¥ 217 // pÅeslech sedà pÅesnÄ na jeho rozmÄr. 218 var $loaderTarget = $('#content-wrapper'); 219 220 function showAjaxLoader(){ 221 $('body').addClass('ajax-pending'); 222 $loaderTarget.addClass('loader-wrapper').css('position', 'relative'); 223 } 224 225 function hideAjaxLoader(){ 226 $('body').removeClass('ajax-pending'); 227 $loaderTarget.removeClass('loader-wrapper').css('position', ''); 228 } 229 230 $btn.on('click', function(){ 231 if(loading) return; 232 233 var $nextLink = $pagination.find('[data-testid="linkNextPage"]'); 234 var nextUrl = $nextLink.attr('href'); 235 if(!nextUrl) return; 236 237 loading = true; 238 $btn.prop('disabled', true).text('NaÄÃtám...'); 239 showAjaxLoader(); 240 241 $.get(nextUrl, function(html){ 242 var $doc = $($.parseHTML(html, document, true)); 243 var $newItems = $doc.find('#newsWrapper .news-item'); 244 var $newPagination = $doc.find('.listingControls .pagination'); 245 246 // Obrázky z natažené (jeÅ¡tÄ nezpracované) stránky majà lazyload jen 247 // pÅes data-src - Shoptet vlastnà lazyload skript sleduje jen obrázky 248 // pÅÃtomné pÅi naÄtenà stránky, na novÄ vložené nedosáhne. 249 $newItems.find('img[data-src]').each(function(){ 250 var $img = $(this); 251 var dataSrc = $img.attr('data-src'); 252 if(dataSrc && $img.attr('src') !== dataSrc){ 253 $img.attr('src', dataSrc); 254 } 255 $img.removeAttr('loading'); 256 }); 257 258 $wrapper.append($newItems); 259 $(document).trigger('newsItemsAppended', [$newItems]); 260 261 if(window.history && window.history.pushState){ 262 window.history.pushState({}, '', nextUrl); 263 } 264 265 if($newPagination.length){ 266 $pagination.replaceWith($newPagination); 267 $pagination = $newPagination; 268 } 269 270 if(!$pagination.find('[data-testid="linkNextPage"]').length){ 271 $btnWrapper.remove(); 272 } else { 273 loading = false; 274 $btn.prop('disabled', false).text('Zobrazit dalÅ¡Ã'); 275 } 276 }).fail(function(){ 277 loading = false; 278 $btn.prop('disabled', false).text('Zobrazit dalÅ¡Ã'); 279 }).always(function(){ 280 hideAjaxLoader(); 281 }); 282 });
283 } 284 285 function scheduleAjaxRefresh($nodes, shouldUpdateProgress){ 286 clearTimeout(ajaxRefreshTimer); 287 288 ajaxRefreshTimer = setTimeout(function(){ 289 if(ajaxRefreshRunning) return; 290 291 ajaxRefreshRunning = true; 292 293 if($nodes && $nodes.length){ 294 applyFlagLogic($nodes); 295 applyDeliveryDate($nodes); 296 applyRatingBadges($nodes); 297 } 298 299 applyDeliveryDate(); 300 applyRatingBadges(); 301 fixLoadMoreButton(); 302 303 if(shouldUpdateProgress){ 304 $('.iuv-progress-wrapper').remove(); 305 updateProgressBar(); 306 } 307 308 ajaxRefreshRunning = false; 309 }, 80); //80 310 } 311 312 updateProgressBar(); 313 fixLoadMoreButton(); 314 initNewsLoadMore(); 315 316 var observerProgress = new MutationObserver(function(mutations){ 317 if(ajaxRefreshRunning || progressUpdating) return; 318 319 var shouldUpdateProgress = false; 320 var $newNodes = $(); 321 322 mutations.forEach(function(mutation){ 323 var target = mutation.target; 324 var $target = $(target); 325 326 if( 327 $target.is('#products') || 328 $target.closest('#products').length || 329 $target.is('#newsWrapper') || 330 $target.closest('#newsWrapper').length || 331 $target.is('.itemsTotal') || 332 $target.is('.pageInfoSpan') || 333 $target.closest('.pageInfoSpan').length 334 ){ 335 shouldUpdateProgress = true; 336 } 337 338 if(mutation.addedNodes && mutation.addedNodes.length){ 339 mutation.addedNodes.forEach(function(node){ 340 if(node.nodeType === 1){ 341 $newNodes = $newNodes.add(node); 342 } 343 }); 344 } 345 }); 346 347 if($newNodes.length || shouldUpdateProgress){ 348 scheduleAjaxRefresh($newNodes, shouldUpdateProgress); 349 } 350 }); 351 352 observerProgress.observe(document.body, { 353 childList: true, 354 subtree: true, 355 attributes: true, 356 attributeFilter: ['data-current'] 357 }); 358 359 function initButton(c){ 360 var $btn = $(`<div class="homepage-products-button"><a href="${c.link}" class="btn btn-primary">Zobrazit všechny produkty</a></div>`); 361 362 function move(){ 363 if($(window).width() < 992){ 364 if(!$(c.products).next($btn).length){ 365 $(c.products).after($btn); 366 } 367 $btn.addClass('mobile'); 368 } else { 369 if(!$(c.heading).prev($btn).length){ 370 $(c.heading).before($btn); 371 } 372 $btn.removeClass('mobile'); 373 } 374 } 375 376 move(); 377 $(window).on('resize', move); 378 } 379 380 initButton({ heading: '.homepage-products-heading-5', products: '#products-5', link: '#' }); 381 initButton({ heading: '.homepage-products-heading-8', products: '#products-8', link: '#' }); 382 383});
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.