1/** 2* @author Amazzing 3* @copyright Amazzing 4* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) 5*/ 6 7var af_product_list_selector = '#js-product-list', 8 locked_class = af_classes['icon-lock'], 9 unlocked_class = af_classes['icon-unlock-alt'], 10 unlocked_selector = '.'+unlocked_class.replace(/ /g, '.'), 11 pagination_class = af_classes['pagination'], 12 customThemeActions = { 13 documentReady: function() {}, 14 updateContentAfter: function(jsonData){} 15 }; 16 17var af = { 18 defineVariables: function() { 19 $.extend(af, { 20 // basic varibales 21 blockAjax: false, resizeTimer: false, mouseLeaveTimer: false, qsTimer: false, cosCounter: 1, 22 // misc variables 23 isCompact: false, 24 autoScroll: false, 25 useUniform: !!$.fn.uniform, 26 dimZeroMatches: parseInt($('#af_dim_zero_matches').val()), 27 hideZeroMatches: parseInt($('#af_hide_zero_matches').val()), 28 showCounters: parseInt($('#af_count_data').val()), 29 includeGroup: parseInt($('#af_include_group').val()), 30 dynamicParams: { 31 f: parseInt($('#af_url_filters').val()), 32 s: parseInt($('#af_url_sorting').val()), 33 p: parseInt($('#af_url_page').val()), 34 }, 35 nbItems: { 36 current: $('#af_nb_items').val(), 37 orig: $('#af_npp').val(), 38 }, 39 isHorizontal: $('#af_layout').val() == 'horizontal', 40 productItemSelector: '.'+af_classes['js-product-miniature'], 41 noItemsClass: 'no-available-items', 42 infiniteScrollThreshold: 700, 43 popstateURL: af.removeHash(window.location.href), 44 reqNum: 0, 45 // basic $elements 46 $w: $(window), 47 $listWrapper: $('.af_pl_wrapper'), // redefined later in setWrapper() 48 $filterBlock: $('#amazzing_filter'), 49 $selectedFilters: $('.selectedFilters'), 50 $pageInput: $('#af_page'), 51 $viewBtn: $('.viewFilteredProducts'), 52 $dynamicContainer: $('#products').first(), 53 }); 54 if (!af.$dynamicContainer.length) { 55 af.$dynamicContainer = $('#content').length ? $('#content') : $('#main'); 56 } 57 }, 58 documentReady: function() { 59 af.defineVariables(); 60 customThemeActions.documentReady(); 61 af.setWrapper(); 62 af.bindEvents(); 63 af.toggleCompactView(); 64 if ('slider' in af) { 65 af.slider.prepareAll(); 66 } 67 af.cutOff.prepare(); 68 af.adjustFolderedStructure(); 69 af.prepareLoadMoreIfRequired(); 70 af.updateSelectedFilters(); 71 if (af.$listWrapper.length && $('.customer-filter-option').length) { 72 af.updateURL(af.prepareUrlAndVerifyParams()); 73 } 74 }, 75 prepareLoadMoreIfRequired: function() { 76 if (load_more && af.$listWrapper.length) { 77 $('.dynamic-product-count').html(af_product_count_text); 78 $('.dynamic-loading.next').removeClass('hidden').insertAfter(af.$listWrapper); 79 $('.dynamic-loading.prev').removeClass('hidden').insertBefore(af.$listWrapper); 80 if (!show_load_more_btn) { 81 $('.loadMore.next').addClass('hidden'); 82 } 83 $('.loadMore').on('click', function() { 84 var $parent = $(this).closest('.dynamic-loading'), 85 p = parseInt(af.$pageInput.val()); 86 if ($parent.hasClass('next')) { 87 p++; 88 } else { // prev 89 $(this).data('p', $(this).data('p') - 1); 90 if ($(this).data('p') < 2) { 91 af.doAfterAjaxOnce = function() { 92 $parent.addClass('hidden'); 93 } 94 } 95 } 96 $parent.addClass('loading'); 97 af.$pageInput.val(p).change(); 98 }); 99 af.rememberScrollPosition(); 100 if ($('#af_p_type').val() == 3) { 101 af.activateInfiniteScroll(); 102 } 103 } 104 }, 105 rememberScrollPosition: function() { 106 $(document).on('click', af.productItemSelector, function(e) { 107 var possibleLink = $(e.target).closest('a').attr('href'); 108 if (possibleLink && !possibleLink.startsWith('#')) { 109 af.$lastClickedItem = $(this); 110 clearTimeout(af.lastClickedItemTimer); 111 af.lastClickedItemTimer = setTimeout(function() { 112 delete af.$lastClickedItem; // if unloading doesn't happen within 1s after clicking on possibleLink 113 }, 1000); 114 } 115 }); 116 af.$w.on('unload', function() { 117 if (af.$lastClickedItem) { 118 var $currentItems = af.$listWrapper.find(af.productItemSelector), 119 prevNum = $currentItems.index(af.$lastClickedItem), 120 nbItems = parseInt(af.nbItems.current), 121 scrolledPage = Math.floor(prevNum / nbItems), 122 initialPage = $('.loadMore.prev').data('p') || 1, 123 elIndexInPage = prevNum - (scrolledPage * nbItems), 124 rememberPage = scrolledPage + initialPage, 125 scrollCompensation = (af.$w.height() - af.$lastClickedItem.height()) / 2, 126 requiredScrollPosition = $currentItems.eq(elIndexInPage).offset().top - scrollC
126ompensation; 127 af.$pageInput.val(rememberPage); 128 af.updateURL(af.prepareUrlAndVerifyParams()); // page param is updated in URL and it will be loaded when user clicks back 129 window.scrollTo(0, requiredScrollPosition); // scroll position is restored when user clicks back 130 } 131 }); 132 }, 133 bindEvents: function() { 134 Object.keys(af.events).forEach(function(type) { 135 Object.keys(af.events[type]).forEach(function(event) { 136 af.events[type][event](); 137 }); 138 }); 139 }, 140 events: { 141 filter: { 142 general: function() { 143 af.$filterBlock.on('click', 'a[href="#"]', function(e) { 144 e.preventDefault(); 145 }).on('change', 'input, select', function() { 146 if ($(this).data('notrigger')) { 147 return; 148 } 149 var trigger = $(this).attr('id'), 150 type = $(this).attr('type') || $(this).prop('tagName').toLowerCase(), 151 $parent = $(this).closest('.af_filter'), 152 isHiddenInput = $(this).parent().hasClass('hidden_inputs'), 153 updateList = !af.$viewBtn.data('active') || isHiddenInput; 154 if (type == 'checkbox' || type == 'radio') { 155 if (type == 'radio') { 156 $parent.find('li.active').removeClass('active'); 157 } 158 $(this).closest('li').toggleClass('active', $(this).prop('checked')); 159 } else if (type == 'select' && !$(this).closest('.selector-with-customer-filter').hasClass('hidden') && 160 $(this).find('option[value="'+$(this).val()+'"]').hasClass('customer-filter')) { 161 $(this).closest('.af_filter').find('.customer-filter-label').click(); 162 return; 163 } 164 if (trigger != 'af_page') { 165 af.$pageInput.val(1); 166 } 167 if (!af.blockAjax) { 168 if (af.$viewBtn.data('active') && !isHiddenInput) { 169 af.$viewBtn.addClass('loading').data('animate-after-loading', 1); 170 } 171 af.applyFilters(trigger, updateList); 172 } 173 }).on('click', '.customer-filter-label', function() { 174 $(this).toggleClass('unlocked'); 175 var locked = !$(this).hasClass('unlocked'), 176 iconClass = locked ? locked_class : unlocked_class, 177 $input = $(this).find('input[type="hidden"]'); 178 $(this).find('a').first().attr('class', iconClass); 179 if ($input.length) { 180 var name = locked ? $input.data('name') : 'nosubmit'; 181 $input.attr('name', name).change(); 182 } else { // selects 183 var val = locked ? $('option[id="'+$(this).data('id')+'"]').val() : 0; 184 $(this).toggleClass('hidden-name', !locked).next().toggleClass('hidden', locked) 185 .find('select').val(val).change(); 186 } 187 }); 188 }, 189 selectedFilters: function() { 190 af.$selectedFilters.on('click', 'a', function(e) { 191 e.preventDefault(); 192 var $parentRow = $(this).parent(), 193 $groupBlock = $('.af_filter[data-url="'+$parentRow.data('group')+'"]'); 194 if ($(this).hasClass('close')) { 195 if ($groupBlock.hasClass('type-1') || $groupBlock.hasClass('type-2')) { 196 var $input = $groupBlock.find('input[data-url="'+$parentRow.data('url')+'"]'); 197 $input.prop('checked', false).change(); 198 if (af.useUniform) { 199 $input.parent().removeClass('checked'); 200 } 201 } else if ($groupBlock.hasClass('type-3')) { 202 $groupBlock.find('select').val('').change(); 203 } else if ($groupBlock.hasClass('has-slider')) { 204 af.slider.resetValues(af.slider.$[$groupBlock.find('.af-slider').data('type')]); 205 } 206 } else if ($(this).hasClass('all')) { 207 af.blockAjax = true; 208 af.$selectedFilters.find('.cf').find('a').not(unlocked_selector).click(); 209 af.blockAjax = false; 210 if (af.$viewBtn.data('active')) { 211 af.$viewBtn.addClass('loading').data('animate-after-loading', 1); 212 } 213 af.applyFilters('clear_all', !af.$viewBtn.data('active')); 214 } else if ($parentRow.hasClass('customer-filter-option')) { 215 if ($groupBlock.hasClass('type-3')) { // select 216 $groupBlock.find('.customer-filter-label').click(); 217 } else { // checkbox 218 $groupBlock.find('.customer-filter[data-url="'+$parentRow.data('url')+'"]') 219 .closest('.customer-filter-label').click(); 220 } 221 } 222 }); 223 }, 224 dim: function() { 225 if (af.dimZeroMatches && !af.hideZeroMatches) { // block visible checkboxes/radio with 0 matches 226 af.$filterBlock.on('click', 'input.af.checkbox, input.af.radio', function(e) { 227 // prop checked becomes true for unchecked inputs, right after click 228 if ($(this).prop('checked') && $(this).closest('li').hasClass('no-matches')) { 229 e.preventDefault(); 230 $(this).prop('checked', false); 231 if (af.useUniform) { 232 $(this).parent().removeClass('checked').parent().removeClass('focus'); 233 if ($(this).hasClass('radio')) { 234 var $parentBlock = $(this).closest('.af_filter'), 235 url = $('.cf[data-group="'+$parentBlock.data('url')+'"]').data('url'); 236 // keep checked styles on radioboxes that were checked before 237 $parentBlock.find('input[data-url="'+url+'"]').parent().addClass('checked').parent().addClass('focus'); 238 } 239 } 240 } 241 });
242 } 243 }, 244 viewBtn: function() { 245 af.$viewBtn.on('click', function(e) { 246 e.preventDefault(); 247 if (!$(this).hasClass('loading')) { 248 $(this).addClass('loading'); 249 af.applyFilters('view_products', true); 250 if (af.isCompact) { 251 $('.af-compact-overlay').click(); 252 } 253 } 254 }); 255 }, 256 foldered: function() { 257 $('.af-toggle-child').on('click', function() { 258 $(this).closest('.af-parent-category').toggleClass('open'); 259 af.cutOff.prepare($(this).closest('.af_filter')); 260 }); 261 }, 262 toggleableContent: function() { 263 $('.af_subtitle').not('.no-toggle').on('click', function(e) { 264 e.preventDefault(); 265 var $filter = $(this).closest('.af_filter'); 266 if (!$filter.hasClass(af.noItemsClass)) { 267 $filter.toggleClass('closed'); 268 if (!$filter.hasClass('closed')) { 269 if ($filter.hasClass('type-3') && af.useUniform) { 270 $filter.find('.af-select').uniform(); 271 } 272 if (af.isCompact) { 273 $filter.siblings('.af_filter').addClass('closed'); 274 } else if (af.isHorizontal) { 275 af.autoCloseFilterContent($filter); 276 } 277 } 278 } 279 af.cutOff.prepare($filter); 280 }); 281 }, 282 quickSearch: function() { 283 af.$filterBlock.on('keyup', '.qsInput', function() { 284 var $qsInput = $(this); 285 clearTimeout(af.qsTimer); 286 af.qsTimer = setTimeout(function() { 287 var value = $qsInput.val().toLowerCase(), 288 $options = $qsInput.closest('.af_filter_content').find('li'); 289 $options.removeClass('qs-hidden'); 290 if (value.length) { 291 $options.each(function() { 292 if ($(this).children('label').children('.name').text().toLowerCase().indexOf(value) === -1) { 293 $(this).addClass('qs-hidden'); 294 } 295 }); 296 } 297 $qsInput.toggleClass('has-value', value.length > 0).siblings('.qs-no-matches'). 298 toggleClass('hidden', !!$options.not('.qs-hidden, .no-matches').length); 299 if ($qsInput.data('tree')) { 300 $options.removeClass('qs-half-hidden').filter('.af-parent-category.qs-hidden').each(function() { 301 if ($(this).find('li').not('.qs-hidden').length) { 302 $(this).addClass('qs-half-hidden open'); 303 } 304 }); 305 } 306 af.cutOff.prepare($qsInput.closest('.af_filter')); 307 }, 200); 308 }); 309 }, 310 }, 311 theme: { 312 nbItems: function() { 313 $(document).off('change', 'select[name="n"]').on('change', 'select[name="n"]', function() { 314 af.nbItems.current = $(this).val(); 315 $('#af_nb_items').val(af.nbItems.current).change(); 316 }).on('submit', '.showall', function(e) { 317 e.preventDefault(); 318 var num = $(this).find('input[name="n"]').val(), 319 $nSelect = $('select[name="n"]'); 320 if (!$nSelect.find('option[value="'+num+'"]').length) { 321 var maxNum = $nSelect.find('option').last().val(); 322 if (parseInt(maxNum) >= parseInt(num)) { 323 num = maxNum; 324 } else { 325 var newOptionHTML = '<option value="'+num+'">'+num+'</option>'; 326 $nSelect.append(newOptionHTML); 327 if (af.useUniform) { 328 $nSelect.uniform(); 329 } 330 } 331 } 332 $nSelect.val(num).change(); 333 }); 334 }, 335 sorting: function() { 336 $('body').off('click', '.js-search-link').on('click', '.select-list.js-search-link', function(e) { 337 e.preventDefault(); 338 $(this).addClass('current').siblings().removeClass('current'); 339 // todo: consider cases when "order=" is not present in href 340 var value = $(this).attr('href').split('order=')[1].split('&')[0].split('.'); 341 orderBy = value[1], 342 orderWay = value[2], 343 sortingName = $(this).text(), 344 $title = $(this).closest('.products-sort-order').find('.select-title'), 345 $htmlElementsInTitle = $title.children();
346 af.applySorting(orderBy, orderWay); 347 $title.html(sortingName).append($htmlElementsInTitle); 348 }); 349 }, 350 pagination: function() { 351 $(document).on('click','.'+pagination_class+' a', function(e) { 352 e.preventDefault(); 353 var page = 1; 354 if ($(this).attr('href').indexOf('?') > -1) { 355 var params = af.unserialize($(this).attr('href').split('?')[1], false); 356 if (page_link_rewrite_text in params && params[page_link_rewrite_text] > 1) { 357 page = params[page_link_rewrite_text]; 358 } 359 } 360 af.$pageInput.val(page).change(); 361 }); 362 }, 363 }, 364 browser: { 365 popstate: function() { 366 af.$w.on('popstate', function() { // when user clicks back/forward in browser 367 if (af.removeHash(window.location.href) != af.popstateURL) { 368 af.updateFiltersBasingOnURL(window.location.href); 369 } 370 }); 371 }, 372 resize: function() { 373 af.$w.on('resize', function() { 374 clearTimeout(af.resizeTimer); 375 af.resizeTimer = setTimeout(function() {af.toggleCompactView()}, 100); 376 }); 377 }, 378 }, 379 }, 380 autoCloseFilterContent: function($filter) { 381 $filter.off('mouseenter mouseleave').on('mouseenter', function() { 382 clearTimeout(af.mouseLeaveTimer); 383 }).on('mouseleave', function() { 384 af.mouseLeaveTimer = setTimeout(function() { 385 if (!$filter.hasClass('closed')) { 386 $filter.find('.af_subtitle').click(); 387 } 388 $filter.off('mouseenter mouseleave'); 389 }, 1000); 390 }); 391 setTimeout(function() { 392 af.onClickOutSide( 393 $filter.find('.af_filter_content'), 394 function() {$filter.addClass('closed');} 395 ); 396 }, 10); 397 }, 398 onClickOutSide: function($el, action) { 399 var identifier = af.cosCounter++; 400 $(document).off('click.'+identifier).on('click.'+identifier, function(e) { 401 if (!$el.is(e.target) && $el.has(e.target).length === 0) { 402 action(); 403 $(document).off('click.'+identifier); 404 } 405 }); 406 }, 407 applySorting: function (orderBy, orderWay) { 408 $('#af_orderBy').val(orderBy); 409 $('#af_orderWay').val(orderWay).change(); 410 }, 411 prepareCompactView: function() { 412 if ($('.af-compact-overlay').hasClass('ready')) { 413 return; 414 } 415 // if ($('.compact-toggle.external').length) { 416 // af.$filterBlock.find('.compact-toggle').remove(); 417 // } 418 $('.compact-toggle, .af-compact-overlay').on('click', function(e) { 419 e.preventDefault(); 420 var $body = $('body'); 421 if (!$body.hasClass('show-filter')) { 422 $body.data('scroll', af.$w.scrollTop()); 423 } 424 $body.toggleClass('show-filter'); 425 if ($body.hasClass('show-filter')) { 426 $body.css('top', '-'+$body.data('scroll')+'px'); // block scrolling to top because of position: fixed 427 } else { 428 $body.css('top', ''); 429 window.scrollTo(0,+$body.data('scroll')); 430 } 431 }).addClass('ready'); 432 if ('ontouchstart' in document.documentElement) { 433 var swipeThreshold = 150, xStart = 0, xEnd = 0, 434 compactLeft = af.$filterBlock.hasClass('compact-offset-left'); 435 af.$filterBlock.on('touchstart', function (e) { 436 xStart = e.originalEvent.touches[0].clientX; 437 xEnd = xStart; 438 }).on('touchmove',function (e) { 439 xEnd = e.originalEvent.touches[0].clientX; 440 }).on('touchend',function (e) { 441 var diff = compactLeft ? xStart - xEnd : xEnd - xStart; 442 if (diff > swipeThreshold && // detect swipe towards edge 443 !$(e.target).closest('.af_filter').not('.closed').hasClass('has-slider')) { // no swiping on sliders 444 $('body').removeClass('show-filter'); 445 } // TODO: else detect swipe from edge to open filter panel 446 }); 447 } 448 }, 449 toggleCompactView: function() { 450 var isCompactBefore = af.isCompact; 451 af.isCompact = af.$filterBlock.css('position') == 'fixed'; 452 af.autoScroll = af.isCompact ? 1 : parseInt($('#af_autoscroll').val()); 453 if (isCompactBefore != af.isCompact) { 454 $('body').toggleClass('has-compact-filter', af.isCompact); 455 var $afBlocks = af.$filterBlock.find('.af_filter'), $btnHolder = af.$filterBlock.find('.btn-holder'); 456 if (af.isCompact) { 457 af.prepareCompactView(); 458 $afBlocks.filter('.closed').addClass('cl-orig'); 459 $afBlocks.filter('.foldered').addClass('fd-orig'); 460 $afBlocks.addClass('closed').filter('.folderable').addClass('foldered'); 461 af.$filterBlock.removeClass('horizontal-layout').before('<span class="af-orig hidden"></span>').appendTo('body'); 462 $('.af-compact-overlay').appendTo('body'); 463 $btnHolder.appendTo(af.$filterBlock); // avoid position:absolute + -webkit-overflow-scrolling: touch; 464 setTimeout(function() { 465 af.$filterBlock.addClass('animation-ready'); 466 if (typeof accordion == 'function') {af.$filterBlock.find('.block_content').stop().attr('style','');} 467 }, 500); 468 } else { 469 af.$filterBlock.removeClass('animation-ready').toggleClass('horizontal-layout', af.isHorizontal); 470 $('.af-orig').before(af.$filterBlock).before($('.af-compact-overlay')).remove(); 471 $btnHolder.insertAfter('#af_form'); // move it to original position for compatibility with accordion() 472 $afBlocks.each(function() { 473 $(this).toggleClass('closed', $(this).hasClass('cl-orig')) 474 .toggleClass('foldered', $(this).hasClass('fd-orig')); 475 }); 476 if (af.isHorizontal) { 477 af.cutOff.cancel($afBlocks); 478 } 479 } 480 af.cutOff.prepare($afBlocks); 481 } 482 af.updateSFPositionIfRequired(); 483 af.toggleViewBtn(); 484 }, 485 toggleViewBtn: function() { 486 var showBtn = $('#af_reload_action').val() == 2 || af.isCompact; 487 af.$viewBtn.toggleClass('hidden', !showBtn).data('active', showBtn) 488 .parent().toggleClass('hidden', !showBtn && !$('.manage-permanent-filters').length); 489 }, 490 setWrapper: function() { 491 if (!af.$listWrapper.length) { 492 $(af_product_list_selector).first().wrap('<div class="af_pl_wrapper clearfix"></div>'); 493 af.$listWrapper = $('.af_pl_wrapper'); 494 } 495 }, 496 updateSFPositionIfRequired: function() { 497 if ($('#af_sf_position').val() == 1) { 498 if (!af.isCompact) { 499 var $before = is_17 ? $('#products').first() : $('.content_sortPagiBar').first(); 500 af.$selectedFilters.addClass('inline af').insertBefore($before); 501 } else { 502 af.$selectedFilters.removeClass('inline af').insertBefore('#af_form'); 503 } 504 } 505 }, 506 applyFilters: function(trigger, updateList) { 507 if (af.$listWrapper.length && (updateList || af.$viewBtn.data('active'))) { 508 af.updateSelectedFilters(); 509 } 510 af.loadProducts(trigger, updateList); 511 }, 512 prepareParamsForAjaxRequest: function(trigger, updateList) { 513 if (updateList && !$('.dynamic-loading').hasClass('loading')) { 514 af.$listWrapper.stop().animate({'opacity': 0.3}, 350); 515 } 516 if (af.dimZeroMatches) { 517 $('option:selected:disabled').prop('disabled', false); // submit values from selected disabled options 518 } 519 $('.af-select').not('.no-submit').each(function() { 520 if (!$(this).val()) { 521 $(this).addClass('no-submit').data('inputname', $(this).attr('name')).attr('name', 'no_submit'); 522 } 523 }); 524 var params = $('#af_form').serialize(); 525 if (!updateList) { 526 params += '&nb_items=0'; 527 } else if (!af.$listWrapper.length) { 528 if (!is_17 && page_name != 'index') { 529 af.updateSelectedFilters(); 530 af.updateURL(af.prepareUrlAndVerifyParams()); 531 window.location.reload(); 532 return; 533 } 534 params += '&layout_required=1'; 535 af.$dynamicContainer.animate({'opacity': 0.3}, 350); 536 } 537 if (load_more) { 538 var $prevLoader = $('.dynamic-loading.prev'); 539 if (trigger == 'af_page') { 540 if (!$prevLoader.length) { 541 params += '&page_from=1'; 542 } else if ($prevLoader.hasClass('loading')) { 543 params += '&page='+$('.loadMore.prev').data('p')+'&page_to='+af.$pageInput.val(); 544 } else { 545 params += '&page_from='+$('.loadMore.prev').data('p'); 546 } 547 } else { 548 $prevLoader.remove(); 549 } 550 } 551 return params; 552 }, 553 loadProducts: function(trigger, updateList) { 554 if (af.blockAjax) { 555 return; 556 } 557 var params = af.prepareParamsForAjaxRequest(trigger, updateList); 558 requestIdentifier = ++af.reqNum; 559 af.newURL = af.prepareUrlAndVerifyParams(); 560 $.ajax({
561 type: 'POST', 562 url: af_ajax_path, 563 dataType : 'json', 564 data: { 565 params: params, 566 current_url: af.newURL, 567 trigger: trigger, 568 }, 569 success: function(r) { 570 if (requestIdentifier != af.reqNum) { 571 return; // update layout only for last request if checkboxes are clicked too fast 572 } 573 af.updateContent(r, trigger, updateList); 574 af.updateURL(af.newURL); 575 if (af.doAfterAjaxOnce) { 576 af.doAfterAjaxOnce(); 577 delete af.doAfterAjaxOnce; 578 } 579 }, 580 error: function(r) { 581 console.warn($(r.responseText).text() || r.responseText); 582 } 583 }); 584 }, 585 updateContent: function(jsonData, trigger, updateList) { 586 // var af_timeStart = new Date().getTime()/1000; 587 if (updateList) { 588 if ('layout' in jsonData) { 589 af.updateListLayout(jsonData.layout); 590 } 591 af.updateProductList(jsonData, trigger); 592 if (af.autoScroll && (!load_more || trigger != 'af_page')) { 593 af.autoscrollToTopOfTheList(); 594 } 595 } 596 if (trigger != 'af_page') { 597 $('.af-total-count').html(parseInt(jsonData.products_num)); 598 af.updateFilteringBlocks(jsonData); 599 } 600 if (af.$viewBtn.data('active')) { 601 af.$viewBtn.removeClass('loading'); 602 if (af.$viewBtn.data('animate-after-loading')) { 603 af.$viewBtn.addClass('btn-pulsate').data('animate-after-loading', 0); 604 setTimeout(function() { 605 af.$viewBtn.removeClass('btn-pulsate'); 606 }, 300); 607 } 608 } 609 // var af_timeEnd = new Date().getTime()/1000; 610 // af_timeEnd = af_timeEnd - af_timeStart 611 // console.dir('all elements updated: '+af_timeEnd); 612 }, 613 updateProductList: function(jsonData, trigger) { 614 if (load_more && trigger == 'af_page') { 615 var $result = $('<div>'+af.utf8_decode(jsonData.product_list_html)+'</div>'), 616 $items = $result.find(af.productItemSelector); 617 if ($('.dynamic-loading.prev').hasClass('loading')) { 618 af.$listWrapper.find(af.productItemSelector).first().before($items); 619 } else { 620 af.$listWrapper.find(af.productItemSelector).last().after($items); 621 } 622 $('.dynamic-loading').removeClass('loading'); 623 if (is_17 && !$('#js-product-list-top').html()) { 624 $('#js-product-list-top').replaceWith(af.utf8_decode(jsonData.product_list_top_html)); 625 } 626 } else { 627 $(af_product_list_selector).replaceWith(af.utf8_decode(jsonData.product_list_html)); 628 if (is_17) { 629 $('#js-product-list-top').replaceWith(af.utf8_decode(jsonData.product_list_top_html)); 630 $('#js-product-list-bottom').replaceWith(af.utf8_decode(jsonData.product_list_bottom_html)); 631 } else { 632 $('.'+af_classes['product-count']).remove(); 633 $('#'+pagination_holder_id).replaceWith(af.utf8_decode(jsonData.pagination_html)); 634 $('#'+pagination_bottom_holder_id).replaceWith(af.utf8_decode(jsonData.pagination_bottom_html)); 635 } 636 } 637 if (load_more) { 638 var $countContainer = is_17 ? $('.dynamic-product-count') : $('.'+af_classes['product-count']); 639 $countContainer.html(af.utf8_decode(jsonData.product_count_text)); 640 $('.loadMore.next').toggleClass('hidden', jsonData.hide_load_more_btn); 641 } 642 var animationTime = is_17 ? 500 : 1000; 643 $('.af_pl_wrapper').animate({'opacity': 1}, animationTime); 644 af.updateListAfter(jsonData); 645 }, 646 updateListAfter: function(jsonData) { 647 if (typeof display == 'function' && $.totalStorage 648 && $.totalStorage('display') && $.totalStorage('display') != 'grid') { 649 display($.totalStorage('display')); 650 } 651 // prestashop.emit('updateProductList'); //todo: add configurable action 652 customThemeActions.updateContentAfter(jsonData); 653 if (typeof updateContentAfter == 'function') updateContentAfter(jsonData); // retro compatibility 654 af.$filterBlock.trigger('updateProductList', jsonData); 655 }, 656 updateFilteringBlocks: function(jsonData) { 657 if ($.isEmptyObject(jsonData.count_data)) { 658 return; 659 } 660 $('.af_filter').each(function() { 661 if ($.inArray($(this).data('type'), [1,2,5]) > -1) { // checkbox, radio, textbox 662 var key = $(this).data('key'); 663 $(this).find('input.af').each(function() { 664 var count = jsonData.count_data[key][$(this).val()] || 0, 665 $li = $(this).closest('li'); 666 if (count) { 667 $li.removeClass('no-matches'); 668 if (af.showCounters) { 669 $li.find('.count').first().html(count); 670 } 671 } else if (!$li.hasClass('no-matches')) { 672 $li.addClass('no-matches'); 673 if (af.showCounters) { 674 $li.find('.count').first().html(count); 675 }; 676 } 677 }); 678 af.checkAvailableItems($(this), false); 679 } else if ($(this).data('type') == 3) { // selects 680 var key = $(this).data('key'), 681 $select = $(this).find('.af-select'), 682 currentValue = $select.val(), 683 html = ''; 684 $(this).find('.dynamic-select-options').children().each(function() { 685 var data = $(this).data(), 686 count = jsonData.count_data[key][data.value] || 0; 687 if (count || data.value == currentValue || $(this).hasClass('customer-filter') || !af.hideZeroMatches) { 688 html += '<option id="'+data.id+'" value="'+data.value+'"'; 689 html += ' class="'+$(this).attr('class')+(count ? '' : ' no-matches')+'"'; 690 html += ' data-url="'+data.url+'" data-text="'+data.text+'"'; 691 html += (af.dimZeroMatches && !count ? ' disabled' : '')+'>'; 692 html += data.text+(af.showCounters ? ' ('+count+')': '')+'</option>'; 693 } 694 }); 695 $select.children().first().nextAll().remove(); // keep only first option 696 if ($select.hasClass('no-submit')) { 697 $select.removeClass('no-submit').attr('name', $select.data('inputname')); 698 } 699 if (html) { 700 $select.append(html).val(currentValue); 701 if (af.useUniform) { 702 $select.uniform() 703 }; 704 } 705 af.checkAvailableItems($(this), true); 706 } 707 }); 708 af.cutOff.prepare(); 709 af.adjustFolderedStructure(); 710 if (jsonData.ranges) { 711 $.each(jsonData.ranges, function(key, range) { 712 if ('min' in range && 'max' in range && af.slider && af.slider.$[key]) { 713 af.slider.updMinMax(af.slider.$[key], range.min, range.max); 714 } 715 }); 716 } 717 }, 718 prepareUrlAndVerifyParams: function() { 719 var url = af.getStaticURL(), 720 dynamicParams = af.prepareDynamicParams(); 721 if (!$.isEmptyObject(dynamicParams)) { 722 url += (url.indexOf('?') > -1 ? '&' : '?')+decodeURIComponent($.param(dynamicParams, true)); 723 } 724 return url; 725 }, 726 updateURL: function(url) { 727 if (url && url != window.location.href) { 728 window.history.pushState(null, null, url); 729 af.popstateURL = url; 730 } 731 }, 732 getStaticURL: function() { 733 if (!af.staticURL) { 734 if (typeof af_sp_base_url != 'undefined') { 735 af.staticURL = af_sp_base_url; 736 if (!af_sp_fixed_criteria) { 737 $('.sp-hidden-filter').addClass('sp-dynamic-params'); 738 } 739 } else { 740 var splittedUrl = decodeURIComponent(window.location.href).split('?'); 741 af.staticURL = af.removeHash(splittedUrl[0]); 742 if (splittedUrl.length == 2) { 743 var staticParams = af.unserialize(splittedUrl[1], true); 744 if (!$.isEmptyObject(staticParams)) { 745 af.staticURL += '?'+decodeURIComponent($.param(staticParams, true)); 746 } 747 } 748 } 749 } 750 return af.staticURL; 751 }, 752 prepareDynamicParams: function() { 753 var dynamicParams = {}, page = af.$pageInput.val(); 754 if (af.dynamicParams.f) { 755 af.$selectedFilters.find('.cf').add('.sp-dynamic-params').each(function() { 756 if (!$(this).find(unlocked_selector).length) { 757 var n = $(this).data('group'), v = $(this).data('url'); 758 if (n && v) { 759 if (n in dynamicParams) { 760 dynamicParams[n] += ','+v; 761 } else { 762 dynamicParams[n] = v; 763 } 764 } 765 } 766 }); 767 } 768 if (af.dynamicParams.p && page > 1) { 769 dynamicParams[page_link_rewrite_text] = page; 770 } 771 if (af.dynamicParams.s) { 772 var order = {by: $('#af_orderBy').val(), way: $('#af_orderWay').val()}; 773 if (order.by+':'+order.way != $('#af_defaultSorting').val()) { 774 if (is_17) { 775 dynamicParams.order = 'product.'+order.by+'.'+order.way; 776 } else { 777 dynamicParams.orderby = order.by 778 dynamicParams.orderway = order.way 779 } 780 } 781 } 782 if (af.nbItems.current != af.nbItems.orig) { 783 dynamicParams['n'] = af.nbItems.current; 784 } 785 return dynamicParams; 786 }, 787 autoscrollToTopOfTheList: function() { 788 if (af.$listWrapper.length) { 789 var wrapperTop = af.$listWrapper.offset().top; 790 if (af.isCompact || !af.isInViewPort(wrapperTop, wrapperTop)) { 791 $('html, body').animate({scrollTop: wrapperTop - 150}, 100); 792 } 793 } 794 }, 795 isInViewPort: function (top, bottom) { 796 var scrollTop = af.$w.scrollTop(), windowHeight = af.$w.height(); 797 return (scrollTop + windowHeight) > top && scrollTop < bottom; 798 }, 799 checkAvailableItems: function($block, isSelect) { 800 if (af.dimZeroMatches || af.hideZeroMatches) { 801 var noItems = !isSelect ? $block.find('li').not('.no-matches:not(.active)').length < 1 802 : $block.find('option').not('.no-matches:not(:selected), .first').length < 1; 803 $block.toggleClass(af.noItemsClass, noItems); 804 } 805 }, 806 cutOff: { 807 prepare: function($blocks) { 808 if (af.isHorizontal && !af.isCompact) { 809 return; 810 } 811 $blocks = $blocks ? $blocks : $('.af_filter'); 812 $blocks.not('.closed').find('.toggle-cut-off').each(function() { 813 var $filter = $(this).closest('.af_filter'); 814 af.cutOff.apply($filter, $(this).data('cut')); 815 if (!$(this).data('click-ready')) { 816 $(this).on('click', function(e) { 817 e.preventDefault(); 818 $filter.toggleClass('cut-off'); 819 }).data('click-ready', 1); 820 } 821 }); 822 }, 823 apply: function($filter, maxItems) { 824 if (!$filter.hasClass('cut-off')) { 825 return; 826 } 827 let except = '.qs-hidden'+(af.hideZeroMatches ? ', .no-matches' : ''); 828 $filter.find('li').not(except).each(function() { 829 if (maxItems) { 830 $(this).removeClass('cut'); 831 maxItems--; 832 } else if (!$(this).hasClass('cut')) { 833 $(this).addClass('cut'); 834 } 835 }); 836 $filter.toggleClass('expandable', !maxItems && !!$filter.find('.cut').length); 837 }, 838 cancel: function($filter) { 839 $filter.find('.cut').removeClass('cut'); 840 }, 841 }, 842 adjustFolderedStructure: function() { 843 $('.af_filter.foldered').find('.af-parent-category').each(function() { 844 var $children = $(this).children('ul').find('li'), 845 childrenWithMatches = $children.not('.no-matches').length, 846 checkedChildren = $children.filter('.active').length; 847 if (af.hideZeroMatches) { 848 // hide foldered trigger if none of subcategories are available 849 $(this).children('label').find('.af-toggle-child').toggleClass('hidden', !childrenWithMatches && !checkedChildren); 850 } 851 if (checkedChildren || (childrenWithMatches && $(this).hasClass('no-matches'))) { 852 $(this).addClass('open'); 853 if (af.hideZeroMatches || af.dimZeroMatches) { 854 $(this).removeClass('no-matches'); 855 } 856 } 857 }); 858 }, 859 updateListLayout: function(layout_html) { 860 if ($.contains(af.$dynamicContainer[0], af.$filterBlock[0])) { 861 af.$filterBlock.insertBefore(af.$dynamicContainer); 862 $('.af.dynamic-loading').insertAfter(af.$filterBlock); 863 } 864 af.$dynamicContainer.html(af.utf8_decode(layout_html)).animate({'opacity': 1}, 350); 865 af.setWrapper(); 866 af.updateSFPositionIfRequired(); 867 af.updateSelectedFilters(); 868 af.prepareLoadMoreIfRequired(); 869 }, 870 updateSelectedFilters: function() { 871 var html = '', 872 $customerFilterLabels = $('.customer-filter-label'); 873 $customerFilterLabels.each(function() { 874 var url = $('#'+$(this).data('id')).data('url'), 875 $f = $(this).closest('.af_filter'), 876 groupURL = $f.data('url'), 877 groupText = af.includeGroup ? $f.find('.af_subtitle').text()+': ' : '', 878 text = groupText+$(this).find('.name').text(), 879 unlocked = $(this).hasClass('unlocked'), 880 divClass = 'customer-filter-option'+(unlocked ? ' unlocked' : ''), 881 iClass = unlocked ? unlocked_class : locked_class;
882 html += af.renderSelectedOption(url, groupURL, text, divClass, iClass); 883 }); 884 $('.af_filter').each(function() { 885 var groupURL = $(this).data('url'), 886 groupText = af.includeGroup && !$(this).hasClass('special') ? $(this).find('.af_subtitle').text()+': ' : ''; 887 iClass = af_classes['u-times']+' close', 888 hasSelection = $(this).find('.customer-filter-label').not('.unlocked').length > 0; 889 if ($(this).hasClass('has-slider')) { 890 var $bar = af.slider.$[$(this).find('.af-slider').data('type')]; 891 if ($bar.values.from > $bar.values.min || $bar.values.to < $bar.values.max) { 892 var rangeURL = $bar.$inputs.from.val()+'-'+$bar.$inputs.to.val(), 893 prefix = $(this).find('.prefix').first().text(), 894 suffix = $(this).find('.suffix').first().text(), 895 text = groupText+prefix+$bar.$displayValues.from.text()+' - '+$bar.$displayValues.to.text()+suffix; 896 html += af.renderSelectedOption(rangeURL, groupURL, text, 'slider-option', iClass); 897 hasSelection = true; 898 } 899 } else { 900 $(this).find('input, option:not(.first, .customer-filter)').filter(':checked, :selected').each(function() { 901 var text = groupText+($(this).data('text') || $(this).closest('label').find('.name').text()); 902 html += af.renderSelectedOption($(this).data('url'), groupURL, text, '', iClass); 903 hasSelection = true; 904 }); 905 } 906 $(this).toggleClass('has-selection', hasSelection); 907 }); 908 af.$selectedFilters.find('.cf').remove(); 909 af.$selectedFilters.append(html).toggleClass('hidden', !html); 910 if ($customerFilterLabels.length) { 911 af.$selectedFilters.find('.clearAll').toggleClass('hidden', !af.$selectedFilters.find('.cf').not('.unlocked').length); 912 } 913 }, 914 renderSelectedOption: function(url, group, text, divClass, iClass) { 915 return '<div class="cf '+divClass+'" data-url="'+url+'" data-group="'+group+'">'+text+' <a href="#" class="'+iClass+'"></a></div>'; 916 }, 917 activateInfiniteScroll: function() { 918 var scrollTimer, 919 lastViewportTop = af.$w.scrollTop(), 920 $dl = $('.dynamic-loading.next'), 921 $btn = $('.loadMore.next'); 922 af.$w.on('scroll', function() { 923 var viewportTop = af.$w.scrollTop(), 924 scrollingDown = viewportTop > lastViewportTop; 925 lastViewportTop = viewportTop; 926 clearTimeout(scrollTimer); 927 scrollTimer = setTimeout(function() { 928 if (scrollingDown && af.$listWrapper.length && !$dl.hasClass('loading') && !$btn.hasClass('hidden')) { 929 var listBottom = af.$listWrapper.offset().top + af.$listWrapper.outerHeight(); 930 if (af.isInViewPort(listBottom - af.infiniteScrollThreshold, listBottom)) { 931 $btn.click(); 932 } 933 } 934 }, 50); 935 }); 936 }, 937 unserialize: function(params, excludeDynamicParams) { 938 params = params.split('&'); 939 var result = {}, dynamicParams = {order:0, orderby:0, orderway:0, n: 0}; 940 dynamicParams[page_link_rewrite_text] = 0; 941 for (var i in params) { 942 var splitted = params[i].split('='), name = splitted[0]; 943 if (splitted.length == 2 && (!excludeDynamicParams || 944 !$('.af_filter[data-url="'+name+'"]').length && !(name in dynamicParams))) { 945 result[name] = splitted[1]; 946 } 947 } 948 return result; 949 }, 950 updateFiltersBasingOnURL: function(url) { 951 window.location.reload(); 952 // TODO: dynamically update filters and product list basing on URL, or may be other global variable 953 // var splittedUrl = decodeURIComponent(url).split('?'); 954 // if (splittedUrl.length == 2) { 955 // $.each(af.unserialize(splittedUrl[1]), function(name, val) { 956 // if ($('.af_filter[data-url="'+name+'"]').length) { 957 // console.dir(val); 958 // } 959 // }); 960 961 // } 962 }, 963 removeHash: function(url) { 964 return url.split('#')[0]; 965 }, 966 utf8_decode: function(utfstr) { 967 var res = ''; 968 for (var i = 0; i < utfstr.length;) { 969 var c = utfstr.charCodeAt(i); 970 if (c < 128) { 971 res += String.fromCharCode(c); 972 i++; 973 } else if((c > 191) && (c < 224)) { 974 var c1 = utfstr.charCodeAt(i+1); 975 res += String.fromCharCode(((c & 31) << 6) | (c1 & 63));
976 i += 2; 977 } else { 978 var c1 = utfstr.charCodeAt(i+1); 979 var c2 = utfstr.charCodeAt(i+2); 980 res += String.fromCharCode(((c & 15) << 12) | ((c1 & 63) << 6) | (c2 & 63)); 981 i += 3; 982 } 983 } 984 return res; 985 }, 986}; 987 988$(document).ready(function() { 989 af.documentReady(); 990}); 991/* since 3.1.7 */
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.