{"version":3,"sources":["jquery.auto-complete-helper.js","app.module.js","dirPagination.js","searchDatalayerService.js","searchController.js","region-selector.js","virtual-basket.js","functions.js","app.js"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACpBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC3BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC/nBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC3EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACvFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACtFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACzEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACzKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"../js/script.js","sourcesContent":["//Extract to LookupHelpers\r\nfunction configureSource(getCountryRegNrFunction) {\r\n return function (term, response) { \r\n $.getJSON(dynamicData.page.virtualRoot + 'api/regions/get', { countryRegNr: getCountryRegNrFunction(), searchTerm: term }, function (data) {\r\n var list = [];\r\n for (var i = 0; i < data.length; i++) {\r\n list.push([data[i].zipPlaceRegNr, data[i].zip, data[i].place]);\r\n }\r\n response(list);\r\n });\r\n }\r\n}\r\n\r\nfunction configureRenderItem() {\r\n return function (item, search) {\r\n search = search.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\r\n var re = new RegExp(\"(\" + search.split(' ').join('|') + \")\", \"gi\");\r\n var zipCityCombined = item[1] + ' - ' + item[2];\r\n return '
' + zipCityCombined.replace(re, \"$1\") + '
';\r\n }\r\n}","var appWebshop = angular.module('appWebshop', []);\r\n\r\n//this input directive enables the initialization of a model from the html\r\nappWebshop.directive('input', ['$parse', function ($parse) {\r\n return {\r\n restrict: 'E',\r\n require: '?ngModel',\r\n link: function (scope, element, attrs) {\r\n if (attrs.ngModel && attrs.value) {\r\n $parse(attrs.ngModel).assign(scope, attrs.value);\r\n }\r\n }\r\n };\r\n}]);\r\n\r\nappWebshop.directive('myEnter', function () {\r\n return function (scope, element, attrs) {\r\n element.bind(\"keydown keypress\", function (event) {\r\n if (event.which === 13) {\r\n scope.$apply(function () {\r\n scope.$eval(attrs.myEnter);\r\n });\r\n\r\n event.preventDefault();\r\n }\r\n });\r\n };\r\n});","/**\r\n * dirPagination - AngularJS module for paginating (almost) anything.\r\n *\r\n *\r\n * Credits\r\n * =======\r\n *\r\n * Daniel Tabuenca: https://groups.google.com/d/msg/angular/an9QpzqIYiM/r8v-3W1X5vcJ\r\n * for the idea on how to dynamically invoke the ng-repeat directive.\r\n *\r\n * I borrowed a couple of lines and a few attribute names from the AngularUI Bootstrap project:\r\n * https://github.com/angular-ui/bootstrap/blob/master/src/pagination/pagination.js\r\n *\r\n * Copyright 2014 Michael Bromley \r\n */\r\n\r\n(function() {\r\n\r\n /**\r\n * Config\r\n */\r\n var moduleName = 'angularUtils.directives.dirPagination';\r\n var DEFAULT_ID = '__default';\r\n\r\n /**\r\n * Module\r\n */\r\n angular.module(moduleName, [])\r\n .directive('dirPaginate', ['$compile', '$parse', 'paginationService', dirPaginateDirective])\r\n .directive('dirPaginateNoCompile', noCompileDirective)\r\n .directive('dirPaginationControls', ['paginationService', 'paginationTemplate', dirPaginationControlsDirective])\r\n .filter('itemsPerPage', ['paginationService', itemsPerPageFilter])\r\n .service('paginationService', paginationService)\r\n .provider('paginationTemplate', paginationTemplateProvider)\r\n .run(['$templateCache',dirPaginationControlsTemplateInstaller]);\r\n\r\n function dirPaginateDirective($compile, $parse, paginationService) {\r\n\r\n return {\r\n terminal: true,\r\n multiElement: true,\r\n priority: 100,\r\n compile: dirPaginationCompileFn\r\n };\r\n\r\n function dirPaginationCompileFn(tElement, tAttrs){\r\n\r\n var expression = tAttrs.dirPaginate;\r\n // regex taken directly from https://github.com/angular/angular.js/blob/v1.4.x/src/ng/directive/ngRepeat.js#L339\r\n var match = expression.match(/^\\s*([\\s\\S]+?)\\s+in\\s+([\\s\\S]+?)(?:\\s+as\\s+([\\s\\S]+?))?(?:\\s+track\\s+by\\s+([\\s\\S]+?))?\\s*$/);\r\n\r\n var filterPattern = /\\|\\s*itemsPerPage\\s*:\\s*(.*\\(\\s*\\w*\\)|([^\\)]*?(?=\\s+as\\s+))|[^\\)]*)/;\r\n if (match[2].match(filterPattern) === null) {\r\n throw 'pagination directive: the \\'itemsPerPage\\' filter must be set.';\r\n }\r\n var itemsPerPageFilterRemoved = match[2].replace(filterPattern, '');\r\n var collectionGetter = $parse(itemsPerPageFilterRemoved);\r\n\r\n addNoCompileAttributes(tElement);\r\n\r\n // If any value is specified for paginationId, we register the un-evaluated expression at this stage for the benefit of any\r\n // dir-pagination-controls directives that may be looking for this ID.\r\n var rawId = tAttrs.paginationId || DEFAULT_ID;\r\n paginationService.registerInstance(rawId);\r\n\r\n return function dirPaginationLinkFn(scope, element, attrs){\r\n\r\n // Now that we have access to the `scope` we can interpolate any expression given in the paginationId attribute and\r\n // potentially register a new ID if it evaluates to a different value than the rawId.\r\n var paginationId = $parse(attrs.paginationId)(scope) || attrs.paginationId || DEFAULT_ID;\r\n \r\n // (TODO: this seems sound, but I'm reverting as many bug reports followed it's introduction in 0.11.0.\r\n // Needs more investigation.)\r\n // In case rawId != paginationId we deregister using rawId for the sake of general cleanliness\r\n // before registering using paginationId\r\n // paginationService.deregisterInstance(rawId);\r\n paginationService.registerInstance(paginationId);\r\n\r\n var repeatExpression = getRepeatExpression(expression, paginationId);\r\n addNgRepeatToElement(element, attrs, repeatExpression);\r\n\r\n removeTemporaryAttributes(element);\r\n var compiled = $compile(element);\r\n\r\n var currentPageGetter = makeCurrentPageGetterFn(scope, attrs, paginationId);\r\n paginationService.setCurrentPageParser(paginationId, currentPageGetter, scope);\r\n\r\n if (typeof attrs.totalItems !== 'undefined') {\r\n paginationService.setAsyncModeTrue(paginationId);\r\n scope.$watch(function() {\r\n return $parse(attrs.totalItems)(scope);\r\n }, function (result) {\r\n if (0 <= result) {\r\n paginationService.setCollectionLength(paginationId, result);\r\n }\r\n });\r\n } else {\r\n paginationService.setAsyncModeFalse(paginationId);\r\n scope.$watchCollection(function() {\r\n return collectionGetter(scope);\r\n }, function(collection) {\r\n if (collection) {\r\n var collectionLength = (collection instanceof Array) ? collection.length : Object.keys(collection).length;\r\n paginationService.setCollectionLength(paginationId, collectionLength);\r\n }\r\n });\r\n }\r\n\r\n // Delegate to the link function returned by the new compilation of the ng-repeat\r\n compiled(scope);\r\n \r\n // (TODO: Reverting this due to many bug reports in v 0.11.0. Needs investigation as the\r\n // principle is sound)\r\n // When the scope is destroyed, we make sure to remove the reference to it in paginationService\r\n // so that it can be properly garbage collected\r\n // scope.$on('$destroy', function destroyDirPagination() {\r\n // paginationService.deregisterInstance(paginationId);\r\n // });\r\n };\r\n }\r\n\r\n /**\r\n * If a pagination id has been specified, we need to check that it is present as the second argument passed to\r\n * the itemsPerPage filter. If it is not there, we add it and return the modified expression.\r\n *\r\n * @param expression\r\n * @param paginationId\r\n * @returns {*}\r\n */\r\n function getRepeatExpression(expression, paginationId) {\r\n var repeatExpression,\r\n idDefinedInFilter = !!expression.match(/(\\|\\s*itemsPerPage\\s*:[^|]*:[^|]*)/);\r\n\r\n if (paginationId !== DEFAULT_ID && !idDefinedInFilter) {\r\n repeatExpression = expression.replace(/(\\|\\s*itemsPerPage\\s*:\\s*[^|\\s]*)/, \"$1 : '\" + paginationId + \"'\");\r\n } else {\r\n repeatExpression = expression;\r\n }\r\n\r\n return repeatExpression;\r\n }\r\n\r\n /**\r\n * Adds the ng-repeat directive to the element. In the case of multi-element (-start, -end) it adds the\r\n * appropriate multi-element ng-repeat to the first and last element in the range.\r\n * @param element\r\n * @param attrs\r\n * @param repeatExpression\r\n */\r\n function addNgRepeatToElement(element, attrs, repeatExpression) {\r\n if (element[0].hasAttribute('dir-paginate-start') || element[0].hasAttribute('data-dir-paginate-start')) {\r\n // using multiElement mode (dir-paginate-start, dir-paginate-end)\r\n attrs.$set('ngRepeatStart', repeatExpression);\r\n element.eq(element.length - 1).attr('ng-repeat-end', true);\r\n } else {\r\n attrs.$set('ngRepeat', repeatExpression);\r\n }\r\n }\r\n\r\n /**\r\n * Adds the dir-paginate-no-compile directive to each element in the tElement range.\r\n * @param tElement\r\n */\r\n function addNoCompileAttributes(tElement) {\r\n angular.forEach(tElement, function(el) {\r\n if (el.nodeType === 1) {\r\n angular.element(el).attr('dir-paginate-no-compile', true);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Removes the variations on dir-paginate (data-, -start, -end) and the dir-paginate-no-compile directives.\r\n * @param element\r\n */\r\n function removeTemporaryAttributes(element) {\r\n angular.forEach(element, function(el) {\r\n if (el.nodeType === 1) {\r\n angular.element(el).removeAttr('dir-paginate-no-compile');\r\n }\r\n });\r\n element.eq(0).removeAttr('dir-paginate-start').removeAttr('dir-paginate').removeAttr('data-dir-paginate-start').removeAttr('data-dir-paginate');\r\n element.eq(element.length - 1).removeAttr('dir-paginate-end').removeAttr('data-dir-paginate-end');\r\n }\r\n\r\n /**\r\n * Creates a getter function for the current-page attribute, using the expression provided or a default value if\r\n * no current-page expression was specified.\r\n *\r\n * @param scope\r\n * @param attrs\r\n * @param paginationId\r\n * @returns {*}\r\n */\r\n function makeCurrentPageGetterFn(scope, attrs, paginationId) {\r\n var currentPageGetter;\r\n if (attrs.currentPage) {\r\n currentPageGetter = $parse(attrs.currentPage);\r\n } else {\r\n // If the current-page attribute was not set, we'll make our own.\r\n // Replace any non-alphanumeric characters which might confuse\r\n // the $parse service and give unexpected results.\r\n // See https://github.com/michaelbromley/angularUtils/issues/233\r\n var defaultCurrentPage = (paginationId + '__currentPage').replace(/\\W/g, '_');\r\n scope[defaultCurrentPage] = 1;\r\n currentPageGetter = $parse(defaultCurrentPage);\r\n }\r\n return currentPageGetter;\r\n }\r\n }\r\n\r\n /**\r\n * This is a helper directive that allows correct compilation when in multi-element mode (ie dir-paginate-start, dir-paginate-end).\r\n * It is dynamically added to all elements in the dir-paginate compile function, and it prevents further compilation of\r\n * any inner directives. It is then removed in the link function, and all inner directives are then manually compiled.\r\n */\r\n function noCompileDirective() {\r\n return {\r\n priority: 5000,\r\n terminal: true\r\n };\r\n }\r\n\r\n function dirPaginationControlsTemplateInstaller($templateCache) {\r\n $templateCache.put('angularUtils.directives.dirPagination.template', '');\r\n }\r\n\r\n function dirPaginationControlsDirective(paginationService, paginationTemplate) {\r\n\r\n var numberRegex = /^\\d+$/;\r\n\r\n var DDO = {\r\n restrict: 'AE',\r\n scope: {\r\n maxSize: '=?',\r\n onPageChange: '&?',\r\n paginationId: '=?',\r\n autoHide: '=?'\r\n },\r\n link: dirPaginationControlsLinkFn\r\n };\r\n\r\n // We need to check the paginationTemplate service to see whether a template path or\r\n // string has been specified, and add the `template` or `templateUrl` property to\r\n // the DDO as appropriate. The order of priority to decide which template to use is\r\n // (highest priority first):\r\n // 1. paginationTemplate.getString()\r\n // 2. attrs.templateUrl\r\n // 3. paginationTemplate.getPath()\r\n var templateString = paginationTemplate.getString();\r\n if (templateString !== undefined) {\r\n DDO.template = templateString;\r\n } else {\r\n DDO.templateUrl = function(elem, attrs) {\r\n return attrs.templateUrl || paginationTemplate.getPath();\r\n };\r\n }\r\n return DDO;\r\n\r\n function dirPaginationControlsLinkFn(scope, element, attrs) {\r\n\r\n // rawId is the un-interpolated value of the pagination-id attribute. This is only important when the corresponding dir-paginate directive has\r\n // not yet been linked (e.g. if it is inside an ng-if block), and in that case it prevents this controls directive from assuming that there is\r\n // no corresponding dir-paginate directive and wrongly throwing an exception.\r\n var rawId = attrs.paginationId || DEFAULT_ID;\r\n var paginationId = scope.paginationId || attrs.paginationId || DEFAULT_ID;\r\n\r\n if (!paginationService.isRegistered(paginationId) && !paginationService.isRegistered(rawId)) {\r\n var idMessage = (paginationId !== DEFAULT_ID) ? ' (id: ' + paginationId + ') ' : ' ';\r\n if (window.console) {\r\n console.warn('Pagination directive: the pagination controls' + idMessage + 'cannot be used without the corresponding pagination directive, which was not found at link time.');\r\n }\r\n }\r\n\r\n if (!scope.maxSize) { scope.maxSize = 9; }\r\n scope.autoHide = scope.autoHide === undefined ? true : scope.autoHide;\r\n scope.directionLinks = angular.isDefined(attrs.directionLinks) ? scope.$parent.$eval(attrs.directionLinks) : true;\r\n scope.boundaryLinks = angular.isDefined(attrs.boundaryLinks) ? scope.$parent.$eval(attrs.boundaryLinks) : false;\r\n\r\n var paginationRange = Math.max(scope.maxSize, 5);\r\n scope.pages = [];\r\n scope.pagination = {\r\n last: 1,\r\n current: 1\r\n };\r\n scope.range = {\r\n lower: 1,\r\n upper: 1,\r\n total: 1\r\n };\r\n\r\n scope.$watch('maxSize', function(val) {\r\n if (val) {\r\n paginationRange = Math.max(scope.maxSize, 5);\r\n generatePagination();\r\n }\r\n });\r\n\r\n scope.$watch(function() {\r\n if (paginationService.isRegistered(paginationId)) {\r\n return (paginationService.getCollectionLength(paginationId) + 1) * paginationService.getItemsPerPage(paginationId);\r\n }\r\n }, function(length) {\r\n if (0 < length) {\r\n generatePagination();\r\n }\r\n });\r\n\r\n scope.$watch(function() {\r\n if (paginationService.isRegistered(paginationId)) {\r\n return (paginationService.getItemsPerPage(paginationId));\r\n }\r\n }, function(current, previous) {\r\n if (current != previous && typeof previous !== 'undefined') {\r\n goToPage(scope.pagination.current);\r\n }\r\n });\r\n\r\n scope.$watch(function() {\r\n if (paginationService.isRegistered(paginationId)) {\r\n return paginationService.getCurrentPage(paginationId);\r\n }\r\n }, function(currentPage, previousPage) {\r\n if (currentPage != previousPage) {\r\n goToPage(currentPage);\r\n }\r\n });\r\n\r\n scope.setCurrent = function(num) {\r\n if (paginationService.isRegistered(paginationId) && isValidPageNumber(num)) {\r\n num = parseInt(num, 10);\r\n paginationService.setCurrentPage(paginationId, num);\r\n }\r\n };\r\n\r\n /**\r\n * Custom \"track by\" function which allows for duplicate \"...\" entries on long lists,\r\n * yet fixes the problem of wrongly-highlighted links which happens when using\r\n * \"track by $index\" - see https://github.com/michaelbromley/angularUtils/issues/153\r\n * @param id\r\n * @param index\r\n * @returns {string}\r\n */\r\n scope.tracker = function(id, index) {\r\n return id + '_' + index;\r\n };\r\n\r\n function goToPage(num) {\r\n if (paginationService.isRegistered(paginationId) && isValidPageNumber(num)) {\r\n var oldPageNumber = scope.pagination.current;\r\n\r\n scope.pages = generatePagesArray(num, paginationService.getCollectionLength(paginationId), paginationService.getItemsPerPage(paginationId), paginationRange);\r\n scope.pagination.current = num;\r\n updateRangeValues();\r\n\r\n // if a callback has been set, then call it with the page number as the first argument\r\n // and the previous page number as a second argument\r\n if (scope.onPageChange) {\r\n scope.onPageChange({\r\n newPageNumber : num,\r\n oldPageNumber : oldPageNumber\r\n });\r\n }\r\n }\r\n }\r\n\r\n function generatePagination() {\r\n if (paginationService.isRegistered(paginationId)) {\r\n var page = parseInt(paginationService.getCurrentPage(paginationId)) || 1;\r\n scope.pages = generatePagesArray(page, paginationService.getCollectionLength(paginationId), paginationService.getItemsPerPage(paginationId), paginationRange);\r\n scope.pagination.current = page;\r\n scope.pagination.last = scope.pages[scope.pages.length - 1];\r\n if (scope.pagination.last < scope.pagination.current) {\r\n scope.setCurrent(scope.pagination.last);\r\n } else {\r\n updateRangeValues();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * This function updates the values (lower, upper, total) of the `scope.range` object, which can be used in the pagination\r\n * template to display the current page range, e.g. \"showing 21 - 40 of 144 results\";\r\n */\r\n function updateRangeValues() {\r\n if (paginationService.isRegistered(paginationId)) {\r\n var currentPage = paginationService.getCurrentPage(paginationId),\r\n itemsPerPage = paginationService.getItemsPerPage(paginationId),\r\n totalItems = paginationService.getCollectionLength(paginationId);\r\n\r\n scope.range.lower = (currentPage - 1) * itemsPerPage + 1;\r\n scope.range.upper = Math.min(currentPage * itemsPerPage, totalItems);\r\n scope.range.total = totalItems;\r\n }\r\n }\r\n function isValidPageNumber(num) {\r\n return (numberRegex.test(num) && (0 < num && num <= scope.pagination.last));\r\n }\r\n }\r\n\r\n /**\r\n * Generate an array of page numbers (or the '...' string) which is used in an ng-repeat to generate the\r\n * links used in pagination\r\n *\r\n * @param currentPage\r\n * @param rowsPerPage\r\n * @param paginationRange\r\n * @param collectionLength\r\n * @returns {Array}\r\n */\r\n function generatePagesArray(currentPage, collectionLength, rowsPerPage, paginationRange) {\r\n var pages = [];\r\n var totalPages = Math.ceil(collectionLength / rowsPerPage);\r\n var halfWay = Math.ceil(paginationRange / 2);\r\n var position;\r\n\r\n if (currentPage <= halfWay) {\r\n position = 'start';\r\n } else if (totalPages - halfWay < currentPage) {\r\n position = 'end';\r\n } else {\r\n position = 'middle';\r\n }\r\n\r\n var ellipsesNeeded = paginationRange < totalPages;\r\n var i = 1;\r\n while (i <= totalPages && i <= paginationRange) {\r\n var pageNumber = calculatePageNumber(i, currentPage, paginationRange, totalPages);\r\n\r\n var openingEllipsesNeeded = (i === 2 && (position === 'middle' || position === 'end'));\r\n var closingEllipsesNeeded = (i === paginationRange - 1 && (position === 'middle' || position === 'start'));\r\n if (ellipsesNeeded && (openingEllipsesNeeded || closingEllipsesNeeded)) {\r\n pages.push('...');\r\n } else {\r\n pages.push(pageNumber);\r\n }\r\n i ++;\r\n }\r\n return pages;\r\n }\r\n\r\n /**\r\n * Given the position in the sequence of pagination links [i], figure out what page number corresponds to that position.\r\n *\r\n * @param i\r\n * @param currentPage\r\n * @param paginationRange\r\n * @param totalPages\r\n * @returns {*}\r\n */\r\n function calculatePageNumber(i, currentPage, paginationRange, totalPages) {\r\n var halfWay = Math.ceil(paginationRange/2);\r\n if (i === paginationRange) {\r\n return totalPages;\r\n } else if (i === 1) {\r\n return i;\r\n } else if (paginationRange < totalPages) {\r\n if (totalPages - halfWay < currentPage) {\r\n return totalPages - paginationRange + i;\r\n } else if (halfWay < currentPage) {\r\n return currentPage - halfWay + i;\r\n } else {\r\n return i;\r\n }\r\n } else {\r\n return i;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * This filter slices the collection into pages based on the current page number and number of items per page.\r\n * @param paginationService\r\n * @returns {Function}\r\n */\r\n function itemsPerPageFilter(paginationService) {\r\n\r\n return function(collection, itemsPerPage, paginationId) {\r\n if (typeof (paginationId) === 'undefined') {\r\n paginationId = DEFAULT_ID;\r\n }\r\n if (!paginationService.isRegistered(paginationId)) {\r\n throw 'pagination directive: the itemsPerPage id argument (id: ' + paginationId + ') does not match a registered pagination-id.';\r\n }\r\n var end;\r\n var start;\r\n if (angular.isObject(collection)) {\r\n itemsPerPage = parseInt(itemsPerPage) || 9999999999;\r\n if (paginationService.isAsyncMode(paginationId)) {\r\n start = 0;\r\n } else {\r\n start = (paginationService.getCurrentPage(paginationId) - 1) * itemsPerPage;\r\n }\r\n end = start + itemsPerPage;\r\n paginationService.setItemsPerPage(paginationId, itemsPerPage);\r\n\r\n if (collection instanceof Array) {\r\n // the array just needs to be sliced\r\n return collection.slice(start, end);\r\n } else {\r\n // in the case of an object, we need to get an array of keys, slice that, then map back to\r\n // the original object.\r\n var slicedObject = {};\r\n angular.forEach(keys(collection).slice(start, end), function(key) {\r\n slicedObject[key] = collection[key];\r\n });\r\n return slicedObject;\r\n }\r\n } else {\r\n return collection;\r\n }\r\n };\r\n }\r\n\r\n /**\r\n * Shim for the Object.keys() method which does not exist in IE < 9\r\n * @param obj\r\n * @returns {Array}\r\n */\r\n function keys(obj) {\r\n if (!Object.keys) {\r\n var objKeys = [];\r\n for (var i in obj) {\r\n if (obj.hasOwnProperty(i)) {\r\n objKeys.push(i);\r\n }\r\n }\r\n return objKeys;\r\n } else {\r\n return Object.keys(obj);\r\n }\r\n }\r\n\r\n /**\r\n * This service allows the various parts of the module to communicate and stay in sync.\r\n */\r\n function paginationService() {\r\n\r\n var instances = {};\r\n var lastRegisteredInstance;\r\n\r\n this.registerInstance = function(instanceId) {\r\n if (typeof instances[instanceId] === 'undefined') {\r\n instances[instanceId] = {\r\n asyncMode: false\r\n };\r\n lastRegisteredInstance = instanceId;\r\n }\r\n };\r\n\r\n this.deregisterInstance = function(instanceId) {\r\n delete instances[instanceId];\r\n };\r\n \r\n this.isRegistered = function(instanceId) {\r\n return (typeof instances[instanceId] !== 'undefined');\r\n };\r\n\r\n this.getLastInstanceId = function() {\r\n return lastRegisteredInstance;\r\n };\r\n\r\n this.setCurrentPageParser = function(instanceId, val, scope) {\r\n instances[instanceId].currentPageParser = val;\r\n instances[instanceId].context = scope;\r\n };\r\n this.setCurrentPage = function(instanceId, val) {\r\n instances[instanceId].currentPageParser.assign(instances[instanceId].context, val);\r\n };\r\n this.getCurrentPage = function(instanceId) {\r\n var parser = instances[instanceId].currentPageParser;\r\n return parser ? parser(instances[instanceId].context) : 1;\r\n };\r\n\r\n this.setItemsPerPage = function(instanceId, val) {\r\n instances[instanceId].itemsPerPage = val;\r\n };\r\n this.getItemsPerPage = function(instanceId) {\r\n return instances[instanceId].itemsPerPage;\r\n };\r\n\r\n this.setCollectionLength = function(instanceId, val) {\r\n instances[instanceId].collectionLength = val;\r\n };\r\n this.getCollectionLength = function(instanceId) {\r\n return instances[instanceId].collectionLength;\r\n };\r\n\r\n this.setAsyncModeTrue = function(instanceId) {\r\n instances[instanceId].asyncMode = true;\r\n };\r\n\r\n this.setAsyncModeFalse = function(instanceId) {\r\n instances[instanceId].asyncMode = false;\r\n };\r\n\r\n this.isAsyncMode = function(instanceId) {\r\n return instances[instanceId].asyncMode;\r\n };\r\n }\r\n\r\n /**\r\n * This provider allows global configuration of the template path used by the dir-pagination-controls directive.\r\n */\r\n function paginationTemplateProvider() {\r\n\r\n var templatePath = 'angularUtils.directives.dirPagination.template';\r\n var templateString;\r\n\r\n /**\r\n * Set a templateUrl to be used by all instances of \r\n * @param {String} path\r\n */\r\n this.setPath = function(path) {\r\n templatePath = path;\r\n };\r\n\r\n /**\r\n * Set a string of HTML to be used as a template by all instances\r\n * of . If both a path *and* a string have been set,\r\n * the string takes precedence.\r\n * @param {String} str\r\n */\r\n this.setString = function(str) {\r\n templateString = str;\r\n };\r\n\r\n this.$get = function() {\r\n return {\r\n getPath: function() {\r\n return templatePath;\r\n },\r\n getString: function() {\r\n return templateString;\r\n }\r\n };\r\n };\r\n }\r\n})();\r\n","appWebshop.service('searchDatalayerService', function () {\r\n \r\n var productsPageSize = 6;\r\n\r\n this.pushProductImpressionsToDatalayer = function(productsOfCurrentPage) { \r\n var productImpressions = [];\r\n for (var i = 0; i < productsOfCurrentPage.length; i++) {\r\n var product = productsOfCurrentPage[i];\r\n\r\n var productImpression = new Object();\r\n productImpression.name = product.Name;\r\n productImpression.id = product.ID;\r\n productImpression.price = product.Price;\r\n productImpression.brand = 'Fleurop';\r\n productImpression.category = 'Search';\r\n productImpression.list = 'productListing';\r\n productImpression.position = i + 1;\r\n productImpressions.push(productImpression)\r\n\r\n if (i + 1 >= productsPageSize) {\r\n break;\r\n }\r\n }\r\n\r\n var ecommerce = new Object();\r\n ecommerce.currencyCode = 'CHF';\r\n ecommerce.impressions = productImpressions;\r\n\r\n var productsDatalayerObject = new Object();\r\n productsDatalayerObject.event = 'productPromotion';\r\n productsDatalayerObject.ecommerce = ecommerce;\r\n\r\n dataLayer.push(productsDatalayerObject);\r\n }\r\n\r\n this.pushProductImpressionsSummaryToDatalayer = function(products) { \r\n var minPrice = 0\r\n var maxPrice = 0;\r\n for (var i = 0; i < products.length; i++) {\r\n var product = products[i];\r\n if (product.Price > 0 && (product.Price < minPrice || minPrice == 0)) {\r\n minPrice = product.Price;\r\n }\r\n if (product.Price > maxPrice) {\r\n maxPrice = product.Price;\r\n }\r\n }\r\n var listingCount = products.length;\r\n\r\n var summaryDatalayerObject = new Object();\r\n summaryDatalayerObject.listingCategory = 'Search';\r\n summaryDatalayerObject.listingCategoryEmarsys = 'Search';\r\n summaryDatalayerObject.listingCategoryEN = 'Search';\r\n summaryDatalayerObject.listingCount = listingCount;\r\n summaryDatalayerObject.listingMaxPrice = maxPrice;\r\n summaryDatalayerObject.listingMinPrice = minPrice;\r\n\r\n dataLayer.push(summaryDatalayerObject);\r\n }\r\n\r\n this.pushSearchTermToDatalayer = function(searchTerm) { \r\n dataLayer.push({ \"searchTerm\": searchTerm });\r\n }\r\n\r\n this.getProductsOfCurrentPage = function(products, newPageNumber) {\r\n var indexOfFirstProductOfCurrentPage = (newPageNumber - 1) * productsPageSize;\r\n var firstProductOfCurrentPage = products[indexOfFirstProductOfCurrentPage];\r\n\r\n var productsOfCurrentPage = [];\r\n for (var i = indexOfFirstProductOfCurrentPage; (i < products.length) && (i - indexOfFirstProductOfCurrentPage) < productsPageSize; i++) {\r\n productsOfCurrentPage.push(products[i]);\r\n }\r\n return productsOfCurrentPage;\r\n }\r\n\r\n});","appWebshop.requires.push('angularUtils.directives.dirPagination')\r\n\r\nappWebshop.controller('searchController', ['$scope', 'searchDatalayerService', function ($scope, searchDatalayerService) {\r\n\r\n //DOM Ready - Entry point\r\n angular.element(document).ready(function () {\r\n angularSearchController = $scope;\r\n $scope.searchTerm = getQueryStringParameter('q');\r\n $scope.search();\r\n $scope.$apply();\r\n });\r\n\r\n //Variables\r\n $scope.searchTerm = '';\r\n $scope.searchInProgress = true; \r\n $scope.products = [];\r\n $scope.sites = [];\r\n\r\n $scope.searchBoxKeyUp = function(event) { \r\n //Esc clears the search term\r\n if (event.keyCode == 27) {\r\n $scope.searchTerm = '';\r\n } \r\n\r\n //On each key up search is performed.\r\n $scope.search();\r\n };\r\n \r\n //Search for products. Has 0.7 Second debounce delay, so only last keyup is sent.\r\n $scope.search = debounce(function () {\r\n if ($scope.searchTerm.length >= 3) {\r\n\r\n $scope.searchInProgress = true;\r\n searchDatalayerService.pushSearchTermToDatalayer($scope.searchTerm);\r\n\r\n FleuropWebShop.SearchService.Search($scope.searchTerm, function (result) {\r\n currentProductPageNumber = 1;\r\n\r\n for (var i = 0; i < result.Products.length; i++) {\r\n result.Products[i].NameHtmlEncoded = result.Products[i].Name.replace('
', ' ');\r\n }\r\n\r\n $scope.products = result.Products;\r\n $scope.sites = result.Sites;\r\n $scope.searchInProgress = false;\r\n $scope.$apply();\r\n\r\n history.pushState(null, \"Suchresultat: \" + $scope.searchTerm, \"?q=\" + $scope.searchTerm);\r\n //$('body').adaptSelection();\r\n\r\n if ($scope.isEmptySearchResult()) {\r\n //No Search result found. Favorite products slider is made visible. \r\n } else {\r\n //Regular results get pushed to Datalayer.\r\n searchDatalayerService.pushProductImpressionsToDatalayer(searchDatalayerService.getProductsOfCurrentPage(result.Products, 1));\r\n searchDatalayerService.pushProductImpressionsSummaryToDatalayer(result.Products);\r\n }\r\n dataLayer.push({ 'event': 'searchPageLoad' });\r\n configureFavorites();\r\n }); \r\n\r\n } else {\r\n $scope.products = [];\r\n $scope.sites =[];\r\n $scope.searchInProgress = false;\r\n $scope.$apply();\r\n } \r\n\r\n }, 700);\r\n\r\n $scope.isEmptySearchResult = function () {\r\n return ($scope.products.length == 0 && $scope.sites.length == 0 && !$scope.searchInProgress)\r\n }\r\n\r\n var currentProductPageNumber = 1;\r\n $scope.productPageChanged = function (newPageNumber, oldPageNumber) {\r\n if (newPageNumber != currentProductPageNumber) {\r\n var productsOfCurrentPage = searchDatalayerService.getProductsOfCurrentPage($scope.products, newPageNumber);\r\n searchDatalayerService.pushProductImpressionsToDatalayer(productsOfCurrentPage);\r\n dataLayer.push({ 'event': 'searchPageLoad' });\r\n currentProductPageNumber = newPageNumber;\r\n configureFavorites();\r\n } \r\n }\r\n \r\n\r\n \r\n}]);","/*\r\n'***********************************************************\t\r\n'\tWorkfile: \tRegionSelector.js \r\n' Version:\t3\t\t \t\r\n'************************************************************\r\n*/\r\n//-------------------------------------------\r\n// This module contains RegionSelector Ajax Features\r\n// (clientside) Javascript functions \r\n//-------------------------------------------\r\n\r\nvar _helper = {\r\n zipIDTextBox: \"\", placeIDTextBox: \"\", zipplaceIDTextBox: \"\", countryRegNr: \"\",\r\n searchContainerIDDiv: \"searchResultContainer\", searchResultTemplateID: \"searchResultTemplate\",\r\n hiddenIDZipPlaceRegNr: \"\", callerID: \"\", callbackonSetPlace: null\r\n}\r\n\r\n//---------------------------------------------------------------------------------------------------------------------\r\n//Helper Functions\r\n\r\n//---------------------------------------------------------------------------------------------------------------------\r\ncheckZipAndPlace = debounce(function (helper) { \r\n _helper = helper;\r\n _searchText = \"\";\r\n if (_helper.zipplaceIDTextBox != \"\" && $(\"#\" + _helper.zipplaceIDTextBox).val().length > 2)\r\n _searchText = $(\"#\" + _helper.zipplaceIDTextBox).val();\r\n else if (_helper.zipIDTextBox != \"\" && $(\"#\" + _helper.zipIDTextBox).val().length > 2 && _helper.zipIDTextBox == _helper.callerID)\r\n _searchText = $(\"#\" + _helper.zipIDTextBox).val();\r\n else if (_helper.placeIDTextBox != \"\" && $(\"#\" + _helper.placeIDTextBox).val().length > 2 && _helper.placeIDTextBox == _helper.callerID)\r\n _searchText = $(\"#\" + _helper.placeIDTextBox).val();\r\n\r\n if (_searchText.length > 2) {\r\n FleuropWebShop.RegionSelector.GetZipAndPlace(_searchText, _helper.countryRegNr, checkZipAndPlace_OnComplete);\r\n }\r\n else {\r\n hideTemplate();\r\n }\r\n}, 700);\r\n\r\nfunction checkZipAndPlace_OnComplete(result) { \r\n if (result.length >= 1) {\r\n $('#' + _helper.searchContainerIDDiv).empty();\r\n //Template laden...\r\n var html = parseTemplate($(\"#\" + _helper.searchResultTemplateID).html(), { items: result });\r\n $(html).appendTo(\"#\" + _helper.searchContainerIDDiv);\r\n\r\n //Container zeigen\r\n $('#' + _helper.searchContainerIDDiv).fadeIn(\"slow\");\r\n }\r\n}\r\n\r\nfunction findRegionExact(zip, city, countryRegNr, callbackAdr) {\r\n FleuropWebShop.RegionSelector.FindExact(zip, city, countryRegNr, callbackAdr);\r\n}\r\n\r\nfunction hideTemplate() {\r\n $('.suggestBox').fadeOut('slow'); //#searchResultContainer\r\n $('.suggestBox').empty();\r\n}\r\n\r\n\r\nfunction SetZipAndPlace(zip, place, zipPlaceRegNr, helper) {\r\n if (helper.hiddenIDZipPlaceRegNr != \"\") {\r\n $('#' + helper.hiddenIDZipPlaceRegNr).val(zipPlaceRegNr); \r\n }\r\n\r\n if (helper.zipplaceIDTextBox != \"\") {\r\n $('#' + helper.zipplaceIDTextBox).val(zip + ' ' + place);\r\n //makes sure that the validation engine reevaluates the field.\r\n $('#' + helper.zipplaceIDTextBox).blur();\r\n } else {\r\n if (zip != '') {\r\n $('#' + helper.zipIDTextBox).val(zip);\r\n $('#' + helper.zipIDTextBox).blur();\r\n }\r\n $('#' + helper.placeIDTextBox).val(place); \r\n $('#' + helper.placeIDTextBox).blur();\r\n }\r\n\r\n hideTemplate();\r\n\r\n if (helper.callbackonSetPlace != null)\r\n helper.callbackonSetPlace();\r\n}\r\n\r\n//---------------------------------------------------------------------------------------------------------------------\r\n","/*\r\nVirtual basket features (Emarsys)\r\n\r\n- The features are initialized here.\r\n- Basket is pushed to Datalayer on Layout.Master on window.load (to not affect load performance) \r\n- Basket gets cleared in Orderconfirmation.aspx\r\n*/\r\n\r\nvar virtualBasketCache = BoomerangCache.create('virtualBasket', { storage: 'local', encrypt: false });\r\nvar daysToKeepItemsInEmarsysBasket = 14;\r\nvar secondsToKeepItemsInEmarsysBasket = daysToKeepItemsInEmarsysBasket * 24 * 60 * 60;\r\n\r\nfunction addBasketItemToVirtualBasket(productID, orderFormController) {\r\n try {\r\n if (virtualBasketCache.check()) { \r\n var price = orderFormController.basket.Items[0].Price;\r\n virtualBasketCache.set(productID, price, secondsToKeepItemsInEmarsysBasket);\r\n console.log('Virtual Basket: added product ' + productID + ' with price: ' + price);\r\n \r\n }\r\n } catch (err) {\r\n console.log('Virtual Basket: failed to add product')\r\n }\r\n}\r\n\r\nfunction pushVirtualBasketToDatalayer() {\r\n\r\n try {\r\n if (virtualBasketCache.check()) {\r\n\r\n virtualBasketCache.flushExpired();\r\n var basketDictionary = virtualBasketCache.getAll();\r\n var basketStructureToPush = [];\r\n\r\n if (virtualBasketCache.length() > 0) {\r\n for (key in basketDictionary) {\r\n var item = basketDictionary[key];\r\n basketStructureToPush.push({ \"id\": key, \"price\": item });\r\n }\r\n\r\n dataLayer.push({ \"cart\": basketStructureToPush });\r\n console.log('Virtual Basket: pushed ' + virtualBasketCache.length() + ' basket items to datalayer')\r\n } else {\r\n dataLayer.push({ \"cart\": \"empty\" });\r\n console.log('Virtual Basket: pushed empty basket to datalayer')\r\n }\r\n\r\n }\r\n } catch (err) {\r\n console.log('Virtual Basket: failed to push to datalayer')\r\n }\r\n\r\n}\r\n\r\nfunction clearVirtualBasket() {\r\n //Clear virtual basket\r\n try {\r\n if (virtualBasketCache.check()) {\r\n //virtualBasketCache.clear() kills the whole local storage. \r\n //so each key is removed individually.\r\n\r\n var basketDictionary = virtualBasketCache.getAll();\r\n if (virtualBasketCache.length() > 0) {\r\n for (key in basketDictionary) {\r\n virtualBasketCache.remove(key);\r\n }\r\n }\r\n\r\n console.log('Virtual Basket: cleared')\r\n }\r\n } catch (err) {\r\n console.log('Virtual Basket: could not clear')\r\n }\r\n}","// Functions that are not bound to a page or masterpage\r\n\r\n//Content:\r\n//----------------------\r\n// Utilities\r\n// Google GTM DataLayer push functions\r\n//----------------------\r\n\r\n//Utilities\r\nfunction getQueryStringParameter(name) {\r\n name = name.replace(/[\\[]/, \"\\\\\\[\").replace(/[\\]]/, \"\\\\\\]\");\r\n var regexS = \"[\\\\?&]\" + name + \"=([^&#]*)\";\r\n var regex = new RegExp(regexS);\r\n var results = regex.exec(window.location.href);\r\n if (results == null)\r\n return \"\";\r\n else\r\n return decodeURIComponent(results[1].replace(/\\+/g, \" \"));\r\n}\r\n\r\n//includes() isn't supported in all IE versions by default (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes#Browser_compatibility)\r\nString.prototype.includes = function (match) {\r\n return this.indexOf(match) !== -1;\r\n}\r\n\r\nfunction roundTo(n, digits) {\r\n if (digits === undefined) {\r\n digits = 0;\r\n }\r\n\r\n var multiplicator = Math.pow(10, digits);\r\n n = parseFloat((n * multiplicator).toFixed(11));\r\n var test = (Math.round(n) / multiplicator);\r\n return +(test.toFixed(digits));\r\n}\r\n\r\nfunction roundToFive(n, digits) {\r\n if (digits === undefined) {\r\n digits = 0;\r\n }\r\n\r\n var multiplicator = Math.pow(10, digits);\r\n n = parseFloat((n * multiplicator).toFixed(11));\r\n var test = (Math.round(n * 0.2) / 0.2 / multiplicator);\r\n return +(test.toFixed(digits));\r\n}\r\n\r\nfunction formatPrice(price) {\r\n var isPriceWIthoutComma = (price % 1 == 0);\r\n var result = '';\r\n\r\n if (isPriceWIthoutComma) {\r\n result = (price + '.-')\r\n } else {\r\n result = price.toFixed(2);\r\n };\r\n\r\n return result;\r\n}\r\n\r\nfunction extractUrl(valueToExtractFrom) {\r\n var myReg = /\\(\"?(.*?)\"?\\)/i;\r\n var match = myReg.exec(valueToExtractFrom)\r\n return match[1]; \r\n}\r\n\r\nfunction htmlEncode(value) {\r\n \"use strict\";\r\n //create a in-memory div, set it's inner text(which jQuery automatically encodes)\r\n //then grab the encoded contents back out. The div never exists on the page.\r\n return $('
').text(value).html();\r\n}\r\n\r\nfunction htmlDecode(value) {\r\n \"use strict\";\r\n return $('
').html(value).text();\r\n}\r\n\r\n// Returns a function, that, as long as it continues to be invoked, will not\r\n// be triggered. The function will be called after it stops being called for\r\n// N milliseconds. If `immediate` is passed, trigger the function on the\r\n// leading edge, instead of the trailing.\r\nfunction debounce(func, wait, immediate) {\r\n var timeout;\r\n return function () {\r\n var context = this, args = arguments;\r\n var later = function () {\r\n timeout = null;\r\n if (!immediate) func.apply(context, args);\r\n };\r\n var callNow = immediate && !timeout;\r\n clearTimeout(timeout);\r\n timeout = setTimeout(later, wait);\r\n if (callNow) func.apply(context, args);\r\n };\r\n};\r\n\r\nfunction setRadioButton(nameEndsWith, value) {\r\n $('input[name$=' + nameEndsWith + '][value=' + value + ']').prop(\"checked\", true).trigger('change');\r\n}\r\n\r\nfunction configureTextboxForBirthdaySelection(tbBirthday) {\r\n tbBirthday.datepicker({\r\n setDate: null,\r\n dateFormat: 'dd.mm.yy',\r\n changeMonth: true,\r\n changeYear: true,\r\n yearRange: \"-100:+0\",\r\n firstDay: 1,\r\n minDate: new Date(1900, 1 - 1, 1)\r\n });\r\n\r\n try {\r\n if (tbBirthday.length > 0 && tbBirthday[0].defaultValue != '') {\r\n tbBirthday.datepicker(\"setDate\", tbBirthday[0].defaultValue);\r\n }\r\n else {\r\n tbBirthday.datepicker(\"setDate\", null);\r\n }\r\n } catch (e) {\r\n console.write('err caught ' + e)\r\n } \r\n}\r\n\r\n// Google Tag DataLayer push functions\r\n// ========================================================= \r\nfunction onPromoClick(promoObj, data) {\r\n gtdl_push(7, data, promoObj);\r\n}\r\nfunction onProductClick(productObj, data) { \r\n gtdl_push(8, data, productObj);\r\n}\r\nfunction onAddonClick(productObj, data) {\r\n gtdl_push(9, data, productObj);\r\n}\r\nfunction gtdl_push(t, data, obj) {\r\n\r\n switch (t) {\r\n case 1: dataLayer.push({ 'event': (data == 1) ? 'openPickupShop' : 'openPartnerShop' }); break;\r\n case 2: dataLayer.push({ 'event': 'loginOpen' }); break;\r\n case 3: dataLayer.push({ 'event': 'formError', 'formError': 'Login failed.' }); break;\r\n case 4: dataLayer.push({ 'event': 'formError', 'formError': 'Mobile Login failed.' }); break;\r\n case 5: dataLayer.push({ 'event': (data == 1) ? 'selectPickupShop' : 'selectPartnerShop' }); break;\r\n case 6: dataLayer.push({ 'event': (data == 1) ? 'removePickupShop' : 'removePartnerShop' }); break;\r\n case 7:\r\n dataLayer.push({\r\n 'event': 'promotionClick', 'ecommerce': { 'promoClick': { 'promotions': [data] } }, 'eventCallback': function () {\r\n //if (obj != null) document.location = obj.href;\r\n //line caused problem with links that open in new windows. apparently it's not needed.\r\n }\r\n }); break;\r\n case 8:\r\n dataLayer.push({\r\n 'event': 'productClick', 'ecommerce': { 'click': { 'actionField': { 'list': data.list }, 'products': [data] } }\r\n }); break;\r\n case 9:\r\n dataLayer.push({\r\n 'event': $(obj).closest('.product').hasClass(\"active\") ? 'removeAddonClick' : 'addAddonClick', 'ecommerce': { 'click': { 'actionField': { 'list': data.list }, 'products': [data] } }, 'eventCallback': function () {\r\n }\r\n }); break;\r\n case 10:\r\n if (data.length == 1) dataLayer.push({ 'event': data[0] });\r\n else if (data.length > 1) dataLayer.push({ 'event': data[data.length - 2] }, { 'event': data[data.length - 1] }); break;\r\n case 11: dataLayer.push({ 'event': 'formError', 'formError': data }); break;\r\n case 12: dataLayer.push({ 'event': 'cardSelected', 'cardId': data.id, 'cardName': data.name, 'cardPrice': data.price, 'cardImage': data.image }); break;\r\n case 13: dataLayer.push({ 'productVariant': data.variant, 'productPriceCustom': data.price }); break;\r\n case 14: dataLayer.push({ 'event': 'formError', 'formError': 'Login not allowed. Email is not verified.' }); break;\r\n case 15: dataLayer.push({ 'event': 'formError', 'formError': 'Mobile Login not allowed. Email is not verified.' }); break;\r\n }\r\n}","$(document).ready(function() {\r\n \r\n function mobileDropdownHeight() {\r\n var windowHeight = $(window).height();\r\n var topArea = $('#top-area').height();\r\n var navbar = $('header .navbar').height();\r\n var stickyBar = $('#sticky-bar').height();\r\n if($('body').hasClass('country')) {\r\n var countrySelector = $('#country-selector').outerHeight();\r\n var finalHeight = windowHeight - topArea - countrySelector - navbar - stickyBar\r\n } else {\r\n var finalHeight = windowHeight - topArea - navbar - stickyBar\r\n }\r\n $('#main-nav').height(finalHeight);\r\n }\r\n \r\n \r\n // Tooltip init\r\n $('[data-toggle=\"tooltip\"]').tooltip({\r\n offset: '0 5 0 0'\r\n });\r\n \r\n $('.products-list .favorite').on('shown.bs.tooltip', function () {\r\n $('body > .tooltip.show').addClass('tooltip-favorite');\r\n })\r\n $('.products-list .favorite').on('hidden.bs.tooltip', function () {\r\n $('body > .tooltip.show').removeClass('tooltip-favorite');\r\n })\r\n \r\n \r\n // < 768\r\n enquire.register('screen and (max-width: 767px)', function() {\r\n $('#home-articles .title, #home-articles .text').removeAttr('style');\r\n });\r\n \r\n // < 992\r\n enquire.register('screen and (max-width: 991px)', function() {\r\n // Remove inline css\r\n $('#overlay, #overlay-header').hide();\r\n $('body').removeClass('navbar-drop-open').css('overflow','');\r\n $('header .navbar .nav-item').removeClass('show').children('.nav-link').attr('aria-expanded','false').next('.dropdown-menu').removeClass('show').height('');\r\n $('header .navbar .nav-item').removeClass('show')\r\n .children('.nav-link').attr('aria-expanded','false')\r\n .next('.dropdown-menu').removeClass('show')\r\n .find('.category-image').css({\r\n 'width': '',\r\n 'height': ''\r\n });\r\n $('header, #sticky-bar').removeAttr('style');\r\n \r\n // Destroy datepicker\r\n if($('#ui-datepicker-div').length) {\r\n $('#delivery-date input').datepicker('hide');\r\n }\r\n \r\n // Create/remove scrollable area on menu dropdown\r\n $('header .navbar .nav-item').on('hidden.bs.dropdown', function () {\r\n $('body').removeClass('navbar-item-open');\r\n $('#main-nav').css('height','');\r\n });\r\n $('header .navbar .nav-item').on('shown.bs.dropdown', function () {\r\n $('body').addClass('navbar-item-open');\r\n mobileDropdownHeight();\r\n \r\n // Scroll to opened menu item\r\n // var navbarPosition = $('header .navbar').offset().top;\r\n // var elementPosition = $(this).offset().top;\r\n // scrollPosition = elementPosition - navbarPosition;\r\n // $('#main-nav').animate({\r\n // scrollTop: scrollPosition\r\n // }, 500);\r\n })\r\n \r\n // Open/close mobile nav menu\r\n $('#main-nav-toggle').on('click', function() {\r\n if($('body').hasClass('navbar-menu-open')) {\r\n $('#main-nav').slideUp(100);\r\n $('body').removeClass('navbar-menu-open');\r\n setTimeout(function() {\r\n $('#main-nav').css('height','');\r\n }, 100);\r\n } else {\r\n $('#main-nav').slideDown(100);\r\n $('body').addClass('navbar-menu-open');\r\n }\r\n });\r\n ;\r\n // Open/close footer sections\r\n $('footer .section:not(.static) > h4.title').on('click',function() {\r\n if($(this).parents('.section').hasClass('active')){\r\n $(this).next('.section-content').slideUp(300);\r\n $(this).parents('.section').removeClass('active');\r\n } else {\r\n $('footer .section:not(.static) .section-content').slideUp(300);\r\n $('footer .section:not(.static)').removeClass('active');\r\n $(this).next('.section-content').slideDown(300);\r\n $(this).parents('.section').addClass('active');\r\n \r\n // Scroll to opened menu item\r\n var $this = $(this);\r\n setTimeout(function() {\r\n var elementPosition = $this.offset().top;\r\n var topArea = $('#top-area').height();\r\n var navbar = $('header .navbar').height();\r\n if($('body').hasClass('country')) {\r\n var countrySelector = $('#country-selector').outerHeight();\r\n var finalPosition = elementPosition - topArea - countrySelector - navbar\r\n } else {\r\n var finalPosition = elementPosition - topArea - navbar\r\n }\r\n $('html, body').animate({\r\n scrollTop: finalPosition\r\n }, 500);\r\n }, 300);\r\n \r\n }\r\n });\r\n });\r\n \r\n \r\n // > 768\r\n enquire.register('screen and (min-width: 768px)', function() {\r\n function equalHeightArticles() {\r\n // Home articles: Equal height rows inside columns\r\n $('#home-articles').each(function(){\r\n var highestTitle = 0;\r\n var highestText = 0;\r\n $('.title', this).each(function(){\r\n $(this).height('');\r\n if($(this).height() > highestTitle) {\r\n highestTitle = $(this).height(); \r\n }\r\n });\r\n $('.text', this).each(function(){\r\n $(this).height('');\r\n if($(this).height() > highestText) {\r\n highestText = $(this).height(); \r\n }\r\n });\r\n $('.title',this).height(highestTitle);\r\n $('.text',this).height(highestText);\r\n });\r\n }\r\n \r\n equalHeightArticles();\r\n $(window).resize(function() {\r\n equalHeightArticles();\r\n });\r\n });\r\n \r\n // > 992\r\n enquire.register('screen and (min-width: 992px)', function() {\r\n // Remove inline css\r\n $('header .navbar-nav').removeAttr('style');\r\n $('body').removeClass('navbar-menu-open');\r\n $('header .navbar .nav-item').removeClass('show').children('.nav-link').attr('aria-expanded','false').next('.dropdown-menu').removeClass('show');\r\n $('footer .section:not(.static) > h4.title').unbind('click');\r\n $('footer .section').removeClass('active').children('.section-content').removeAttr('style');\r\n $('header, #sticky-bar').removeAttr('style');\r\n \r\n // Destroy datepicker\r\n if($('#ui-datepicker-div').length) {\r\n $('#delivery-date input').datepicker('hide');\r\n }\r\n \r\n // Add vertical scroll to navbar dropdown\r\n $('header .navbar .nav-item').on('shown.bs.dropdown', function () {\r\n var windowWidth = $(window).width();\r\n var windowHeight = $(window).height();\r\n var topArea = $('#top-area').height();\r\n var navbar = $('header .navbar').height();\r\n if($('body').hasClass('country')) {\r\n var countrySelector = $('#country-selector').outerHeight();\r\n var screenHeight = windowHeight - topArea - countrySelector - navbar\r\n } else {\r\n var screenHeight = windowHeight - topArea - navbar\r\n }\r\n var dropdownMenuHeight = $(this).find('.dropdown-menu').height();\r\n\r\n if(dropdownMenuHeight > screenHeight) {\r\n $(this).find('.dropdown-menu').height(screenHeight);\r\n }\r\n $('body').css('overflow','hidden');\r\n $('header').width(windowWidth);\r\n });\r\n $('header .navbar .nav-item').on('hidden.bs.dropdown', function () {\r\n $(this).find('.dropdown-menu').height('');\r\n $('body').css('overflow','');\r\n $('header').width('');\r\n });\r\n \r\n // Show/hide overlay on navbar open/close\r\n $('header .navbar .nav-item').on('shown.bs.dropdown', function () {\r\n $('#overlay, #overlay-header').show();\r\n $('body').addClass('navbar-drop-open');\r\n // $('header').css('top',$(window).scrollTop());\r\n })\r\n $('header .navbar .nav-item').on('hidden.bs.dropdown', function () {\r\n $('#overlay, #overlay-header').hide();\r\n $('body').removeClass('navbar-drop-open');\r\n // $('header').css('top','');\r\n });\r\n \r\n // Navbar dropdown category image width/height\r\n function navbarBackground() {\r\n var element = $('header .navbar .nav-item.show');\r\n windowWidth = $(window).width();\r\n var dropdownContainer = element.find('.category-image').next('.container').width()\r\n var outerContainerRightArea = (windowWidth - dropdownContainer) / 2;\r\n var categoryColumnWidth = element.find('.category-info').outerWidth();\r\n var categoryColumnHeight = element.find('.category-info').outerHeight();\r\n element.find('.category-image').css({\r\n 'width': outerContainerRightArea + categoryColumnWidth,\r\n 'height': categoryColumnHeight\r\n });\r\n }\r\n function navbarBackgroundMenuAction() {\r\n $('header .navbar .nav-item').on('shown.bs.dropdown', function () {\r\n navbarBackground();\r\n });\r\n $('header .navbar .nav-item').on('hidden.bs.dropdown', function () {\r\n $(this).find('.category-image').css({\r\n 'width': '',\r\n 'height': ''\r\n });\r\n });\r\n }\r\n navbarBackgroundMenuAction();\r\n $(window).resize(function() {\r\n navbarBackground();\r\n });\r\n });\r\n \r\n \r\n // Show/hide country-selector\r\n function countrySelector() {\r\n if($('#country-selector').length) {\r\n var countrySelector = $('#country-selector').outerHeight();\r\n var topArea = $('#top-area').height();\r\n var navbar = $('header .navbar').height();\r\n if($(window).scrollTop() > (topArea + navbar)) {\r\n // if($(window).scrollTop() > countrySelector) {\r\n // if($(window).scrollTop() > 0) {\r\n $('#country-selector, header .navbar').css({\r\n 'transform': 'translateY(-'+ countrySelector +'px)'\r\n });\r\n $('header #country-dropdown .dropdown').dropdown('hide');\r\n $('body').removeClass('country').css('margin-top',countrySelector);\r\n \r\n // Update dropdown height after hiding the country selector\r\n enquire.register('screen and (max-width: 991px)', function() {\r\n if($('body').hasClass('navbar-item-open')) {\r\n mobileDropdownHeight();\r\n }\r\n });\r\n } else {\r\n $('#country-selector, header .navbar').css({\r\n 'transform': ''\r\n });\r\n $('body').addClass('country').css('margin-top','');\r\n \r\n // Update dropdown height after hiding the country selector\r\n enquire.register('screen and (max-width: 991px)', function() {\r\n if($('body').hasClass('navbar-item-open')) {\r\n mobileDropdownHeight();\r\n }\r\n });\r\n }\r\n }\r\n }\r\n \r\n \r\n // Show/hide country-selector on scroll\r\n $(window).scroll(function(){\r\n countrySelector();\r\n });\r\n \r\n \r\n // Show/hide country-selector on resize\r\n $(window).resize(function(){\r\n countrySelector();\r\n });\r\n \r\n \r\n // Home slider\r\n $('#home-slider .owl-carousel').owlCarousel({\r\n loop: true,\r\n autoplay: true,\r\n autoplayTimeout: 5000,\r\n autoplayHoverPause: true,\r\n smartSpeed: 750,\r\n margin: 10,\r\n items: 1,\r\n nav: false,\r\n dotsContainer: '#slider-dots'\r\n });\r\n\r\n \r\n // Add offset for modal\r\n $('.modal').on('show.bs.modal', function() {\r\n function modalOffset() {\r\n var windowWidth = $(window).width();\r\n var modalOffset = $('body').css('padding-right')\r\n modalOffset = modalOffset.replace(\"px\", \"\");\r\n enquire.register('screen and (max-width: 991px)', function() {\r\n $('header').width(windowWidth - modalOffset);\r\n $('#sticky-bar').width(windowWidth - modalOffset);\r\n });\r\n enquire.register('screen and (min-width: 992px)', function() {\r\n $('header').width(windowWidth - modalOffset);\r\n });\r\n }\r\n modalOffset();\r\n $(window).resize(function(){\r\n modalOffset();\r\n });\r\n })\r\n $('.modal').on('hidden.bs.modal', function() {\r\n $('header, #sticky-bar').removeAttr('style');\r\n });\r\n \r\n \r\n // Show login form password\r\n $('.account-popup .show-password').on('click',function(){\r\n if($(this).parents('form').find('.password').attr('type') == 'password') {\r\n $(this).parents('form').find('.password').attr('type','text');\r\n } else {\r\n $(this).parents('form').find('.password').attr('type','password');\r\n }\r\n });\r\n \r\n \r\n // Toggle login/register popup\r\n $('.account-popup .btn-register').on('click',function(){\r\n $('.account-popup .login-content').slideUp(400);\r\n $('.account-popup .register-content').slideDown(400);\r\n setTimeout(function() {\r\n $('.account-popup .modal-body').animate({\r\n scrollTop: 0\r\n }, 400);\r\n }, 400);\r\n });\r\n $('.account-popup .btn-login').on('click',function(){\r\n $('.account-popup .register-content').slideUp(400);\r\n $('.account-popup .login-content').slideDown(400);\r\n setTimeout(function() {\r\n $('.account-popup .modal-body').animate({\r\n scrollTop: 0\r\n }, 400);\r\n }, 400);\r\n });\r\n $('.account-popup').on('hidden.bs.modal', function() {\r\n $('.account-popup .login-content, .account-popup .register-content').removeAttr('style');\r\n });\r\n \r\n // Product page custom price click\r\n $('#custom-price').on('click',function() {\r\n $(this).parents('.custom-price').find('.form-check-input').trigger('click');\r\n }); \r\n\r\n $('.calendar-field span').on('click', function () {\r\n var input = $(this).siblings('input');\r\n if (!input.attr('disabled'))\r\n input.datepicker('show');\r\n }); \r\n \r\n // Show more items\r\n $('.show-more-items').on('click',function() { \r\n var topArea = $('#top-area').height();\r\n var navbar = $('header .navbar').height();\r\n\r\n if($(this).hasClass('more')) {\r\n var itemsPerRow = $(this).data('row-items');\r\n $('html, body').animate({\r\n scrollTop: $(this).closest('.product-section').offset().top - topArea - navbar\r\n }, 500);\r\n $(this).text($(this).data('more'))\r\n .removeClass('more')\r\n .closest('.product-section-content').find('.items-container').find('.item').slice(itemsPerRow).addClass('d-none');\r\n } else {\r\n $(this).text($(this).data('less'))\r\n .addClass('more')\r\n .closest('.product-section-content').find('.items-container').find('.item.d-none').removeClass('d-none');\r\n\r\n if ($(this).closest('#addon-actions').length) {\r\n dataLayer.push({ 'event': 'addons', 'addons': 'expanded' });\r\n }\r\n }\r\n }); \r\n\r\n // Show more cards\r\n $('.show-more-cards').on('click', function () {\r\n var topArea = $('#top-area').height();\r\n var navbar = $('header .navbar').height();\r\n\r\n if ($(this).hasClass('more')) {\r\n var itemsPerRow = $(this).data('row-items');\r\n $('html, body').animate({\r\n scrollTop: $(this).closest('.product-card-category').offset().top - topArea - navbar\r\n }, 500);\r\n $(this).text($(this).data('more'))\r\n .removeClass('more')\r\n .closest('.product-card-content').find('.items-container').find('.item').slice(itemsPerRow).addClass('d-none');\r\n } else {\r\n $(this).text($(this).data('less'))\r\n .addClass('more')\r\n .closest('.product-card-content').find('.items-container').find('.item.d-none').removeClass('d-none');\r\n }\r\n }); \r\n \r\n // Show add-on descriptions\r\n $('.show-descriptions').on('click',function() {\r\n if($(this).hasClass('more')) {\r\n $(this).text($(this).data('more'))\r\n .removeClass('more')\r\n .closest('.product-section-content').find('.items-container').find('.product-description').addClass('d-none'); \r\n } else {\r\n $(this).text($(this).data('less'))\r\n .addClass('more')\r\n .closest('.product-section-content').find('.items-container').find('.product-description.d-none').removeClass('d-none');\r\n dataLayer.push({ 'event': 'addons', 'descriptions': 'expanded' });\r\n }\r\n\r\n var topArea = $('#top-area').height();\r\n var navbar = $('header .navbar').height();\r\n $('html, body').animate({\r\n scrollTop: $(this).closest('.product-section').offset().top - topArea - navbar\r\n }, 500); \r\n }); \r\n \r\n // Product card text options\r\n $('.choose-card-text > a').on('click',function() {\r\n if(!$(this).hasClass('selected')) {\r\n $('.choose-card-text > a').removeClass('selected');\r\n if($(this).hasClass('with')) {\r\n $(this).addClass('selected');\r\n }\r\n if($(this).hasClass('without')) {\r\n $(this).addClass('selected');\r\n }\r\n }\r\n }); \r\n \r\n // Order shipping options\r\n $('.shipping-options > a').on('click',function() {\r\n if(!$(this).hasClass('selected')) {\r\n $('.shipping-options > a').removeClass('selected');\r\n if($(this).hasClass('deliver')) {\r\n $(this).addClass('selected');\r\n $('#pickup-content').hide();\r\n $('#delivery-content').show();\r\n }\r\n if($(this).hasClass('pickup')) {\r\n $(this).addClass('selected');\r\n $('#delivery-content').hide();\r\n $('#pickup-content').show();\r\n }\r\n }\r\n }); \r\n\r\n function articleEqualHeight() {\r\n var articleWidth = $('.articles-list .article:not(.horizontal-span-2):first').width();\r\n $('.articles-list .article:not(.vertical-span-2)').height(articleWidth);\r\n }\r\n\r\n articleEqualHeight();\r\n\r\n $(window).resize(function () {\r\n articleEqualHeight();\r\n });\r\n \r\n});\r\n"]}