{"version":3,"sources":["mshop-category-page.js"],"names":["XmxCategory","$_document","$_html","$_grid","$_description","$_listEnd","$_title","$_productCount","$_filterDrawer","$_filterResetButton","$_filterSubmitButton","$_filterSubmitButtonLabel","$_filters","$_showMoreMessage","$_showMoreMessageDescription","$_showMoreMessageProgress","$_showMoreMessageButton","$_navigation","$_fillupMessage","$_fillupMessageButton","$_filterBar","$_filterBarButton","_isDrawerOpened","_isDrawerAnimating","_configuration","_products","_ajaxHandle","_canPreloadNextPage","_preloadScrollPosition","_isLoadingNextPage","_preloadedServerResponse","_hasLoadedNextPage","_displayNextPageImmediately","_countdowns","_expandedFilterOptions","_expandedFilters","_didUpdateFilters","_intersectionObserver","boot","window","naeCategoryConfiguration","naeProductListConfiguration","XmxApp","supportsIntersectionObserver","IntersectionObserver","onIntersection","root","rootMargin","threshold","jQuery","document","$productLinks","on","onProductLinkClick","each","observe","this","onFilterFormSubmit","onFilterResetButtonClick","onFilterSubmitButtonClick","onFilterDrawerSkrimClick","onFilterBarButtonClick","onShowMoreMessageButtonClick","onFillupMessageButtonClick","restoredState","supportsSessionStorage","getSessionStorageString","id","configuration","getSessionStorageJSON","url","products","remove","destroyCountdowns","renderProducts","scrollPosition","scrollTop","restoreState","updateShowMoreMessage","updateProductCount","updateNavigation","updateFilterBar","updateNextPagePreloading","registerScrollEventObserver","handleScroll","saveState","XmxEventQueue","trackEvent","c","countdown","XmxCountdown","push","onProductImpression","element","productId","parseInt","dataset","position","p","r","unobserve","entries","index","entry","target","timeoutHandle","th","intersectionRatio","setTimeout","bind","clearTimeout","updateFilters","updateSubmitButtonLabel","updateResetFiltersButton","addClass","offset","openFilterDrawer","renderedOptionIds","filters","promotedOptions","i","promotedOption","$filterBarItem","attr","filterIndex","optionIndex","onPromotedFilterBarItemClick","selected","count","$filterBarItemIcon","appendTo","$filterBarItemName","html","name","insertBefore","filter","type","from","to","$priceFilterBarItem","onCustomFilterBarItemClick","$priceFilterBarItemIcon","$priceFilterBarItemName","formatAmount","naeCategoryTranslations","options","option","indexOf","$customFilterBarItem","$customFilterBarItemIcon","$customFilterBarItemName","sorting","order","defaultOrder","direction","sortingName","methodIndex","methods","method","$sortingFilterBarItem","onSortingFilterBarItemClick","$sortingFilterBarItemIcon","$sortingFilterBarItemName","$me","hasClass","removeClass","commitFilters","resetSorting","destroy","navigation","length","navigationIndex","empty","$wrap","$link","data","onNavigationLinkClick","active","navigationEntry","resetEverythingAndReload","postData","pageFilterIndex","pageFilter","undefined","key","value","sortOrder","sortDirection","activeFilterCount","show","hide","noProducts","oneProduct","xProducts","replace","noResults","viewOneProduct","viewXProducts","page","pageCount","top","scrollOffsetY","loadNextPage","viewedProducts","pageSize","percent","Math","round","youHaveSeen","css","$fragment","createDocumentFragment","$filter","includes","$filterHead","onFilterHeadClick","$filterName","sortBy","sotingIndex","$filterSubtitle","$filterContent","$options","$option","$input","onSortingInputChange","$optionLabel","$optionText","$optionName","$optionRadio","$optionRadioBullet","renderSorting","$separator","createElement","classList","add","appendChild","renderAttributeFilter","renderPriceFilter","renderSwatchesFilter","renderSizesFilter","renderRatingFilter","onPriceFilterInputChange","inputValue","val","parseFloat","minimum","maximum","onFilterInputChange","changedFilterIndex","changedOptionIndex","isSelected","is","attribute","sortingIndex","fragment","filterSubtitle","setAttribute","addEventListener","innerText","description","$filterDescription","$colors","isDisabled","$color","$colorLabel","style","color","$colorCheckIcon","$colorCount","light","$sizes","$size","$sizeLabel","$optionCount","parent","filterGroupCode","splice","collapseOptions","$imageFrame","image","$image","$optionTitle","featured","$badgeContainer","$badge","$optionDescription","$optionCheckbox","$optionCheckboxIcon","$expandOptions","$expandButton","$expandButtonLabel","showMore","renderRating","rating","$parent","$rating","star","$star","$count","stars","andMore","filterLabel","$priceRange","$priceInputFrom","$priceInputTo","displayPreloadedPage","handleServerResponse","response","productsToRender","fillupMode","productIndex","category","addProduct","existingProductIndex","headline","urlBefore","location","href","supportsHistoryApi","history","replaceState","pageTitle","title","gtag","page_title","page_location","ga","pathname","updateBrowserState","setSessionStorageString","setSessionStorageJSON","countdownsToStart","showBanners","product","isFeatured","banners","positionKey","banner","$bannerLink","link","size","nofollow","$bannerContent","$bannerPicture","lastBannerImageData","imageIndex","images","bannerImageData","$bannerSource","media","src","$bannerImage","imageAlt","$bannerCta","label","$bannerLabel","$bannerTitle","$bannerDescription","$countdown","countdownStyle","deadline","$countdownDaysBox","$countdownDaysDigit","$countdownDaysLabel","countdownDays","$countdownHoursBox","$countdownHoursDigit","$countdownHoursLabel","countdownHours","$countdownMinutesBox","$countdownMinutesDigit","$countdownMinutesLabel","countdownMinutes","$countdownSecondsBox","$countdownSecondsDigit","$countdownSecondsLabel","countdownSeconds","button","$bannerButton","buttonStyle","$bannerButtonLabel","$productElement","displayType","$inner","imageType","hoverImageType","$imageRegular","$imageRegularPicture","lastImageData","imageData","$imageRegularSource","$imageRegularImage","width","height","hoverImage","$hoverImage","$hoverImagePicture","$mobileHoverImage","$desktopHoverImage","$hoverImageImage","isOutOfStock","$stockBadges","$stockBadge","stockBadge","primaryBadge","secondaryBadge","specialBadge","campaignBadge","$badges","$campaignBadge","$specialBadge","$primaryBadge","$secondaryBadge","$text","reviews","brand","$brand","$name","subtitle","$subtitle","freeShipping","tags","$tags","tagIndex","$tag","$freeShippingTag","$price","finalPrice","price","$oldPrice","priceString","$newPrice","showFromPrice","finalPriceString","$discount","discountPercentString","$regularPrice","basePriceString","$basePrice","countdownIndex","before","countdownHandle","buildPostData","j","fillupCategory","event","preventDefault","enforcedPostData","abort","skeletonCount","max","$skeleton","$line1","$line2","$line3","createProductSkeletons","ajax","dataType","cache","xhr","XMLHttpRequest","success","complete","resetFilters","endpoint","dir","is_ajax","supportsMediaQueries","matchMediaQuery","downloadImage","isDesktop","preloadProductImages","closeFilterDrawer","construct","isFilterDrawedOpen"],"mappings":"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","file":"mshop-category-page-4.7.3.min.js","sourcesContent":["var XmxCategory = (function()\r\n{\r\n /**\r\n * Props\r\n */\r\n var _isDrawerOpened = false;\r\n var _isDrawerAnimating = false;\r\n var _configuration = null;\r\n var _products = [];\r\n var _ajaxHandle = null;\r\n var _canPreloadNextPage = false;\r\n var _preloadScrollPosition = 0;\r\n var _isLoadingNextPage = false;\r\n var _preloadedServerResponse = null;\r\n var _hasLoadedNextPage = false;\r\n var _displayNextPageImmediately = false;\r\n var _countdowns = [];\r\n var _expandedFilterOptions = [];\r\n var _expandedFilters = [];\r\n var _didUpdateFilters = false;\r\n var _intersectionObserver = null;\r\n\r\n /**\r\n * Elements\r\n */\r\n var $_document;\r\n var $_html;\r\n var $_grid;\r\n var $_description;\r\n var $_listEnd;\r\n var $_title;\r\n var $_productCount;\r\n var $_filterDrawer;\r\n var $_filterDrawerSkrim;\r\n var $_filterResetButton;\r\n var $_filterSubmitButton;\r\n var $_filterSubmitButtonLabel;\r\n var $_filters;\r\n var $_filterForm;\r\n var $_showMoreMessage;\r\n var $_showMoreMessageDescription;\r\n var $_showMoreMessageProgress;\r\n var $_showMoreMessageButton;\r\n var $_navigation;\r\n var $_fillupMessage; \r\n var $_fillupMessageButton; \r\n var $_filterBar;\r\n var $_filterBarButton;\r\n\r\n /**\r\n * Executed after page load\r\n */\r\n function boot()\r\n {\r\n _configuration = window.naeCategoryConfiguration;\r\n _products = window.naeProductListConfiguration;\r\n\r\n // Some categories dont have that, e.g. gender landing pages\r\n if (_configuration == null || _products == null)\r\n {\r\n return;\r\n }\r\n\r\n // Start intersection observer, if browser supports it\r\n if (XmxApp.supportsIntersectionObserver())\r\n {\r\n _intersectionObserver = new IntersectionObserver(onIntersection, {\r\n root: null,\r\n rootMargin: '0px',\r\n threshold: 0.75 // min. 75% on screen\r\n });\r\n }\r\n\r\n $_document = jQuery(document);\r\n $_html = jQuery('html');\r\n $_grid = jQuery('#category-grid');\r\n $_listEnd = jQuery('#category-list-end');\r\n $_title = jQuery('#category-title');\r\n $_productCount = jQuery('#category-product-count');\r\n $_description = jQuery('#category-description');\r\n $_filters = jQuery('#category-filters');\r\n\r\n $_filterDrawer = jQuery('#category-filter-drawer');\r\n $_navigation = jQuery('#category-navigation');\r\n\r\n // Hook existing product links, so we can save state\r\n var $productLinks = jQuery('.xmx-category-product-click-target', $_grid);\r\n $productLinks.on('click', onProductLinkClick); // Mouse 1 \r\n $productLinks.on('auxclick', onProductLinkClick); // Mouse 3\r\n\r\n if (_intersectionObserver)\r\n {\r\n $productLinks.each(function()\r\n {\r\n _intersectionObserver.observe(this);\r\n });\r\n }\r\n\r\n $_filterForm = jQuery('#category-filter-form');\r\n $_filterForm.on('submit', onFilterFormSubmit);\r\n \r\n $_filterResetButton = jQuery('#category-filter-reset-button');\r\n $_filterResetButton.on('click', onFilterResetButtonClick);\r\n\r\n $_filterSubmitButton = jQuery('#category-filter-submit-button');\r\n $_filterSubmitButton.on('click', onFilterSubmitButtonClick);\r\n\r\n $_filterSubmitButtonLabel = jQuery('#category-filter-submit-button-label');\r\n\r\n $_filterDrawerSkrim = jQuery('#category-filter-drawer-skrim');\r\n $_filterDrawerSkrim.on('click', onFilterDrawerSkrimClick);\r\n\r\n $_filterBar = jQuery('#category-filter-bar');\r\n $_filterBarButton = jQuery('#category-filter-bar-button');\r\n $_filterBarButton.on('click', onFilterBarButtonClick);\r\n\r\n $_showMoreMessage = jQuery('#category-show-more-message');\r\n $_showMoreMessageDescription = jQuery('#category-show-more-message-description');\r\n $_showMoreMessageProgress = jQuery('#category-show-more-message-progress');\r\n $_showMoreMessageButton = jQuery('#category-show-more-message-button');\r\n $_showMoreMessageButton.on('click', onShowMoreMessageButtonClick);\r\n\r\n $_fillupMessage = jQuery('#category-fillup-message');\r\n $_fillupMessageButton = jQuery('#category-fillup-message-button');\r\n $_fillupMessageButton.on('click', onFillupMessageButtonClick);\r\n\r\n // Hook all existing grid banners\r\n /*for (var i in _configuration.banners)\r\n {\r\n var banner = _configuration.banners[i];\r\n var $gridBanner = jQuery('[data-grid-banner-id=\"' + banner.id + '\"]', $_grid);\r\n \r\n // Track Banner CTR\r\n XmxApp.registerInternalPromotion($gridBanner, 'grid_banner_' + banner.id,\r\n {\r\n 'creative_name': 'grid_banner',\r\n 'creative_slot': _configuration.name,\r\n 'location_id': _configuration.id,\r\n 'promotion_id': 'grid_banner_' + banner.id,\r\n 'promotion_name': banner.name\r\n });\r\n }*/\r\n\r\n // if there is a state, try to restore it\r\n var restoredState = restoreState();\r\n\r\n // Update filters etc.\r\n updateShowMoreMessage();\r\n updateProductCount();\r\n updateNavigation();\r\n updateFilterBar();\r\n\r\n // Find out when to preload the next page\r\n updateNextPagePreloading();\r\n\r\n // Hook the scroll event observer.\r\n // Cannot use intersection observers yet, as they are not that supported right ow.\r\n XmxApp.registerScrollEventObserver('category', handleScroll);\r\n\r\n // Save the state, so that when we switch categories back and forth, the browser\r\n // does not jump\r\n if (!restoredState)\r\n {\r\n saveState();\r\n }\r\n\r\n // Send a category view\r\n /*global XmxEventQueue*/\r\n XmxEventQueue.trackEvent('cv', \r\n {\r\n 'c': _configuration.id\r\n });\r\n\r\n // Start all countdowns that have not yet been started via restoreState()\r\n // Boot all countdowns\r\n jQuery('[data-start-countdown=\"true\"]', $_grid).each(function()\r\n {\r\n /*global XmxCountdown*/\r\n var countdown = new XmxCountdown(jQuery(this));\r\n _countdowns.push(countdown);\r\n });\r\n }\r\n\r\n /**\r\n * Fired when a product was visible for at least 1 second\r\n * \r\n * @param {Element} element \r\n */\r\n function onProductImpression(element)\r\n {\r\n var productId = parseInt(element.dataset.productId);\r\n var position = parseInt(element.dataset.position);\r\n\r\n /*global XmxEventQueue*/\r\n XmxEventQueue.trackEvent('cpv', \r\n {\r\n p: productId, \r\n c: _configuration.id,\r\n r: position\r\n });\r\n\r\n if (_intersectionObserver)\r\n {\r\n _intersectionObserver.unobserve(element);\r\n }\r\n }\r\n\r\n /**\r\n * Handles element<>viewport intersections\r\n * \r\n * @param {IntersectionObserverEntry[]} entries \r\n */\r\n function onIntersection(entries)\r\n {\r\n for (var index in entries)\r\n {\r\n var entry = entries[index];\r\n var element = entry.target;\r\n var timeoutHandle = ('th' in element.dataset) ? element.dataset.th : null;\r\n \r\n // If the element is visible for at least 75%, start \r\n // a timeout for 1s to count the impression. Otherwise\r\n // abort the timeout if the element is not visible (anymore)\r\n if (entry.intersectionRatio >= 0.75)\r\n {\r\n if (!timeoutHandle)\r\n {\r\n timeoutHandle = setTimeout(onProductImpression.bind(this, element), 1000);\r\n element.dataset.th = timeoutHandle;\r\n }\r\n }\r\n else \r\n {\r\n if (timeoutHandle)\r\n {\r\n clearTimeout(timeoutHandle);\r\n delete element.dataset.th;\r\n }\r\n }\r\n }\r\n }\r\n\r\n function onFilterBarButtonClick()\r\n {\r\n openFilterDrawer();\r\n }\r\n\r\n /**\r\n * Updates the new filter bar showing promoted filters, custom filters, price filters and sorting in one UI element\r\n */\r\n function updateFilterBar()\r\n {\r\n // Throw away everything\r\n jQuery('.xmx-filter-bar-item', $_filterBar).remove();\r\n\r\n // Remember the promoted options, so that they dont draw\r\n // again when selected\r\n var renderedOptionIds = [];\r\n\r\n // Add promoted filter options\r\n if (_configuration.filters.promotedOptions)\r\n {\r\n for (var i in _configuration.filters.promotedOptions)\r\n {\r\n var promotedOption = _configuration.filters.promotedOptions[i];\r\n\r\n var $filterBarItem = jQuery('<div>');\r\n $filterBarItem.addClass('xmx-filter-bar-item');\r\n $filterBarItem.attr('data-type', 'promoted');\r\n $filterBarItem.attr('data-filter-index', promotedOption.filterIndex);\r\n $filterBarItem.attr('data-option-index', promotedOption.optionIndex);\r\n $filterBarItem.on('click', onPromotedFilterBarItemClick);\r\n\r\n if (promotedOption.selected)\r\n {\r\n $filterBarItem.addClass('xmx-filter-bar-item--active');\r\n }\r\n\r\n if (promotedOption.count == 0)\r\n {\r\n $filterBarItem.addClass('xmx-filter-bar-item--disabled');\r\n }\r\n\r\n var $filterBarItemIcon = jQuery('<div>');\r\n $filterBarItemIcon.addClass('xmx-filter-bar-item-icon');\r\n $filterBarItemIcon.appendTo($filterBarItem);\r\n\r\n var $filterBarItemName = jQuery('<div>');\r\n $filterBarItemName.addClass('xmx-filter-bar-item-name');\r\n $filterBarItemName.html(promotedOption.name);\r\n $filterBarItemName.appendTo($filterBarItem);\r\n\r\n $filterBarItem.insertBefore($_filterBarButton);\r\n\r\n renderedOptionIds.push(promotedOption.id);\r\n }\r\n }\r\n\r\n // Then add custom-added filters\r\n if (_configuration.filters.filters)\r\n {\r\n for (var filterIndex in _configuration.filters.filters)\r\n {\r\n var filter = _configuration.filters.filters[filterIndex];\r\n\r\n switch (filter.type)\r\n {\r\n case 'price':\r\n {\r\n if (filter.from || filter.to)\r\n {\r\n var $priceFilterBarItem = jQuery('<div>');\r\n $priceFilterBarItem.addClass('xmx-filter-bar-item');\r\n $priceFilterBarItem.attr('data-type', 'custom');\r\n $priceFilterBarItem.attr('data-filter-index', filterIndex);\r\n $priceFilterBarItem.on('click', onCustomFilterBarItemClick);\r\n $priceFilterBarItem.addClass('xmx-filter-bar-item--active');\r\n \r\n var $priceFilterBarItemIcon = jQuery('<div>');\r\n $priceFilterBarItemIcon.addClass('xmx-filter-bar-item-icon');\r\n $priceFilterBarItemIcon.appendTo($priceFilterBarItem);\r\n \r\n var $priceFilterBarItemName = jQuery('<div>');\r\n $priceFilterBarItemName.addClass('xmx-filter-bar-item-name');\r\n\r\n if (filter.from && filter.to)\r\n {\r\n $priceFilterBarItemName.html(window.XmxApp.formatAmount(filter.from) + ' - ' + window.XmxApp.formatAmount(filter.to));\r\n }\r\n else if (filter.to)\r\n {\r\n $priceFilterBarItemName.html(window.naeCategoryTranslations.to + ' ' + window.XmxApp.formatAmount(filter.to)); \r\n }\r\n else if (filter.from)\r\n {\r\n $priceFilterBarItemName.html(window.naeCategoryTranslations.from + ' ' + window.XmxApp.formatAmount(filter.from)); \r\n }\r\n\r\n $priceFilterBarItemName.appendTo($priceFilterBarItem);\r\n \r\n $priceFilterBarItem.insertBefore($_filterBarButton);\r\n }\r\n\r\n break;\r\n }\r\n\r\n case 'rating':\r\n case 'multiselect': \r\n case 'swatches': \r\n case 'sizes':\r\n case 'thumbnails':\r\n case 'radio':\r\n {\r\n for (var optionIndex in filter.options)\r\n {\r\n var option = filter.options[optionIndex];\r\n\r\n if (option.selected)\r\n {\r\n // Skip, if already rendered\r\n // Array.includes() is not supported on stoneage browsers (yes, there are users)\r\n //if (!renderedOptionIds.includes(option.id))\r\n if (renderedOptionIds.indexOf(option.id) == -1)\r\n {\r\n var $customFilterBarItem = jQuery('<div>');\r\n $customFilterBarItem.addClass('xmx-filter-bar-item');\r\n $customFilterBarItem.addClass('xmx-filter-bar-item--active');\r\n $customFilterBarItem.attr('data-type', 'custom');\r\n $customFilterBarItem.attr('data-filter-index', filterIndex);\r\n $customFilterBarItem.attr('data-option-index', optionIndex);\r\n $customFilterBarItem.on('click', onCustomFilterBarItemClick);\r\n \r\n var $customFilterBarItemIcon = jQuery('<div>');\r\n $customFilterBarItemIcon.addClass('xmx-filter-bar-item-icon');\r\n $customFilterBarItemIcon.appendTo($customFilterBarItem);\r\n \r\n var $customFilterBarItemName = jQuery('<div>');\r\n $customFilterBarItemName.addClass('xmx-filter-bar-item-name');\r\n $customFilterBarItemName.html(option.name);\r\n $customFilterBarItemName.appendTo($customFilterBarItem);\r\n \r\n $customFilterBarItem.insertBefore($_filterBarButton);\r\n }\r\n }\r\n }\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Add a chip for the sorting as well\r\n if (!(_configuration.sorting.order == _configuration.sorting.defaultOrder && _configuration.sorting.direction == 'asc'))\r\n {\r\n var sortingName = '';\r\n \r\n for (var methodIndex in _configuration.sorting.methods)\r\n {\r\n var method = _configuration.sorting.methods[methodIndex];\r\n\r\n if (method.order == _configuration.sorting.order && method.direction == _configuration.sorting.direction)\r\n {\r\n sortingName = method.name;\r\n break;\r\n }\r\n }\r\n\r\n var $sortingFilterBarItem = jQuery('<div>');\r\n $sortingFilterBarItem.addClass('xmx-filter-bar-item');\r\n $sortingFilterBarItem.addClass('xmx-filter-bar-item--active');\r\n $sortingFilterBarItem.attr('data-type', 'sorting');\r\n $sortingFilterBarItem.on('click', onSortingFilterBarItemClick);\r\n\r\n var $sortingFilterBarItemIcon = jQuery('<div>');\r\n $sortingFilterBarItemIcon.addClass('xmx-filter-bar-item-icon');\r\n $sortingFilterBarItemIcon.appendTo($sortingFilterBarItem);\r\n\r\n var $sortingFilterBarItemName = jQuery('<div>');\r\n $sortingFilterBarItemName.addClass('xmx-filter-bar-item-name');\r\n $sortingFilterBarItemName.html(sortingName);\r\n $sortingFilterBarItemName.appendTo($sortingFilterBarItem);\r\n\r\n $sortingFilterBarItem.insertBefore($_filterBarButton);\r\n }\r\n }\r\n\r\n /**\r\n * User wants to toggle a promoted filter\r\n */\r\n function onPromotedFilterBarItemClick()\r\n {\r\n var $me = jQuery(this);\r\n var filterIndex = $me.attr('data-filter-index');\r\n var optionIndex = $me.attr('data-option-index');\r\n\r\n // If this is disabled, get out of here\r\n if ($me.hasClass('xmx-filter-bar-item--disabled'))\r\n {\r\n return;\r\n }\r\n \r\n // Is it active right now?\r\n if (_configuration.filters.filters[filterIndex].options[optionIndex].selected)\r\n {\r\n // Remove the filter\r\n _configuration.filters.filters[filterIndex].options[optionIndex].selected = false;\r\n\r\n // Deselect the bar item\r\n $me.removeClass('xmx-filter-bar-item--active');\r\n }\r\n else \r\n {\r\n // Add the filter\r\n _configuration.filters.filters[filterIndex].options[optionIndex].selected = true;\r\n\r\n // Select the bar item\r\n $me.addClass('xmx-filter-bar-item--active');\r\n }\r\n\r\n // Reload everything\r\n commitFilters(null);\r\n }\r\n\r\n /**\r\n * User wants to reset sorting\r\n */\r\n function onSortingFilterBarItemClick()\r\n {\r\n // Delete filter bar item\r\n var $me = jQuery(this);\r\n $me.remove();\r\n\r\n // Reset sorting\r\n resetSorting();\r\n\r\n // Reload everything\r\n commitFilters(null);\r\n }\r\n\r\n /**\r\n * User wants to remove custom filter\r\n */\r\n function onCustomFilterBarItemClick()\r\n {\r\n var $me = jQuery(this);\r\n var filterIndex = $me.attr('data-filter-index');\r\n var filter = _configuration.filters.filters[filterIndex];\r\n\r\n // Unset price filters\r\n if (filter.type == 'price')\r\n {\r\n _configuration.filters.filters[filterIndex].from = null;\r\n _configuration.filters.filters[filterIndex].to = null;\r\n }\r\n else \r\n {\r\n // Unset option filters\r\n var optionIndex = $me.attr('data-option-index');\r\n\r\n // Unselect option\r\n _configuration.filters.filters[filterIndex].options[optionIndex].selected = false;\r\n }\r\n\r\n // Delete filter bar item\r\n $me.remove();\r\n\r\n // Reload everything\r\n commitFilters(null);\r\n }\r\n\r\n /**\r\n * Destroys all countdowns so that they clear their interval\r\n */\r\n function destroyCountdowns()\r\n {\r\n for (var index in _countdowns)\r\n {\r\n _countdowns[index].destroy();\r\n }\r\n\r\n _countdowns = [];\r\n }\r\n\r\n /**\r\n * Updates the navigation, including \"view all\", links and pages\r\n */\r\n function updateNavigation()\r\n {\r\n // If there is nothing to do, get out of here\r\n if (_configuration.navigation.length == 0)\r\n {\r\n return;\r\n }\r\n\r\n // Throw away all entries\r\n $_navigation.empty();\r\n\r\n for (var navigationIndex in _configuration.navigation)\r\n {\r\n var entry = _configuration.navigation[navigationIndex];\r\n\r\n var $wrap = jQuery('<div>');\r\n $wrap.addClass('xmx-category-cross-link-wrap');\r\n\r\n var $link = jQuery('<a>');\r\n $link.attr('href', entry.url);\r\n $link.html(entry.name);\r\n $link.addClass('xmx-cross-link');\r\n $link.data('index', navigationIndex);\r\n\r\n if (entry.type != 'link')\r\n {\r\n $link.on('click', onNavigationLinkClick);\r\n }\r\n\r\n if (entry.active)\r\n {\r\n $link.addClass('xmx-cross-link--current');\r\n }\r\n\r\n $link.appendTo($wrap);\r\n $wrap.appendTo($_navigation);\r\n }\r\n }\r\n\r\n /**\r\n * \r\n */\r\n function onNavigationLinkClick()\r\n {\r\n var $link = jQuery(this);\r\n var navigationIndex = $link.data('index');\r\n var navigationEntry = _configuration.navigation[navigationIndex];\r\n \r\n // User has clicked the \"view all\" button\r\n if (navigationEntry.type == 'all')\r\n {\r\n resetEverythingAndReload();\r\n }\r\n else \r\n {\r\n // User has clicked a page\r\n var postData = {};\r\n\r\n // Jump to page 1\r\n postData['p'] = 1;\r\n\r\n // Apply filters\r\n for (var pageFilterIndex in navigationEntry.filters)\r\n {\r\n var pageFilter = navigationEntry.filters[pageFilterIndex];\r\n\r\n if (postData[pageFilter.key] === undefined)\r\n {\r\n postData[pageFilter.key] = pageFilter.value;\r\n }\r\n else \r\n {\r\n postData[pageFilter.key] = postData[pageFilter.key] + ',' + pageFilter.value;\r\n } \r\n }\r\n\r\n // Apply sorting\r\n if (navigationEntry.sortOrder != '' && navigationEntry.sortDirection != '')\r\n {\r\n postData['dir'] = navigationEntry.sortDirection;\r\n postData['order'] = navigationEntry.sortOrder;\r\n }\r\n else \r\n {\r\n postData['dir'] = 'asc';\r\n postData['order'] = 'position';\r\n }\r\n\r\n // So that we get a JSON response\r\n postData['is_ajax'] = 1;\r\n\r\n // Reload category\r\n commitFilters(postData);\r\n }\r\n // Do not follow link\r\n return false;\r\n }\r\n\r\n /**\r\n *\r\n */\r\n function updateCategoryHeadline()\r\n {\r\n $_title.html(_configuration.headline);\r\n }\r\n\r\n /**\r\n * \r\n */\r\n function updateBrowserState()\r\n {\r\n var urlBefore = window.location.href;\r\n\r\n if (XmxApp.supportsHistoryApi())\r\n {\r\n history.replaceState(null, _configuration.pageTitle, _configuration.url);\r\n }\r\n\r\n // Most browsers currently ignore the this parameter, \r\n // although they may use it in the future. Passing \r\n // the empty string here should be safe against future changes to the method. \r\n document.title = _configuration.pageTitle;\r\n\r\n // If the URL changes, send a new page view event to Google Analytics\r\n if (urlBefore != _configuration.url)\r\n {\r\n if (typeof gtag !== 'undefined')\r\n {\r\n gtag('event', 'page_view', \r\n {\r\n 'page_title': _configuration.pageTitle, \r\n 'page_location': _configuration.url\r\n });\r\n }\r\n\r\n if (typeof ga !== 'undefined')\r\n {\r\n ga('send', 'pageview', window.location.pathname);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n *\r\n */\r\n function updateCategoryDescription()\r\n {\r\n\t\t// Update the description\r\n\t\tif (_configuration.description)\r\n\t\t{\r\n\t\t\t$_description.html(_configuration.description);\r\n\t\t\t$_description.show();\r\n\t\t}\r\n\t\telse \r\n\t\t{\r\n\t\t\t$_description.hide();\r\n\t\t\t$_description.empty();\r\n\t\t}\r\n }\r\n\r\n /**\r\n * \r\n */\r\n function updateResetFiltersButton()\r\n {\r\n if (_configuration.filters.activeFilterCount > 0)\r\n {\r\n $_filterResetButton.show();\r\n }\r\n else \r\n {\r\n $_filterResetButton.hide();\r\n }\r\n }\r\n\r\n /**\r\n * Updates the number of products\r\n */\r\n function updateProductCount()\r\n {\r\n // Update button label\r\n switch (_configuration.products)\r\n {\r\n case 0: $_productCount.html(window.naeCategoryTranslations.noProducts); break;\r\n case 1: $_productCount.html(window.naeCategoryTranslations.oneProduct); break;\r\n default: $_productCount.html(window.naeCategoryTranslations.xProducts.replace('%s', _configuration.products)); break;\r\n }\r\n }\r\n\r\n /**\r\n * \r\n */\r\n function updateSubmitButtonLabel()\r\n {\r\n // Update button label\r\n switch (_configuration.products)\r\n {\r\n case 0: $_filterSubmitButtonLabel.html(window.naeCategoryTranslations.noResults); break; \r\n case 1: $_filterSubmitButtonLabel.html(window.naeCategoryTranslations.viewOneProduct); break; \r\n default: $_filterSubmitButtonLabel.html(window.naeCategoryTranslations.viewXProducts.replace('%s', _configuration.products)); break;\r\n }\r\n }\r\n\r\n /**\r\n * Determines wether a next page can be loaded and if so, finds out the\r\n * scroll position and which it can be pre-loaded. Use with caution, this\r\n * may cause reflows/layout.\r\n */\r\n function updateNextPagePreloading()\r\n {\r\n // We can preload the next page, if there are some\r\n if (_configuration.page < _configuration.pageCount)\r\n {\r\n _canPreloadNextPage = true;\r\n\r\n // Take the position of the \"show more\" message and add an offset.\r\n // 2000 is ensured to be alright on both mobiles, tablets and desktops\r\n _preloadScrollPosition = $_showMoreMessage.offset().top - 2000;\r\n }\r\n else \r\n {\r\n _canPreloadNextPage = false;\r\n }\r\n }\r\n\r\n /**\r\n * Fires when the user has scrolled. Called only if there has been changes.\r\n * Called inside an animation frame.\r\n * \r\n * Optimize for performance, as this affects FPS so hard.\r\n */\r\n function handleScroll()\r\n {\r\n var scrollPosition = XmxApp.scrollOffsetY;\r\n\r\n // Is there a next page?\r\n if (_canPreloadNextPage)\r\n {\r\n // Did we scroll down far enough?\r\n if (scrollPosition >= _preloadScrollPosition)\r\n {\r\n // Are we not already preloading the next page?\r\n if (!_isLoadingNextPage)\r\n {\r\n // Lock this\r\n _canPreloadNextPage = false;\r\n _isLoadingNextPage = true;\r\n\r\n // Get out of the render thread of the browser\r\n setTimeout(loadNextPage, 16);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * \r\n */\r\n function updateShowMoreMessage()\r\n {\r\n if (_configuration.page >= _configuration.pageCount)\r\n {\r\n $_showMoreMessage.hide();\r\n }\r\n else \r\n {\r\n var viewedProducts = _configuration.page * _configuration.pageSize;\r\n var percent = Math.round(viewedProducts * 100 / _configuration.products);\r\n\r\n $_showMoreMessageDescription.html(window.naeCategoryTranslations.youHaveSeen.replace('%1', viewedProducts).replace('%2', _configuration.products));\r\n $_showMoreMessageProgress.css('width', percent + '%');\r\n $_showMoreMessage.show();\r\n }\r\n }\r\n\r\n /**\r\n * \r\n */\r\n function updateFilters()\r\n {\r\n // Throw away all filters\r\n $_filters.empty();\r\n\r\n // Create a fragment for the filters\r\n var $fragment = document.createDocumentFragment();\r\n\r\n // Add sorting first\r\n renderSorting($fragment);\r\n\r\n // And rebuild them\r\n if (_configuration.filters.filters)\r\n {\r\n for (var filterIndex in _configuration.filters.filters)\r\n {\r\n var filter = _configuration.filters.filters[filterIndex];\r\n\r\n var $separator = document.createElement('div');\r\n $separator.classList.add('xmx-filter-separator');\r\n $fragment.appendChild($separator);\r\n\r\n switch (filter.type)\r\n {\r\n case 'multiselect': renderAttributeFilter($fragment, filterIndex, filter, 'checkbox'); break; // DONE\r\n case 'thumbnails': renderAttributeFilter($fragment, filterIndex, filter, 'checkbox'); break; // DONE\r\n case 'price': renderPriceFilter($fragment, filterIndex, filter); break; // DONE\r\n case 'swatches': renderSwatchesFilter($fragment, filterIndex, filter); break; // DONE\r\n case 'sizes': renderSizesFilter($fragment, filterIndex, filter); break; // DONE\r\n case 'radio': renderAttributeFilter($fragment, filterIndex, filter, 'radio'); break; // DONE\r\n case 'rating': renderRatingFilter($fragment, filterIndex, filter); break; // DONE\r\n default: break;\r\n }\r\n }\r\n }\r\n\r\n $_filters[0].appendChild($fragment);\r\n }\r\n\r\n /**\r\n * Fired after a price input was changed\r\n */\r\n function onPriceFilterInputChange()\r\n {\r\n var $input = jQuery(this);\r\n var name = $input.attr('name');\r\n var filterIndex = $input.data('filter-index');\r\n var inputValue = $input.val();\r\n var value = -1;\r\n\r\n if (inputValue == '')\r\n {\r\n value = null;\r\n }\r\n else \r\n {\r\n value = parseFloat(inputValue);\r\n\r\n // Clamp it\r\n if (value < _configuration.filters.filters[filterIndex].minimum)\r\n {\r\n value = _configuration.filters.filters[filterIndex].minimum;\r\n }\r\n\r\n if (value > _configuration.filters.filters[filterIndex].maximum)\r\n {\r\n value = _configuration.filters.filters[filterIndex].maximum;\r\n }\r\n }\r\n\r\n if (name == 'price-from')\r\n {\r\n _configuration.filters.filters[filterIndex].from = value;\r\n }\r\n else \r\n {\r\n _configuration.filters.filters[filterIndex].to = value;\r\n }\r\n\r\n // Reload everything\r\n commitFilters(null);\r\n }\r\n\r\n /**\r\n * Fired after the user has changed a filter\r\n */\r\n function onFilterInputChange()\r\n {\r\n var $input = jQuery(this);\r\n var changedFilterIndex = $input.data('filter-index');\r\n var changedOptionIndex = $input.data('option-index');\r\n var isSelected = $input.is(':checked');\r\n\r\n // If this is a rating filter, we can only allow a single selection\r\n // Yes, it is a checkbox, but users would not be able to release\r\n // a radio selection...\r\n if (_configuration.filters.filters[changedFilterIndex].attribute == 'rating')\r\n {\r\n if (isSelected)\r\n {\r\n // Go through all options that are selected already and release it\r\n for (var optionIndex in _configuration.filters.filters[changedFilterIndex].options)\r\n {\r\n if (optionIndex != changedOptionIndex)\r\n {\r\n if (_configuration.filters.filters[changedFilterIndex].options[optionIndex].selected)\r\n {\r\n // Remove filter option\r\n _configuration.filters.filters[changedFilterIndex].options[optionIndex].selected = false;\r\n\r\n // Adjust UI\r\n jQuery('#filter-rating-' + _configuration.filters.filters[changedFilterIndex].options[optionIndex].value, $_filters).attr('checked', false);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Change the selection\r\n _configuration.filters.filters[changedFilterIndex].options[changedOptionIndex].selected = isSelected;\r\n\r\n // Reload everything\r\n commitFilters(null);\r\n }\r\n\r\n /**\r\n * Fired after the user has changed sorting\r\n */\r\n function onSortingInputChange()\r\n {\r\n var $input = jQuery(this);\r\n var sortingIndex = $input.val();\r\n var sorting = _configuration.sorting.methods[sortingIndex];\r\n\r\n _configuration.sorting.order = sorting.order;\r\n _configuration.sorting.direction = sorting.direction;\r\n\r\n // Go for it\r\n commitFilters(null);\r\n }\r\n\r\n /**\r\n * \r\n * @param {object} filter \r\n */\r\n function renderSorting()\r\n {\r\n var $filter = jQuery('<div>');\r\n $filter.addClass('xmx-filter');\r\n $filter.addClass('xmx-filter--sorting');\r\n $filter.attr('data-group', 'sorting');\r\n\r\n // Is the filter opened?\r\n if (_expandedFilters.includes('sorting'))\r\n {\r\n $filter.addClass('xmx-filter--expanded');\r\n }\r\n\r\n // Create the head\r\n var $filterHead = jQuery('<div>');\r\n $filterHead.addClass('xmx-filter-head');\r\n $filterHead.on('click', onFilterHeadClick);\r\n $filterHead.appendTo($filter);\r\n\r\n var $filterName = jQuery('<div>');\r\n $filterName.addClass('xmx-filter-name');\r\n $filterName.html(window.naeCategoryTranslations.sortBy);\r\n $filterName.appendTo($filterHead);\r\n\r\n // Does the filter have changes?\r\n if (_configuration.sorting.order != _configuration.sorting.defaultOrder)\r\n {\r\n for (var sotingIndex in _configuration.sorting.methods)\r\n {\r\n var sorting = _configuration.sorting.methods[sotingIndex];\r\n\r\n if (_configuration.sorting.order == sorting.order)\r\n {\r\n if (_configuration.sorting.direction == sorting.direction)\r\n {\r\n var $filterSubtitle = jQuery('<div>');\r\n $filterSubtitle.addClass('xmx-subtitle');\r\n $filterSubtitle.html(sorting.name);\r\n $filterSubtitle.appendTo($filterHead);\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Create the content\r\n var $filterContent = jQuery('<div>');\r\n $filterContent.addClass('xmx-filter-content');\r\n $filterContent.appendTo($filter);\r\n\r\n var $options = jQuery('<div>');\r\n $options.addClass('xmx-filter-options');\r\n $options.appendTo($filterContent);\r\n\r\n for (var methodIndex in _configuration.sorting.methods)\r\n {\r\n var method = _configuration.sorting.methods[methodIndex];\r\n var id = 'sorting-' + method.order + '-' + method.direction;\r\n\r\n var $option = jQuery('<div>');\r\n $option.addClass('xmx-filter-option');\r\n $option.appendTo($options);\r\n\r\n var $input = jQuery('<input>');\r\n $input.addClass('xmx-filter-option-input');\r\n $input.attr('id', id);\r\n $input.attr('type', 'radio');\r\n $input.attr('name', 'sorting');\r\n $input.attr('value', methodIndex);\r\n $input.on('change', onSortingInputChange);\r\n\r\n if (_configuration.sorting.order == method.order)\r\n {\r\n if (_configuration.sorting.direction == method.direction)\r\n {\r\n $input.attr('checked', true);\r\n }\r\n }\r\n\r\n $input.appendTo($option);\r\n\r\n var $optionLabel = jQuery('<label>');\r\n $optionLabel.attr('for', id);\r\n $optionLabel.addClass('xmx-filter-option-label');\r\n $optionLabel.appendTo($option);\r\n\r\n var $optionText = jQuery('<div>');\r\n $optionText.addClass('xmx-filter-option-text');\r\n $optionText.appendTo($optionLabel);\r\n\r\n var $optionName = jQuery('<div>');\r\n $optionName.addClass('xmx-filter-option-name');\r\n $optionName.html(method.name);\r\n $optionName.appendTo($optionText);\r\n\r\n var $optionRadio = jQuery('<div>');\r\n $optionRadio.addClass('xmx-filter-option-radio');\r\n $optionRadio.appendTo($optionLabel);\r\n\r\n var $optionRadioBullet = jQuery('<div>');\r\n $optionRadioBullet.addClass('xmx-filter-option-radio-bullet');\r\n $optionRadioBullet.appendTo($optionRadio);\r\n }\r\n\r\n $filter.appendTo($_filters);\r\n }\r\n\r\n /**\r\n * @param {DocumentFragment} fragment\r\n * @param {int} filterIndex\r\n * @param {object} filter \r\n */\r\n function renderSwatchesFilter(fragment, filterIndex, filter)\r\n {\r\n var filterSubtitle = '';\r\n\r\n var $filter = document.createElement('div');\r\n $filter.classList.add('xmx-filter', 'xmx-filter--' + filter.type);\r\n $filter.setAttribute('data-group', filter.attribute);\r\n\r\n // Is the filter opened?\r\n if (_expandedFilters.includes(filter.attribute))\r\n {\r\n $filter.classList.add('xmx-filter--expanded');\r\n }\r\n\r\n // Create the head\r\n var $filterHead = document.createElement('div');\r\n $filterHead.classList.add('xmx-filter-head');\r\n $filterHead.addEventListener('click', onFilterHeadClick);\r\n $filter.appendChild($filterHead);\r\n\r\n var $filterName = document.createElement('div');\r\n $filterName.classList.add('xmx-filter-name');\r\n $filterName.innerText = filter.name;\r\n $filterHead.appendChild($filterName);\r\n\r\n // Create the content\r\n var $filterContent = document.createElement('div');\r\n $filterContent.classList.add('xmx-filter-content');\r\n $filter.appendChild($filterContent);\r\n\r\n if (filter.description)\r\n {\r\n var $filterDescription = document.createElement('div');\r\n $filterDescription.classList.add('xmx-filter-description');\r\n $filterDescription.innerText = filter.description;\r\n $filter.appendChild($filterDescription);\r\n }\r\n\r\n var $colors = document.createElement('div');\r\n $colors.classList.add('xmx-filter-colors');\r\n $filterContent.appendChild($colors);\r\n\r\n for (var optionIndex in filter.options)\r\n {\r\n var option = filter.options[optionIndex];\r\n var id = 'filter-' + filter.attribute + '-' + option.value;\r\n var isDisabled = option.count == 0;\r\n\r\n var $color = document.createElement('div');\r\n $color.classList.add('xmx-filter-color');\r\n\r\n if (isDisabled)\r\n {\r\n $color.classList.add('xmx-filter-color--disabled'); \r\n }\r\n\r\n $colors.appendChild($color);\r\n\r\n var $input = document.createElement('input');\r\n $input.classList.add('xmx-filter-color-input');\r\n $input.setAttribute('id', id);\r\n $input.setAttribute('type', 'checkbox');\r\n $input.setAttribute('name', filter.attribute);\r\n $input.setAttribute('value', option.value);\r\n $input.setAttribute('data-filter-index', filterIndex);\r\n $input.setAttribute('data-option-index', optionIndex);\r\n $input.addEventListener('change', onFilterInputChange);\r\n\r\n if (option.selected)\r\n {\r\n $input.setAttribute('checked', true);\r\n\r\n if (filterSubtitle != '')\r\n {\r\n filterSubtitle += ', ';\r\n }\r\n\r\n filterSubtitle += option.name;\r\n }\r\n\r\n if (isDisabled)\r\n {\r\n $input.setAttribute('disabled', true);\r\n }\r\n\r\n $color.appendChild($input);\r\n\r\n var $colorLabel = document.createElement('label');\r\n $colorLabel.setAttribute('for', id);\r\n $colorLabel.classList.add('xmx-filter-color-label');\r\n $colorLabel.style['background-color'] = option.color;\r\n\r\n if (option.color == '#ffffff')\r\n {\r\n $colorLabel.classList.add('xmx-filter-color-label--outlined');\r\n }\r\n\r\n $color.appendChild($colorLabel);\r\n\r\n var $colorCheckIcon = document.createElement('div');\r\n $colorCheckIcon.classList.add('xmx-filter-color-icon');\r\n $colorLabel.appendChild($colorCheckIcon);\r\n\r\n var $colorCount = document.createElement('div');\r\n $colorCount.innerText = '(' + option.count + ')';\r\n $colorCount.classList.add('xmx-filter-option-count');\r\n $colorLabel.appendChild($colorCount);\r\n\r\n if (option.light)\r\n {\r\n $colorCheckIcon.classList.add('xmx-icon-check-white');\r\n $colorCount.classList.add('xmx-filter-option-count--light');\r\n }\r\n else \r\n {\r\n $colorCheckIcon.classList.add('xmx-icon-check');\r\n }\r\n }\r\n\r\n // Does the filter have changes?\r\n if (filterSubtitle != '')\r\n {\r\n var $filterSubtitle = document.createElement('div');\r\n $filterSubtitle.classList.add('xmx-subtitle');\r\n $filterSubtitle.innerText = filterSubtitle;\r\n $filterHead.appendChild($filterSubtitle);\r\n }\r\n\r\n fragment.appendChild($filter);\r\n }\r\n\r\n /**\r\n * @param {DocumentFragment} fragment\r\n * @param {int} filterIndex\r\n * @param {object} filter \r\n */\r\n function renderSizesFilter(fragment, filterIndex, filter)\r\n {\r\n var filterSubtitle = '';\r\n\r\n var $filter = document.createElement('div');\r\n $filter.classList.add('xmx-filter', 'xmx-filter--' + filter.type);\r\n $filter.setAttribute('data-group', filter.attribute);\r\n\r\n // Is the filter opened?\r\n if (_expandedFilters.includes(filter.attribute))\r\n {\r\n $filter.classList.add('xmx-filter--expanded');\r\n }\r\n\r\n // Create the head\r\n var $filterHead = document.createElement('div');\r\n $filterHead.classList.add('xmx-filter-head');\r\n $filterHead.addEventListener('click', onFilterHeadClick);\r\n $filter.appendChild($filterHead);\r\n\r\n var $filterName = document.createElement('div');\r\n $filterName.classList.add('xmx-filter-name');\r\n $filterName.innerText = filter.name;\r\n $filterHead.appendChild($filterName);\r\n\r\n // Create the content\r\n var $filterContent = document.createElement('div');\r\n $filterContent.classList.add('xmx-filter-content');\r\n $filter.appendChild($filterContent);\r\n\r\n if (filter.description)\r\n {\r\n var $filterDescription = document.createElement('div');\r\n $filterDescription.classList.add('xmx-filter-description');\r\n $filterDescription.innerText = filter.description;\r\n $filterContent.appendChild($filterDescription);\r\n }\r\n\r\n var $sizes = document.createElement('div');\r\n $sizes.classList.add('xmx-filter-sizes');\r\n $filterContent.appendChild($sizes);\r\n\r\n for (var optionIndex in filter.options)\r\n {\r\n var option = filter.options[optionIndex];\r\n var id = 'filter-' + filter.attribute + '-' + option.value;\r\n var isDisabled = option.count == 0;\r\n\r\n var $size = document.createElement('div');\r\n $size.classList.add('xmx-filter-size');\r\n\r\n if (isDisabled)\r\n {\r\n $size.classList.add('xmx-filter-size--disabled');\r\n }\r\n\r\n $sizes.appendChild($size);\r\n\r\n var $input = document.createElement('input');\r\n $input.classList.add('xmx-filter-size-input');\r\n $input.setAttribute('id', id);\r\n $input.setAttribute('type', 'checkbox');\r\n $input.setAttribute('name', filter.attribute);\r\n $input.setAttribute('value', option.value);\r\n $input.setAttribute('data-filter-index', filterIndex);\r\n $input.setAttribute('data-option-index', optionIndex);\r\n $input.addEventListener('change', onFilterInputChange);\r\n\r\n if (option.selected)\r\n {\r\n $input.setAttribute('checked', true);\r\n\r\n if (filterSubtitle != '')\r\n {\r\n filterSubtitle += ', ';\r\n }\r\n\r\n filterSubtitle += option.name;\r\n }\r\n\r\n if (isDisabled)\r\n {\r\n $input.setAttribute('disabled', true);\r\n }\r\n\r\n $size.appendChild($input);\r\n\r\n var $sizeLabel = document.createElement('label');\r\n $sizeLabel.setAttribute('for', id);\r\n $sizeLabel.classList.add('xmx-filter-size-label');\r\n $size.appendChild($sizeLabel);\r\n\r\n var $optionName = document.createElement('div');\r\n $optionName.innerText = option.name;\r\n $optionName.classList.add('xmx-filter-option-name');\r\n $sizeLabel.appendChild($optionName);\r\n\r\n var $optionCount = document.createElement('div');\r\n $optionCount.innerText = '(' + option.count + ')';\r\n $optionCount.classList.add('xmx-filter-option-count');\r\n $sizeLabel.appendChild($optionCount);\r\n }\r\n\r\n // Does the filter have changes?\r\n if (filterSubtitle != '')\r\n {\r\n var $filterSubtitle = document.createElement('div');\r\n $filterSubtitle.classList.add('xmx-subtitle');\r\n $filterSubtitle.innerText = filterSubtitle;\r\n $filterHead.appendChild($filterSubtitle);\r\n }\r\n\r\n fragment.appendChild($filter);\r\n }\r\n\r\n /**\r\n * A user has clicked on a filter head\r\n */\r\n function onFilterHeadClick()\r\n {\r\n var $filterHead = jQuery(this);\r\n var $filter = $filterHead.parent();\r\n var filterGroupCode = $filter.data('group');\r\n var index = _expandedFilters.indexOf(filterGroupCode);\r\n\r\n if (index == -1)\r\n {\r\n $filter.addClass('xmx-filter--expanded');\r\n\r\n _expandedFilters.push(filterGroupCode)\r\n }\r\n else \r\n {\r\n $filter.removeClass('xmx-filter--expanded');\r\n\r\n _expandedFilters.splice(index, 1);\r\n }\r\n }\r\n\r\n /**\r\n * @param {DocumentFragment} fragment\r\n * @param {int} filterIndex\r\n * @param {object} filter \r\n * @param {string} type\r\n */\r\n function renderAttributeFilter(fragment, filterIndex, filter, type)\r\n {\r\n var filterSubtitle = '';\r\n\r\n // Truncating a single filtering value adds needless friction, \r\n // as displaying the truncation link takes up as much space as \r\n // displaying the actual value would. The truncation threshold \r\n // should instead be offset by an extra item so it only \r\n // truncates 2+ values.\r\n // Displaying 6 to 10 filtering values before truncating the \r\n // rest of the list was observed to perform decently\r\n var collapseOptions = filter.options.length >= 7;\r\n var collapseAt = 5;\r\n\r\n // If the filter will collapse and there is an active option\r\n // that will be collapsed, prevent collapsing, so that the \r\n // active option is visible\r\n if (collapseOptions && filter.selected)\r\n {\r\n // Start at \"collapseAt\", so basically skip the first 5,\r\n // as they will never be collapsed and thus dont need\r\n // to be evaluated\r\n for (var i = collapseAt; i < filter.options.length; i++)\r\n {\r\n if (i >= collapseAt)\r\n {\r\n if (filter.options[i].selected)\r\n {\r\n collapseOptions = false;\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // If the filter group was expanded before, keep it open.\r\n // Otherwise you can expand the filter group, then check \r\n // an option and uncheck it again. The filter group\r\n // would then collapse again, so lets prevent that, as it\r\n // is bad for usability.\r\n if (_expandedFilterOptions.includes(filter.attribute))\r\n {\r\n collapseOptions = false;\r\n }\r\n\r\n var $filter = document.createElement('div');\r\n $filter.classList.add('xmx-filter', 'xmx-filter--' + filter.type);\r\n $filter.setAttribute('data-group', filter.attribute);\r\n\r\n // Is the filter opened?\r\n if (_expandedFilters.includes(filter.attribute))\r\n {\r\n $filter.classList.add('xmx-filter--expanded');\r\n }\r\n\r\n // Create the head\r\n var $filterHead = document.createElement('div');\r\n $filterHead.classList.add('xmx-filter-head');\r\n $filterHead.addEventListener('click', onFilterHeadClick);\r\n $filter.appendChild($filterHead);\r\n\r\n var $filterName = document.createElement('div');\r\n $filterName.classList.add('xmx-filter-name');\r\n $filterName.innerText = filter.name;\r\n $filterHead.appendChild($filterName);\r\n\r\n // Create the content\r\n var $filterContent = document.createElement('div');\r\n $filterContent.classList.add('xmx-filter-content');\r\n $filter.appendChild($filterContent);\r\n\r\n if (filter.description)\r\n {\r\n var $filterDescription = document.createElement('div');\r\n $filterDescription.classList.add('xmx-filter-description');\r\n $filterDescription.innerText = filter.description;\r\n $filterContent.appendChild($filterDescription);\r\n }\r\n\r\n var $options = document.createElement('div');\r\n $options.classList.add('xmx-filter-options');\r\n $filterContent.appendChild($options);\r\n\r\n for (var optionIndex in filter.options)\r\n {\r\n var option = filter.options[optionIndex];\r\n var id = 'filter-' + filter.attribute + '-' + option.value;\r\n var isDisabled = option.count == 0;\r\n\r\n var $option = document.createElement('div');\r\n $option.classList.add('xmx-filter-option');\r\n\r\n if (collapseOptions)\r\n {\r\n if (optionIndex >= collapseAt)\r\n {\r\n $option.style['display'] = 'none';\r\n }\r\n }\r\n\r\n if (isDisabled)\r\n {\r\n $option.classList.add('xmx-filter-option--disabled');\r\n }\r\n\r\n $options.appendChild($option);\r\n\r\n var $input = document.createElement('input');\r\n $input.classList.add('xmx-filter-option-input');\r\n $input.setAttribute('id', id);\r\n $input.setAttribute('type', type);\r\n $input.setAttribute('name', filter.attribute);\r\n $input.setAttribute('value', option.value);\r\n $input.setAttribute('data-filter-index', filterIndex);\r\n $input.setAttribute('data-option-index', optionIndex);\r\n $input.addEventListener('change', onFilterInputChange);\r\n\r\n if (option.selected)\r\n {\r\n $input.setAttribute('checked', true);\r\n\r\n if (filterSubtitle != '')\r\n {\r\n filterSubtitle += ', ';\r\n }\r\n\r\n filterSubtitle += option.name;\r\n }\r\n\r\n if (isDisabled)\r\n {\r\n $input.setAttribute('disabled', true);\r\n }\r\n\r\n $option.appendChild($input);\r\n\r\n var $optionLabel = document.createElement('label');\r\n $optionLabel.setAttribute('for', id);\r\n $optionLabel.classList.add('xmx-filter-option-label');\r\n $option.appendChild($optionLabel);\r\n\r\n if (filter.type == 'thumbnails')\r\n {\r\n var $imageFrame = document.createElement('div');\r\n $imageFrame.classList.add('xmx-image-link-frame');\r\n $optionLabel.appendChild($imageFrame);\r\n\r\n $option.classList.add('xmx-filter-option--with-image');\r\n\r\n if (option.image)\r\n {\r\n var $image = document.createElement('img');\r\n $image.classList.add('xmx-image-link-image');\r\n $image.setAttribute('importance', 'low');\r\n $image.setAttribute('width', '46');\r\n $image.setAttribute('height', '46');\r\n $image.setAttribute('alt', option.name);\r\n $image.setAttribute('src', option.image);\r\n $imageFrame.appendChild($image);\r\n }\r\n }\r\n\r\n var $optionText = document.createElement('div')\r\n $optionText.classList.add('xmx-filter-option-text');\r\n $optionLabel.appendChild($optionText);\r\n\r\n var $optionTitle = document.createElement('div');\r\n $optionTitle.classList.add('xmx-filter-option-title');\r\n $optionText.appendChild($optionTitle);\r\n\r\n if (option.featured)\r\n {\r\n var $badgeContainer = document.createElement('div');\r\n $badgeContainer.classList.add('xmx-filter-option-badge-container');\r\n $optionTitle.appendChild($badgeContainer);\r\n\r\n var $badge = document.createElement('div');\r\n $badge.classList.add('xmx-badge');\r\n $badge.innerText = window.naeCategoryTranslations.top;\r\n $badgeContainer.appendChild($badge);\r\n }\r\n\r\n var $optionName = document.createElement('span');\r\n $optionName.classList.add('xmx-filter-option-name');\r\n $optionName.innerText = option.name;\r\n $optionTitle.appendChild($optionName);\r\n\r\n var $optionCount = document.createElement('span');\r\n $optionCount.classList.add('xmx-filter-option-count');\r\n $optionCount.innerText = '(' + option.count + ')';\r\n $optionTitle.appendChild($optionCount);\r\n\r\n if (option.description)\r\n {\r\n $option.classList.add('xmx-filter-option--with-description');\r\n\r\n var $optionDescription = document.createElement('div');\r\n $optionDescription.classList.add('xmx-filter-option-description');\r\n $optionDescription.innerText = option.description;\r\n $optionText.appendChild($optionDescription);\r\n }\r\n\r\n if (type == 'checkbox')\r\n {\r\n var $optionCheckbox = document.createElement('div');\r\n $optionCheckbox.classList.add('xmx-filter-option-checkbox');\r\n $optionLabel.appendChild($optionCheckbox);\r\n\r\n var $optionCheckboxIcon = document.createElement('div');\r\n $optionCheckboxIcon.classList.add('xmx-filter-option-checkbox-icon', 'xmx-icon-check-white');\r\n $optionCheckbox.appendChild($optionCheckboxIcon);\r\n }\r\n else \r\n {\r\n var $optionRadio = document.createElement('div');\r\n $optionRadio.classList.add('xmx-filter-option-radio');\r\n $optionLabel.appendChild($optionRadio);\r\n\r\n var $optionRadioBullet = document.createElement('div');\r\n $optionRadioBullet.classList.add('xmx-filter-option-radio-bullet');\r\n $optionRadio.appendChild($optionRadioBullet);\r\n }\r\n }\r\n\r\n if (collapseOptions)\r\n {\r\n var $expandOptions = document.createElement('div');\r\n $expandOptions.classList.add('xmx-filter-expand-options');\r\n $filterContent.appendChild($expandOptions);\r\n\r\n var $expandButton = document.createElement('button');\r\n $expandButton.setAttribute('type', 'button');\r\n $expandButton.classList.add('xmx-button', 'xmx-button--secondary', 'xmx-button--fullwidth');\r\n $expandOptions.appendChild($expandButton);\r\n $expandButton.addEventListener('click', function()\r\n {\r\n jQuery('.xmx-filter-option', jQuery($options)).css('display', 'block');\r\n\r\n $expandButton.remove();\r\n\r\n _expandedFilterOptions.push(filter.attribute);\r\n });\r\n\r\n var $expandButtonLabel = document.createElement('div');\r\n $expandButtonLabel.innerText = window.naeCategoryTranslations.showMore;\r\n $expandButtonLabel.classList.add('xmx-button-label');\r\n $expandButton.appendChild($expandButtonLabel);\r\n }\r\n\r\n // Does the filter have changes?\r\n if (filterSubtitle != '')\r\n {\r\n var $filterSubtitle = document.createElement('div');\r\n $filterSubtitle.classList.add('xmx-subtitle');\r\n $filterSubtitle.innerText = filterSubtitle;\r\n $filterHead.appendChild($filterSubtitle);\r\n }\r\n\r\n fragment.appendChild($filter);\r\n }\r\n\r\n /**\r\n * Renders xmx-rating\r\n * \r\n * @param {int} rating \r\n * @param {int|null} count \r\n * @param {element} $parent\r\n */\r\n function renderRating(rating, count, $parent)\r\n {\r\n var $rating = document.createElement('div');\r\n $rating.classList.add('xmx-rating');\r\n\r\n for (var star = 1; star <= 5; star++)\r\n {\r\n var $star = document.createElement('div');\r\n\r\n if (rating >= star)\r\n {\r\n $star.classList.add('xmx-icon-star');\r\n }\r\n else \r\n {\r\n if (rating >= star - 0.5)\r\n {\r\n $star.classList.add('xmx-icon-star-half');\r\n }\r\n else \r\n {\r\n $star.classList.add('xmx-icon-star-empty');\r\n }\r\n }\r\n\r\n $rating.appendChild($star);\r\n }\r\n\r\n if (count !== null)\r\n {\r\n var $count = document.createElement('div');\r\n $count.classList.add('xmx-rating-reviews');\r\n $count.innerText = '(' + count + ')';\r\n $rating.appendChild($count);\r\n }\r\n\r\n $parent.appendChild($rating);\r\n }\r\n\r\n /**\r\n * @param {DocumentFragment} $fragment\r\n * @param {*} filterIndex \r\n * @param {*} filter \r\n */\r\n function renderRatingFilter($fragment, filterIndex, filter)\r\n {\r\n var filterSubtitle = '';\r\n\r\n var $filter = document.createElement('div');\r\n $filter.classList.add('xmx-filter', 'xmx-filter--' + filter.type);\r\n $filter.setAttribute('data-group', filter.attribute);\r\n\r\n // Is the filter opened?\r\n if (_expandedFilters.includes(filter.attribute))\r\n {\r\n $filter.classList.add('xmx-filter--expanded');\r\n }\r\n\r\n // Create the head\r\n var $filterHead = document.createElement('div');\r\n $filterHead.classList.add('xmx-filter-head');\r\n $filterHead.addEventListener('click', onFilterHeadClick);\r\n $filter.appendChild($filterHead);\r\n\r\n var $filterName = document.createElement('div');\r\n $filterName.classList.add('xmx-filter-name');\r\n $filterName.innerText = filter.name;\r\n $filterHead.appendChild($filterName);\r\n\r\n // Create the content\r\n var $filterContent = document.createElement('div');\r\n $filterContent.classList.add('xmx-filter-content');\r\n $filter.appendChild($filterContent);\r\n\r\n if (filter.description)\r\n {\r\n var $filterDescription = document.createElement('div');\r\n $filterDescription.classList.add('xmx-filter-description');\r\n $filterDescription.innerText = filter.description;\r\n $filter.appendChild($filterDescription);\r\n }\r\n\r\n var $options = document.createElement('div');\r\n $options.classList.add('xmx-filter-options');\r\n $filterContent.appendChild($options);\r\n\r\n for (var optionIndex in filter.options)\r\n {\r\n var option = filter.options[optionIndex];\r\n var id = 'filter-' + filter.attribute + '-' + option.value;\r\n var isDisabled = option.count == 0;\r\n \r\n var $option = document.createElement('div');\r\n $option.classList.add('xmx-filter-option');\r\n\r\n if (isDisabled)\r\n {\r\n $option.classList.add('xmx-filter-option--disabled');\r\n }\r\n\r\n $options.appendChild($option);\r\n\r\n var $input = document.createElement('input');\r\n $input.classList.add('xmx-filter-option-input');\r\n $input.setAttribute('id', id);\r\n $input.setAttribute('type', 'checkbox');\r\n $input.setAttribute('name', filter.attribute);\r\n $input.setAttribute('value', option.value);\r\n $input.setAttribute('data-filter-index', filterIndex);\r\n $input.setAttribute('data-option-index', optionIndex);\r\n $input.addEventListener('change', onFilterInputChange);\r\n\r\n if (option.selected)\r\n {\r\n $input.setAttribute('checked', true);\r\n filterSubtitle = option.name;\r\n }\r\n\r\n if (isDisabled)\r\n {\r\n $input.setAttribute('disabled', true);\r\n }\r\n\r\n $option.appendChild($input);\r\n\r\n var $optionLabel = document.createElement('label');\r\n $optionLabel.setAttribute('for', id);\r\n $optionLabel.classList.add('xmx-filter-option-label');\r\n $option.appendChild($optionLabel);\r\n\r\n var $optionText = document.createElement('div');\r\n $optionText.classList.add('xmx-filter-option-text');\r\n $optionLabel.appendChild($optionText);\r\n\r\n var $optionTitle = document.createElement('div');\r\n $optionTitle.classList.add('xmx-filter-option-title');\r\n $optionText.appendChild($optionTitle);\r\n\r\n var $rating = document.createElement('div');\r\n $rating.classList.add('xmx-rating', 'xmx-rating--big');\r\n $optionTitle.appendChild($rating);\r\n\r\n var $star;\r\n\r\n for (var star = 1; star <= 5; star++)\r\n {\r\n $star = document.createElement('span');\r\n $star.classList.add('xmx-icon');\r\n $star.classList.add(option.stars >= star ? 'xmx-icon-star' : 'xmx-icon-star-empty');\r\n $rating.appendChild($star);\r\n }\r\n\r\n var $optionName = document.createElement('span');\r\n $optionName.classList.add('xmx-filter-option-name');\r\n $optionName.innerText = window.naeCategoryTranslations.andMore;\r\n $optionTitle.appendChild($optionName);\r\n\r\n var $optionCount = document.createElement('span');\r\n $optionCount.classList.add('xmx-filter-option-count');\r\n $optionCount.innerText = '(' + option.count + ')';\r\n $optionTitle.appendChild($optionCount);\r\n\r\n var $optionCheckbox = document.createElement('div');\r\n $optionCheckbox.classList.add('xmx-filter-option-checkbox');\r\n $optionLabel.appendChild($optionCheckbox);\r\n\r\n var $optionCheckboxIcon = document.createElement('div');\r\n $optionCheckboxIcon.classList.add('xmx-filter-option-checkbox-icon', 'xmx-icon-check-white');\r\n $optionCheckbox.appendChild($optionCheckboxIcon);\r\n }\r\n\r\n // Does the filter have changes?\r\n if (filterSubtitle != '')\r\n {\r\n var $filterSubtitle = document.createElement('div');\r\n $filterSubtitle.classList.add('xmx-subtitle');\r\n $filterSubtitle.innerText = filterSubtitle;\r\n $filterHead.appendChild($filterSubtitle);\r\n }\r\n\r\n $fragment.appendChild($filter);\r\n }\r\n\r\n /**\r\n * @param {DocumentFragment} fragment\r\n * @param {int} filterIndex\r\n * @param {object} filter \r\n */\r\n function renderPriceFilter(fragment, filterIndex, filter)\r\n {\r\n var $filter = document.createElement('div');\r\n $filter.classList.add('xmx-filter', 'xmx-filter--' + filter.type);\r\n $filter.setAttribute('data-group', 'price');\r\n\r\n // Is the filter opened?\r\n if (_expandedFilters.includes(filter.attribute))\r\n {\r\n $filter.classList.add('xmx-filter--expanded');\r\n }\r\n\r\n // Create the head\r\n var $filterHead = document.createElement('div');\r\n $filterHead.classList.add('xmx-filter-head');\r\n $filterHead.addEventListener('click', onFilterHeadClick);\r\n $filter.appendChild($filterHead);\r\n\r\n var $filterName = document.createElement('div');\r\n $filterName.classList.add('xmx-filter-name');\r\n $filterName.innerText = filter.name;\r\n $filterHead.appendChild($filterName);\r\n\r\n // Does the filter have changes?\r\n if (filter.selected)\r\n {\r\n var filterLabel = '';\r\n\r\n if (filter.from && filter.to)\r\n {\r\n filterLabel = window.XmxApp.formatAmount(filter.from) + ' - ' + window.XmxApp.formatAmount(filter.to);\r\n }\r\n else if (filter.to)\r\n {\r\n filterLabel = window.naeCategoryTranslations.to + ' ' + window.XmxApp.formatAmount(filter.to);\r\n }\r\n else if (filter.from)\r\n {\r\n filterLabel = window.naeCategoryTranslations.from + ' ' + window.XmxApp.formatAmount(filter.from);\r\n }\r\n\r\n var $filterSubtitle = document.createElement('div');\r\n $filterSubtitle.classList.add('xmx-subtitle');\r\n $filterSubtitle.innerText = filterLabel;\r\n $filterHead.appendChild($filterSubtitle);\r\n }\r\n\r\n // Create the content\r\n var $filterContent = document.createElement('div');\r\n $filterContent.classList.add('xmx-filter-content');\r\n $filter.appendChild($filterContent);\r\n\r\n var $priceRange = document.createElement('div');\r\n $priceRange.classList.add('xmx-filter-price-range');\r\n $filterContent.appendChild($priceRange);\r\n\r\n var $priceInputFrom = document.createElement('input');\r\n $priceInputFrom.classList.add('xmx-filter-price-range-input', 'xmx-input', 'xmx-input--number');\r\n $priceInputFrom.setAttribute('type', 'number');\r\n $priceInputFrom.setAttribute('name', 'price-from');\r\n $priceInputFrom.setAttribute('min', filter.minimum);\r\n $priceInputFrom.setAttribute('max', filter.maximum);\r\n $priceInputFrom.setAttribute('placeholder', XmxApp.formatAmount(filter.minimum));\r\n\r\n if (filter.from)\r\n {\r\n $priceInputFrom.setAttribute('value', filter.from);\r\n }\r\n\r\n $priceInputFrom.setAttribute('data-filter-index', filterIndex);\r\n $priceInputFrom.addEventListener('change', onPriceFilterInputChange);\r\n $priceRange.appendChild($priceInputFrom);\r\n\r\n var $separator = document.createElement('div');\r\n $separator.classList.add('xmx-filter-price-range-separator');\r\n $separator.innerText = window.naeCategoryTranslations.to;\r\n $priceRange.appendChild($separator);\r\n\r\n var $priceInputTo = document.createElement('input');\r\n $priceInputTo.classList.add('xmx-filter-price-range-input', 'xmx-input', 'xmx-input--number');\r\n $priceInputTo.setAttribute('type', 'number');\r\n $priceInputTo.setAttribute('name', 'price-to');\r\n $priceInputTo.setAttribute('min', filter.minimum);\r\n $priceInputTo.setAttribute('max', filter.maximum);\r\n $priceInputTo.setAttribute('placeholder', XmxApp.formatAmount(filter.maximum));\r\n \r\n if (filter.to)\r\n {\r\n $priceInputTo.setAttribute('value', filter.to);\r\n }\r\n\r\n $priceInputTo.setAttribute('data-filter-index', filterIndex);\r\n $priceInputTo.addEventListener('change', onPriceFilterInputChange);\r\n $priceRange.appendChild($priceInputTo);\r\n\r\n fragment.appendChild($filter);\r\n }\r\n\r\n /**\r\n * Takes the preloaded server data and displays it, then forgets about it.\r\n */\r\n function displayPreloadedPage()\r\n {\r\n // Display the pre-loaded data\r\n handleServerResponse(_preloadedServerResponse);\r\n\r\n // And forget about it\r\n _preloadedServerResponse = null;\r\n _hasLoadedNextPage = false;\r\n }\r\n\r\n /**\r\n * Used to pre-load product images before the user has pressed the \"show more\" button.\r\n * Fired after a page has been pre-loaded while scrolling (Main Thread)\r\n * \r\n * @param {object} response Server response\r\n */\r\n function preloadProductImages(response)\r\n {\r\n // Does the browser support media query matching? Too lazy to write my own and \r\n // support looks good: https://caniuse.com/#search=matchmedia\r\n if (XmxApp.supportsMediaQueries())\r\n {\r\n if (response.products)\r\n {\r\n for (var productIndex in response.products)\r\n {\r\n var product = response.products[productIndex];\r\n\r\n if (product.images)\r\n {\r\n for (var imageIndex in product.images)\r\n {\r\n var image = product.images[imageIndex];\r\n\r\n if (XmxApp.matchMediaQuery(image.media))\r\n {\r\n XmxApp.downloadImage(image.src);\r\n\r\n // Download the first matching image only, as the browser\r\n // would in the <picture> element\r\n break;\r\n }\r\n }\r\n\r\n if (XmxApp.isDesktop())\r\n {\r\n if (product.hoverImage)\r\n {\r\n XmxApp.downloadImage(product.hoverImage.src);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Takes the response of the server and makes it effective.\r\n * This is a separate function, so we can either pass in a \r\n * pre-loaded server response or one that is handled immediately.\r\n * \r\n * @param {object} response \r\n */\r\n function handleServerResponse(response)\r\n {\r\n var productsToRender = [];\r\n\r\n // Append the products\r\n // In fill up mode, prevent things from being added twice\r\n if (_configuration.fillupMode)\r\n {\r\n // Only take over a couple of things in fill up mode\r\n _configuration.page = response.category.page;\r\n _configuration.pageCount = response.category.pageCount;\r\n _configuration.pageSize = response.category.pageSize;\r\n _configuration.products = response.category.products;\r\n\r\n for (var productIndex in response.products)\r\n {\r\n var addProduct = true;\r\n\r\n // TODO: The complexity of this is pretty high and will even be worse\r\n // when loading many pages. If we figure out this might become too slow,\r\n // store a list of all product IDs and use that for checking\r\n for (var existingProductIndex in _products)\r\n {\r\n if (_products[existingProductIndex].id == response.products[productIndex].id)\r\n {\r\n addProduct = false;\r\n break;\r\n }\r\n }\r\n\r\n if (addProduct)\r\n {\r\n _products.push(response.products[productIndex]);\r\n productsToRender.push(response.products[productIndex]);\r\n }\r\n }\r\n }\r\n else \r\n {\r\n // Only take over the complete configuration whe not in fillup mode\r\n _configuration = response.category;\r\n productsToRender = response.products;\r\n\r\n for (var index in response.products)\r\n {\r\n _products.push(response.products[index]);\r\n }\r\n }\r\n\r\n // Desktop Chrome is keeping the load more button in focus, so remeber the current scroll position\r\n // and then jump to where we have been before\r\n var scrollPosition = XmxApp.scrollOffsetY;\r\n\r\n renderProducts(productsToRender);\r\n updateFilters();\r\n updateCategoryHeadline();\r\n updateCategoryDescription();\r\n updateBrowserState();\r\n updateShowMoreMessage();\r\n updateProductCount();\r\n updateResetFiltersButton();\r\n updateFilterBar();\r\n updateSubmitButtonLabel();\r\n updateNavigation();\r\n\r\n $_document.scrollTop(scrollPosition);\r\n\r\n // Find out when to pre-load next time (causes reflow)\r\n updateNextPagePreloading();\r\n\r\n // Save the current state\r\n saveState();\r\n }\r\n\r\n /**\r\n * Saves the current state\r\n */\r\n function saveState()\r\n {\r\n if (XmxApp.supportsSessionStorage())\r\n {\r\n XmxApp.setSessionStorageString('xmx-category-id', _configuration.id);\r\n XmxApp.setSessionStorageString('xmx-category-scroll-position', XmxApp.scrollOffsetY);\r\n XmxApp.setSessionStorageJSON('xmx-category-configuration', _configuration);\r\n XmxApp.setSessionStorageJSON('xmx-category-products', _products);\r\n }\r\n }\r\n\r\n /**\r\n * Restores the last saved state\r\n * \r\n * @return bool True if state was restored\r\n */\r\n function restoreState()\r\n {\r\n var restoredState = false;\r\n\r\n if (XmxApp.supportsSessionStorage())\r\n {\r\n var categoryId = XmxApp.getSessionStorageString('xmx-category-id');\r\n\r\n // Is the saved state for this category id? if so, load it\r\n if (categoryId == _configuration.id)\r\n {\r\n // Only restore it if there is no page (\"p\") parameter.\r\n // The p parameter is only used when paginating in the browser via\r\n // the URL. Mostly for Google only. Users usually never get there, hopefully,\r\n // since we have a much nicer pagination for users via the load more button.\r\n\r\n // Restore configuration\r\n var configuration = XmxApp.getSessionStorageJSON('xmx-category-configuration');\r\n\r\n if (configuration)\r\n {\r\n // Only restore the state, if the states matches.\r\n // The URL contains the filters, sorting and category, so basically\r\n // everything we needed :)\r\n if (configuration.url != _configuration.url)\r\n {\r\n return;\r\n }\r\n\r\n // TODO: Cache Buster for\r\n\r\n _configuration = configuration;\r\n }\r\n\r\n // Restore products\r\n var products = XmxApp.getSessionStorageJSON('xmx-category-products');\r\n\r\n if (products)\r\n {\r\n // Delete all product and banner elements and replace them\r\n jQuery('.xmx-category-product', $_grid).remove();\r\n jQuery('.xmx-category-grid-banner', $_grid).remove();\r\n destroyCountdowns();\r\n\r\n /*for (var i in _configuration.banners)\r\n {\r\n XmxApp.unregisterInternalPromotion('grid_banner_', _configuration.banners[i].id);\r\n }*/\r\n\r\n _products = products;\r\n\r\n renderProducts(_products);\r\n }\r\n\r\n // Restore scroll position\r\n var scrollPosition = XmxApp.getSessionStorageString('xmx-category-scroll-position');\r\n\r\n if (scrollPosition)\r\n {\r\n $_document.scrollTop(scrollPosition);\r\n }\r\n \r\n restoredState = true;\r\n }\r\n }\r\n\r\n return restoredState;\r\n }\r\n\r\n /**\r\n * Add new products to the results\r\n * \r\n * @param {array} products \r\n */\r\n function renderProducts(products)\r\n {\r\n var position = 0;\r\n var countdownsToStart = [];\r\n var showBanners = _configuration.filters.activeFilterCount == 0 \r\n && _configuration.sorting.order == _configuration.sorting.defaultOrder\r\n && _configuration.sorting.direction == 'asc'\r\n && _configuration.page == 1;\r\n\r\n var $fragment = document.createDocumentFragment();\r\n\r\n for (var productIndex in products)\r\n {\r\n position++;\r\n var product = products[productIndex];\r\n var isFeatured = product['id'] == _configuration['bestsellerProductId'];\r\n\r\n // Render Banners\r\n if (_configuration.banners && showBanners)\r\n {\r\n var positionKey = \"p\" + position;\r\n\r\n if (_configuration.banners[positionKey] !== undefined)\r\n {\r\n var banner = _configuration.banners[positionKey];\r\n\r\n var $bannerLink = document.createElement('a');\r\n $bannerLink.classList.add('xmx-category-grid-banner');\r\n $bannerLink.setAttribute('href', banner.link);\r\n\r\n if (banner.size == 'big')\r\n {\r\n $bannerLink.classList.add('xmx-category-grid-banner--big');\r\n }\r\n\r\n if (banner.nofollow)\r\n {\r\n $bannerLink.setAttribute('rel', 'nofollow');\r\n }\r\n \r\n var $bannerContent = document.createElement('div');\r\n $bannerContent.classList.add('xmx-category-grid-banner-content');\r\n $bannerLink.appendChild($bannerContent);\r\n \r\n var $bannerPicture = document.createElement('picture')\r\n $bannerPicture.classList.add('xmx-category-grid-banner-picture');\r\n $bannerContent.appendChild($bannerPicture);\r\n \r\n var lastBannerImageData = '';\r\n\r\n for (imageIndex in banner.images)\r\n {\r\n var bannerImageData = banner.images[imageIndex];\r\n \r\n var $bannerSource = document.createElement('source')\r\n $bannerSource.setAttribute('media', bannerImageData.media);\r\n $bannerSource.setAttribute('srcset', bannerImageData.src);\r\n $bannerPicture.appendChild($bannerSource);\r\n \r\n lastBannerImageData = bannerImageData;\r\n }\r\n \r\n var $bannerImage = document.createElement('img');\r\n $bannerImage.classList.add('xmx-category-grid-banner-image');\r\n $bannerImage.setAttribute('src', lastBannerImageData.src);\r\n $bannerImage.setAttribute('alt', banner.imageAlt);\r\n $bannerPicture.appendChild($bannerImage);\r\n \r\n var $bannerCta = document.createElement('div');\r\n $bannerCta.classList.add('xmx-category-grid-banner-overlay');\r\n \r\n if (banner.color == 'white')\r\n {\r\n $bannerCta.classList.add('xmx-category-grid-banner-overlay--white');\r\n }\r\n \r\n $bannerContent.appendChild($bannerCta);\r\n \r\n if (banner.label != '')\r\n {\r\n var $bannerLabel = document.createElement('div');\r\n $bannerLabel.classList.add('xmx-label');\r\n $bannerLabel.innerText = banner.label;\r\n $bannerCta.appendChild($bannerLabel);\r\n }\r\n \r\n if (banner.title != '')\r\n {\r\n var $bannerTitle = document.createElement('div');\r\n $bannerTitle.classList.add('xmx-h2');\r\n $bannerTitle.innerText = banner.title;\r\n $bannerCta.appendChild($bannerTitle);\r\n }\r\n \r\n if (banner.description != '')\r\n {\r\n var $bannerDescription = document.createElement('div');\r\n $bannerDescription.classList.add('xmx-short-description');\r\n $bannerDescription.innerText = banner.description;\r\n $bannerCta.appendChild($bannerDescription);\r\n }\r\n \r\n if (banner.countdown)\r\n {\r\n var $countdown = document.createElement('div');\r\n $countdown.classList.add('xmx-countdown', 'xmx-countdown--big', 'xmx-countdown--' + banner.countdownStyle);\r\n $countdown.setAttribute('data-deadline', banner.deadline);\r\n $bannerCta.appendChild($countdown);\r\n \r\n // Days\r\n var $countdownDaysBox = document.createElement('div');\r\n $countdownDaysBox.classList.add('xmx-countdown-box', 'xmx-countdown--days-only');\r\n $countdown.appendChild($countdownDaysBox);\r\n \r\n var $countdownDaysDigit = document.createElement('div');\r\n $countdownDaysDigit.classList.add('xmx-countdown-digit', 'xmx-countdown--days');\r\n $countdownDaysBox.appendChild($countdownDaysDigit);\r\n \r\n var $countdownDaysLabel = document.createElement('div');\r\n $countdownDaysLabel.classList.add('xmx-label');\r\n $countdownDaysLabel.innerText = window.naeCategoryTranslations.countdownDays;\r\n $countdownDaysBox.appendChild($countdownDaysLabel);\r\n \r\n // Hours\r\n var $countdownHoursBox = document.createElement('div');\r\n $countdownHoursBox.classList.add('xmx-countdown-box');\r\n $countdown.appendChild($countdownHoursBox);\r\n \r\n var $countdownHoursDigit = document.createElement('div');\r\n $countdownHoursDigit.classList.add('xmx-countdown-digit', 'xmx-countdown--hours');\r\n $countdownHoursBox.appendChild($countdownHoursDigit);\r\n\r\n var $countdownHoursLabel = document.createElement('div');\r\n $countdownHoursLabel.classList.add('xmx-label');\r\n $countdownHoursLabel.innerText = window.naeCategoryTranslations.countdownHours;\r\n $countdownHoursBox.appendChild($countdownHoursLabel);\r\n \r\n // Minutes\r\n var $countdownMinutesBox = document.createElement('div');\r\n $countdownMinutesBox.classList.add('xmx-countdown-box');\r\n $countdown.appendChild($countdownMinutesBox);\r\n \r\n var $countdownMinutesDigit = document.createElement('div');\r\n $countdownMinutesDigit.classList.add('xmx-countdown-digit', 'xmx-countdown--minutes');\r\n $countdownMinutesBox.appendChild($countdownMinutesDigit);\r\n \r\n var $countdownMinutesLabel = document.createElement('div');\r\n $countdownMinutesLabel.classList.add('xmx-label');\r\n $countdownMinutesLabel.innerText = window.naeCategoryTranslations.countdownMinutes;\r\n $countdownMinutesBox.appendChild($countdownMinutesLabel);\r\n \r\n // Seconds\r\n var $countdownSecondsBox = document.createElement('div');\r\n $countdownSecondsBox.classList.add('xmx-countdown-box');\r\n $countdown.appendChild($countdownSecondsBox);\r\n \r\n var $countdownSecondsDigit = document.createElement('div');\r\n $countdownSecondsDigit.classList.add('xmx-countdown-digit', 'xmx-countdown--seconds');\r\n $countdownSecondsBox.appendChild($countdownSecondsDigit);\r\n \r\n var $countdownSecondsLabel = document.createElement('div');\r\n $countdownSecondsLabel.classList.add('xmx-label');\r\n $countdownSecondsLabel.innerText = window.naeCategoryTranslations.countdownSeconds;\r\n $countdownSecondsBox.appendChild($countdownSecondsLabel);\r\n \r\n countdownsToStart.push($countdown);\r\n }\r\n\r\n if (banner.button != '')\r\n {\r\n var $bannerButton = document.createElement('span');\r\n $bannerButton.classList.add('xmx-button', 'xmx-button--' + banner.buttonStyle);\r\n $bannerCta.appendChild($bannerButton);\r\n \r\n var $bannerButtonLabel = document.createElement('div');\r\n $bannerButtonLabel.classList.add('xmx-button-label', 'xmx-button-label--big-desktop');\r\n $bannerButtonLabel.innerText = banner.button;\r\n $bannerButton.appendChild($bannerButtonLabel);\r\n }\r\n \r\n $fragment.appendChild($bannerLink);\r\n \r\n // Track Banner CTR\r\n /*XmxApp.registerInternalPromotion(jQuery($bannerLink), 'grid_banner_' + banner.id, \r\n {\r\n 'creative_name': 'grid_banner',\r\n 'creative_slot': _configuration.name,\r\n 'location_id': _configuration.id,\r\n 'promotion_id': 'grid_banner_' + banner.id,\r\n 'promotion_name': banner.name\r\n });*/\r\n }\r\n }\r\n \r\n var $productElement = document.createElement('div');\r\n $productElement.classList.add('xmx-category-product');\r\n\r\n if (isFeatured)\r\n {\r\n $productElement.classList.add('xmx-category-product-hero');\r\n }\r\n else \r\n {\r\n $productElement.classList.add('xmx-category-product--' + _configuration.displayType);\r\n }\r\n\r\n var $inner = document.createElement('div');\r\n $inner.classList.add('xmx-category-product-inner');\r\n $productElement.appendChild($inner);\r\n\r\n var $link = document.createElement('a');\r\n $link.classList.add('xmx-category-product-click-target');\r\n $link.setAttribute('href', product.url);\r\n $link.setAttribute('data-product-id', product.id);\r\n $link.setAttribute('data-position', product.position);\r\n $link.setAttribute('title', product.name);\r\n $link.addEventListener('click', onProductLinkClick); // Mouse 1 \r\n $link.addEventListener('auxclick', onProductLinkClick); // Mouse 3\r\n $inner.appendChild($link);\r\n\r\n // Track impressions\r\n if (_intersectionObserver)\r\n {\r\n _intersectionObserver.observe($link);\r\n }\r\n\r\n // Images\r\n var $image = document.createElement('div');\r\n $image.classList.add('xmx-product-image', 'xmx-product-image--' + product.imageType, 'xmx-product-hover-image--' + product.hoverImageType);\r\n $inner.appendChild($image);\r\n\r\n var $imageRegular = document.createElement('div');\r\n $imageRegular.classList.add('xmx-product-image-regular');\r\n $image.appendChild($imageRegular);\r\n\r\n if (product.images.length > 0)\r\n {\r\n var $imageRegularPicture = document.createElement('picture');\r\n $imageRegular.appendChild($imageRegularPicture);\r\n\r\n var lastImageData = null;\r\n\r\n for (var imageIndex in product.images)\r\n {\r\n var imageData = product.images[imageIndex];\r\n var $imageRegularSource = document.createElement('source');\r\n $imageRegularSource.setAttribute('media', imageData.media);\r\n $imageRegularSource.setAttribute('srcset', imageData.src);\r\n $imageRegularPicture.appendChild($imageRegularSource);\r\n\r\n lastImageData = imageData;\r\n }\r\n\r\n if (lastImageData)\r\n {\r\n var $imageRegularImage = document.createElement('img');\r\n $imageRegularImage.setAttribute('src', lastImageData.src);\r\n $imageRegularImage.setAttribute('width', lastImageData.width);\r\n $imageRegularImage.setAttribute('height', lastImageData.height);\r\n $imageRegularImage.setAttribute('alt', product.name);\r\n $imageRegularPicture.appendChild($imageRegularImage);\r\n }\r\n }\r\n\r\n // Hover image\r\n if (product.hoverImage)\r\n {\r\n var $hoverImage = document.createElement('div');\r\n $hoverImage.classList.add('xmx-product-image-hover');\r\n $image.appendChild($hoverImage);\r\n\r\n var $hoverImagePicture = document.createElement('picture');\r\n $hoverImage.appendChild($hoverImagePicture);\r\n\r\n var $mobileHoverImage = document.createElement('source');\r\n $mobileHoverImage.setAttribute('media', '(max-width: 1279px)');\r\n $mobileHoverImage.setAttribute('srcset', '/static/transparent.gif');\r\n $hoverImagePicture.appendChild($mobileHoverImage);\r\n\r\n var $desktopHoverImage = document.createElement('source');\r\n $desktopHoverImage.setAttribute('media', '(min-width: 1280px)');\r\n $desktopHoverImage.setAttribute('srcset', product.hoverImage.src);\r\n $hoverImagePicture.appendChild($desktopHoverImage);\r\n\r\n var $hoverImageImage = document.createElement('img');\r\n $hoverImageImage.setAttribute('importance', 'low');\r\n $hoverImageImage.setAttribute('width', product.hoverImage.width);\r\n $hoverImageImage.setAttribute('height', product.hoverImage.height);\r\n $hoverImageImage.setAttribute('alt', product.name);\r\n $hoverImageImage.setAttribute('src', product.hoverImage.src);\r\n $hoverImagePicture.appendChild($hoverImageImage);\r\n }\r\n\r\n if (product.isOutOfStock)\r\n {\r\n var $stockBadges = document.createElement('div');\r\n $stockBadges.classList.add('xmx-product-image-badges');\r\n $image.appendChild($stockBadges);\r\n\r\n var $stockBadge = document.createElement('div');\r\n $stockBadge.classList.add('xmx-badge', 'xmx-badge--stock');\r\n $stockBadge.innerText = product.stockBadge;\r\n $stockBadges.appendChild($stockBadge);\r\n }\r\n else \r\n {\r\n // Image badges\r\n if (product.primaryBadge != '' || product.secondaryBadge != '' || product.specialBadge != '' || product.campaignBadge != '')\r\n {\r\n var $badges = document.createElement('div');\r\n $badges.classList.add('xmx-product-image-badges');\r\n $image.appendChild($badges);\r\n\r\n if (product.campaignBadge != '')\r\n {\r\n var $campaignBadge = document.createElement('div');\r\n $campaignBadge.classList.add('xmx-badge', 'xmx-badge--special');\r\n $campaignBadge.innerText = product.campaignBadge;\r\n $badges.appendChild($campaignBadge);\r\n }\r\n\r\n if (product.specialBadge != '')\r\n {\r\n var $specialBadge = document.createElement('div');\r\n $specialBadge.classList.add('xmx-badge', 'xmx-badge--special');\r\n $specialBadge.innerText = product.specialBadge;\r\n $badges.appendChild($specialBadge);\r\n }\r\n\r\n if (product.primaryBadge != '')\r\n {\r\n var $primaryBadge = document.createElement('div');\r\n $primaryBadge.classList.add('xmx-badge', 'xmx-badge--primary');\r\n $primaryBadge.innerText = product.primaryBadge;\r\n $badges.appendChild($primaryBadge);\r\n }\r\n\r\n if (product.secondaryBadge != '')\r\n {\r\n var $secondaryBadge = document.createElement('div');\r\n $secondaryBadge.classList.add('xmx-badge', 'xmx-badge--secondary');\r\n $secondaryBadge.innerText = product.secondaryBadge;\r\n $badges.appendChild($secondaryBadge);\r\n }\r\n }\r\n }\r\n\r\n // Textual part\r\n var $text = document.createElement('div');\r\n $text.classList.add('xmx-category-product-text');\r\n\r\n if (isFeatured)\r\n {\r\n $text.classList.add('xmx-icon-x');\r\n }\r\n\r\n $inner.appendChild($text);\r\n\r\n if (product.rating > 0 && _configuration.displayType == 'spec-driven')\r\n {\r\n renderRating(product.rating, product.reviews, $text);\r\n }\r\n\r\n if (product.brand != '')\r\n {\r\n var $brand = document.createElement('div');\r\n $brand.classList.add('xmx-subtitle');\r\n $brand.innerText = product.brand;\r\n $text.appendChild($brand);\r\n }\r\n\r\n if (product.name != '')\r\n {\r\n var $name = document.createElement('a');\r\n $name.classList.add('xmx-name');\r\n $name.classList.add('xmx-name--link');\r\n $name.setAttribute('href', product.url);\r\n $name.setAttribute('data-product-id', product.id);\r\n $link.setAttribute('data-position', product.position);\r\n $name.setAttribute('title', product.name);\r\n $name.addEventListener('click', onProductLinkClick); // Mouse 1 \r\n $name.addEventListener('auxclick', onProductLinkClick); // Mouse 3\r\n $name.innerText = product.name;\r\n $text.appendChild($name);\r\n }\r\n\r\n if (product.subtitle != '' && _configuration.displayType == 'spec-driven')\r\n {\r\n var $subtitle = document.createElement('div');\r\n $subtitle.classList.add('xmx-short-description');\r\n $subtitle.innerText = product.subtitle;\r\n $text.appendChild($subtitle);\r\n }\r\n\r\n // Tags\r\n if (product.freeShipping || product.tags.length > 0)\r\n {\r\n var $tags = document.createElement('div');\r\n $tags.classList.add('xmx-tags');\r\n $text.appendChild($tags);\r\n\r\n for (var tagIndex in product.tags)\r\n {\r\n var $tag = document.createElement('div');\r\n $tag.classList.add('xmx-tag');\r\n $tag.innerText = product.tags[tagIndex];\r\n $tags.appendChild($tag);\r\n }\r\n\r\n if (product.freeShipping)\r\n {\r\n var $freeShippingTag = document.createElement('div');\r\n $freeShippingTag.classList.add('xmx-tag', 'xmx-tag--shipping');\r\n $freeShippingTag.innerText = window.naeCategoryTranslations.freeShipping;\r\n $tags.appendChild($freeShippingTag);\r\n }\r\n }\r\n\r\n // Price\r\n var $price = document.createElement('div');\r\n $price.classList.add('xmx-price');\r\n $text.appendChild($price);\r\n\r\n if (product.finalPrice < product.price)\r\n {\r\n var $oldPrice = document.createElement('div');\r\n $oldPrice.classList.add('xmx-price-old');\r\n $oldPrice.innerText = product.priceString;\r\n $price.appendChild($oldPrice);\r\n\r\n var $newPrice = document.createElement('div');\r\n $newPrice.classList.add('xmx-price-new');\r\n\r\n if (product.showFromPrice)\r\n {\r\n $newPrice.innerText = window.naeCategoryTranslations.from + ' ' + product.finalPriceString;\r\n }\r\n else \r\n {\r\n $newPrice.innerText = product.finalPriceString;\r\n }\r\n\r\n $price.appendChild($newPrice);\r\n\r\n var $discount = document.createElement('div');\r\n $discount.classList.add('xmx-price-discount');\r\n $discount.innerText = product.discountPercentString;\r\n $price.appendChild($discount);\r\n }\r\n else \r\n {\r\n var $regularPrice = document.createElement('div');\r\n $regularPrice.classList.add('xmx-price-regular');\r\n \r\n if (product.showFromPrice)\r\n {\r\n $regularPrice.innerText = window.naeCategoryTranslations.from + ' ' + product.finalPriceString; \r\n }\r\n else \r\n {\r\n $regularPrice.innerText = product.finalPriceString;\r\n }\r\n\r\n $price.appendChild($regularPrice);\r\n }\r\n\r\n if (product.basePriceString !== null && product.basePriceString != '')\r\n {\r\n var $basePrice = document.createElement('div');\r\n $basePrice.classList.add('xmx-price-unit');\r\n $basePrice.innerText = product.basePriceString;\r\n $text.appendChild($basePrice);\r\n }\r\n\r\n $fragment.appendChild($productElement);\r\n }\r\n\r\n $_listEnd[0].before($fragment);\r\n\r\n for (var countdownIndex in countdownsToStart)\r\n {\r\n /*global XmxCountdown*/\r\n var countdownHandle = new XmxCountdown(jQuery(countdownsToStart[countdownIndex]));\r\n _countdowns.push(countdownHandle);\r\n }\r\n }\r\n\r\n\t/**\r\n\t *\r\n\t */\r\n\tfunction buildPostData(page)\r\n\t{\r\n\t\tvar postData = {};\r\n\r\n if (_configuration.filters.filters)\r\n {\r\n for (var i in _configuration.filters.filters)\r\n {\r\n var filter = _configuration.filters.filters[i];\r\n\r\n switch (filter.type)\r\n {\r\n case 'price':\r\n {\r\n if (filter.from && filter.to)\r\n {\r\n postData['price'] = filter.from + '-' + filter.to;\r\n }\r\n else if (filter.to)\r\n {\r\n postData['price'] = '-' + filter.to;\r\n }\r\n else if (filter.from)\r\n {\r\n postData['price'] = filter.from + '-';\r\n }\r\n\r\n break;\r\n }\r\n\r\n case 'swatches':\r\n case 'multiselect':\r\n case 'radio':\r\n case 'sizes':\r\n case 'thumbnails':\r\n case 'rating':\r\n {\r\n for (var j in filter.options)\r\n {\r\n var option = filter.options[j];\r\n\r\n if (option.selected)\r\n {\r\n if (postData[filter.attribute] === undefined)\r\n {\r\n postData[filter.attribute] = option.value;\r\n }\r\n else \r\n {\r\n postData[filter.attribute] = postData[filter.attribute] + ',' + option.value;\r\n }\r\n }\r\n }\r\n\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n\t\t// Add the current page\r\n\t\tpostData['p'] = page;\r\n\r\n\t\t// Add the current direction\r\n\t\tpostData['dir'] = _configuration.sorting.direction;\r\n\r\n\t\t// Add the current sorting\r\n\t\tpostData['order'] = _configuration.sorting.order;\r\n\r\n\t\t// So that we get a JSON response\r\n\t\tpostData['is_ajax'] = 1;\r\n\r\n\t\treturn postData;\r\n\t}\r\n\r\n /**\r\n * User has clicked the \"show more products\" button to show products\r\n * from another category\r\n */\r\n function onFillupMessageButtonClick()\r\n {\r\n // This should never be the case...\r\n if (!_configuration.fillupCategory)\r\n {\r\n return;\r\n }\r\n\r\n // Get out of there, if we are in fill-up mode\r\n if (_configuration.fillupMode)\r\n {\r\n return;\r\n }\r\n\r\n // Remember that we are in fill up mode\r\n _configuration.fillupMode = true;\r\n _configuration.page = 0; // loadNextPage() increases this\r\n\r\n // Reset everything\r\n _isLoadingNextPage = false;\r\n _hasLoadedNextPage = false;\r\n _displayNextPageImmediately = true;\r\n\r\n // Set the button into loading state\r\n $_fillupMessageButton.addClass('xmx-button--loading');\r\n\r\n loadNextPage();\r\n }\r\n\r\n /**\r\n * User has clicked the \"show more products\" button\r\n */\r\n function onShowMoreMessageButtonClick(event)\r\n {\r\n // Do not actually follow this link\r\n event.preventDefault();\r\n\r\n // Did we pre-loading the page already?\r\n // If so, just show it\r\n if (_hasLoadedNextPage)\r\n {\r\n displayPreloadedPage();\r\n }\r\n else \r\n {\r\n // We do not have the next page data yet, so let us\r\n // load it if not in progress already and ensure it \r\n // is displayed immediately\r\n _displayNextPageImmediately = true;\r\n\r\n // Indicate things are loading\r\n $_showMoreMessageButton.addClass('xmx-button--loading');\r\n\r\n if (!_isLoadingNextPage)\r\n {\r\n _isLoadingNextPage = true;\r\n\r\n loadNextPage();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Creates a certain number of skeletons\r\n * \r\n * @param {int} skeletonCount \r\n */\r\n function createProductSkeletons(skeletonCount)\r\n {\r\n var $fragment = document.createDocumentFragment();\r\n\r\n for (var i = 0; i < skeletonCount; i++)\r\n {\r\n var $skeleton = document.createElement('div');\r\n $skeleton.classList.add('xmx-category-product-skeleton');\r\n\r\n if (_configuration.displayType == 'spec-driven')\r\n {\r\n $skeleton.classList.add('xmx-category-product-skeleton--spec-driven');\r\n }\r\n\r\n var $link = document.createElement('div');\r\n $link.classList.add('xmx-category-product-skeleton-link');\r\n $skeleton.appendChild($link);\r\n\r\n var $image = document.createElement('div');\r\n $image.classList.add('xmx-skeleton', 'xmx-category-product-skeleton-image');\r\n $link.appendChild($image);\r\n\r\n var $text = document.createElement('div');\r\n $text.classList.add('xmx-category-product-skeleton-text');\r\n $link.appendChild($text);\r\n\r\n var $line1 = document.createElement('div');\r\n $line1.classList.add('xmx-skeleton', 'xmx-category-product-skeleton-line-1');\r\n $text.appendChild($line1);\r\n\r\n var $line2 = document.createElement('div');\r\n $line2.classList.add('xmx-skeleton', 'xmx-category-product-skeleton-line-2');\r\n $text.appendChild($line2);\r\n\r\n var $line3 = document.createElement('div');\r\n $line3.classList.add('xmx-skeleton', 'xmx-category-product-skeleton-line-3');\r\n $text.appendChild($line3);\r\n\r\n $fragment.appendChild($skeleton);\r\n }\r\n\r\n $_listEnd[0].before($fragment);\r\n }\r\n\r\n /**\r\n * Deletes all product skeletons from the grid\r\n */\r\n function removeProductSkeletons()\r\n {\r\n jQuery('.xmx-category-product-skeleton', $_grid).remove();\r\n }\r\n\r\n /**\r\n * Sends the filters to Magento and re-loads the category\r\n */\r\n function commitFilters(enforcedPostData)\r\n {\r\n // Abort AJAX stuff going on right now\r\n if (_ajaxHandle !== null)\r\n {\r\n _ajaxHandle.abort();\r\n }\r\n\r\n // Show button loader\r\n $_filterSubmitButton.addClass('xmx-button--loading');\r\n\r\n // Count all products, so we can replace them with skeletons\r\n // Ensure there are at least one skeleton\r\n var skeletonCount = Math.max(1, _products.length);\r\n\r\n // Forget about all products\r\n _products = [];\r\n\r\n // Remove all products and grid banners\r\n jQuery('.xmx-category-product', $_grid).remove();\r\n jQuery('.xmx-category-grid-banner', $_grid).remove();\r\n destroyCountdowns();\r\n\r\n // Remove all grid banner internal promotion tracking\r\n /*for (var i in _configuration.banners)\r\n {\r\n XmxApp.unregisterInternalPromotion('grid_banner_', _configuration.banners[i].id);\r\n }*/\r\n\r\n // Add skeletons\r\n createProductSkeletons(skeletonCount);\r\n\r\n // Re-load page #1\r\n var postData = enforcedPostData ? enforcedPostData : buildPostData(1);\r\n\r\n jQuery.ajax\r\n ({\r\n url: '/catalog/category/view/id/' + _configuration.id,\r\n dataType: 'json',\r\n type: 'post',\r\n cache: false,\r\n data: postData,\r\n xhr: function()\r\n {\r\n _ajaxHandle = new window.XMLHttpRequest();\r\n\r\n return _ajaxHandle;\r\n },\r\n success: function(response)\r\n {\r\n // Remove all skeletons\r\n removeProductSkeletons();\r\n\r\n // Display the data\r\n handleServerResponse(response);\r\n\r\n // Reset everything\r\n _displayNextPageImmediately = false;\r\n _preloadedServerResponse = null;\r\n _hasLoadedNextPage = false;\r\n _isLoadingNextPage = false;\r\n },\r\n complete: function()\r\n {\r\n $_filterSubmitButton.removeClass('xmx-button--loading');\r\n\r\n // Empty our AJAX handle, since there is nothing\r\n // to cancel anymore\r\n _ajaxHandle = null;\r\n }\r\n });\t\r\n }\r\n\r\n /**\r\n * Resets all filters (does not touch sorting)\r\n */\r\n function resetFilters()\r\n {\r\n _configuration.filters.activeFilterCount = 0;\r\n\r\n if (_configuration.filters.filters)\r\n {\r\n for (var filterIndex in _configuration.filters.filters)\r\n {\r\n var filter = _configuration.filters.filters[filterIndex];\r\n\r\n _configuration.filters.filters[filterIndex].selected = false;\r\n\r\n switch (filter.type)\r\n {\r\n case 'price':\r\n {\r\n _configuration.filters.filters[filterIndex].from = null;\r\n _configuration.filters.filters[filterIndex].to = null;\r\n break;\r\n }\r\n\r\n case 'swatches':\r\n case 'multiselect':\r\n case 'radio':\r\n case 'sizes':\r\n case 'thumbnails':\r\n case 'rating':\r\n {\r\n for (var optionIndex in filter.options)\r\n {\r\n var option = filter.options[optionIndex];\r\n\r\n if (option.selected)\r\n {\r\n _configuration.filters.filters[filterIndex].options[optionIndex].selected = false;\r\n }\r\n }\r\n\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Hide reset button\r\n $_filterResetButton.hide();\r\n\r\n // Do not auto-expand filters anymore, as we reset everything\r\n _expandedFilterOptions = [];\r\n }\r\n\r\n /**\r\n * Reset sorting (not vanilla Magento like View.php)\r\n */\r\n function resetSorting()\r\n {\r\n _configuration.sorting.order = _configuration.sorting.defaultOrder;\r\n _configuration.sorting.direction = 'asc';\r\n }\r\n\r\n /**\r\n * \r\n */\r\n function resetEverythingAndReload()\r\n {\r\n resetFilters();\r\n resetSorting();\r\n commitFilters(null);\r\n }\r\n\r\n /**\r\n * \r\n */\r\n function loadNextPage()\r\n {\r\n // This method is locked inside the scroll handler, so no need to do it again here\r\n\r\n // Abort AJAX stuff going on right now\r\n if (_ajaxHandle !== null)\r\n {\r\n _ajaxHandle.abort();\r\n }\r\n\r\n // Build the post data for the next page\r\n var endpoint = null;\r\n var postData = null;\r\n\r\n if (_configuration.fillupMode)\r\n {\r\n endpoint = '/catalog/category/view/id/' + _configuration.fillupCategory.id;\r\n\r\n // Do not pass in filters to the other category. Just the sorting etc.\r\n postData = \r\n {\r\n p: _configuration.page + 1,\r\n dir: _configuration.sorting.direction,\r\n order: _configuration.sorting.order,\r\n is_ajax: 1\r\n };\r\n }\r\n else \r\n {\r\n endpoint = '/catalog/category/view/id/' + _configuration.id;\r\n postData = buildPostData(_configuration.page + 1);\r\n }\r\n\r\n jQuery.ajax\r\n ({\r\n url: endpoint,\r\n dataType: 'json',\r\n type: 'post',\r\n cache: false,\r\n data: postData,\r\n xhr: function()\r\n {\r\n _ajaxHandle = new window.XMLHttpRequest();\r\n\r\n return _ajaxHandle;\r\n },\r\n success: function(response)\r\n {\r\n // Remember it for later\r\n _preloadedServerResponse = response;\r\n _hasLoadedNextPage = true;\r\n\r\n // Should we display it immediately?\r\n if (_displayNextPageImmediately)\r\n {\r\n displayPreloadedPage();\r\n _displayNextPageImmediately = false;\r\n }\r\n else \r\n {\r\n // Pre-Load images as well. There is no point\r\n // to tell the browser about this, if the next\r\n // page is displayed immediately\r\n preloadProductImages(response);\r\n }\r\n },\r\n complete: function()\r\n {\r\n // We are done preloading \r\n _isLoadingNextPage = false;\r\n\r\n // Empty our AJAX handle, since there is nothing\r\n // to cancel anymore\r\n _ajaxHandle = null;\r\n\r\n // Remove the button loading states\r\n $_showMoreMessageButton.removeClass('xmx-button--loading');\r\n $_fillupMessageButton.removeClass('xmx-button--loading');\r\n $_fillupMessage.hide();\r\n }\r\n });\t\r\n }\r\n\r\n /**\r\n * Fired when the user submits the filter form (e.g. by pressing return) \r\n * @param {Event} event \r\n */\r\n function onFilterFormSubmit(event)\r\n {\r\n // Track clicks\r\n /*XmxApp.sendGoogleAnalyticsEvent\r\n (\r\n 'Category UI',\r\n 'Submitted Filter Form', \r\n null,\r\n false\r\n );*/\r\n\r\n commitFilters(null);\r\n\r\n event.preventDefault();\r\n\r\n // Cancel event\r\n return false;\r\n }\r\n\r\n /**\r\n * \r\n * @param {Event} event \r\n */\r\n function onFilterSubmitButtonClick(event)\r\n {\r\n // Track clicks\r\n /*XmxApp.sendGoogleAnalyticsEvent\r\n (\r\n 'Category UI',\r\n 'Clicked Filter Submit Button', \r\n null,\r\n false\r\n );*/\r\n\r\n closeFilterDrawer();\r\n\r\n event.preventDefault();\r\n\r\n // Cancel event\r\n return false;\r\n }\r\n\r\n /**\r\n * \r\n * @param {Event} event \r\n */\r\n function onFilterResetButtonClick()\r\n {\r\n // Track clicks\r\n /*XmxApp.sendGoogleAnalyticsEvent\r\n (\r\n 'Category UI',\r\n 'Clicked Reset All Filters Button', \r\n null,\r\n false\r\n );*/\r\n\r\n resetEverythingAndReload();\r\n }\r\n\r\n /**\r\n * Returns the product object for a given product ID\r\n * \r\n * @param {int} id \r\n * @returns object|null\r\n */\r\n /*function getProductById(id)\r\n {\r\n for (var i in _products)\r\n {\r\n if (_products[i].id == id)\r\n {\r\n return _products[i];\r\n }\r\n }\r\n\r\n return null;\r\n }*/\r\n\r\n /**\r\n * Fired when a user has clicked on a product. Used to save the current state before\r\n * the user goes to the product.\r\n */\r\n function onProductLinkClick()\r\n {\r\n var $link = jQuery(this);\r\n var productId = parseInt($link.data('product-id'));\r\n var position = parseInt($link.data('position'));\r\n\r\n /*global XmxEventQueue*/\r\n XmxEventQueue.trackEvent('cpc', \r\n {\r\n 'p': productId,\r\n 'c': _configuration.id,\r\n 'r': position\r\n });\r\n\r\n saveState();\r\n }\r\n\r\n /**\r\n * \r\n */\r\n function onFilterDrawerSkrimClick()\r\n {\r\n closeFilterDrawer();\r\n }\r\n\r\n /**\r\n * Opens the filter drawer, if possible\r\n */\r\n function openFilterDrawer()\r\n {\r\n // Render the filters, if not done already\r\n if (!_didUpdateFilters)\r\n {\r\n updateFilters();\r\n updateSubmitButtonLabel();\r\n updateResetFiltersButton();\r\n\r\n _didUpdateFilters = true;\r\n }\r\n\r\n if (_isDrawerOpened || _isDrawerAnimating)\r\n {\r\n return;\r\n }\r\n \r\n _isDrawerAnimating = true;\r\n\r\n $_html.addClass('xmx--prevent-scrolling');\r\n $_filterDrawer.addClass('xmx-drawer--visible');\r\n $_filterDrawer.offset(); // Force reflow\r\n $_filterDrawer.addClass('xmx-drawer--open');\r\n\r\n setTimeout(function() \r\n {\r\n _isDrawerOpened = true;\r\n _isDrawerAnimating = false;\r\n \r\n }, 250);\r\n }\r\n\r\n /**\r\n * Closes the filter drawer, if possible\r\n */\r\n function closeFilterDrawer()\r\n {\r\n if (!_isDrawerOpened || _isDrawerAnimating)\r\n {\r\n return;\r\n }\r\n\r\n _isDrawerAnimating = true;\r\n\r\n $_html.removeClass('xmx--prevent-scrolling');\r\n $_filterDrawer.removeClass('xmx-drawer--open');\r\n\r\n setTimeout(function() \r\n {\r\n _isDrawerOpened = false;\r\n _isDrawerAnimating = false;\r\n\r\n $_filterDrawer.removeClass('xmx-drawer--visible');\r\n }, 200);\r\n }\r\n\r\n /**\r\n * Public interface\r\n */\r\n return { // line break is not allowed here\r\n\r\n /**\r\n * Constructor, boots the checkout\r\n */\r\n construct: function() \r\n {\r\n boot();\r\n },\r\n\r\n isFilterDrawedOpen: function()\r\n {\r\n return _isDrawerOpened;\r\n },\r\n };\r\n})();\r\n\r\nXmxCategory.construct();"]}