PageSourceSearch

https://distribucionmayorista.online/modules/amazzingfilter/views/js/front.js

js distribucionmayorista.online collected 2026-10-04 13:26:57 UTC 37,958 bytes, 991 lines download raw bytes

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.