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