(function () {
    'use strict';
    /* Initialize the main module */
    var Xapp = angular.module('btApp', ['bw.paging', 'btAutoComplete', 'CapturePlus', 'ui.sortable', 'ordinal', 'btImageUtil', 'btImageUtilV2', 'btimageutilcustom', 'btRecommendation','vcRecaptcha']);

    window.app = Xapp;
    Xapp.constant('BASE_URL', window.location.origin);

    window.app.config( function ($httpProvider) {
        $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
        $httpProvider.useApplyAsync(true);

        $httpProvider.interceptors.push(function ($q) {
            return {
                request: function (config) {
                    return config || $q.when(config);
                },
                response: function (response) {

                    //update cookie time to 30 minutes at every request/activity. 
                    var sessionCookie = $.cookie('sid');
                    if (sessionCookie != null && sessionCookie != undefined)
                    {
                        $.removeCookie('sid');
                        $.cookie('sid', sessionCookie, { path: '/', expires: 30 / 1440 });
                    }
                    return response;
                },
                responseError: function (response) {
                    var responseInfo = {
                        status: response.status,
                        statusText: response.statusText,
                        headers: response.headers && response.headers(),
                        data: response.data,
                        config: response.config
                    };
                   
                    if (response.status === 500) {
                        console.log(response)
                    }
                    return $q.reject(response);
                }
            };
        });

    });
})();;
(function () {
    'use strict';

    /**
     * autocomplete
     * Autocomplete directive for AngularJS
     * By Daryl Rowland
     * https://github.com/darylrowland/angucomplete
     */
    var searchid = new Date().getTime();
    angular.module('btAutoComplete', [])
        .directive('btAutoComplete', function ($parse, $http, $sce, $timeout) {
            return {
                restrict: 'EA',
                scope: {
                    "id": "@id",
                    "placeholder": "@placeholder",
                    "selectedObject": "=selectedobject",
                    "url": "@url",
                    "dataField": "@datafield",
                    "titleField": "@titlefield",
                    "descriptionField": "@descriptionfield",
                    "imageField": "@imagefield",
                    "imageUri": "@imageuri",
                    "inputClass": "@inputclass",
                    "userPause": "@pause",
                    "localData": "=localdata",
                    "searchFields": "@searchfields",
                    "minLengthUser": "@minlength",
                    "matchClass": "@matchclass",
                    "returnkeyios": "@returnkeyios"
                },
                template: ' <div class="tfs-search-box">' +
                    '<form method="post" action="{{dynamicUrl}}">' +
                    '<div class="autocomplete-holder">' +
                    '<div class="autocomplete-search-box-container">' +
                    '<div class="mobile-search-back-btn" ng-click="closeSearchDialog()"><svg xmlns="http://www.w3.org/2000/svg" width="10" height="18"><path fill="#1D1258" fill-rule="evenodd" d="M.213 8.486a.712.712 0 000 1.016l8.35 8.255a.842.842 0 00.595.243.844.844 0 00.595-.243.823.823 0 000-1.176L2.08 8.994l7.673-7.582a.822.822 0 000-1.176.868.868 0 00-1.19 0l-8.35 8.25z"/></svg></div>' +
                    '<input title="{{returnkeyios}}" ng-class="{\'bottom-border-radius-none\': ((searching && searchStr.length >= minLength) || (!searching && (results.length == 0 && searchStr.length >= minLength) && showDropdown) || results.length > 0)}" name="txtAutoSearch' + searchid + '"  maxlength="60"  autocomplete="false"  ng-keyup="$event.keyCode == 13 && headerSearch()"  ng-model="searchStr" type="search" placeholder="Search fragrance & beauty" class="typeAheadSearchInput search-textbox search-textbox-mobile" ng-focus="resetHideResults()" ng-blur="hideResults()" autofocus />' +
                    '<div class="input-group-btn-clear" ng-click="clearSearch(true)" ng-if="searchStr.length > 0"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 15 15"><path fill="#999" fill-rule="evenodd" d="M15 14.308a.687.687 0 0 0-.203-.49l-6.318-6.32 6.318-6.315a.688.688 0 0 0 0-.98.709.709 0 0 0-.98 0L7.5 6.52 1.182.203A.688.688 0 0 0 .692 0a.694.694 0 0 0-.49 1.183L6.52 7.499.202 13.818a.694.694 0 0 0 .98.98L7.5 8.48l6.318 6.317a.693.693 0 0 0 1.183-.49"/></svg></div>' +
                    '<div class="input-group-btn-search hidden-xs" ng-class="{\'tfs-btn-disabled\': (searchStr === null || searchStr.length === 0)}" ng-click="headerSearch()"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="#1D1258" fill-rule="evenodd" d="M8.914 16.105h-.04c-3.978 0-7.227-3.233-7.25-7.225a7.169 7.169 0 0 1 2.094-5.11 7.157 7.157 0 0 1 5.096-2.145h.03c3.99 0 7.245 3.223 7.26 7.2.019 3.992-3.208 7.258-7.19 7.28M23.75 23.78a.81.81 0 0 0 .014-1.158c-2.676-2.685-4.564-4.571-6.45-6.459l-.292-.288a77.054 77.054 0 0 0-.851-.839l-.491-.48.107-.142c1.742-2.301 2.326-4.78 1.737-7.366-.81-3.564-3.052-5.856-6.663-6.813a7.716 7.716 0 0 0-.893-.168C9.824.045 9.681.025 9.537 0l-1.38.003c-.113.023-.258.044-.407.067-.313.046-.61.091-.902.17-3.463.923-5.685 3.144-6.607 6.605-.08.294-.124.59-.17.905-.022.148-.045.295-.071.441l.02 1.48c.015.088.03.178.04.268.25 1.872.975 3.476 2.157 4.77 2.257 2.468 5.07 3.427 8.377 2.845 1.373-.244 2.581-.805 3.804-1.767l.14-.111.127.127s4.557 4.57 7.963 7.965a.804.804 0 0 0 1.12.013"/></svg></div>' +
                    '<div ng-style="dropdownHeight" class="autocomplete-dropdown" ng-class="{\'show-block\': ((searching && searchStr.length >= minLength) || (!searching && (results.length == 0 && searchStr.length >= minLength) && showDropdown) || results.length > 0)}">' +
                    '<div class="autocompleting" ng-show="searching && searchStr.length >= minLength">Searching...</div>' +
                    '<div class="autocomplete-searching" ng-show="!searching && (results.length == 0 && searchStr.length >= minLength) && showDropdown">' +
                    '<div class="no-results-header">No results found for "{{searchStr}}"</div>' +
                    '<div class="no-results-header-info">Please check for spelling errors, or try a more general term.</div>' +
                    '</div>' +
                    '<div class="autocomplete-brands" ng-if="brands.length > 0 && results.length > 0 && !searching">' +
                    '<a ng-repeat="brand in brands" class="autocomplete-brands-item" href="{{ brand.slug }}">' +
                    'Shop all <span ng-bind-html="brand.title"></span>' +
                    '</a>' +
                    '</div>' +
                    '<div ng-repeat="result in results" class="autocomplete-results" ng-if="results.length > 0 && $index<resultsToFetch && !searching">' +
                    '<div class="">' +
                    '<a class="tfs-search-link" href="{{result.slug }}">' +
                    '<div class="autocomplete-image-holder" ng-if="imageField">' +
                    '<img ng-srcset="{{result.image}}?h=64 1x, {{result.image}}?h=64&dpr=2 2x" ng-src="{{result.image}}?h=64" alt="{{result.title}}" class="autocomplete-image"/>' +
                    '</div>' +
                    '<div class="autocomplete-title-holder">' +
                    '<div class="autocomplete-title-result" ng-bind-html="result.title"></div>' +
                    '</div>' +
                    '</a>' +
                    '</div>' +
                    '</div>' +
                    '<div class="autocomplete-bestsellers" ng-if="bestSellers.length > 0 && !searching && (results.length == 0 && searchStr.length >= minLength)">You might like some of our bestsellers</div>' +
                    '<div ng-repeat="bestResult in bestSellers" ng-if="bestSellers.length > 0 && !searching && (results.length == 0 && searchStr.length >= minLength)" >' +
                    '<div class="">' +
                    '<a class="tfs-search-link" href="{{bestResult.slug}}">' +
                    '<div class="autocomplete-image-holder" ng-if="imageField">' +
                    '<img ng-srcset="{{bestResult.image}}?h=64 1x, {{bestResult.image}}?h=64&dpr=2 2x" ng-src="{{bestResult.image}}?h=64" alt="bestResult.title" class="autocomplete-image"/>' +
                    '</div>' +
                    '<div class="autocomplete-title-holder">' +
                    '<div class="autocomplete-title-result">{{ bestResult.title }}</div>' +
                    '</div>' +
                    '</a>' +
                    '</div>' +
                    '</div>' +
                    '</div>' +
                    '</div>' +
                    '</div>' +
                    '</form>' +
                    '</div>',

                link: function ($scope, elem, attrs) {
                    $scope.lastSearchTerm = null;
                    $scope.currentIndex = null;
                    $scope.justChanged = false;
                    $scope.searchTimer = null;
                    $scope.hideTimer = null;
                    $scope.searching = false;
                    $scope.pause = 200;
                    $scope.minLength = 2;
                    $scope.searchStr = null;
                    $scope.returnkeyios = "Search";
                    $scope.statWith = '/';
                    $scope.results = [];
                    $scope.bestSellers = [];
                    $scope.brands = [];
                    $scope.brandsToFetch = 3;
                    $scope.resultsToFetch = 10;
                    $scope.bestsellersToFetch = 5;
                    $scope.currentRequest = null;
                    $scope.bestResultsRequest = null;
                    $scope.brandsRequest = null;
                    $scope.showDropdown = false;
                    $scope.dropdownHeight = {"height": "calc(100vh - 66px)"};
                    $scope.dynamicUrl = null;
                    $scope.matchClass = 'autocomplete-highlight';

                    $(document).ready(function () {
                        $(window).on('resize touchstart', function (event) {
                            var attr = $('html').hasClass('overflow-hidden');
                            if (typeof attr !== typeof undefined && attr !== false) {
                                var height = window.innerHeight - 66;
                                $scope.$apply(function () {
                                    $scope.dropdownHeight = {"height": height + "px"};
                                });
                            }
                        }).resize();
                        $(document).on('touchstart', function (event) {
                            var attr = $('html').hasClass('overflow-hidden');
                            if (typeof attr !== typeof undefined && attr !== false) {
                                var target = $(event.target);
                                if ((!target.closest('.typeAheadSearchInput').length && $('.typeAheadSearchInput').is(":visible")) &&
                                    (!target.closest('.input-group-btn-clear').length)) {
                                    $('.typeAheadSearchInput').blur();
                                }
                            }
                        });
                    });

                    $scope.isNewSearchNeeded = function (newTerm, oldTerm) {
                        return newTerm.length >= $scope.minLength && newTerm !== oldTerm;
                    };
                    $scope.headerSearch = function () {
                        if ($scope.searchStr === null || $scope.searchStr.length === 0) {
                            return;
                        }
                        window.location = "//" + window.location.host + "/search?freeText=" + $scope.searchStr.toLowerCase();
                    };

                    $scope.hideResults = function () {
                        var attr = $('html').hasClass('overflow-hidden');
                        // For some browsers, `attr` is undefined; for others,
                        // `attr` is false.  Check for both.
                        if (typeof attr === typeof undefined || attr === false) {
                            $scope.hideTimer = $timeout(function () {
                                $scope.clearSearch(false);
                            }, $scope.pause);
                        }
                    };

                    $scope.closeSearchDialog = function () {
                        var containerMobile = $('.mobileSearch');
                        var containerDesktop = $('.tfs-header-search-bar');
                        if (containerMobile.hasClass('active')) {
                            containerMobile.removeClass("active");
                            containerMobile.find('.typeAheadSearchInput').blur();
                        }
                        if (containerDesktop.hasClass('active')) {
                            containerDesktop.removeClass("active");
                            containerDesktop.find('.typeAheadSearchInput').blur();
                        }
                        $('html, body').removeClass('overflow-hidden');
                        $scope.clearSearch(false);
                    };

                    $scope.resetHideResults = function () {
                        if ($scope.hideTimer) {
                            $timeout.cancel($scope.hideTimer);
                        }
                    };

                    $scope.applyMatchClass = function (text, lookup) {
                        var re = new RegExp(lookup, 'i');
                        var strPart = text.match(re);
                        if (strPart === null) {
                            text = $sce.trustAsHtml(text);
                        } else {
                            text = $sce.trustAsHtml(text.replace(re, '<span class="' + $scope.matchClass + '">' + strPart[0] + '</span>'));
                        }
                        return text;
                    };

                    $scope.clearSearch = function (focus) {
                        $scope.searchStr = null;
                        $scope.lastSearchTerm = null;
                        $scope.showDropdown = false;
                        $scope.currentIndex = null;
                        $scope.results = [];
                        $scope.brands = [];
                        $scope.bestSellers = [];
                        $timeout.cancel($scope.searchTimer);
                        $timeout.cancel($scope.hideTimer);
                        if ($scope.currentRequest != null) {
                            $scope.currentRequest.abort();
                        }
                        if ($scope.brandsRequest != null) {
                            $scope.brandsRequest.abort();
                        }
                        $scope.searching = false;
                        if (focus === true) {
                            $('.typeAheadSearchInput').focus();
                        }
                    };
                    $scope.getBestResults = function () {
                        if ($scope.bestSellers.length > 0) {
                            return;
                        }
                        $scope.bestResultsRequest = $.ajax({
                            type: 'GET',
                            url: '/json/bestsellers',
                            beforeSend: function () {
                                if ($scope.bestResultsRequest != null) {
                                    $scope.bestResultsRequest.abort();
                                }
                            },
                            success: function (data) {
                                // Success
                                if (!data) {
                                    return;
                                }
                                $scope.$apply(function () {
                                    $scope.bestSellers = data.map(function (ele) {
                                        var link = (ele.slug.charAt(0) === '/') ? ele.slug : '/' + ele.slug;
                                        return {
                                            title: ele.brand + ' ' + ele.subBrand + ' ' + ele.name,
                                            slug: link,
                                            image: ele.image
                                        };
                                    }).slice(0, $scope.bestsellersToFetch);
                                    $scope.searching = false;
                                    $scope.showDropdown = true;
                                });
                            },
                            error: function (e) {
                                // Error
                                // console.log("error");
                            }
                        });
                    };

                    $scope.getBrands = function (str) {
                        if (str.length >= $scope.minLength) {
                            $scope.brandsRequest = $.ajax({
                                type: 'GET',
                                url: '/json/brands?q=' + str,
                                beforeSend: function () {
                                    if ($scope.brandsRequest != null) {
                                        $scope.brandsRequest.abort();
                                    }
                                },
                                success: function (data) {
                                    // Success
                                    if (!data) {
                                        return;
                                    }
                                    $scope.$apply(function () {
                                        $scope.brands = data.map(function (ele) {
                                            var link = (ele.link.charAt(0) === '/') ? ele.link : '/' + ele.link;
                                            return {
                                                title: $scope.applyMatchClass(ele.manufacturerName, str),
                                                slug: link
                                            };
                                        }).slice(0, $scope.brandsToFetch);
                                    });
                                },
                                error: function (e) {
                                    // Error
                                }
                            });
                        }
                    };

                    $scope.processResults = function (responseData, str) {
                        if (responseData && responseData.length > 0) {
                            $scope.results = responseData.map(function (result) {
                                var link = (result.slug.charAt(0) === '/') ? result.slug : '/' + result.slug;
                                return {
                                    title: $scope.applyMatchClass(result.name, str),
                                    slug: link,
                                    image: result.image
                                }
                            });
                        } else {
                            $scope.getBestResults();
                            $scope.results = [];
                        }
                        $scope.searching = false;
                        $scope.showDropdown = true;
                        PubSub.publish("search", str, responseData);
                    };
                    PubSub.subscribe('search', function (searchKey, eventData) {

                        var HeroProcess = window.HeroProcess || null;
                        if (HeroProcess)
                            HeroProcess.HeroSearchTransmitter(searchKey);

                        if (eventData != null && dataLayer && typeof omnilytics != 'undefined' && omnilytics) {
                            var data = dataLayer[0];
                            var entity = {'FreeText': searchKey, 'ResultCount': eventData.length};
                            data["Entity"] = JSON.stringify(entity);
                            data["EntityId"] = searchKey;
                            data["EntityName"] = searchKey;
                            data["EntityType"] = "Search";
                            data["EventType"] = "Search";
                            data["Action"] = "search";
                            dataLayer[0] = data;
                            omnilytics.emit('Search', null);

                        }
                    });
                    $scope.getSearchResults = function (str) {
                        if (str.length >= $scope.minLength) {
                            $scope.currentRequest = $.ajax({
                                type: 'GET',
                                url: $scope.url + str,
                                beforeSend: function () {
                                    if ($scope.currentRequest != null) {
                                        $scope.currentRequest.abort();
                                    }
                                },
                                success: function (responseData) {
                                    // Success
                                    $scope.$apply(function () {
                                        if (!responseData) {
                                            $scope.getBestResults();
                                            $scope.results = [];
                                            return;
                                        }
                                        $scope.processResults(responseData.products, str);
                                    });
                                },
                                error: function (e) {
                                    // Error 500 sometimes is returned when server thinks it's a SQL injection attack
                                    // We can still fetch best sellers in that case
                                    if (e.status === 500) {
                                        $scope.getBestResults();
                                        $scope.results = [];
                                    }
                                }
                            });
                        }
                    };

                    $scope.keyPressed = function (event) {
                        $scope.$apply(function (event) {
                            $scope.searching = true;
                            
                                if ($scope.searchStr != null && $scope.searchStr.length > 0) {
                                    $scope.dynamicUrl = "//" + window.location.host + "/search?freeText=" + $scope.searchStr.toLowerCase();
                            }
                            if (event.which !== 13) {
                                if (!$scope.searchStr || $scope.searchStr.length === 0) {
                                    $scope.clearSearch(false);
                                } else if ($scope.searchStr.length < $scope.minLength) {
                                    $scope.results = [];
                                    $scope.brands = [];
                                    if ($scope.currentRequest != null) {
                                        $scope.currentRequest.abort();
                                    }
                                    if ($scope.brandsRequest != null) {
                                        $scope.brandsRequest.abort();
                                    }
                                    $scope.searching = false;
                                } else if ($scope.searchStr.length >= $scope.minLength) {
                                    clearTimeout($scope.searchTimer);
                                    $scope.lastSearchTerm = $scope.searchStr;
                                    $scope.currentIndex = null;
                                    $scope.results = [];
                                    $scope.brands = [];
                                    $scope.searchTimer = setTimeout(function () {
                                        $scope.getBrands($scope.searchStr);
                                        $scope.getSearchResults($scope.searchStr);
                                    }, $scope.pause);
                                }
                            } else {
                                event.preventDefault();
                            }
                        });
                    };

                    elem.find('input').on('keyup', $scope.keyPressed);
                }
            };
        });

}());
;
(function () {
    'use strict';
    angular.module('btImageUtil', [])
        .directive('btImageUtil', function ($parse, $http, $sce) {
            return {
                restrict: 'EA',
                scope: {
                    "imageUrl": "@imageurl",
                    "itemName": "@itemname",
                    "imageType": "@imagetype",
                },
                template: '<picture ng-if="imageUrl!=\'\'">' +
                    '<source media="(min-width: 1440px)" data-srcset="{{imageUrl}}?h={{imageUtil.HiRes_H}}&w={{imageUtil.HiRes_W}}&min-w={{imageUtil.HiRes_W}}&min-h={{imageUtil.HiRes_H}} 1x, {{imageUrl}}?h={{imageUtil.HiRes_H}}&w={{imageUtil.HiRes_W}}&min-w={{imageUtil.HiRes_W}}&min-h={{imageUtil.HiRes_H}}&dpr=2 2x">' +
                    '<source media="(min-width: 1200px)" data-srcset="{{imageUrl}}?h={{imageUtil.Desktop_H}}&w={{imageUtil.Desktop_W}}&min-w={{imageUtil.Desktop_W}}&min-h={{imageUtil.Desktop_H}} 1x, {{imageUrl}}?h={{imageUtil.Desktop_H}}&w={{imageUtil.Desktop_W}}&min-w={{imageUtil.Desktop_W}}&min-h={{imageUtil.Desktop_H}}&dpr=2 2x">' +
                    '<source media="(min-width: 768px)" data-srcset="{{imageUrl}}?h={{imageUtil.Tablet_H}}&w={{imageUtil.Tablet_W}}&min-w={{imageUtil.Tablet_W}}&min-h={{imageUtil.Tablet_H}} 1x, {{imageUrl}}?h={{imageUtil.Tablet_H}}&w={{imageUtil.Tablet_W}}&min-w={{imageUtil.Tablet_W}}&min-h={{imageUtil.Tablet_H}}&dpr=2 2x">' +
                    '<source media="(min-width: 480px)" data-srcset="{{imageUrl}}?h={{imageUtil.Mobile_H}}&w={{imageUtil.Mobile_W}}&min-w={{imageUtil.Mobile_W}}&min-h={{imageUtil.Mobile_H}} 1x, {{imageUrl}}?h={{imageUtil.Mobile_H}}&w={{imageUtil.Mobile_W}}&min-w={{imageUtil.Mobile_W}}&min-h={{imageUtil.Mobile_H}}&dpr=2 2x">' +
                    '<img data-src="{{imageUrl}}?h={{imageUtil.Mobile_H}}&w={{imageUtil.Mobile_W}}&min-w={{imageUtil.Mobile_W}}&min-h={{imageUtil.Mobile_H}}" data-srcset="{{imageUrl}}?h={{imageUtil.Mobile_H}}&w={{imageUtil.Mobile_W}}&min-w={{imageUtil.Mobile_W}}&min-h={{imageUtil.Mobile_H}} 1x, {{imageUrl}}?h={{imageUtil.Mobile_H}}&w={{imageUtil.Mobile_W}}&min-w={{imageUtil.Mobile_W}}&min-h={{imageUtil.Mobile_H}}&dpr=2 2x" alt="{{itemName}}" class="image1 omni-img lazyload">' +
                    '</picture>' +
                    '<img  ng-if="imageUrl==\'\'" data-src="/assets/theme/tfs/images/noimagefound.jpg" alt="{{itemName}}" class="img-responsive omni-img lazyload"/ >',
                link: function ($scope, elem, attrs) {
                    $scope.imageUrl = attrs.imageurl;
                    $scope.itemName = attrs.itemname;
                    $scope.imageType = attrs.imagetype;

                    $scope.imageUtil = imageUtils.filter(function (item) {
                        return item.ImageType === $scope.imageType;
                    })[0];

                    $scope.$watch("imageUrl", function (newValue, oldValue) {
                        //This gets called when data changes.
                        if (oldValue !== newValue) {
                            const img = elem.find('img');
                            if (img && img.hasClass('lazyloaded')) {
                                img.removeClass('lazyloaded');
                                img.addClass('ls-reloading');
                                img.addClass('lazyload');
                            }
                        }
                    });
                }
            };
        });

}());;
(function () {
    'use strict';
    angular.module('btimageutilcustom', [])
        .directive('btimageutilcustom', function ($parse, $http, $sce) {
            return {
                restrict: 'A',
                template: '<picture>' +
                    ' <source media="(min-width: 1440px)" data-srcset="{{imageUrl}}?h={{imageUtil.HiRes_H}}&w={{imageUtil.HiRes_W}}">' +
                    '<source media="(min-width: 1200px)" data-srcset="{{imageUrl}}?h={{imageUtil.Desktop_H}}&w={{imageUtil.Desktop_W}}">' +
                    '<source media="(min-width: 768px)" data-srcset="{{imageUrl}}?h={{imageUtil.Tablet_H}}&w={{imageUtil.Tablet_W}}">' +
                    '<source media="(min-width: 480px)" data-srcset="{{imageUrl}}?h={{imageUtil.Mobile_H}}&w={{imageUtil.Mobile_W}}">' +
                    '<img data-src="{{imageUrl}}?h={{imageUtil.Mobile_H}}&w={{imageUtil.Mobile_W}}" alt="{{itemName}}" class="image1 omni-img lazyload">' +
                    '</picture>',
                replace: true,
                scope: true,
                link: function ($scope, elem, attrs) {
                    $scope.imageUrl = attrs.src;
                    $scope.imageUtil = {
                        HiRes_H: attrs.hiresH, HiRes_W: attrs.hiresW,
                        Desktop_H: attrs.desktopH, Desktop_W: attrs.desktopW,
                        Tablet_H: attrs.tabletH, Tablet_W: attrs.tabletW,
                        Mobile_H: attrs.mobileH, Mobile_W: attrs.mobileW
                    };
                }
            };
        });

}());;
(function () {
    'use strict';
    angular.module('btImageUtilV2', [])
        .directive('btImageUtilV2', function ($parse, $http, $sce) {
            return {
                restrict: 'EA',
                scope: {
                    "imageUrl": "@imageurl",
                    "itemName": "@itemname",
                    "imageType": "@imagetype",
                },
                template: '<picture ng-if="imageUrl!=\'\'">' +
                    '<source media="(min-width: 1440px)" srcset="{{imageUrl}}?h={{imageUtil.HiRes_H}}&w={{imageUtil.HiRes_W}}&min-w={{imageUtil.HiRes_W}}&min-h={{imageUtil.HiRes_H}}&dpr=2 2x, {{imageUrl}}?h={{imageUtil.HiRes_H}}&w={{imageUtil.HiRes_W}}&min-w={{imageUtil.HiRes_W}}&min-h={{imageUtil.HiRes_H}} 1x">' +
                    '<source media="(min-width: 1200px)" srcset="{{imageUrl}}?h={{imageUtil.Desktop_H}}&w={{imageUtil.Desktop_W}}&min-w={{imageUtil.Desktop_W}}&min-h={{imageUtil.Desktop_H}}&dpr=2 2x, {{imageUrl}}?h={{imageUtil.Desktop_H}}&w={{imageUtil.Desktop_W}}&min-w={{imageUtil.Desktop_W}}&min-h={{imageUtil.Desktop_H}} 1x">' +
                    '<source media="(min-width: 768px)" srcset="{{imageUrl}}?h={{imageUtil.Tablet_H}}&w={{imageUtil.Tablet_W}}&min-w={{imageUtil.Tablet_W}}&min-h={{imageUtil.Tablet_H}} 2x, {{imageUrl}}?h={{imageUtil.Tablet_H}}&w={{imageUtil.Tablet_W}}&min-w={{imageUtil.Tablet_W}}&min-h={{imageUtil.Tablet_H}} 1x">' +
                    '<source media="(min-width: 480px)" srcset="{{imageUrl}}?h={{imageUtil.Mobile_H}}&w={{imageUtil.Mobile_W}}&min-w={{imageUtil.Mobile_W}}&min-h={{imageUtil.Mobile_H}} 2x, {{imageUrl}}?h={{imageUtil.Mobile_H}}&w={{imageUtil.Mobile_W}}&min-w={{imageUtil.Mobile_W}}&min-h={{imageUtil.Mobile_H}} 1x">' +
                    '<img data-src="{{imageUrl}}?h={{imageUtil.Mobile_H}}&w={{imageUtil.Mobile_W}}&min-w={{imageUtil.Mobile_W}}&min-h={{imageUtil.Mobile_H}}&dpr=2" srcset="{{imageUrl}}?h={{imageUtil.Mobile_H}}&w={{imageUtil.Mobile_W}}&min-w={{imageUtil.Mobile_W}}&min-h={{imageUtil.Mobile_H}}&dpr=2 2x, {{imageUrl}}?h={{imageUtil.Mobile_H}}&w={{imageUtil.Mobile_W}}&min-w={{imageUtil.Mobile_W}}&min-h={{imageUtil.Mobile_H}} 1x" alt="{{itemName}}" class="image1 omni-img lazyload">' +
                    '</picture> ' +
                    '<img ng-if="imageUrl==\'\'" data-src="/assets/theme/tfs/images/noimagefound.jpg"  alt="{{itemName}}" class="img-responsive omni-img lazyload"/ >',
                link: function ($scope, elem, attrs) {
                    $scope.imageUrl = attrs.imageurl;
                    $scope.itemName = attrs.itemname;
                    $scope.imageType = attrs.imagetype;

                    $scope.imageUtil = imageUtils.filter(function (item) {
                        return item.ImageType === $scope.imageType;
                    })[0];
                }
            };
        });

}());;
(function () {
    'use strict';
    angular.module('btRecommendation', [])
        .directive('btRecommendation', function ($parse, $http, $sce, $timeout) {
            return {
                restrict: 'EA',
                scope: {
                    "itemId": "@itemid",
                    "userId": "@userid",
                    "type": "@type",
                    "title": "@title",
                    "noOfItems": "@noofitems",
                    "displayRRPDiscountLabelOn": "@displayrrpdiscountlabelon"
                },
                controller: 'globalCtrl',
                controllerAs: 'gm',
                template: ' <div class="col-sm-12 col-xs-12 gridView"> ' +
                ' <div ng-repeat="prod in recommendProducts" class="col-md-5ths col-sm-5ths col-xs-5ths col-lg-5ths resultContainerRelated ng-scope" > ' +
                '<div class="product-container-panel"> ' +
                '<div class="imagePanel"> ' +
                '<a ng-href="/{{prod.slug}}?rvw=1"> ' +
                '<span class="tooltiptext ng-binding"></span> ' +
                '<bt-image-util imagetype="Product_List_Product_Image" itemname="{{prod.name}}" imageurl="{{prod.image}}" /> ' +
                '</a>' +
                '</div>' +
                '<div class="dataPanel"> ' +
                '<div class="ribbon-info">' +
                '<a ng-href="/{{prod.slug}}?rvw=1"> ' +
                '<span class="brand" ng-bind="prod.brand"></span> ' +
                '<span class="subbrand" ng-bind="prod.subBrand"></span> ' +
                '<span class="product-tfs" ng-bind="prod.name"></span> ' +
                '</a>' +
                '</div>' +
                '<div class="price-info"> ' +
                '<div class="col-sm-8 col-xs-12 no-padding"> ' +
                '<h3> ' +
                    '<span ng-hide="showChangedCurrency" class="ng-binding" ng-bind="prod.price.formatted.withTax"></span> ' +
                    '<span ng-show="showChangedCurrency" class="ng-binding" ng-bind="prod.currencyExchangePrice"></span> ' +
                    '<span  ng-if="!showChangedCurrency && prod.displayRRP" class="sml ng-binding" ng-bind="prod.listPrice.formatted.withTax"></span> ' +
                    '<span ng-if="prod.displayRRP && showChangedCurrency" class="sml ng-binding" ng-bind="prod.currencyExchangeListPrice"></span> ' +
                '</h3> ' +
                '</div> ' +
                '</div> ' +
                '<div class="action-info">' +
                '<button ng-controller=\'globalCtrl as gm\'" ng-if="prod.subscriptionPlanType == \'None\'" type="submit" class="btn-primary animate btn-xl pull-left width-full cart-add-btn recaddtobasket" ng-click="gm.offerCategoryName=prod.classification.mainCategoryName;gm.addToBasket(prod.recordId,1,0)" data-attr=\'{ "id": "{{prod.recordId}}","name":"{{prod.brand}} {{prod.subBrand}}","image":"{{prod.image}}","price":{{prod.priceFrom.raw.withTax}},"brand":"{{prod.brand}}","category":"{{prod.classification.mainCategoryName}}","variant":"{{ prod.name }}","stockCode":"{{ prod.stockCode }}"}\' >Add to Bag</button >' +
                '<button ng-controller=\'subscriptionCtrl as sm\'" ng-if="prod.subscriptionPlanType != \'None\'" type="submit" class="btn-pink animate btn-xl pull-left width-full cart-add-btn recaddtobasket" ng-click="gm.offerCategoryName=prod.classification.mainCategoryName;sm.addSubscriptionToBasket(prod.recordId)"  data-attr=\'{ "id": "{{prod.recordId}}","name":"{{prod.brand}} {{prod.subBrand}}","image":"{{prod.image}}","price":{{prod.priceFrom.raw.withTax}},"brand":"{{prod.brand}}","category":"{{prod.classification.mainCategoryName}}","variant":"{{ prod.name }},"stockCode":"{{ prod.stockCode }}"}\' >Add To Scentaddict List</button >' +
                //'<input type="text">{{prod}}<input>' +
                '</div >' +
                '</div> ' +
                '</div> ' +
                '</div> ' +
                '</div>',
                link: function ($scope, elem, attrs) {

                    $scope.recommendProducts = null;

                    $scope.userId = "";
                    if (attrs.userid) {
                        $scope.userId = attrs.userid;
                    }
                    if (attrs.productdata) {
                        $scope.recommendProducts = userProducts;
                    }

                    var CURRENCY_COOKIE = '_ctcc';
                    $scope.recommendTypes = { Home: "Home", Product: "Product", Basket: "Basket", Personalised: "Personalised", Order: "Order", Promotion: "Promotion", NewForYou: "NewForYou", Popular: "Popular", RecentView: "RecentView" };
                    $http.post('/tfsrecomendation/getrecommendations', { itemId: $scope.itemId, recommedType: $scope.type, noOfItems: $scope.noOfItems, userId: $scope.userId }
                    ).success(function (resp) {
                        $scope.recommendProducts = resp;
                        if ($scope.recommendProducts != null) {
                            angular.forEach($scope.recommendProducts, function (recom) {
                                if ((recom.listPrice.raw.withTax - recom.price.raw.withTax) >= $scope.displayRRPDiscountLabelOn) {
                                    recom.displayRRP = true;
                                }
                                else {
                                    recom.displayRRP = false;
                                }
                              });
                            $scope.showChangedCurrency = false;
                            var changeToCurrencyCode = $.cookie(CURRENCY_COOKIE);
                            if (changeToCurrencyCode) {
                                $http.get('/Home/GetCurrencyExchangeRate' + "?changeToCurrencyCode=" + changeToCurrencyCode).then(function (resp) {
                                    if (resp != null && resp.data != false && resp.data.rate != 1) {
                                        $scope.showChangedCurrency = true;
                                        $scope.selectedCurrencySymbol = resp.data.currencySymbol;
                                        $scope.currencyExchangeRate = resp.data.rate;
                                        angular.forEach($scope.recommendProducts, function (recom) {
                                            recom.currencyExchangePrice = $scope.selectedCurrencySymbol + (recom.price.raw.withTax * resp.data.rate).toFixed(2);
                                            recom.currencyExchangeListPrice = $scope.selectedCurrencySymbol + (recom.listPrice.raw.withTax * resp.data.rate).toFixed(2);
                                        });
                                    }
                                    else
                                        $scope.showChangedCurrency = false;
                                    $.cookie("_ctcc", changeToCurrencyCode, { path: '/', expires: 1000 });
                                });
                            }
                        }
                    }).error(function (err) { console.log(err) });
                }
            };
        });

}());;
/*global angular, DocumentTouch*/
(function () {
    'use strict';

    window.app.directive('ngMagnify', ngMagnify);

    function ngMagnify() {
    return {
      restrict: 'EA',
      replace: true,
      template: '<div class="magnify-container" data-ng-style="getContainerStyle()">' +
                  '<div class="magnify-glass" data-ng-style="getGlassStyle()"></div>' +
                  '<img class="magnify-image" alt="Product" data-ng-src="{{ imageSrc }}"/>' +
                '</div>',
      scope: {
        imageSrc: '@',
        imageWidth: '=',
        imageHeight: '=',
        glassWidth: '=',
        glassHeight: '='
      },
      link: function (scope, element, attrs) {
        var glass = element.find('div'),
          image = element.find('img'),
          el, nWidth, nHeight;

        scope.getContainerStyle = function () {
          return {
            width: (scope.imageWidth) ? scope.imageWidth + 'px' : '',
            height: (scope.imageHeight) ? scope.imageHeight + 'px' : ''
          };
        };

        scope.getGlassStyle = function () {
          return {
            background: 'url(' + scope.imageSrc + ') no-repeat',
            width: (scope.glassWidth) ? scope.glassWidth + 'px' : '',
            height: (scope.glassHeight) ? scope.glassHeight + 'px' : ''
          };
        };

        // if touch devices, do something
        if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
          return;
        }
        element.on('mouseenter', function () {
          el = angular.extend(getOffset(element[0]), {
            width: element[0].offsetWidth,
            height: element[0].offsetHeight
          });
        })
        .on('mousemove', function (evt) {
          if (magnify(evt)) {
            glass.css( magnify(evt) );
          }
        })
        .on('mouseout', function () {
          glass.on('mouseleave', function () {
            glass.css('display', 'none');
          });
        });

        function magnify (evt) {
          var mx, my, rx, ry, px, py, bgp, img;

          if (!nWidth && !nHeight) {
            img = new Image();
            img.onload = function () {
              nWidth = img.width;
              nHeight = img.height;
            };
            img.src = scope.imageSrc;
          } else {
            // IE8 uses evt.x and evt.y
            mx = (evt.pageX) ? (evt.pageX - el.left) : evt.x;
            my = (evt.pageY) ? (evt.pageY - el.top) : evt.y;

            if (mx < el.width && my < el.height && mx > 0 && my > 0) {
              glass.css('display', 'block');
            } else {
              glass.css('display', 'none');
              return;
            }

            rx = Math.round(mx/image[0].offsetWidth*nWidth - glass[0].offsetWidth/2)*-1;
            ry = Math.round(my/image[0].offsetHeight*nHeight - glass[0].offsetHeight/2)*-1;
            bgp = rx + 'px ' + ry + 'px';

            px = mx - glass[0].offsetWidth/2;
            py = my - glass[0].offsetHeight/2;

            // glass.css({ left: px+'px', top: py+'px', backgroundPosition: bgp });
            return { left: px+'px', top: py+'px', backgroundPosition: bgp };
          }
          return;
        }

        function getOffset (el) {
          var offsetLeft = 0,
            offsetTop = 0;

          do {
            if (!isNaN(el.offsetLeft)) {
              offsetLeft += el.offsetLeft;
              offsetTop += el.offsetTop;
            }
          } while (el = el.offsetParent);

          return {
            left: offsetLeft,
            top: offsetTop
          };
        }
      }
    };
  };
})();;
(function () {
	'use strict';

	window.app.directive('formGroupValidation', formGroupValidation);

	function formGroupValidation() {
		return {
			require: '^form',
			replace: true,
			transclude: true,
			template:
				'<div class="has-feedback" ng-class="vm.getValidationClass()">' +
					'<ng-transclude></ng-transclude>' +
					'<input-validation-icons field="vm.field"></input-validation-icons>' +
				'</div>',
			scope: {
				field: '@formGroupValidation'
			},
			controller: controller,
			controllerAs: 'vm',
			link: function (scope, element, attrs, formCtrl) {
				scope.form = formCtrl;
			}
		}
	}

	controller.$inject = ['$scope'];
	function controller($scope) {
		var vm = this;

		vm.field = $scope.field;
		vm.getValidationClass = getValidationClass;

		function getValidationClass() {
			if (!canBeValidated()) return '';

			if (isValid()) return 'has-success';

			return 'has-error';
		}

		function canBeValidated() {
		    if ($scope.form[vm.field] === undefined) return false;
			return ($scope.form[vm.field].$touched || $scope.form.$submitted);
		}

		function isValid() {
			return $scope.form[vm.field].$valid;
		}
	}

})();;
/*
 * Lazy Load Product Images. For use on angular modules only.
 */
(function () {
  function lazyLoad() {

    return {
      link: function (scope, element, attr) {
        scope.productImages = document.querySelectorAll(".c-product-item__img-container__img");

        // create an instance of IntersectionObserver
        //prodWatcher = new IntersectionObserver(function (entries) {
        //  scope.entries = entries;
        //  for (var i = 0, length = scope.entries.length; i < length; i++) {
        //    //when image comes into view, attempt to load image.

        //    if (scope.entries[i].intersectionRatio > 0) {
        //      loadImage(scope.entries[i].target);
        //      prodWatcher.unobserve(entries[i].target);
        //    }

        //  }
        //});
       

        //for (var i = 0, length = scope.productImages.length; i < length; i++) {
        //  prodWatcher.observe(scope.productImages[i]);
        //}

        function loadImage(image) {
          var src = image.getAttribute("data-src");
          
          image.setAttribute("src", src);
          image.onerror = function () {
              image.setAttribute("src", "/assets/theme/tfs/images/noimagefound.jpg");
          }
          
        }

      }

    }
  };
  window.app.directive('lazyLoad', lazyLoad);
})(window.app);
;
/*
 jQuery UI Sortable plugin wrapper

 @param [ui-sortable] {object} Options to pass to $.fn.sortable() merged onto ui.config
 */
angular.module('ui.sortable', [])
  .value('uiSortableConfig', {
      // the default for jquery-ui sortable is "> *", we need to restrict this to
      // ng-repeat items
      // if the user uses
      items: '> [ng-repeat],> [data-ng-repeat],> [x-ng-repeat]'
  })
  .directive('uiSortable', [
    'uiSortableConfig', '$timeout', '$log',
    function (uiSortableConfig, $timeout, $log) {
        return {
            require: '?ngModel',
            scope: {
                ngModel: '=',
                uiSortable: '='
            },
            link: function (scope, element, attrs, ngModel) {
                var savedNodes;

                function combineCallbacks(first, second) {
                    var firstIsFunc = first && (typeof first === 'function');
                    var secondIsFunc = second && (typeof second === 'function');
                    if (firstIsFunc && secondIsFunc) {
                        return function () {
                            first.apply(this, arguments);
                            second.apply(this, arguments);
                        };
                    } else if (secondIsFunc) {
                        return second;
                    }
                    return first;
                }

                function getSortableWidgetInstance(element) {
                    // this is a fix to support jquery-ui prior to v1.11.x
                    // otherwise we should be using `element.sortable('instance')`
                    var data = element.data('ui-sortable');
                    if (data && typeof data === 'object' && data.widgetFullName === 'ui-sortable') {
                        return data;
                    }
                    return null;
                }

                function patchSortableOption(key, value) {
                    if (callbacks[key]) {
                        if (key === 'stop') {
                            // call apply after stop
                            value = combineCallbacks(
                              value, function () { scope.$apply(); });

                            value = combineCallbacks(value, afterStop);
                        }
                        // wrap the callback
                        value = combineCallbacks(callbacks[key], value);
                    } else if (wrappers[key]) {
                        value = wrappers[key](value);
                    }

                    // patch the options that need to have values set
                    if (!value) {
                        if (key === 'items') {
                            value = uiSortableConfig.items;
                        } else if (key === 'ui-model-items') {
                            value = uiSortableConfig.items;
                        }
                    }

                    return value;
                }

                function patchUISortableOptions(newVal, oldVal, sortableWidgetInstance) {
                    function addDummyOptionKey(value, key) {
                        if (!(key in opts)) {
                            // add the key in the opts object so that
                            // the patch function detects and handles it
                            opts[key] = null;
                        }
                    }
                    // for this directive to work we have to attach some callbacks
                    angular.forEach(callbacks, addDummyOptionKey);

                    // only initialize it in case we have to
                    // update some options of the sortable
                    var optsDiff = null;

                    if (oldVal) {
                        // reset deleted options to default
                        var defaultOptions;
                        angular.forEach(oldVal, function (oldValue, key) {
                            if (!newVal || !(key in newVal)) {
                                if (key in directiveOpts) {
                                    if (key === 'ui-floating') {
                                        opts[key] = 'auto';
                                    } else {
                                        opts[key] = patchSortableOption(key, undefined);
                                    }
                                    return;
                                }

                                if (!defaultOptions) {
                                    defaultOptions = angular.element.ui.sortable().options;
                                }
                                var defaultValue = defaultOptions[key];
                                defaultValue = patchSortableOption(key, defaultValue);

                                if (!optsDiff) {
                                    optsDiff = {};
                                }
                                optsDiff[key] = defaultValue;
                                opts[key] = defaultValue;
                            }
                        });
                    }

                    // update changed options
                    angular.forEach(newVal, function (value, key) {
                        // if it's a custom option of the directive,
                        // handle it approprietly
                        if (key in directiveOpts) {
                            if (key === 'ui-floating' && (value === false || value === true) && sortableWidgetInstance) {
                                sortableWidgetInstance.floating = value;
                            }

                            opts[key] = patchSortableOption(key, value);
                            return;
                        }

                        value = patchSortableOption(key, value);

                        if (!optsDiff) {
                            optsDiff = {};
                        }
                        optsDiff[key] = value;
                        opts[key] = value;
                    });

                    return optsDiff;
                }

                function getPlaceholderElement(element) {
                    var placeholder = element.sortable('option', 'placeholder');

                    // placeholder.element will be a function if the placeholder, has
                    // been created (placeholder will be an object).  If it hasn't
                    // been created, either placeholder will be false if no
                    // placeholder class was given or placeholder.element will be
                    // undefined if a class was given (placeholder will be a string)
                    if (placeholder && placeholder.element && typeof placeholder.element === 'function') {
                        var result = placeholder.element();
                        // workaround for jquery ui 1.9.x,
                        // not returning jquery collection
                        result = angular.element(result);
                        return result;
                    }
                    return null;
                }

                function getPlaceholderExcludesludes(element, placeholder) {
                    // exact match with the placeholder's class attribute to handle
                    // the case that multiple connected sortables exist and
                    // the placeholder option equals the class of sortable items
                    var notCssSelector = opts['ui-model-items'].replace(/[^,]*>/g, '');
                    var excludes = element.find('[class="' + placeholder.attr('class') + '"]:not(' + notCssSelector + ')');
                    return excludes;
                }

                function hasSortingHelper(element, ui) {
                    var helperOption = element.sortable('option', 'helper');
                    return helperOption === 'clone' || (typeof helperOption === 'function' && ui.item.sortable.isCustomHelperUsed());
                }

                function getSortingHelper(element, ui, savedNodes) {
                    var result = null;
                    if (hasSortingHelper(element, ui) &&
                        element.sortable('option', 'appendTo') === 'parent') {
                        // The .ui-sortable-helper element (that's the default class name)
                        // is placed last.
                        result = savedNodes.last();
                    }
                    return result;
                }

                // thanks jquery-ui
                function isFloating(item) {
                    return (/left|right/).test(item.css('float')) || (/inline|table-cell/).test(item.css('display'));
                }

                function getElementScope(elementScopes, element) {
                    var result = null;
                    for (var i = 0; i < elementScopes.length; i++) {
                        var x = elementScopes[i];
                        if (x.element[0] === element[0]) {
                            result = x.scope;
                            break;
                        }
                    }
                    return result;
                }

                function afterStop(e, ui) {
                    ui.item.sortable._destroy();
                }

                // return the index of ui.item among the items
                // we can't just do ui.item.index() because there it might have siblings
                // which are not items
                function getItemIndex(ui) {
                    return ui.item.parent()
                      .find(opts['ui-model-items'])
                      .index(ui.item);
                }

                var opts = {};

                // directive specific options
                var directiveOpts = {
                    'ui-floating': undefined,
                    'ui-model-items': uiSortableConfig.items
                };

                var callbacks = {
                    receive: null,
                    remove: null,
                    start: null,
                    stop: null,
                    update: null
                };

                var wrappers = {
                    helper: null
                };

                angular.extend(opts, directiveOpts, uiSortableConfig, scope.uiSortable);

                if (!angular.element.fn || !angular.element.fn.jquery) {
                    $log.error('ui.sortable: jQuery should be included before AngularJS!');
                    return;
                }

                function wireUp() {
                    // When we add or remove elements, we need the sortable to 'refresh'
                    // so it can find the new/removed elements.
                    scope.$watchCollection('ngModel', function () {
                        // Timeout to let ng-repeat modify the DOM
                        $timeout(function () {
                            // ensure that the jquery-ui-sortable widget instance
                            // is still bound to the directive's element
                            if (!!getSortableWidgetInstance(element)) {
                                element.sortable('refresh');
                            }
                        }, 0, false);
                    });

                    callbacks.start = function (e, ui) {
                        if (opts['ui-floating'] === 'auto') {
                            // since the drag has started, the element will be
                            // absolutely positioned, so we check its siblings
                            var siblings = ui.item.siblings();
                            var sortableWidgetInstance = getSortableWidgetInstance(angular.element(e.target));
                            sortableWidgetInstance.floating = isFloating(siblings);
                        }

                        // Save the starting position of dragged item
                        var index = getItemIndex(ui);
                        ui.item.sortable = {
                            model: ngModel.$modelValue[index],
                            index: index,
                            source: ui.item.parent(),
                            sourceModel: ngModel.$modelValue,
                            cancel: function () {
                                ui.item.sortable._isCanceled = true;
                            },
                            isCanceled: function () {
                                return ui.item.sortable._isCanceled;
                            },
                            isCustomHelperUsed: function () {
                                return !!ui.item.sortable._isCustomHelperUsed;
                            },
                            _isCanceled: false,
                            _isCustomHelperUsed: ui.item.sortable._isCustomHelperUsed,
                            _destroy: function () {
                                angular.forEach(ui.item.sortable, function (value, key) {
                                    ui.item.sortable[key] = undefined;
                                });
                            }
                        };
                    };

                    callbacks.activate = function (e, ui) {
                        // We need to make a copy of the current element's contents so
                        // we can restore it after sortable has messed it up.
                        // This is inside activate (instead of start) in order to save
                        // both lists when dragging between connected lists.
                        savedNodes = element.contents();

                        // If this list has a placeholder (the connected lists won't),
                        // don't inlcude it in saved nodes.
                        var placeholder = getPlaceholderElement(element);
                        if (placeholder && placeholder.length) {
                            var excludes = getPlaceholderExcludesludes(element, placeholder);
                            savedNodes = savedNodes.not(excludes);
                        }

                        // save the directive's scope so that it is accessible from ui.item.sortable
                        var connectedSortables = ui.item.sortable._connectedSortables || [];

                        connectedSortables.push({
                            element: element,
                            scope: scope
                        });

                        ui.item.sortable._connectedSortables = connectedSortables;
                    };

                    callbacks.update = function (e, ui) {
                        // Save current drop position but only if this is not a second
                        // update that happens when moving between lists because then
                        // the value will be overwritten with the old value
                        if (!ui.item.sortable.received) {
                            ui.item.sortable.dropindex = getItemIndex(ui);
                            var droptarget = ui.item.parent();
                            ui.item.sortable.droptarget = droptarget;

                            var droptargetScope = getElementScope(ui.item.sortable._connectedSortables, droptarget);
                            ui.item.sortable.droptargetModel = droptargetScope.ngModel;

                            // Cancel the sort (let ng-repeat do the sort for us)
                            // Don't cancel if this is the received list because it has
                            // already been canceled in the other list, and trying to cancel
                            // here will mess up the DOM.
                            element.sortable('cancel');
                        }

                        // Put the nodes back exactly the way they started (this is very
                        // important because ng-repeat uses comment elements to delineate
                        // the start and stop of repeat sections and sortable doesn't
                        // respect their order (even if we cancel, the order of the
                        // comments are still messed up).
                        var sortingHelper = !ui.item.sortable.received && getSortingHelper(element, ui, savedNodes);
                        if (sortingHelper && sortingHelper.length) {
                            // Restore all the savedNodes except from the sorting helper element.
                            // That way it will be garbage collected.
                            savedNodes = savedNodes.not(sortingHelper);
                        }
                        savedNodes.appendTo(element);

                        // If this is the target connected list then
                        // it's safe to clear the restored nodes since:
                        // update is currently running and
                        // stop is not called for the target list.
                        if (ui.item.sortable.received) {
                            savedNodes = null;
                        }

                        // If received is true (an item was dropped in from another list)
                        // then we add the new item to this list otherwise wait until the
                        // stop event where we will know if it was a sort or item was
                        // moved here from another list
                        if (ui.item.sortable.received && !ui.item.sortable.isCanceled()) {
                            scope.$apply(function () {
                                ngModel.$modelValue.splice(ui.item.sortable.dropindex, 0,
                                                           ui.item.sortable.moved);
                            });
                        }
                    };

                    callbacks.stop = function (e, ui) {
                        // If the received flag hasn't be set on the item, this is a
                        // normal sort, if dropindex is set, the item was moved, so move
                        // the items in the list.
                        if (!ui.item.sortable.received &&
                           ('dropindex' in ui.item.sortable) &&
                           !ui.item.sortable.isCanceled()) {

                            scope.$apply(function () {
                                ngModel.$modelValue.splice(
                                  ui.item.sortable.dropindex, 0,
                                  ngModel.$modelValue.splice(ui.item.sortable.index, 1)[0]);
                            });
                        } else {
                            // if the item was not moved, then restore the elements
                            // so that the ngRepeat's comment are correct.
                            if ((!('dropindex' in ui.item.sortable) || ui.item.sortable.isCanceled()) &&
                                !angular.equals(element.contents(), savedNodes)) {

                                var sortingHelper = getSortingHelper(element, ui, savedNodes);
                                if (sortingHelper && sortingHelper.length) {
                                    // Restore all the savedNodes except from the sorting helper element.
                                    // That way it will be garbage collected.
                                    savedNodes = savedNodes.not(sortingHelper);
                                }
                                savedNodes.appendTo(element);
                            }
                        }

                        // It's now safe to clear the savedNodes
                        // since stop is the last callback.
                        savedNodes = null;
                    };

                    callbacks.receive = function (e, ui) {
                        // An item was dropped here from another list, set a flag on the
                        // item.
                        ui.item.sortable.received = true;
                    };

                    callbacks.remove = function (e, ui) {
                        // Workaround for a problem observed in nested connected lists.
                        // There should be an 'update' event before 'remove' when moving
                        // elements. If the event did not fire, cancel sorting.
                        if (!('dropindex' in ui.item.sortable)) {
                            element.sortable('cancel');
                            ui.item.sortable.cancel();
                        }

                        // Remove the item from this list's model and copy data into item,
                        // so the next list can retrive it
                        if (!ui.item.sortable.isCanceled()) {
                            scope.$apply(function () {
                                ui.item.sortable.moved = ngModel.$modelValue.splice(
                                  ui.item.sortable.index, 1)[0];
                            });
                        }
                    };

                    wrappers.helper = function (inner) {
                        if (inner && typeof inner === 'function') {
                            return function (e, item) {
                                var innerResult = inner.apply(this, arguments);
                                item.sortable._isCustomHelperUsed = item !== innerResult;
                                return innerResult;
                            };
                        }
                        return inner;
                    };

                    scope.$watchCollection('uiSortable', function (newVal, oldVal) {
                        // ensure that the jquery-ui-sortable widget instance
                        // is still bound to the directive's element
                        var sortableWidgetInstance = getSortableWidgetInstance(element);
                        if (!!sortableWidgetInstance) {
                            var optsDiff = patchUISortableOptions(newVal, oldVal, sortableWidgetInstance);

                            if (optsDiff) {
                                element.sortable('option', optsDiff);
                            }
                        }
                    }, true);

                    patchUISortableOptions(opts);
                }

                function init() {
                    if (ngModel) {
                        wireUp();
                    } else {
                        $log.info('ui.sortable: ngModel not provided!', element);
                    }

                    // Create sortable
                    element.sortable(opts);
                }

                function initIfEnabled() {
                    if (scope.uiSortable && scope.uiSortable.disabled) {
                        return false;
                    }

                    init();

                    // Stop Watcher
                    initIfEnabled.cancelWatcher();
                    initIfEnabled.cancelWatcher = angular.noop;

                    return true;
                }

                initIfEnabled.cancelWatcher = angular.noop;

                if (!initIfEnabled()) {
                    initIfEnabled.cancelWatcher = scope.$watch('uiSortable.disabled', initIfEnabled);
                }
            }
        };
    }
  ]);;
(function () {
    'use strict';

    /**
     * Set Class When At Top
     */
   // var app = angular.module('app', []);
    angular.module('numbersOnly', []).directive('numbersOnly', function () {
       return {
           require: 'ngModel',
           link: function (scope, element, attr, ngModelCtrl) {              
               element.on('keydown', function (event) {
                   var $input = $(this);
                   var value = $input.val();
                   value = value.replace(/[^0-9]/g, '')
                   $input.val(value);
                   if (event.which == 64 || event.which == 16) {
                       // to allow numbers  
                       return false;
                   } else if (event.which >= 48 && event.which <= 57) {
                       // to allow numbers  
                       return true;
                   } else if (event.which >= 96 && event.which <= 105) {
                       // to allow numpad number  
                       return true;
                   } else if ([8, 13, 27, 37, 38, 39, 40].indexOf(event.which) > -1) {
                       // to allow backspace, enter, escape, arrows  
                       return true;
                   } else {
                       event.preventDefault();
                       // to stop others  
                       //alert("Sorry Only Numbers Allowed");  
                       return false;
                   } 
               });
               //ngModelCtrl.$parsers.push(fromUser);
           }
       };
   });
}());;
/**
 * @ngDoc directive
 * @name ng.directive:paging
 *
 * @description
 * A directive to aid in paging large datasets
 * while requiring a small amount of page
 * information.
 *
 * @element EA
 *
 */
angular.module('bw.paging', []).directive('paging', function () {


    /**
     * The regex expression to use for any replace methods
     * Feel free to tweak / fork values for your application
     */
    var regex = /\{page\}/g;


    /**
     * The angular return value required for the directive
     * Feel free to tweak / fork values for your application
     */
    return {

        // Restrict to elements and attributes
        restrict: 'EA',

        // Assign the angular link function
        link: fieldLink,

        // Assign the angular directive template HTML
        template: fieldTemplate,

        // Assign the angular scope attribute formatting
        scope: {
            page: '=?page',
            pageSize: '=?pageSize',
            total: '=?total',
            totalRecord: '=?totalRecord',
            disabled: '@',
            dots: '@',
            ulClass: '@',
            activeClass: '@',
            disabledClass: '@',
            adjacent: '@',
            pagingAction: '&',
            pgHref: '@',
            textFirst: '@',
            textLast: '@',
            textNext: '@',
            textPrev: '@',
            textFirstClass: '@',
            textLastClass: '@',
            textNextClass: '@',
            textPrevClass: '@',
            textTitlePage: '@',
            textTitleFirst: '@',
            textTitleLast: '@',
            textTitleNext: '@',
            textTitlePrev: '@'
        }

    };


    /**
     * Link the directive to enable our scope watch values
     *
     * @param {object} scope - Angular link scope
     * @param {object} el - Angular link element
     * @param {object} attrs - Angular link attribute
     */
    function fieldLink(scope, el, attrs) {

        // Hook in our watched items
        scope.$watchCollection('[page,pageSize,total,disabled,totalRecord]', function () {
            build(scope, attrs);
        });
    }


    /**
     * Create our template html 
     * We use a function to figure out how to handle href correctly
     * 
     * @param {object} el - Angular link element
     * @param {object} attrs - Angular link attribute
     */
    function fieldTemplate(el, attrs) {
        return '<div class="col-lg-12">' +
            '<ul data-ng-hide="Hide" data-ng-class="ulClass" class="margin-left-lg"> ' +
            '<li ' +
                'title="{{Item.title}}" ' +
                'data-ng-class="Item.liClass" ' +
                'data-ng-repeat="Item in List"> ' +
                    '<a ' +
                        (attrs.pgHref ? 'data-ng-href="{{Item.pgHref}}" ' : 'href ') +
                        'data-ng-class="Item.aClass" ' +
                        'data-ng-click="Item.action()" ' +
                        'data-ng-bind="Item.value" class="btn btn-default btn-sm">' +
                    '</a> ' +
            '</li>' +

        '</ul>' +
            '</div>'
    }


    /**
     * Assign default scope values from settings
     * Feel free to tweak / fork these for your application
     *
     * @param {Object} scope - The local directive scope object
     * @param {Object} attrs - The local directive attribute object
     */
    function setScopeValues(scope, attrs) {

        scope.List = [];
        scope.Hide = false;
        if (scope.List != undefined && scope.List != null && scope.List.length > 0) {
            scope.currentPage = scope.List[0].currentPage;
        }

        scope.page = parseInt(scope.page) || 1;
        scope.total = parseInt(scope.total) || 0;
        scope.totalRecord = parseInt(scope.totalRecord) || 0;
        scope.adjacent = parseInt(scope.adjacent) || 1;

        scope.pgHref = scope.pgHref || '';
        scope.dots = scope.dots || '...';

        scope.ulClass = scope.ulClass || 'pagination';
        scope.activeClass = scope.activeClass || 'active';
        scope.disabledClass = scope.disabledClass || 'disabled';

        scope.textFirst = scope.textFirst || 'First';
        scope.textLast = scope.textLast || 'Last';
        scope.textNext = scope.textNext || 'Next';
        scope.textPrev = scope.textPrev || 'Prev';

        scope.textFirstClass = scope.textFirstClass || '';
        scope.textLastClass = scope.textLastClass || '';
        scope.textNextClass = scope.textNextClass || '';
        scope.textPrevClass = scope.textPrevClass || '';

        scope.textTitlePage = scope.textTitlePage || 'Page {page}';
        scope.textTitleFirst = scope.textTitleFirst || 'First Page';
        scope.textTitleLast = scope.textTitleLast || 'Last Page';
        scope.textTitleNext = scope.textTitleNext || 'Next Page';
        scope.textTitlePrev = scope.textTitlePrev || 'Previous Page';

        scope.hideIfEmpty = evalBoolAttribute(scope, attrs.hideIfEmpty);
        scope.showPrevNext = evalBoolAttribute(scope, attrs.showPrevNext);
        scope.showFirstLast = evalBoolAttribute(scope, attrs.showFirstLast);
        scope.scrollTop = evalBoolAttribute(scope, attrs.scrollTop);
        scope.isDisabled = evalBoolAttribute(scope, attrs.disabled);
    }


    /**
     * A helper to perform our boolean eval on attributes
     * This allows flexibility in the attribute for strings and variables in scope
     * 
     * @param {Object} scope - The local directive scope object
     * @param {Object} value - The attribute value of interest
     */
    function evalBoolAttribute(scope, value) {
        return angular.isDefined(value)
            ? !!scope.$parent.$eval(value)
            : false;
    }


    /**
     * Validate and clean up any scope values
     * This happens after we have set the scope values
     *
     * @param {Object} scope - The local directive scope object
     * @param {int} pageCount - The last page number or total page count
     */
    function validateScopeValues(scope, pageCount) {

        // Block where the page is larger than the pageCount
        if (scope.page > pageCount) {
            scope.page = pageCount;
        }

        // Block where the page is less than 0
        if (scope.page <= 0) {
            scope.page = 1;
        }

        // Block where adjacent value is 0 or below
        if (scope.adjacent <= 0) {
            scope.adjacent = 2;
        }

        // Hide from page if we have 1 or less pages
        // if directed to hide empty
        if (pageCount <= 1) {
            scope.Hide = scope.hideIfEmpty;
        }
    }


    /**
     * Assign the method action to take when a page is clicked
     *
     * @param {Object} scope - The local directive scope object
     * @param {int} page - The current page of interest
     */
    function internalAction(scope, page) {

        // Block clicks we try to load the active page
        if (scope.page == page) {
            return;
        }

        // Block if we are forcing disabled 
        if (scope.isDisabled) {
            return;
        }

        // Update the page in scope
        scope.page = page;

        // Pass our parameters to the paging action
        scope.pagingAction({
            page: scope.page,
            pageSize: scope.pageSize,
            total: scope.total,
            totalRecord: scope.totalRecord
        });

        // If allowed scroll up to the top of the page
        if (scope.scrollTop) {
            scrollTo(0, 0);
        }
    }


    /**
     * Add the first, previous, next, and last buttons if desired
     * The logic is defined by the mode of interest
     * This method will simply return if the scope.showPrevNext is false
     * This method will simply return if there are no pages to display
     *
     * @param {Object} scope - The local directive scope object
     * @param {int} pageCount - The last page number or total page count
     * @param {string} mode - The mode of interest either prev or last
     */
    function addPrevNext(scope, pageCount, mode) {

        // Ignore if we are not showing
        // or there are no pages to display
        if ((!scope.showPrevNext && !scope.showFirstLast) || pageCount < 1) {
            return;
        }

        // Local variables to help determine logic
        var disabled, alpha, beta;

        // Determine logic based on the mode of interest
        // Calculate the previous / next page and if the click actions are allowed
        if (mode === 'prev') {

            disabled = scope.page - 1 <= 0;
            var prevPage = scope.page - 1 <= 0 ? 1 : scope.page - 1;

            if (scope.showFirstLast == true && disabled == false) {
                alpha = {
                    value: scope.textFirst,
                    title: scope.textTitleFirst,
                    aClass: scope.textFirstClass,
                    page: 1
                };
            }

            if (scope.showPrevNext == true && disabled==false) {
                beta = {
                    value: scope.textPrev,
                    title: scope.textTitlePrev,
                    aClass: scope.textPrevClass,
                    page: prevPage
                };
            }

        } else {

            disabled = scope.page + 1 > pageCount;
            var nextPage = scope.page + 1 >= pageCount ? pageCount : scope.page + 1;

            if (scope.showPrevNext == true && disabled == false) {
                alpha = {
                    value: scope.textNext,
                    title: scope.textTitleNext,
                    aClass: scope.textNextClass,
                    page: nextPage
                };
            }

            if (scope.showFirstLast == true && disabled == false) {
                beta = {
                    value: scope.textLast,
                    title: scope.textTitleLast,
                    aClass: scope.textLastClass,
                    page: pageCount
                };
            }

        }

        // Create the Add Item Function
        var buildItem = function (item, disabled) {
            return {
                title: item.title,
                aClass: item.aClass,
                value: item.aClass ? '' : item.value,
                liClass: disabled ? scope.disabledClass : '',
                pgHref: disabled ? '' : scope.pgHref.replace(regex, item.page),
                action: function () {
                    if (!disabled) {
                        internalAction(scope, item.page);
                    }
                }
            };
        };

        // Force disabled if specified
        if (scope.isDisabled) {
            disabled = true;
        }

        // Add alpha items
        if (alpha) {
            var alphaItem = buildItem(alpha, disabled);
            scope.List.push(alphaItem);
        }

        // Add beta items
        if (beta) {
            var betaItem = buildItem(beta, disabled);
            scope.List.push(betaItem);
        }
    }


    /**
     * Adds a range of numbers to our list
     * The range is dependent on the start and finish parameters
     *
     * @param {int} start - The start of the range to add to the paging list
     * @param {int} finish - The end of the range to add to the paging list
     * @param {Object} scope - The local directive scope object
     */
    function addRange(start, finish, scope) {

        // Add our items where i is the page number
        var i = 0;
        for (i = start; i <= finish; i++) {

            var pgHref = scope.pgHref.replace(regex, i);
            var liClass = scope.page == i ? scope.activeClass : '';

            // Handle items that are affected by disabled
            if (scope.isDisabled) {
                pgHref = '';
                liClass = scope.disabledClass;
            }


            scope.List.push({
                value: i,
                title: scope.textTitlePage.replace(regex, i),
                liClass: liClass,
                pgHref: pgHref,
                action: function () {
                    internalAction(scope, this.value);
                }
            });
        }
    }


    /**
     * Add Dots ie: 1 2 [...] 10 11 12 [...] 56 57
     * This is my favorite function not going to lie
     *
     * @param {Object} scope - The local directive scope object
     */
    function addDots(scope) {
        scope.List.push({
            value: scope.dots,
            liClass: scope.disabledClass
        });
    }


    /**
     * Add the first or beginning items in our paging list
     * We leverage the 'next' parameter to determine if the dots are required
     *
     * @param {Object} scope - The local directive scope object
     * @param {int} next - the next page number in the paging sequence
     */
    function addFirst(scope, next) {

        addRange(1, 1, scope);

        // We ignore dots if the next value is 3
        // ie: 1 2 [...] 3 4 5 becomes just 1 2 3 4 5
        if (next != 2) {
            addDots(scope);
        }
    }


    /**
     * Add the last or end items in our paging list
     * We leverage the 'prev' parameter to determine if the dots are required
     *
     * @param {int} pageCount - The last page number or total page count
     * @param {Object} scope - The local directive scope object
     * @param {int} prev - the previous page number in the paging sequence
     */
    // Add Last Pages
    function addLast(pageCount, scope, prev) {

        // We ignore dots if the previous value is one less that our start range
        // ie: 1 2 3 4 [...] 5 6  becomes just 1 2 3 4 5 6
        if (prev != pageCount - 1) {
            addDots(scope);
        }

        addRange(pageCount, pageCount, scope);
    }



    /**
     * The main build function used to determine the paging logic
     * Feel free to tweak / fork values for your application
     *
     * @param {Object} scope - The local directive scope object
     * @param {Object} attrs - The local directive attribute object
     */
    function build(scope, attrs) {

        // Block divide by 0 and empty page size
        if (!scope.pageSize || scope.pageSize <= 0) {
            scope.pageSize = 1;
        }

        // Determine the last page or total page count
        var pageCount = Math.ceil(scope.total / scope.pageSize);

        // Set the default scope values where needed
        setScopeValues(scope, attrs);

        // Validate the scope values to protect against strange states
        validateScopeValues(scope, pageCount);

        // Create the beginning and end page values
        var start, finish;

        // Calculate the full adjacency value
        var fullAdjacentSize = (scope.adjacent * 2) + 0;


        // Add the Next and Previous buttons to our list
        addPrevNext(scope, pageCount, 'prev');

        // If the page count is less than the full adjacnet size
        // Then we simply display all the pages, Otherwise we calculate the proper paging display
        if (pageCount <= (fullAdjacentSize + 1)) {

            start = 1;
            addRange(start, pageCount, scope);

        } else {

            // Determine if we are showing the beginning of the paging list
            // We know it is the beginning if the page - adjacent is <= 2
            if (scope.page - scope.adjacent <= 2) {

                start = 1;
                finish = 1 + fullAdjacentSize;

                addRange(start, finish, scope);
                addLast(pageCount, scope, finish);
            }

                // Determine if we are showing the middle of the paging list
                // We know we are either in the middle or at the end since the beginning is ruled out above
                // So we simply check if we are not at the end
                // Again 2 is hard coded as we always display two pages after the dots
            else if (scope.page < pageCount - (scope.adjacent + 1)) {

                start = scope.page - scope.adjacent;
                finish = scope.page + scope.adjacent;

                addFirst(scope, start);
                addRange(start, finish, scope);
                addLast(pageCount, scope, finish);
            }

                // If nothing else we conclude we are at the end of the paging list
                // We know this since we have already ruled out the beginning and middle above
            else {

                start = pageCount - fullAdjacentSize;
                finish = pageCount;

                addFirst(scope, start);
                addRange(start, finish, scope);
            }
        }

        // Add the next and last buttons to our paging list
        addPrevNext(scope, pageCount, 'next');
    }

});
;
(function () {
    'use strict';

    window.app.directive('surveyInputField', surveyInputField);
    function surveyInputField($compile) {
        var TEMPLATES = {
            TextInput:
            '<input type="text" class="form-control" ng-model="$parent.ques.selectedOptionValue" />',
            Multiline:
            '<textarea rows="4" cols"60" class="form-control" ng-model="$parent.ques.selectedOptionValue" />',
            RatingScale:
            '<angular-star-rating max="ques.rangeMaxNumber" value="$parent.ques.selectedOptionValue"  hover="true" is-readonly="false"></angular-star-rating>',
            SingleSlider: //http://angular-slider.github.io/angularjs-slider/
            ' <rzslider rz-slider-model="$parent.ques.selectedOptionValue" rz-slider-options="{floor:ques.rangeMinNumber,ceil:ques.rangeMaxNumber}"></rzslider>',
            DoubleSlider:
            ' <rzslider rz-slider-model="$parent.ques.selectedOptionValue" rz-slider-high="ques.rangeMaxNumber" rz-slider-options="{floor:ques.rangeMinNumber,ceil:ques.rangeMaxNumber}"></rzslider>',
            AsDropdown:
            '    <select' +
            '        name="{{ques.recordId}}"' +
            '        ng-model="$parent.ques.selectedOptionValue"' +
            '        class="form-control wizard"' +
            '        >' +
            '        <option ng-repeat="option in ques.inputOptions"  value="{{option.optionValue}}">{{option.optionText}}</option>' +
            '    </select>',
            AsText:
            '   <div class="col-sm-3" ng-repeat="option in ques.inputOptions track by $index">' +
            '       <div class="col-sm-12 col-xs-12 survey-options" ng-show="$parent.$parent.ques.inputDataType == \'OptionsSingleSelect\'">' +
            '           <div class="control-group">' +
            '               <label class="control control--radio">' +
            '                   <span class="label-survey">{{option.optionText}}</span>' +
            '                   <input type="radio" ng-value="option.optionValue" ng-click="option.stopAddToBag==true?$parent.$parent.ques.showHelpText=true:$parent.$parent.ques.showHelpText=false; $parent.$parent.ques.selectedOptionValue=option.optionValue;" name="singleSelect{{$parent.$parent.ques.recordId}}" ng-class="{\'btn btn-selected\':option.selected, \'btn\':!option.selected}">' +
            '                   <div class="control__indicator"></div>' +
            '               </label>' +
            '           </div>' +
            '       </div>' +
            '   </div>' +
            '    <ul class="pull-left">' +
            '        <li class="options-as-text " ng-repeat="option in ques.inputOptions track by $index">' +
            '            <button class="animate btn-default" ng-show="$parent.$parent.ques.inputDataType == \'OptionsMultipleSelect\'" ng-click="option.selected=!option.selected;$parent.$parent.ques.inputOptions[$index].selectedOptionValue = option.selected;$parent.$parent.ques.selectedOptionValue=option.optionValue" ng-class="{\'animate btn-success\':option.selected, \'animate btn-default\':!option.selected}">' +
            '            <span ng-class="{\'fa\':true, \'fa-check\':option.selected, \'fa-times\':!option.selected}"></span>' +
            '           {{option.optionText}}</button>' +
            '       </li>' +
            '    </ul>',
            AsImage:
            '    <ul>' +
            '        <li class="wizardImg-container" ng-repeat="option in ques.inputOptions track by $index" ng-click="option.selected=!option.selected; $parent.$parent.ques.inputOptions[$index].selectedOptionValue = option.selected;$parent.$parent.ques.selectedOptionValue=option.optionValue">' +
            '            <span ng-class="{\'wizardImg-label-selected\':option.selected}"><i ng-class="{\'fa fa-check\':option.selected, \'fa\':!option.selected}"></i> &nbsp; {{ option.optionText }} </span>' +
            '           <img ng-src="{{$parent.$parent.pm.model.imageBaseUrl}}{{option.imageUrl}}" alt="{{option.optionText}}" />' +
            '           <div class="wizadImg-inputs"> ' +
            '              <input ng-show="ques.inputDataType == \'OptionsMultiSelect\'" type="checkbox" value="option.optionValue" ng-model="$parent.$parent.ques.inputOptions[$index].selectedOptionValue" />' +
            '              <input ng-show="ques.inputDataType == \'OptionsSingleSelect\'" type="radio" value="option.optionValue" ng-model="$parent.$parent.ques.inputOptions[$index].selectedOptionValue" />' +
            '           </div>' +
            '        </li>' +
            '    </ul>',
            AsCarousel:
            '    <ul>' +
            '        <li class="options-as-text " ng-repeat="option in ques.inputOptions track by $index" ng-click="option.selected=!option.selected; $parent.$parent.ques.inputOptions[$index].selectedOptionValue = option.selected;$parent.$parent.ques.selectedOptionValue=option.optionValue">' +
            '            {{option.optionText}} ' +
            '           <img ng-src="{{option.imageUrl}}" alt="{{option.optionText}}" />' +
            '           <div> ' +
            '              <input ng-show="ques.inputDataType === \'OptionsMultiSelect\'" type="checkbox" value="option.optionValue" ng-model="$parent.ques.selectedOptionValue" />' +
            '              <input ng-show="ques.inputDataType === \'OptionsSingleSelect\'" type="radio" value="option.optionValue" ng-model="$parent.ques.selectedOptionValue" />' +
            '           </div>' +
            '        </li>' +
            '    </ul>',
        };

        return {
            restrict: 'E',
            scope: {
                question: "@question"
            },
            link: function (scope, element, attrs) {
                scope.ques = eval("(" + scope.question + ")");
                var tmpl = TEMPLATES[scope.ques.inputStyle];
                element.html(tmpl);

                $compile(element.contents())(scope);
            }
        }
    }
})();
;
window.app.filter('ocxDateTime', function ($filter) {
    var angularDateFilter = $filter('date');
    return function (theDate) {
        return angularDateFilter(theDate, 'dd-MMM-yy @ HH:mm');
    }
});
window.app.filter('ocxTime', function ($filter) {
    var angularDateFilter = $filter('date');
    return function (theDate) {
        return angularDateFilter(theDate, 'HH:mm:ss');
    }
});
window.app.filter('ocxDate', function ($filter) {
    var angularDateFilter = $filter('date');
    return function (theDate) {
        return angularDateFilter(theDate, 'dd-MMM-yy');
    }
});
window.app.filter('ocxMonth', function ($filter) {
    var angularDateFilter = $filter('date');
    return function (theDate) {
        return angularDateFilter(theDate, 'MMM');
    }
});;
angular
  .module('ordinal', [])
  .factory('ordinalService', function () {
    var ordinal = function (input) {
      var n = input % 100;
      return n === 0 ? 'th' : (n < 11 || n > 13) ?
        ['st', 'nd', 'rd', 'th'][Math.min((n - 1) % 10, 3)] : 'th';
    };
    return {
      ordinal: ordinal
    };
  })
  .filter('ordinal', ['ordinalService', function (ordinalService) {
    return function (input) {
      return input + ordinalService.ordinal(input);
    };
  }])
  .filter('ordinalOnly', ['ordinalService', function (ordinalService) {
    return function (input) {
      return ordinalService.ordinal(input);
    };
  }]);;
(function () {
    'use strict';

    window.app.constant('REGEX_CONSTANTS', {
        'LETTERS_AND_NUMBERS_ONLY': '^[a-zA-Z0-9 ]+$',
    });
})();;

(function () {
    'use strict';
    /* Service: AlertService
     * generates the bootstrap alerts for displaying messages that time out.
     */
    window.app.factory('alerts', function ($http, $q, BASE_URL) {
        var isRunning = false;
        var alertContainer = $(".alert-container");
        function showAlert(alert) {
            var template = "<div id='remove' class='alert " + alert.alertClass + "  alert-dismissable'>" + "<i class='fa fa-" + alert.alerticonClass + "'" + "></i>" + alert.message + "</div>";
            var alertElement = template;
            if (isRunning == false) {
                alertContainer.append(alertElement);
                isRunning = true;
            }
            window.setTimeout(function () {
                isRunning = false;
                $("." + alert.alertClass).fadeOut(function () { $(this).remove(); });
            }, 10000);
        }
        function success(message) {
            showAlert({ alertClass: "alert-success", message: message, alerticonClass: "check" });
        }

        function info(message) {
            showAlert({ alertClass: "alert-info", message: message, alerticonClass: "info-sign" });
        }

        function warning(message) {
            showAlert({ alertClass: "alert-warning", message: message, alerticonClass: "exclamation-triangle" });
        }

        function error(message) {
            showAlert({ alertClass: "alert-danger", message: message, alerticonClass: "shield" });
        }

        return {
            showAlert: showAlert,
            success: success,
            info: info,
            warning: warning,
            error: error
        };
    });
}());;
var app = angular.module('CapturePlus', []);
app.directive('capturePlus', function () {
    return {
        require: 'ngModel',
        restrict: 'A',
        link: function (scope, elem, attrs) {
            if (navigator.appName == 'Microsoft Internet Explorer') {
                elem[0].attachEvent('onchange', function () {
                    scope.$apply(function () {
                        var model = attrs.ngModel;
                        scope[model] = elem.val();
                    })
                });
            }
            else {
                elem.bind('change', function () {
                    scope.$apply(function () {
                        var model = attrs.ngModel;
                        scope[model] = elem.val();
                    })
                });
            }
        }
    }

});

app.factory('CapturePlus', function () {
    var capture = {
        CapturePlusCallback: function () { },
        CapturePlusError: function () { },
        CapturePlusStartTyping: function () { }
    }
    window.CapturePlusCallback = function (uid, response) {
        var captureFields = getAllElementsWithAttribute('capture-plus');
        for (var i = 0; i < captureFields.length; i++) {
            var field = document.getElementById(captureFields[i].id);
            if ("fireEvent" in field)
                field.fireEvent("onchange");
            else {
                var evt = document.createEvent("HTMLEvents");
                evt.initEvent("change", false, true);
                field.dispatchEvent(evt);
            }
        }
        capture.CapturePlusCallback(uid, response);
    }
    window.CapturePlusStartTyping = function (uid, response) {
        capture.CapturePlusStartTyping(uid, response);
    }
    window.CapturePlusError = function (uid, response) {
        capture.CapturePlusError(uid, response);
    }
    return capture;
});

function getAllElementsWithAttribute(attribute) {
    var matchingElements = [];
    var allElements = document.getElementsByTagName('*');
    for (var i = 0; i < allElements.length; i++) {
        if (allElements[i].attributes) {
            if (allElements[i].attributes[attribute]) {
                matchingElements.push(allElements[i]);
            }
        }
    }
    return matchingElements;
}
;
//Validation Json
function isJSON(str) {
    try {
        return (JSON.parse(str) && !!str);
    } catch (e) {
        return false;
    }
}
//Validation use only for digit
function isNumberValidate(evt) {
    var theEvent = evt || window.event;
    var key = theEvent.keyCode || theEvent.which;
    key = String.fromCharCode(key);
    var regex = /[0-9]|\./;
    if (!regex.test(key)) {
        theEvent.returnValue = false;
        if (theEvent.preventDefault) theEvent.preventDefault();
    }
}

function validatePostCode(postCode, countryCode) {
    var country = '';
    //var country = regxGlobalPostCodes.find(x => x.ISO === countryCode);
    angular.forEach(regxGlobalPostCodes, function (pCode) {
        if (pCode.ISO === countryCode) {
            country = pCode;
        }
    });
    if (country != undefined && country != null) {
        var regex = new RegExp(country.Regex);
        return regex.test(postCode);
    }
    return false;
}
/* This function is included as JS SDK for IE does not contains URLSearchParams and related function.
   Need to add this in Core JS modules for re-usability.
*/
 function GetUrlSearchParams(name) {
    var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(window.location.href);
    if (results == null) {
        return null;
    }
    else {
        return decodeURI(results[1]) || null;
    }
};
var regxGlobalPostCodes= [
   {
     "Note": "Known as the postcode. The first letter(s) indicate the postal area, such as the town or part of London. Placed on a separate line below the city (or county, if used). The UK postcode is made up of two parts separated by a space. These are known as the outward postcode and the inward postcode. The outward postcode is always one of the following formats: AN, ANN, AAN, AANN, ANA, AANA, AAA. The inward postcode is always formatted as NAA. A valid inward postcode never contains the letters: C, I, K, M, O or V. The British Forces Post Office has a different system, but as of 2012 has also adopted UK-style postcodes that begin with \"BF1\" for electronic compatibility.",
     "Country": "United Kingdom",
     "ISO": "GB",
     "Format": "A(A)N(A/N)NAA (A[A]N[A/N] NAA)",
     "Regex": "[A-Z]{1,2}[0-9R][0-9A-Z]? (?:(?![CIKMOV])[0-9][a-zA-Z]{2})"
   }
];
/*

Quicksand 1.2.2

Reorder and filter items with a nice shuffling animation.

Copyright (c) 2010 Jacek Galanciak (razorjack.net) and agilope.com
Big thanks for Piotr Petrus (riddle.pl) for deep code review and wonderful docs & demos.

Dual licensed under the MIT and GPL version 2 licenses.
http://github.com/jquery/jquery/blob/master/MIT-LICENSE.txt
http://github.com/jquery/jquery/blob/master/GPL-LICENSE.txt

Project site: http://razorjack.net/quicksand
Github site: http://github.com/razorjack/quicksand

*/

(function ($) {
    $.fn.quicksand = function (collection, customOptions) {     
        var options = {
            duration: 750,
            easing: 'swing',
            attribute: 'data-id', // attribute to recognize same items within source and dest
            adjustHeight: 'auto', // 'dynamic' animates height during shuffling (slow), 'auto' adjusts it before or after the animation, false leaves height constant
            useScaling: true, // disable it if you're not using scaling effect or want to improve performance
            enhancement: function(c) {}, // Visual enhacement (eg. font replacement) function for cloned elements
            selector: '> *',
            dx: 0,
            dy: 0
        };
        $.extend(options, customOptions);
        
        //if ($.browser.msie || (typeof($.fn.scale) == 'undefined')) {
        //    // Got IE and want scaling effect? Kiss my ass.
        //    options.useScaling = false;
        //}
        
        var callbackFunction;
        if (typeof(arguments[1]) == 'function') {
            var callbackFunction = arguments[1];
        } else if (typeof(arguments[2] == 'function')) {
            var callbackFunction = arguments[2];
        }
    
        
        return this.each(function (i) {
            var val;
            var animationQueue = []; // used to store all the animation params before starting the animation; solves initial animation slowdowns
            var $collection = $(collection).clone(); // destination (target) collection
            var $sourceParent = $(this); // source, the visible container of source collection
            var sourceHeight = $(this).css('height'); // used to keep height and document flow during the animation
            
            var destHeight;
            var adjustHeightOnCallback = false;
            
            var offset = $($sourceParent).offset(); // offset of visible container, used in animation calculations
            var offsets = []; // coordinates of every source collection item            
            
            var $source = $(this).find(options.selector); // source collection items
            
            // Replace the collection and quit if IE6
            //if ($.browser.msie && $.browser.version.substr(0,1)<7) {
            //    $sourceParent.html('').append($collection);
            //    return;
            //}

            // Gets called when any animation is finished
            var postCallbackPerformed = 0; // prevents the function from being called more than one time
            var postCallback = function () {
                
                if (!postCallbackPerformed) {
                    postCallbackPerformed = 1;
                    
                    // hack: 
                    // used to be: $sourceParent.html($dest.html()); // put target HTML into visible source container
                    // but new webkit builds cause flickering when replacing the collections
                    $toDelete = $sourceParent.find('> *');
                    $sourceParent.prepend($dest.find('> *'));
                    $toDelete.remove();
                         
                    if (adjustHeightOnCallback) {
                        $sourceParent.css('height', destHeight);
                    }
                    options.enhancement($sourceParent); // Perform custom visual enhancements on a newly replaced collection
                    if (typeof callbackFunction == 'function') {
                        callbackFunction.call(this);
                    }                    
                }
            };
            
            // Position: relative situations
            var $correctionParent = $sourceParent.offsetParent();
            var correctionOffset = $correctionParent.offset();
            if ($correctionParent.css('position') == 'relative') {
                if ($correctionParent.get(0).nodeName.toLowerCase() == 'body') {

                } else {
                    correctionOffset.top += (parseFloat($correctionParent.css('border-top-width')) || 0);
                    correctionOffset.left +=( parseFloat($correctionParent.css('border-left-width')) || 0);
                }
            } else {
                correctionOffset.top -= (parseFloat($correctionParent.css('border-top-width')) || 0);
                correctionOffset.left -= (parseFloat($correctionParent.css('border-left-width')) || 0);
                correctionOffset.top -= (parseFloat($correctionParent.css('margin-top')) || 0);
                correctionOffset.left -= (parseFloat($correctionParent.css('margin-left')) || 0);
            }
            
            // perform custom corrections from options (use when Quicksand fails to detect proper correction)
            if (isNaN(correctionOffset.left)) {
                correctionOffset.left = 0;
            }
            if (isNaN(correctionOffset.top)) {
                correctionOffset.top = 0;
            }
            
            correctionOffset.left -= options.dx;
            correctionOffset.top -= options.dy;

            // keeps nodes after source container, holding their position
            $sourceParent.css('height', $(this).height());
            
            // get positions of source collections
            $source.each(function (i) {
                offsets[i] = $(this).offset();
            });
            
            // stops previous animations on source container
            $(this).stop();
            var dx = 0; var dy = 0;
            $source.each(function (i) {
                $(this).stop(); // stop animation of collection items
                var rawObj = $(this).get(0);
                if (rawObj.style.position == 'absolute') {
                    dx = -options.dx;
                    dy = -options.dy;
                } else {
                    dx = options.dx;
                    dy = options.dy;                    
                }

                rawObj.style.position = 'absolute';
                rawObj.style.margin = '0';

                rawObj.style.top = (offsets[i].top - parseFloat(rawObj.style.marginTop) - correctionOffset.top + dy) + 'px';
                rawObj.style.left = (offsets[i].left - parseFloat(rawObj.style.marginLeft) - correctionOffset.left + dx) + 'px';
            });
                    
            // create temporary container with destination collection
            var $dest = $($sourceParent).clone();
            var rawDest = $dest.get(0);
            rawDest.innerHTML = '';
            rawDest.setAttribute('id', '');
            rawDest.style.height = 'auto';
            rawDest.style.width = $sourceParent.width() + 'px';
            $dest.append($collection);      
            // insert node into HTML
            // Note that the node is under visible source container in the exactly same position
            // The browser render all the items without showing them (opacity: 0.0)
            // No offset calculations are needed, the browser just extracts position from underlayered destination items
            // and sets animation to destination positions.
            $dest.insertBefore($sourceParent);
            $dest.css('opacity', 0.0);
            rawDest.style.zIndex = -1;
            
            rawDest.style.margin = '0';
            rawDest.style.position = 'absolute';
            rawDest.style.top = offset.top - correctionOffset.top + 'px';
            rawDest.style.left = offset.left - correctionOffset.left + 'px';
            
            
    
            

            if (options.adjustHeight === 'dynamic') {
                // If destination container has different height than source container
                // the height can be animated, adjusting it to destination height
                var heigh=$dest.height()/6;
                $sourceParent.animate({height:heigh }, options.duration, options.easing);
            } else if (options.adjustHeight === 'auto') {
                destHeight = $dest.height();
                if (parseFloat(sourceHeight) < parseFloat(destHeight)) {
                    // Adjust the height now so that the items don't move out of the container
                    $sourceParent.css('height', destHeight);
                } else {
                    //  Adjust later, on callback
                    adjustHeightOnCallback = true;
                }
            }
                
            // Now it's time to do shuffling animation
            // First of all, we need to identify same elements within source and destination collections    
            $source.each(function (i) {
                var destElement = [];
                if (typeof(options.attribute) == 'function') {
                    
                    val = options.attribute($(this));
                    $collection.each(function() {
                        if (options.attribute(this) == val) {
                            destElement = $(this);
                            return false;
                        }
                    });
                } else {
                    destElement = $collection.filter('[' + options.attribute + '=' + $(this).attr(options.attribute) + ']');
                }
                if (destElement.length) {
                    // The item is both in source and destination collections
                    // It it's under different position, let's move it
                    if (!options.useScaling) {
                        animationQueue.push(
                                            {
                                                element: $(this), 
                                                animation: 
                                                    {top: destElement.offset().top - correctionOffset.top, 
                                                     left: destElement.offset().left - correctionOffset.left, 
                                                     opacity: 1.0
                                                    }
                                            });

                    } else {
                        animationQueue.push({
                                            element: $(this), 
                                            animation: {top: destElement.offset().top - correctionOffset.top, 
                                                        left: destElement.offset().left - correctionOffset.left, 
                                                        opacity: 1.0, 
                                                        scale: '1.0'
                                                       }
                                            });

                    }
                } else {
                    // The item from source collection is not present in destination collections
                    // Let's remove it
                    if (!options.useScaling) {
                        animationQueue.push({element: $(this), 
                                             animation: {opacity: '0.0'}});
                    } else {
                        animationQueue.push({element: $(this), animation: {opacity: '0.0', 
                                         scale: '0.0'}});
                    }
                }
            });
            
            $collection.each(function (i) {
                // Grab all items from target collection not present in visible source collection
                
                var sourceElement = [];
                var destElement = [];
                if (typeof(options.attribute) == 'function') {
                    val = options.attribute($(this));
                    $source.each(function() {
                        if (options.attribute(this) == val) {
                            sourceElement = $(this);
                            return false;
                        }
                    });                 

                    $collection.each(function() {
                        if (options.attribute(this) == val) {
                            destElement = $(this);
                            return false;
                        }
                    });
                } else {
                    sourceElement = $source.filter('[' + options.attribute + '=' + $(this).attr(options.attribute) + ']');
                    destElement = $collection.filter('[' + options.attribute + '=' + $(this).attr(options.attribute) + ']');
                }
                
                var animationOptions;
                if (sourceElement.length === 0) {
                    // No such element in source collection...
                    if (!options.useScaling) {
                        animationOptions = {
                            opacity: '1.0'
                        };
                    } else {
                        animationOptions = {
                            opacity: '1.0',
                            scale: '1.0'
                        };
                    }
                    // Let's create it
                    d = destElement.clone();
                    var rawDestElement = d.get(0);
                    rawDestElement.style.position = 'absolute';
                    rawDestElement.style.margin = '0';
                    rawDestElement.style.top = destElement.offset().top - correctionOffset.top + 'px';
                    rawDestElement.style.left = destElement.offset().left - correctionOffset.left + 'px';
                    d.css('opacity', 0.0); // IE
                    if (options.useScaling) {
                        d.css('transform', 'scale(0.0)');
                    }
                    d.appendTo($sourceParent);
                    
                    animationQueue.push({element: $(d), 
                                         animation: animationOptions});
                }
            });
            
            $dest.remove();
            options.enhancement($sourceParent); // Perform custom visual enhancements during the animation
            for (i = 0; i < animationQueue.length; i++) {
                animationQueue[i].element.animate(animationQueue[i].animation, options.duration, options.easing, postCallback);
            }
        });
    };
})(jQuery);;
(function () {
    'use strict';
    window.app.factory('loader', ['$http', '$rootScope', function ($http, $rootScope) {

        angular.element(document).ready(function () {
            angular.element(".dvloader").hide();
        });

        $http.defaults.transformRequest.push(function (data) {
            angular.element(".dvloader").show();
            return data;
        });
        $http.defaults.transformResponse.push(function (data) {
            angular.element(".dvloader").hide();
            return data;
        })
        return $http;
    }]);
}());
;
function loadPCAScript(scriptLoader, pcaAccessCode) {

    if (pcaAccessCode != undefined && pcaAccessCode != '') {
        scriptLoader.load("//services.postcodeanywhere.co.uk/css/captureplus-2.30.min.css?key=" + pcaAccessCode, "text/css", "stylesheet");
        scriptLoader.load("//services.postcodeanywhere.co.uk/js/captureplus-2.30.min.js?key=" + pcaAccessCode, "text/javascript", "");
    }
}
function setPCALookup(pcaAccessCode, country, address1Id, address2Id, cityId, stateId, postCodeid, companynameid, countryCode, countryId, countryElementId) {
    if (pcaAccessCode != undefined && pcaAccessCode != '') {
        if (!countryCode)
            countryCode= document.getElementById("selectedBillCountry").value;
        if (!countryElementId) {
            countryId = 'selectedBillCountry'
        }
        window.setTimeout(function () {
            // address PCA Predict
            var optionsAddress = {
                key: pcaAccessCode,
                countries: { codeList: countryCode}
            };

            var fieldsAddress = [
                { element: address1Id, field: 'Line1' },
                { element: address2Id, field: 'Line2', mode: pca.fieldMode.POPULATE },
                { element: cityId, field: 'City', mode: pca.fieldMode.POPULATE },
                { element: stateId, field: 'Province', mode: pca.fieldMode.POPULATE },
                { element: postCodeid, field: 'PostalCode' },
                { element: countryElementId, field: 'CountryName', mode: pca.fieldMode.COUNTRY }
            ];

            var controlAddress = new pca.Address(fieldsAddress, optionsAddress);

            controlAddress.listen('options', function (options) {
                options.countries = options.countries || {};
                options.countries.codesList = country;
            });

            controlAddress.listen('populate', function (address, variations) {
                CapturePlusCallback();
            });

            controlAddress.load();
        }, 1500);
    }
}
;
(function () {
    'use strict';
    window.app.factory('scriptLoader', function () {
        return {
            load: function (url, type, rel) {
                if (type === undefined) type = 'text/javascript';
                if (url) {
                    var script = document.querySelector("script[src*='" + url + "']");
                    if (!script) {
                        var heads = document.getElementsByTagName("head");
                        if (heads && heads.length) {
                            var head = heads[0];
                            if (head) {
                                if (!rel) {
                                    script = document.createElement('script');
                                    script.setAttribute('src', url)
                                } else {
                                    script = document.createElement('link');
                                    script.setAttribute('href', url)
                                }
                                script.setAttribute('type', type);
                                if (rel) script.setAttribute('rel', rel);
                                head.appendChild(script);
                            }
                        }
                    }
                    return script;
                }
            }
        };
    });
}());;
(function () {
    'use strict';
    /* Service: AdminData
     * Defines the methods related to global data across the app
     */
    window.app.factory('Recommendation', function ($http, $q, BASE_URL) {       
        var factory = {};
        var RECENT_PRODUCT_COOKIE = '_rvp';
        return {
            getRecommendation: function () {
                var deferred = $q.defer();
                var recentViewedProducts = $.cookie(RECENT_PRODUCT_COOKIE);
                if (recentViewedProducts) {
                    var recentViewedProductList = recentViewedProducts.split(",");
                }
                var pagePath = window.location.pathname;
                $http.post(BASE_URL + '/Recomendation/GetItemRecommendations', { itemId: dataLayer[0].EntityId, recentViewedProductList: recentViewedProductList, pageCategory: dataLayer[0].PageCategory }).success(deferred.resolve).error(deferred.reject);
                return deferred.promise;  
            }
        }
    });
}());;
/**
 * Swiper 6.1.1
 * Most modern mobile touch slider and framework with hardware accelerated transitions
 * http://swiperjs.com
 *
 * Copyright 2014-2020 Vladimir Kharlampidi
 *
 * Released under the MIT License
 *
 * Released on: July 31, 2020
 */

!function (e, t) { "object" == typeof exports && "undefined" != typeof module ? module.exports = t() : "function" == typeof define && define.amd ? define(t) : (e = e || self).Swiper = t() }(this, (function () { "use strict"; function e(e, t) { for (var i = 0; i < t.length; i++) { var s = t[i]; s.enumerable = s.enumerable || !1, s.configurable = !0, "value" in s && (s.writable = !0), Object.defineProperty(e, s.key, s) } } function t() { return (t = Object.assign || function (e) { for (var t = 1; t < arguments.length; t++) { var i = arguments[t]; for (var s in i) Object.prototype.hasOwnProperty.call(i, s) && (e[s] = i[s]) } return e }).apply(this, arguments) } function i(e) { return null !== e && "object" == typeof e && "constructor" in e && e.constructor === Object } function s(e, t) { void 0 === e && (e = {}), void 0 === t && (t = {}), Object.keys(t).forEach((function (a) { void 0 === e[a] ? e[a] = t[a] : i(t[a]) && i(e[a]) && Object.keys(t[a]).length > 0 && s(e[a], t[a]) })) } var a = { body: {}, addEventListener: function () { }, removeEventListener: function () { }, activeElement: { blur: function () { }, nodeName: "" }, querySelector: function () { return null }, querySelectorAll: function () { return [] }, getElementById: function () { return null }, createEvent: function () { return { initEvent: function () { } } }, createElement: function () { return { children: [], childNodes: [], style: {}, setAttribute: function () { }, getElementsByTagName: function () { return [] } } }, createElementNS: function () { return {} }, importNode: function () { return null }, location: { hash: "", host: "", hostname: "", href: "", origin: "", pathname: "", protocol: "", search: "" } }; function r() { var e = "undefined" != typeof document ? document : {}; return s(e, a), e } var n = { document: a, navigator: { userAgent: "" }, location: { hash: "", host: "", hostname: "", href: "", origin: "", pathname: "", protocol: "", search: "" }, history: { replaceState: function () { }, pushState: function () { }, go: function () { }, back: function () { } }, CustomEvent: function () { return this }, addEventListener: function () { }, removeEventListener: function () { }, getComputedStyle: function () { return { getPropertyValue: function () { return "" } } }, Image: function () { }, Date: function () { }, screen: {}, setTimeout: function () { }, clearTimeout: function () { }, matchMedia: function () { return {} }, requestAnimationFrame: function (e) { return "undefined" == typeof setTimeout ? (e(), null) : setTimeout(e, 0) }, cancelAnimationFrame: function (e) { "undefined" != typeof setTimeout && clearTimeout(e) } }; function l() { var e = "undefined" != typeof window ? window : {}; return s(e, n), e } function o(e) { return (o = Object.setPrototypeOf ? Object.getPrototypeOf : function (e) { return e.__proto__ || Object.getPrototypeOf(e) })(e) } function d(e, t) { return (d = Object.setPrototypeOf || function (e, t) { return e.__proto__ = t, e })(e, t) } function h() { if ("undefined" == typeof Reflect || !Reflect.construct) return !1; if (Reflect.construct.sham) return !1; if ("function" == typeof Proxy) return !0; try { return Date.prototype.toString.call(Reflect.construct(Date, [], (function () { }))), !0 } catch (e) { return !1 } } function p(e, t, i) { return (p = h() ? Reflect.construct : function (e, t, i) { var s = [null]; s.push.apply(s, t); var a = new (Function.bind.apply(e, s)); return i && d(a, i.prototype), a }).apply(null, arguments) } function u(e) { var t = "function" == typeof Map ? new Map : void 0; return (u = function (e) { if (null === e || (i = e, -1 === Function.toString.call(i).indexOf("[native code]"))) return e; var i; if ("function" != typeof e) throw new TypeError("Super expression must either be null or a function"); if (void 0 !== t) { if (t.has(e)) return t.get(e); t.set(e, s) } function s() { return p(e, arguments, o(this).constructor) } return s.prototype = Object.create(e.prototype, { constructor: { value: s, enumerable: !1, writable: !0, configurable: !0 } }), d(s, e) })(e) } var c = function (e) { var t, i; function s(t) { var i, s, a; return i = e.call.apply(e, [this].concat(t)) || this, s = function (e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e }(i), a = s.__proto__, Object.defineProperty(s, "__proto__", { get: function () { return a }, set: function (e) { a.__proto__ = e } }), i } return i = e, (t = s).prototype = Object.create(i.prototype), t.prototype.constructor = t, t.__proto__ = i, s }(u(Array)); function v(e) { void 0 === e && (e = []); var t = []; return e.forEach((function (e) { Array.isArray(e) ? t.push.apply(t, v(e)) : t.push(e) })), t } function f(e, t) { return Array.prototype.filter.call(e, t) } function m(e, t) { var i = l(), s = r(), a = []; if (!t && e instanceof c) return e; if (!e) return new c(a); if ("string" == typeof e) { var n = e.trim(); if (n.indexOf("<") >= 0 && n.indexOf(">") >= 0) { var o = "div"; 0 === n.indexOf("<li") && (o = "ul"), 0 === n.indexOf("<tr") && (o = "tbody"), 0 !== n.indexOf("<td") && 0 !== n.indexOf("<th") || (o = "tr"), 0 === n.indexOf("<tbody") && (o = "table"), 0 === n.indexOf("<option") && (o = "select"); var d = s.createElement(o); d.innerHTML = n; for (var h = 0; h < d.childNodes.length; h += 1)a.push(d.childNodes[h]) } else a = function (e, t) { if ("string" != typeof e) return [e]; for (var i = [], s = t.querySelectorAll(e), a = 0; a < s.length; a += 1)i.push(s[a]); return i }(e.trim(), t || s) } else if (e.nodeType || e === i || e === s) a.push(e); else if (Array.isArray(e)) { if (e instanceof c) return e; a = e } return new c(function (e) { for (var t = [], i = 0; i < e.length; i += 1)-1 === t.indexOf(e[i]) && t.push(e[i]); return t }(a)) } m.fn = c.prototype; var g, w, b, y = { addClass: function () { for (var e = arguments.length, t = new Array(e), i = 0; i < e; i++)t[i] = arguments[i]; var s = v(t.map((function (e) { return e.split(" ") }))); return this.forEach((function (e) { var t; (t = e.classList).add.apply(t, s) })), this }, removeClass: function () { for (var e = arguments.length, t = new Array(e), i = 0; i < e; i++)t[i] = arguments[i]; var s = v(t.map((function (e) { return e.split(" ") }))); return this.forEach((function (e) { var t; (t = e.classList).remove.apply(t, s) })), this }, hasClass: function () { for (var e = arguments.length, t = new Array(e), i = 0; i < e; i++)t[i] = arguments[i]; var s = v(t.map((function (e) { return e.split(" ") }))); return f(this, (function (e) { return s.filter((function (t) { return e.classList.contains(t) })).length > 0 })).length > 0 }, toggleClass: function () { for (var e = arguments.length, t = new Array(e), i = 0; i < e; i++)t[i] = arguments[i]; var s = v(t.map((function (e) { return e.split(" ") }))); this.forEach((function (e) { s.forEach((function (t) { e.classList.toggle(t) })) })) }, attr: function (e, t) { if (1 === arguments.length && "string" == typeof e) return this[0] ? this[0].getAttribute(e) : void 0; for (var i = 0; i < this.length; i += 1)if (2 === arguments.length) this[i].setAttribute(e, t); else for (var s in e) this[i][s] = e[s], this[i].setAttribute(s, e[s]); return this }, removeAttr: function (e) { for (var t = 0; t < this.length; t += 1)this[t].removeAttribute(e); return this }, transform: function (e) { for (var t = 0; t < this.length; t += 1)this[t].style.transform = e; return this }, transition: function (e) { for (var t = 0; t < this.length; t += 1)this[t].style.transition = "string" != typeof e ? e + "ms" : e; return this }, on: function () { for (var e = arguments.length, t = new Array(e), i = 0; i < e; i++)t[i] = arguments[i]; var s = t[0], a = t[1], r = t[2], n = t[3]; function l(e) { var t = e.target; if (t) { var i = e.target.dom7EventData || []; if (i.indexOf(e) < 0 && i.unshift(e), m(t).is(a)) r.apply(t, i); else for (var s = m(t).parents(), n = 0; n < s.length; n += 1)m(s[n]).is(a) && r.apply(s[n], i) } } function o(e) { var t = e && e.target && e.target.dom7EventData || []; t.indexOf(e) < 0 && t.unshift(e), r.apply(this, t) } "function" == typeof t[1] && (s = t[0], r = t[1], n = t[2], a = void 0), n || (n = !1); for (var d, h = s.split(" "), p = 0; p < this.length; p += 1) { var u = this[p]; if (a) for (d = 0; d < h.length; d += 1) { var c = h[d]; u.dom7LiveListeners || (u.dom7LiveListeners = {}), u.dom7LiveListeners[c] || (u.dom7LiveListeners[c] = []), u.dom7LiveListeners[c].push({ listener: r, proxyListener: l }), u.addEventListener(c, l, n) } else for (d = 0; d < h.length; d += 1) { var v = h[d]; u.dom7Listeners || (u.dom7Listeners = {}), u.dom7Listeners[v] || (u.dom7Listeners[v] = []), u.dom7Listeners[v].push({ listener: r, proxyListener: o }), u.addEventListener(v, o, n) } } return this }, off: function () { for (var e = arguments.length, t = new Array(e), i = 0; i < e; i++)t[i] = arguments[i]; var s = t[0], a = t[1], r = t[2], n = t[3]; "function" == typeof t[1] && (s = t[0], r = t[1], n = t[2], a = void 0), n || (n = !1); for (var l = s.split(" "), o = 0; o < l.length; o += 1)for (var d = l[o], h = 0; h < this.length; h += 1) { var p = this[h], u = void 0; if (!a && p.dom7Listeners ? u = p.dom7Listeners[d] : a && p.dom7LiveListeners && (u = p.dom7LiveListeners[d]), u && u.length) for (var c = u.length - 1; c >= 0; c -= 1) { var v = u[c]; r && v.listener === r || r && v.listener && v.listener.dom7proxy && v.listener.dom7proxy === r ? (p.removeEventListener(d, v.proxyListener, n), u.splice(c, 1)) : r || (p.removeEventListener(d, v.proxyListener, n), u.splice(c, 1)) } } return this }, trigger: function () { for (var e = l(), t = arguments.length, i = new Array(t), s = 0; s < t; s++)i[s] = arguments[s]; for (var a = i[0].split(" "), r = i[1], n = 0; n < a.length; n += 1)for (var o = a[n], d = 0; d < this.length; d += 1) { var h = this[d]; if (e.CustomEvent) { var p = new e.CustomEvent(o, { detail: r, bubbles: !0, cancelable: !0 }); h.dom7EventData = i.filter((function (e, t) { return t > 0 })), h.dispatchEvent(p), h.dom7EventData = [], delete h.dom7EventData } } return this }, transitionEnd: function (e) { var t = this; return e && t.on("transitionend", (function i(s) { s.target === this && (e.call(this, s), t.off("transitionend", i)) })), this }, outerWidth: function (e) { if (this.length > 0) { if (e) { var t = this.styles(); return this[0].offsetWidth + parseFloat(t.getPropertyValue("margin-right")) + parseFloat(t.getPropertyValue("margin-left")) } return this[0].offsetWidth } return null }, outerHeight: function (e) { if (this.length > 0) { if (e) { var t = this.styles(); return this[0].offsetHeight + parseFloat(t.getPropertyValue("margin-top")) + parseFloat(t.getPropertyValue("margin-bottom")) } return this[0].offsetHeight } return null }, styles: function () { var e = l(); return this[0] ? e.getComputedStyle(this[0], null) : {} }, offset: function () { if (this.length > 0) { var e = l(), t = r(), i = this[0], s = i.getBoundingClientRect(), a = t.body, n = i.clientTop || a.clientTop || 0, o = i.clientLeft || a.clientLeft || 0, d = i === e ? e.scrollY : i.scrollTop, h = i === e ? e.scrollX : i.scrollLeft; return { top: s.top + d - n, left: s.left + h - o } } return null }, css: function (e, t) { var i, s = l(); if (1 === arguments.length) { if ("string" != typeof e) { for (i = 0; i < this.length; i += 1)for (var a in e) this[i].style[a] = e[a]; return this } if (this[0]) return s.getComputedStyle(this[0], null).getPropertyValue(e) } if (2 === arguments.length && "string" == typeof e) { for (i = 0; i < this.length; i += 1)this[i].style[e] = t; return this } return this }, each: function (e) { return e ? (this.forEach((function (t, i) { e.apply(t, [t, i]) })), this) : this }, html: function (e) { if (void 0 === e) return this[0] ? this[0].innerHTML : null; for (var t = 0; t < this.length; t += 1)this[t].innerHTML = e; return this }, text: function (e) { if (void 0 === e) return this[0] ? this[0].textContent.trim() : null; for (var t = 0; t < this.length; t += 1)this[t].textContent = e; return this }, is: function (e) { var t, i, s = l(), a = r(), n = this[0]; if (!n || void 0 === e) return !1; if ("string" == typeof e) { if (n.matches) return n.matches(e); if (n.webkitMatchesSelector) return n.webkitMatchesSelector(e); if (n.msMatchesSelector) return n.msMatchesSelector(e); for (t = m(e), i = 0; i < t.length; i += 1)if (t[i] === n) return !0; return !1 } if (e === a) return n === a; if (e === s) return n === s; if (e.nodeType || e instanceof c) { for (t = e.nodeType ? [e] : e, i = 0; i < t.length; i += 1)if (t[i] === n) return !0; return !1 } return !1 }, index: function () { var e, t = this[0]; if (t) { for (e = 0; null !== (t = t.previousSibling);)1 === t.nodeType && (e += 1); return e } }, eq: function (e) { if (void 0 === e) return this; var t = this.length; if (e > t - 1) return m([]); if (e < 0) { var i = t + e; return m(i < 0 ? [] : [this[i]]) } return m([this[e]]) }, append: function () { for (var e, t = r(), i = 0; i < arguments.length; i += 1) { e = i < 0 || arguments.length <= i ? void 0 : arguments[i]; for (var s = 0; s < this.length; s += 1)if ("string" == typeof e) { var a = t.createElement("div"); for (a.innerHTML = e; a.firstChild;)this[s].appendChild(a.firstChild) } else if (e instanceof c) for (var n = 0; n < e.length; n += 1)this[s].appendChild(e[n]); else this[s].appendChild(e) } return this }, prepend: function (e) { var t, i, s = r(); for (t = 0; t < this.length; t += 1)if ("string" == typeof e) { var a = s.createElement("div"); for (a.innerHTML = e, i = a.childNodes.length - 1; i >= 0; i -= 1)this[t].insertBefore(a.childNodes[i], this[t].childNodes[0]) } else if (e instanceof c) for (i = 0; i < e.length; i += 1)this[t].insertBefore(e[i], this[t].childNodes[0]); else this[t].insertBefore(e, this[t].childNodes[0]); return this }, next: function (e) { return this.length > 0 ? e ? this[0].nextElementSibling && m(this[0].nextElementSibling).is(e) ? m([this[0].nextElementSibling]) : m([]) : this[0].nextElementSibling ? m([this[0].nextElementSibling]) : m([]) : m([]) }, nextAll: function (e) { var t = [], i = this[0]; if (!i) return m([]); for (; i.nextElementSibling;) { var s = i.nextElementSibling; e ? m(s).is(e) && t.push(s) : t.push(s), i = s } return m(t) }, prev: function (e) { if (this.length > 0) { var t = this[0]; return e ? t.previousElementSibling && m(t.previousElementSibling).is(e) ? m([t.previousElementSibling]) : m([]) : t.previousElementSibling ? m([t.previousElementSibling]) : m([]) } return m([]) }, prevAll: function (e) { var t = [], i = this[0]; if (!i) return m([]); for (; i.previousElementSibling;) { var s = i.previousElementSibling; e ? m(s).is(e) && t.push(s) : t.push(s), i = s } return m(t) }, parent: function (e) { for (var t = [], i = 0; i < this.length; i += 1)null !== this[i].parentNode && (e ? m(this[i].parentNode).is(e) && t.push(this[i].parentNode) : t.push(this[i].parentNode)); return m(t) }, parents: function (e) { for (var t = [], i = 0; i < this.length; i += 1)for (var s = this[i].parentNode; s;)e ? m(s).is(e) && t.push(s) : t.push(s), s = s.parentNode; return m(t) }, closest: function (e) { var t = this; return void 0 === e ? m([]) : (t.is(e) || (t = t.parents(e).eq(0)), t) }, find: function (e) { for (var t = [], i = 0; i < this.length; i += 1)for (var s = this[i].querySelectorAll(e), a = 0; a < s.length; a += 1)t.push(s[a]); return m(t) }, children: function (e) { for (var t = [], i = 0; i < this.length; i += 1)for (var s = this[i].children, a = 0; a < s.length; a += 1)e && !m(s[a]).is(e) || t.push(s[a]); return m(t) }, filter: function (e) { return m(f(this, e)) }, remove: function () { for (var e = 0; e < this.length; e += 1)this[e].parentNode && this[e].parentNode.removeChild(this[e]); return this } }; function E(e, t) { return void 0 === t && (t = 0), setTimeout(e, t) } function x() { return Date.now() } function T(e, t) { void 0 === t && (t = "x"); var i, s, a, r = l(), n = r.getComputedStyle(e, null); return r.WebKitCSSMatrix ? ((s = n.transform || n.webkitTransform).split(",").length > 6 && (s = s.split(", ").map((function (e) { return e.replace(",", ".") })).join(", ")), a = new r.WebKitCSSMatrix("none" === s ? "" : s)) : i = (a = n.MozTransform || n.OTransform || n.MsTransform || n.msTransform || n.transform || n.getPropertyValue("transform").replace("translate(", "matrix(1, 0, 0, 1,")).toString().split(","), "x" === t && (s = r.WebKitCSSMatrix ? a.m41 : 16 === i.length ? parseFloat(i[12]) : parseFloat(i[4])), "y" === t && (s = r.WebKitCSSMatrix ? a.m42 : 16 === i.length ? parseFloat(i[13]) : parseFloat(i[5])), s || 0 } function C(e) { return "object" == typeof e && null !== e && e.constructor && e.constructor === Object } function S() { for (var e = Object(arguments.length <= 0 ? void 0 : arguments[0]), t = 1; t < arguments.length; t += 1) { var i = t < 0 || arguments.length <= t ? void 0 : arguments[t]; if (null != i) for (var s = Object.keys(Object(i)), a = 0, r = s.length; a < r; a += 1) { var n = s[a], l = Object.getOwnPropertyDescriptor(i, n); void 0 !== l && l.enumerable && (C(e[n]) && C(i[n]) ? S(e[n], i[n]) : !C(e[n]) && C(i[n]) ? (e[n] = {}, S(e[n], i[n])) : e[n] = i[n]) } } return e } function M(e, t) { Object.keys(t).forEach((function (i) { C(t[i]) && Object.keys(t[i]).forEach((function (s) { "function" == typeof t[i][s] && (t[i][s] = t[i][s].bind(e)) })), e[i] = t[i] })) } function z() { return g || (g = function () { var e = l(), t = r(); return { touch: !!("ontouchstart" in e || e.DocumentTouch && t instanceof e.DocumentTouch), pointerEvents: !!e.PointerEvent && "maxTouchPoints" in e.navigator && e.navigator.maxTouchPoints >= 0, observer: "MutationObserver" in e || "WebkitMutationObserver" in e, passiveListener: function () { var t = !1; try { var i = Object.defineProperty({}, "passive", { get: function () { t = !0 } }); e.addEventListener("testPassiveListener", null, i) } catch (e) { } return t }(), gestures: "ongesturestart" in e } }()), g } function P(e) { return void 0 === e && (e = {}), w || (w = function (e) { var t = (void 0 === e ? {} : e).userAgent, i = z(), s = l(), a = s.navigator.platform, r = t || s.navigator.userAgent, n = { ios: !1, android: !1 }, o = s.screen.width, d = s.screen.height, h = r.match(/(Android);?[\s\/]+([\d.]+)?/), p = r.match(/(iPad).*OS\s([\d_]+)/), u = r.match(/(iPod)(.*OS\s([\d_]+))?/), c = !p && r.match(/(iPhone\sOS|iOS)\s([\d_]+)/), v = "Win32" === a, f = "MacIntel" === a; return !p && f && i.touch && ["1024x1366", "1366x1024", "834x1194", "1194x834", "834x1112", "1112x834", "768x1024", "1024x768"].indexOf(o + "x" + d) >= 0 && ((p = r.match(/(Version)\/([\d.]+)/)) || (p = [0, 1, "13_0_0"]), f = !1), h && !v && (n.os = "android", n.android = !0), (p || c || u) && (n.os = "ios", n.ios = !0), n }(e)), w } function k() { return b || (b = function () { var e, t = l(); return { isEdge: !!t.navigator.userAgent.match(/Edge/g), isSafari: (e = t.navigator.userAgent.toLowerCase(), e.indexOf("safari") >= 0 && e.indexOf("chrome") < 0 && e.indexOf("android") < 0), isWebView: /(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(t.navigator.userAgent) } }()), b } Object.keys(y).forEach((function (e) { m.fn[e] = y[e] })); var $ = { name: "resize", create: function () { var e = this; S(e, { resize: { resizeHandler: function () { e && !e.destroyed && e.initialized && (e.emit("beforeResize"), e.emit("resize")) }, orientationChangeHandler: function () { e && !e.destroyed && e.initialized && e.emit("orientationchange") } } }) }, on: { init: function (e) { var t = l(); t.addEventListener("resize", e.resize.resizeHandler), t.addEventListener("orientationchange", e.resize.orientationChangeHandler) }, destroy: function (e) { var t = l(); t.removeEventListener("resize", e.resize.resizeHandler), t.removeEventListener("orientationchange", e.resize.orientationChangeHandler) } } }, L = { attach: function (e, t) { void 0 === t && (t = {}); var i = l(), s = this, a = new (i.MutationObserver || i.WebkitMutationObserver)((function (e) { if (1 !== e.length) { var t = function () { s.emit("observerUpdate", e[0]) }; i.requestAnimationFrame ? i.requestAnimationFrame(t) : i.setTimeout(t, 0) } else s.emit("observerUpdate", e[0]) })); a.observe(e, { attributes: void 0 === t.attributes || t.attributes, childList: void 0 === t.childList || t.childList, characterData: void 0 === t.characterData || t.characterData }), s.observer.observers.push(a) }, init: function () { if (this.support.observer && this.params.observer) { if (this.params.observeParents) for (var e = this.$el.parents(), t = 0; t < e.length; t += 1)this.observer.attach(e[t]); this.observer.attach(this.$el[0], { childList: this.params.observeSlideChildren }), this.observer.attach(this.$wrapperEl[0], { attributes: !1 }) } }, destroy: function () { this.observer.observers.forEach((function (e) { e.disconnect() })), this.observer.observers = [] } }, I = { name: "observer", params: { observer: !1, observeParents: !1, observeSlideChildren: !1 }, create: function () { M(this, { observer: t(t({}, L), {}, { observers: [] }) }) }, on: { init: function (e) { e.observer.init() }, destroy: function (e) { e.observer.destroy() } } }; function O(e) { var t = r(), i = l(), s = this.touchEventsData, a = this.params, n = this.touches; if (!this.animating || !a.preventInteractionOnTransition) { var o = e; o.originalEvent && (o = o.originalEvent); var d = m(o.target); if (("wrapper" !== a.touchEventsTarget || d.closest(this.wrapperEl).length) && (s.isTouchEvent = "touchstart" === o.type, (s.isTouchEvent || !("which" in o) || 3 !== o.which) && !(!s.isTouchEvent && "button" in o && o.button > 0 || s.isTouched && s.isMoved))) if (a.noSwiping && d.closest(a.noSwipingSelector ? a.noSwipingSelector : "." + a.noSwipingClass)[0]) this.allowClick = !0; else if (!a.swipeHandler || d.closest(a.swipeHandler)[0]) { n.currentX = "touchstart" === o.type ? o.targetTouches[0].pageX : o.pageX, n.currentY = "touchstart" === o.type ? o.targetTouches[0].pageY : o.pageY; var h = n.currentX, p = n.currentY, u = a.edgeSwipeDetection || a.iOSEdgeSwipeDetection, c = a.edgeSwipeThreshold || a.iOSEdgeSwipeThreshold; if (!u || !(h <= c || h >= i.screen.width - c)) { if (S(s, { isTouched: !0, isMoved: !1, allowTouchCallbacks: !0, isScrolling: void 0, startMoving: void 0 }), n.startX = h, n.startY = p, s.touchStartTime = x(), this.allowClick = !0, this.updateSize(), this.swipeDirection = void 0, a.threshold > 0 && (s.allowThresholdMove = !1), "touchstart" !== o.type) { var v = !0; d.is(s.formElements) && (v = !1), t.activeElement && m(t.activeElement).is(s.formElements) && t.activeElement !== d[0] && t.activeElement.blur(); var f = v && this.allowTouchMove && a.touchStartPreventDefault; (a.touchStartForcePreventDefault || f) && o.preventDefault() } this.emit("touchStart", o) } } } } function A(e) { var t = r(), i = this.touchEventsData, s = this.params, a = this.touches, n = this.rtlTranslate, l = e; if (l.originalEvent && (l = l.originalEvent), i.isTouched) { if (!i.isTouchEvent || "touchmove" === l.type) { var o = "touchmove" === l.type && l.targetTouches && (l.targetTouches[0] || l.changedTouches[0]), d = "touchmove" === l.type ? o.pageX : l.pageX, h = "touchmove" === l.type ? o.pageY : l.pageY; if (l.preventedByNestedSwiper) return a.startX = d, void (a.startY = h); if (!this.allowTouchMove) return this.allowClick = !1, void (i.isTouched && (S(a, { startX: d, startY: h, currentX: d, currentY: h }), i.touchStartTime = x())); if (i.isTouchEvent && s.touchReleaseOnEdges && !s.loop) if (this.isVertical()) { if (h < a.startY && this.translate <= this.maxTranslate() || h > a.startY && this.translate >= this.minTranslate()) return i.isTouched = !1, void (i.isMoved = !1) } else if (d < a.startX && this.translate <= this.maxTranslate() || d > a.startX && this.translate >= this.minTranslate()) return; if (i.isTouchEvent && t.activeElement && l.target === t.activeElement && m(l.target).is(i.formElements)) return i.isMoved = !0, void (this.allowClick = !1); if (i.allowTouchCallbacks && this.emit("touchMove", l), !(l.targetTouches && l.targetTouches.length > 1)) { a.currentX = d, a.currentY = h; var p = a.currentX - a.startX, u = a.currentY - a.startY; if (!(this.params.threshold && Math.sqrt(Math.pow(p, 2) + Math.pow(u, 2)) < this.params.threshold)) { var c; if (void 0 === i.isScrolling) this.isHorizontal() && a.currentY === a.startY || this.isVertical() && a.currentX === a.startX ? i.isScrolling = !1 : p * p + u * u >= 25 && (c = 180 * Math.atan2(Math.abs(u), Math.abs(p)) / Math.PI, i.isScrolling = this.isHorizontal() ? c > s.touchAngle : 90 - c > s.touchAngle); if (i.isScrolling && this.emit("touchMoveOpposite", l), void 0 === i.startMoving && (a.currentX === a.startX && a.currentY === a.startY || (i.startMoving = !0)), i.isScrolling) i.isTouched = !1; else if (i.startMoving) { this.allowClick = !1, !s.cssMode && l.cancelable && l.preventDefault(), s.touchMoveStopPropagation && !s.nested && l.stopPropagation(), i.isMoved || (s.loop && this.loopFix(), i.startTranslate = this.getTranslate(), this.setTransition(0), this.animating && this.$wrapperEl.trigger("webkitTransitionEnd transitionend"), i.allowMomentumBounce = !1, !s.grabCursor || !0 !== this.allowSlideNext && !0 !== this.allowSlidePrev || this.setGrabCursor(!0), this.emit("sliderFirstMove", l)), this.emit("sliderMove", l), i.isMoved = !0; var v = this.isHorizontal() ? p : u; a.diff = v, v *= s.touchRatio, n && (v = -v), this.swipeDirection = v > 0 ? "prev" : "next", i.currentTranslate = v + i.startTranslate; var f = !0, g = s.resistanceRatio; if (s.touchReleaseOnEdges && (g = 0), v > 0 && i.currentTranslate > this.minTranslate() ? (f = !1, s.resistance && (i.currentTranslate = this.minTranslate() - 1 + Math.pow(-this.minTranslate() + i.startTranslate + v, g))) : v < 0 && i.currentTranslate < this.maxTranslate() && (f = !1, s.resistance && (i.currentTranslate = this.maxTranslate() + 1 - Math.pow(this.maxTranslate() - i.startTranslate - v, g))), f && (l.preventedByNestedSwiper = !0), !this.allowSlideNext && "next" === this.swipeDirection && i.currentTranslate < i.startTranslate && (i.currentTranslate = i.startTranslate), !this.allowSlidePrev && "prev" === this.swipeDirection && i.currentTranslate > i.startTranslate && (i.currentTranslate = i.startTranslate), s.threshold > 0) { if (!(Math.abs(v) > s.threshold || i.allowThresholdMove)) return void (i.currentTranslate = i.startTranslate); if (!i.allowThresholdMove) return i.allowThresholdMove = !0, a.startX = a.currentX, a.startY = a.currentY, i.currentTranslate = i.startTranslate, void (a.diff = this.isHorizontal() ? a.currentX - a.startX : a.currentY - a.startY) } s.followFinger && !s.cssMode && ((s.freeMode || s.watchSlidesProgress || s.watchSlidesVisibility) && (this.updateActiveIndex(), this.updateSlidesClasses()), s.freeMode && (0 === i.velocities.length && i.velocities.push({ position: a[this.isHorizontal() ? "startX" : "startY"], time: i.touchStartTime }), i.velocities.push({ position: a[this.isHorizontal() ? "currentX" : "currentY"], time: x() })), this.updateProgress(i.currentTranslate), this.setTranslate(i.currentTranslate)) } } } } } else i.startMoving && i.isScrolling && this.emit("touchMoveOpposite", l) } function D(e) { var t = this, i = t.touchEventsData, s = t.params, a = t.touches, r = t.rtlTranslate, n = t.$wrapperEl, l = t.slidesGrid, o = t.snapGrid, d = e; if (d.originalEvent && (d = d.originalEvent), i.allowTouchCallbacks && t.emit("touchEnd", d), i.allowTouchCallbacks = !1, !i.isTouched) return i.isMoved && s.grabCursor && t.setGrabCursor(!1), i.isMoved = !1, void (i.startMoving = !1); s.grabCursor && i.isMoved && i.isTouched && (!0 === t.allowSlideNext || !0 === t.allowSlidePrev) && t.setGrabCursor(!1); var h, p = x(), u = p - i.touchStartTime; if (t.allowClick && (t.updateClickedSlide(d), t.emit("tap click", d), u < 300 && p - i.lastClickTime < 300 && t.emit("doubleTap doubleClick", d)), i.lastClickTime = x(), E((function () { t.destroyed || (t.allowClick = !0) })), !i.isTouched || !i.isMoved || !t.swipeDirection || 0 === a.diff || i.currentTranslate === i.startTranslate) return i.isTouched = !1, i.isMoved = !1, void (i.startMoving = !1); if (i.isTouched = !1, i.isMoved = !1, i.startMoving = !1, h = s.followFinger ? r ? t.translate : -t.translate : -i.currentTranslate, !s.cssMode) if (s.freeMode) { if (h < -t.minTranslate()) return void t.slideTo(t.activeIndex); if (h > -t.maxTranslate()) return void (t.slides.length < o.length ? t.slideTo(o.length - 1) : t.slideTo(t.slides.length - 1)); if (s.freeModeMomentum) { if (i.velocities.length > 1) { var c = i.velocities.pop(), v = i.velocities.pop(), f = c.position - v.position, m = c.time - v.time; t.velocity = f / m, t.velocity /= 2, Math.abs(t.velocity) < s.freeModeMinimumVelocity && (t.velocity = 0), (m > 150 || x() - c.time > 300) && (t.velocity = 0) } else t.velocity = 0; t.velocity *= s.freeModeMomentumVelocityRatio, i.velocities.length = 0; var g = 1e3 * s.freeModeMomentumRatio, w = t.velocity * g, b = t.translate + w; r && (b = -b); var y, T, C = !1, S = 20 * Math.abs(t.velocity) * s.freeModeMomentumBounceRatio; if (b < t.maxTranslate()) s.freeModeMomentumBounce ? (b + t.maxTranslate() < -S && (b = t.maxTranslate() - S), y = t.maxTranslate(), C = !0, i.allowMomentumBounce = !0) : b = t.maxTranslate(), s.loop && s.centeredSlides && (T = !0); else if (b > t.minTranslate()) s.freeModeMomentumBounce ? (b - t.minTranslate() > S && (b = t.minTranslate() + S), y = t.minTranslate(), C = !0, i.allowMomentumBounce = !0) : b = t.minTranslate(), s.loop && s.centeredSlides && (T = !0); else if (s.freeModeSticky) { for (var M, z = 0; z < o.length; z += 1)if (o[z] > -b) { M = z; break } b = -(b = Math.abs(o[M] - b) < Math.abs(o[M - 1] - b) || "next" === t.swipeDirection ? o[M] : o[M - 1]) } if (T && t.once("transitionEnd", (function () { t.loopFix() })), 0 !== t.velocity) { if (g = r ? Math.abs((-b - t.translate) / t.velocity) : Math.abs((b - t.translate) / t.velocity), s.freeModeSticky) { var P = Math.abs((r ? -b : b) - t.translate), k = t.slidesSizesGrid[t.activeIndex]; g = P < k ? s.speed : P < 2 * k ? 1.5 * s.speed : 2.5 * s.speed } } else if (s.freeModeSticky) return void t.slideToClosest(); s.freeModeMomentumBounce && C ? (t.updateProgress(y), t.setTransition(g), t.setTranslate(b), t.transitionStart(!0, t.swipeDirection), t.animating = !0, n.transitionEnd((function () { t && !t.destroyed && i.allowMomentumBounce && (t.emit("momentumBounce"), t.setTransition(s.speed), setTimeout((function () { t.setTranslate(y), n.transitionEnd((function () { t && !t.destroyed && t.transitionEnd() })) }), 0)) }))) : t.velocity ? (t.updateProgress(b), t.setTransition(g), t.setTranslate(b), t.transitionStart(!0, t.swipeDirection), t.animating || (t.animating = !0, n.transitionEnd((function () { t && !t.destroyed && t.transitionEnd() })))) : t.updateProgress(b), t.updateActiveIndex(), t.updateSlidesClasses() } else if (s.freeModeSticky) return void t.slideToClosest(); (!s.freeModeMomentum || u >= s.longSwipesMs) && (t.updateProgress(), t.updateActiveIndex(), t.updateSlidesClasses()) } else { for (var $ = 0, L = t.slidesSizesGrid[0], I = 0; I < l.length; I += I < s.slidesPerGroupSkip ? 1 : s.slidesPerGroup) { var O = I < s.slidesPerGroupSkip - 1 ? 1 : s.slidesPerGroup; void 0 !== l[I + O] ? h >= l[I] && h < l[I + O] && ($ = I, L = l[I + O] - l[I]) : h >= l[I] && ($ = I, L = l[l.length - 1] - l[l.length - 2]) } var A = (h - l[$]) / L, D = $ < s.slidesPerGroupSkip - 1 ? 1 : s.slidesPerGroup; if (u > s.longSwipesMs) { if (!s.longSwipes) return void t.slideTo(t.activeIndex); "next" === t.swipeDirection && (A >= s.longSwipesRatio ? t.slideTo($ + D) : t.slideTo($)), "prev" === t.swipeDirection && (A > 1 - s.longSwipesRatio ? t.slideTo($ + D) : t.slideTo($)) } else { if (!s.shortSwipes) return void t.slideTo(t.activeIndex); t.navigation && (d.target === t.navigation.nextEl || d.target === t.navigation.prevEl) ? d.target === t.navigation.nextEl ? t.slideTo($ + D) : t.slideTo($) : ("next" === t.swipeDirection && t.slideTo($ + D), "prev" === t.swipeDirection && t.slideTo($)) } } } function G() { var e = this.params, t = this.el; if (!t || 0 !== t.offsetWidth) { e.breakpoints && this.setBreakpoint(); var i = this.allowSlideNext, s = this.allowSlidePrev, a = this.snapGrid; this.allowSlideNext = !0, this.allowSlidePrev = !0, this.updateSize(), this.updateSlides(), this.updateSlidesClasses(), ("auto" === e.slidesPerView || e.slidesPerView > 1) && this.isEnd && !this.isBeginning && !this.params.centeredSlides ? this.slideTo(this.slides.length - 1, 0, !1, !0) : this.slideTo(this.activeIndex, 0, !1, !0), this.autoplay && this.autoplay.running && this.autoplay.paused && this.autoplay.run(), this.allowSlidePrev = s, this.allowSlideNext = i, this.params.watchOverflow && a !== this.snapGrid && this.checkOverflow() } } function N(e) { this.allowClick || (this.params.preventClicks && e.preventDefault(), this.params.preventClicksPropagation && this.animating && (e.stopPropagation(), e.stopImmediatePropagation())) } function B() { var e = this.wrapperEl, t = this.rtlTranslate; this.previousTranslate = this.translate, this.isHorizontal() ? this.translate = t ? e.scrollWidth - e.offsetWidth - e.scrollLeft : -e.scrollLeft : this.translate = -e.scrollTop, -0 === this.translate && (this.translate = 0), this.updateActiveIndex(), this.updateSlidesClasses(); var i = this.maxTranslate() - this.minTranslate(); (0 === i ? 0 : (this.translate - this.minTranslate()) / i) !== this.progress && this.updateProgress(t ? -this.translate : this.translate), this.emit("setTranslate", this.translate, !1) } var H = !1; function X() { } var Y = { init: !0, direction: "horizontal", touchEventsTarget: "container", initialSlide: 0, speed: 300, cssMode: !1, updateOnWindowResize: !0, width: null, height: null, preventInteractionOnTransition: !1, userAgent: null, url: null, edgeSwipeDetection: !1, edgeSwipeThreshold: 20, freeMode: !1, freeModeMomentum: !0, freeModeMomentumRatio: 1, freeModeMomentumBounce: !0, freeModeMomentumBounceRatio: 1, freeModeMomentumVelocityRatio: 1, freeModeSticky: !1, freeModeMinimumVelocity: .02, autoHeight: !1, setWrapperSize: !1, virtualTranslate: !1, effect: "slide", breakpoints: void 0, spaceBetween: 0, slidesPerView: 1, slidesPerColumn: 1, slidesPerColumnFill: "column", slidesPerGroup: 1, slidesPerGroupSkip: 0, centeredSlides: !1, centeredSlidesBounds: !1, slidesOffsetBefore: 0, slidesOffsetAfter: 0, normalizeSlideIndex: !0, centerInsufficientSlides: !1, watchOverflow: !1, roundLengths: !1, touchRatio: 1, touchAngle: 45, simulateTouch: !0, shortSwipes: !0, longSwipes: !0, longSwipesRatio: .5, longSwipesMs: 300, followFinger: !0, allowTouchMove: !0, threshold: 0, touchMoveStopPropagation: !1, touchStartPreventDefault: !0, touchStartForcePreventDefault: !1, touchReleaseOnEdges: !1, uniqueNavElements: !0, resistance: !0, resistanceRatio: .85, watchSlidesProgress: !1, watchSlidesVisibility: !1, grabCursor: !1, preventClicks: !0, preventClicksPropagation: !0, slideToClickedSlide: !1, preloadImages: !0, updateOnImagesReady: !0, loop: !1, loopAdditionalSlides: 0, loopedSlides: null, loopFillGroupWithBlank: !1, loopPreventsSlide: !0, allowSlidePrev: !0, allowSlideNext: !0, swipeHandler: null, noSwiping: !0, noSwipingClass: "swiper-no-swiping", noSwipingSelector: null, passiveListeners: !0, containerModifierClass: "swiper-container-", slideClass: "swiper-slide", slideBlankClass: "swiper-slide-invisible-blank", slideActiveClass: "swiper-slide-active", slideDuplicateActiveClass: "swiper-slide-duplicate-active", slideVisibleClass: "swiper-slide-visible", slideDuplicateClass: "swiper-slide-duplicate", slideNextClass: "swiper-slide-next", slideDuplicateNextClass: "swiper-slide-duplicate-next", slidePrevClass: "swiper-slide-prev", slideDuplicatePrevClass: "swiper-slide-duplicate-prev", wrapperClass: "swiper-wrapper", runCallbacksOnInit: !0, _emitClasses: !1 }, V = { modular: { useParams: function (e) { var t = this; t.modules && Object.keys(t.modules).forEach((function (i) { var s = t.modules[i]; s.params && S(e, s.params) })) }, useModules: function (e) { void 0 === e && (e = {}); var t = this; t.modules && Object.keys(t.modules).forEach((function (i) { var s = t.modules[i], a = e[i] || {}; s.on && t.on && Object.keys(s.on).forEach((function (e) { t.on(e, s.on[e]) })), s.create && s.create.bind(t)(a) })) } }, eventsEmitter: { on: function (e, t, i) { var s = this; if ("function" != typeof t) return s; var a = i ? "unshift" : "push"; return e.split(" ").forEach((function (e) { s.eventsListeners[e] || (s.eventsListeners[e] = []), s.eventsListeners[e][a](t) })), s }, once: function (e, t, i) { var s = this; if ("function" != typeof t) return s; function a() { s.off(e, a), a.__emitterProxy && delete a.__emitterProxy; for (var i = arguments.length, r = new Array(i), n = 0; n < i; n++)r[n] = arguments[n]; t.apply(s, r) } return a.__emitterProxy = t, s.on(e, a, i) }, onAny: function (e, t) { if ("function" != typeof e) return this; var i = t ? "unshift" : "push"; return this.eventsAnyListeners.indexOf(e) < 0 && this.eventsAnyListeners[i](e), this }, offAny: function (e) { if (!this.eventsAnyListeners) return this; var t = this.eventsAnyListeners.indexOf(e); return t >= 0 && this.eventsAnyListeners.splice(t, 1), this }, off: function (e, t) { var i = this; return i.eventsListeners ? (e.split(" ").forEach((function (e) { void 0 === t ? i.eventsListeners[e] = [] : i.eventsListeners[e] && i.eventsListeners[e].forEach((function (s, a) { (s === t || s.__emitterProxy && s.__emitterProxy === t) && i.eventsListeners[e].splice(a, 1) })) })), i) : i }, emit: function () { var e, t, i, s = this; if (!s.eventsListeners) return s; for (var a = arguments.length, r = new Array(a), n = 0; n < a; n++)r[n] = arguments[n]; "string" == typeof r[0] || Array.isArray(r[0]) ? (e = r[0], t = r.slice(1, r.length), i = s) : (e = r[0].events, t = r[0].data, i = r[0].context || s), t.unshift(i); var l = Array.isArray(e) ? e : e.split(" "); return l.forEach((function (e) { if (s.eventsListeners && s.eventsListeners[e]) { var a = []; s.eventsListeners[e].forEach((function (e) { a.push(e) })), a.forEach((function (e) { e.apply(i, t) })) } })), s } }, update: { updateSize: function () { var e, t, i = this.$el; e = void 0 !== this.params.width && null !== this.params.width ? this.params.width : i[0].clientWidth, t = void 0 !== this.params.height && null !== this.params.width ? this.params.height : i[0].clientHeight, 0 === e && this.isHorizontal() || 0 === t && this.isVertical() || (e = e - parseInt(i.css("padding-left") || 0, 10) - parseInt(i.css("padding-right") || 0, 10), t = t - parseInt(i.css("padding-top") || 0, 10) - parseInt(i.css("padding-bottom") || 0, 10), Number.isNaN(e) && (e = 0), Number.isNaN(t) && (t = 0), S(this, { width: e, height: t, size: this.isHorizontal() ? e : t })) }, updateSlides: function () { var e = l(), t = this.params, i = this.$wrapperEl, s = this.size, a = this.rtlTranslate, r = this.wrongRTL, n = this.virtual && t.virtual.enabled, o = n ? this.virtual.slides.length : this.slides.length, d = i.children("." + this.params.slideClass), h = n ? this.virtual.slides.length : d.length, p = [], u = [], c = []; function v(e, i) { return !t.cssMode || i !== d.length - 1 } var f = t.slidesOffsetBefore; "function" == typeof f && (f = t.slidesOffsetBefore.call(this)); var m = t.slidesOffsetAfter; "function" == typeof m && (m = t.slidesOffsetAfter.call(this)); var g = this.snapGrid.length, w = this.snapGrid.length, b = t.spaceBetween, y = -f, E = 0, x = 0; if (void 0 !== s) { var T, C; "string" == typeof b && b.indexOf("%") >= 0 && (b = parseFloat(b.replace("%", "")) / 100 * s), this.virtualSize = -b, a ? d.css({ marginLeft: "", marginTop: "" }) : d.css({ marginRight: "", marginBottom: "" }), t.slidesPerColumn > 1 && (T = Math.floor(h / t.slidesPerColumn) === h / this.params.slidesPerColumn ? h : Math.ceil(h / t.slidesPerColumn) * t.slidesPerColumn, "auto" !== t.slidesPerView && "row" === t.slidesPerColumnFill && (T = Math.max(T, t.slidesPerView * t.slidesPerColumn))); for (var M, z = t.slidesPerColumn, P = T / z, k = Math.floor(h / t.slidesPerColumn), $ = 0; $ < h; $ += 1) { C = 0; var L = d.eq($); if (t.slidesPerColumn > 1) { var I = void 0, O = void 0, A = void 0; if ("row" === t.slidesPerColumnFill && t.slidesPerGroup > 1) { var D = Math.floor($ / (t.slidesPerGroup * t.slidesPerColumn)), G = $ - t.slidesPerColumn * t.slidesPerGroup * D, N = 0 === D ? t.slidesPerGroup : Math.min(Math.ceil((h - D * z * t.slidesPerGroup) / z), t.slidesPerGroup); I = (O = G - (A = Math.floor(G / N)) * N + D * t.slidesPerGroup) + A * T / z, L.css({ "-webkit-box-ordinal-group": I, "-moz-box-ordinal-group": I, "-ms-flex-order": I, "-webkit-order": I, order: I }) } else "column" === t.slidesPerColumnFill ? (A = $ - (O = Math.floor($ / z)) * z, (O > k || O === k && A === z - 1) && (A += 1) >= z && (A = 0, O += 1)) : O = $ - (A = Math.floor($ / P)) * P; L.css("margin-" + (this.isHorizontal() ? "top" : "left"), 0 !== A && t.spaceBetween && t.spaceBetween + "px") } if ("none" !== L.css("display")) { if ("auto" === t.slidesPerView) { var B = e.getComputedStyle(L[0], null), H = L[0].style.transform, X = L[0].style.webkitTransform; if (H && (L[0].style.transform = "none"), X && (L[0].style.webkitTransform = "none"), t.roundLengths) C = this.isHorizontal() ? L.outerWidth(!0) : L.outerHeight(!0); else if (this.isHorizontal()) { var Y = parseFloat(B.getPropertyValue("width") || 0), V = parseFloat(B.getPropertyValue("padding-left") || 0), F = parseFloat(B.getPropertyValue("padding-right") || 0), W = parseFloat(B.getPropertyValue("margin-left") || 0), R = parseFloat(B.getPropertyValue("margin-right") || 0), q = B.getPropertyValue("box-sizing"); C = q && "border-box" === q ? Y + W + R : Y + V + F + W + R } else { var j = parseFloat(B.getPropertyValue("height") || 0), _ = parseFloat(B.getPropertyValue("padding-top") || 0), U = parseFloat(B.getPropertyValue("padding-bottom") || 0), K = parseFloat(B.getPropertyValue("margin-top") || 0), Z = parseFloat(B.getPropertyValue("margin-bottom") || 0), J = B.getPropertyValue("box-sizing"); C = J && "border-box" === J ? j + K + Z : j + _ + U + K + Z } H && (L[0].style.transform = H), X && (L[0].style.webkitTransform = X), t.roundLengths && (C = Math.floor(C)) } else C = (s - (t.slidesPerView - 1) * b) / t.slidesPerView, t.roundLengths && (C = Math.floor(C)), d[$] && (this.isHorizontal() ? d[$].style.width = C + "px" : d[$].style.height = C + "px"); d[$] && (d[$].swiperSlideSize = C), c.push(C), t.centeredSlides ? (y = y + C / 2 + E / 2 + b, 0 === E && 0 !== $ && (y = y - s / 2 - b), 0 === $ && (y = y - s / 2 - b), Math.abs(y) < .001 && (y = 0), t.roundLengths && (y = Math.floor(y)), x % t.slidesPerGroup == 0 && p.push(y), u.push(y)) : (t.roundLengths && (y = Math.floor(y)), (x - Math.min(this.params.slidesPerGroupSkip, x)) % this.params.slidesPerGroup == 0 && p.push(y), u.push(y), y = y + C + b), this.virtualSize += C + b, E = C, x += 1 } } if (this.virtualSize = Math.max(this.virtualSize, s) + m, a && r && ("slide" === t.effect || "coverflow" === t.effect) && i.css({ width: this.virtualSize + t.spaceBetween + "px" }), t.setWrapperSize && (this.isHorizontal() ? i.css({ width: this.virtualSize + t.spaceBetween + "px" }) : i.css({ height: this.virtualSize + t.spaceBetween + "px" })), t.slidesPerColumn > 1 && (this.virtualSize = (C + t.spaceBetween) * T, this.virtualSize = Math.ceil(this.virtualSize / t.slidesPerColumn) - t.spaceBetween, this.isHorizontal() ? i.css({ width: this.virtualSize + t.spaceBetween + "px" }) : i.css({ height: this.virtualSize + t.spaceBetween + "px" }), t.centeredSlides)) { M = []; for (var Q = 0; Q < p.length; Q += 1) { var ee = p[Q]; t.roundLengths && (ee = Math.floor(ee)), p[Q] < this.virtualSize + p[0] && M.push(ee) } p = M } if (!t.centeredSlides) { M = []; for (var te = 0; te < p.length; te += 1) { var ie = p[te]; t.roundLengths && (ie = Math.floor(ie)), p[te] <= this.virtualSize - s && M.push(ie) } p = M, Math.floor(this.virtualSize - s) - Math.floor(p[p.length - 1]) > 1 && p.push(this.virtualSize - s) } if (0 === p.length && (p = [0]), 0 !== t.spaceBetween && (this.isHorizontal() ? a ? d.filter(v).css({ marginLeft: b + "px" }) : d.filter(v).css({ marginRight: b + "px" }) : d.filter(v).css({ marginBottom: b + "px" })), t.centeredSlides && t.centeredSlidesBounds) { var se = 0; c.forEach((function (e) { se += e + (t.spaceBetween ? t.spaceBetween : 0) })); var ae = (se -= t.spaceBetween) - s; p = p.map((function (e) { return e < 0 ? -f : e > ae ? ae + m : e })) } if (t.centerInsufficientSlides) { var re = 0; if (c.forEach((function (e) { re += e + (t.spaceBetween ? t.spaceBetween : 0) })), (re -= t.spaceBetween) < s) { var ne = (s - re) / 2; p.forEach((function (e, t) { p[t] = e - ne })), u.forEach((function (e, t) { u[t] = e + ne })) } } S(this, { slides: d, snapGrid: p, slidesGrid: u, slidesSizesGrid: c }), h !== o && this.emit("slidesLengthChange"), p.length !== g && (this.params.watchOverflow && this.checkOverflow(), this.emit("snapGridLengthChange")), u.length !== w && this.emit("slidesGridLengthChange"), (t.watchSlidesProgress || t.watchSlidesVisibility) && this.updateSlidesOffset() } }, updateAutoHeight: function (e) { var t, i = [], s = 0; if ("number" == typeof e ? this.setTransition(e) : !0 === e && this.setTransition(this.params.speed), "auto" !== this.params.slidesPerView && this.params.slidesPerView > 1) if (this.params.centeredSlides) this.visibleSlides.each((function (e) { i.push(e) })); else for (t = 0; t < Math.ceil(this.params.slidesPerView); t += 1) { var a = this.activeIndex + t; if (a > this.slides.length) break; i.push(this.slides.eq(a)[0]) } else i.push(this.slides.eq(this.activeIndex)[0]); for (t = 0; t < i.length; t += 1)if (void 0 !== i[t]) { var r = i[t].offsetHeight; s = r > s ? r : s } s && this.$wrapperEl.css("height", s + "px") }, updateSlidesOffset: function () { for (var e = this.slides, t = 0; t < e.length; t += 1)e[t].swiperSlideOffset = this.isHorizontal() ? e[t].offsetLeft : e[t].offsetTop }, updateSlidesProgress: function (e) { void 0 === e && (e = this && this.translate || 0); var t = this.params, i = this.slides, s = this.rtlTranslate; if (0 !== i.length) { void 0 === i[0].swiperSlideOffset && this.updateSlidesOffset(); var a = -e; s && (a = e), i.removeClass(t.slideVisibleClass), this.visibleSlidesIndexes = [], this.visibleSlides = []; for (var r = 0; r < i.length; r += 1) { var n = i[r], l = (a + (t.centeredSlides ? this.minTranslate() : 0) - n.swiperSlideOffset) / (n.swiperSlideSize + t.spaceBetween); if (t.watchSlidesVisibility || t.centeredSlides && t.autoHeight) { var o = -(a - n.swiperSlideOffset), d = o + this.slidesSizesGrid[r]; (o >= 0 && o < this.size - 1 || d > 1 && d <= this.size || o <= 0 && d >= this.size) && (this.visibleSlides.push(n), this.visibleSlidesIndexes.push(r), i.eq(r).addClass(t.slideVisibleClass)) } n.progress = s ? -l : l } this.visibleSlides = m(this.visibleSlides) } }, updateProgress: function (e) { if (void 0 === e) { var t = this.rtlTranslate ? -1 : 1; e = this && this.translate && this.translate * t || 0 } var i = this.params, s = this.maxTranslate() - this.minTranslate(), a = this.progress, r = this.isBeginning, n = this.isEnd, l = r, o = n; 0 === s ? (a = 0, r = !0, n = !0) : (r = (a = (e - this.minTranslate()) / s) <= 0, n = a >= 1), S(this, { progress: a, isBeginning: r, isEnd: n }), (i.watchSlidesProgress || i.watchSlidesVisibility || i.centeredSlides && i.autoHeight) && this.updateSlidesProgress(e), r && !l && this.emit("reachBeginning toEdge"), n && !o && this.emit("reachEnd toEdge"), (l && !r || o && !n) && this.emit("fromEdge"), this.emit("progress", a) }, updateSlidesClasses: function () { var e, t = this.slides, i = this.params, s = this.$wrapperEl, a = this.activeIndex, r = this.realIndex, n = this.virtual && i.virtual.enabled; t.removeClass(i.slideActiveClass + " " + i.slideNextClass + " " + i.slidePrevClass + " " + i.slideDuplicateActiveClass + " " + i.slideDuplicateNextClass + " " + i.slideDuplicatePrevClass), (e = n ? this.$wrapperEl.find("." + i.slideClass + '[data-swiper-slide-index="' + a + '"]') : t.eq(a)).addClass(i.slideActiveClass), i.loop && (e.hasClass(i.slideDuplicateClass) ? s.children("." + i.slideClass + ":not(." + i.slideDuplicateClass + ')[data-swiper-slide-index="' + r + '"]').addClass(i.slideDuplicateActiveClass) : s.children("." + i.slideClass + "." + i.slideDuplicateClass + '[data-swiper-slide-index="' + r + '"]').addClass(i.slideDuplicateActiveClass)); var l = e.nextAll("." + i.slideClass).eq(0).addClass(i.slideNextClass); i.loop && 0 === l.length && (l = t.eq(0)).addClass(i.slideNextClass); var o = e.prevAll("." + i.slideClass).eq(0).addClass(i.slidePrevClass); i.loop && 0 === o.length && (o = t.eq(-1)).addClass(i.slidePrevClass), i.loop && (l.hasClass(i.slideDuplicateClass) ? s.children("." + i.slideClass + ":not(." + i.slideDuplicateClass + ')[data-swiper-slide-index="' + l.attr("data-swiper-slide-index") + '"]').addClass(i.slideDuplicateNextClass) : s.children("." + i.slideClass + "." + i.slideDuplicateClass + '[data-swiper-slide-index="' + l.attr("data-swiper-slide-index") + '"]').addClass(i.slideDuplicateNextClass), o.hasClass(i.slideDuplicateClass) ? s.children("." + i.slideClass + ":not(." + i.slideDuplicateClass + ')[data-swiper-slide-index="' + o.attr("data-swiper-slide-index") + '"]').addClass(i.slideDuplicatePrevClass) : s.children("." + i.slideClass + "." + i.slideDuplicateClass + '[data-swiper-slide-index="' + o.attr("data-swiper-slide-index") + '"]').addClass(i.slideDuplicatePrevClass)), this.emitSlidesClasses() }, updateActiveIndex: function (e) { var t, i = this.rtlTranslate ? this.translate : -this.translate, s = this.slidesGrid, a = this.snapGrid, r = this.params, n = this.activeIndex, l = this.realIndex, o = this.snapIndex, d = e; if (void 0 === d) { for (var h = 0; h < s.length; h += 1)void 0 !== s[h + 1] ? i >= s[h] && i < s[h + 1] - (s[h + 1] - s[h]) / 2 ? d = h : i >= s[h] && i < s[h + 1] && (d = h + 1) : i >= s[h] && (d = h); r.normalizeSlideIndex && (d < 0 || void 0 === d) && (d = 0) } if (a.indexOf(i) >= 0) t = a.indexOf(i); else { var p = Math.min(r.slidesPerGroupSkip, d); t = p + Math.floor((d - p) / r.slidesPerGroup) } if (t >= a.length && (t = a.length - 1), d !== n) { var u = parseInt(this.slides.eq(d).attr("data-swiper-slide-index") || d, 10); S(this, { snapIndex: t, realIndex: u, previousIndex: n, activeIndex: d }), this.emit("activeIndexChange"), this.emit("snapIndexChange"), l !== u && this.emit("realIndexChange"), (this.initialized || this.params.runCallbacksOnInit) && this.emit("slideChange") } else t !== o && (this.snapIndex = t, this.emit("snapIndexChange")) }, updateClickedSlide: function (e) { var t = this.params, i = m(e.target).closest("." + t.slideClass)[0], s = !1; if (i) for (var a = 0; a < this.slides.length; a += 1)this.slides[a] === i && (s = !0); if (!i || !s) return this.clickedSlide = void 0, void (this.clickedIndex = void 0); this.clickedSlide = i, this.virtual && this.params.virtual.enabled ? this.clickedIndex = parseInt(m(i).attr("data-swiper-slide-index"), 10) : this.clickedIndex = m(i).index(), t.slideToClickedSlide && void 0 !== this.clickedIndex && this.clickedIndex !== this.activeIndex && this.slideToClickedSlide() } }, translate: { getTranslate: function (e) { void 0 === e && (e = this.isHorizontal() ? "x" : "y"); var t = this.params, i = this.rtlTranslate, s = this.translate, a = this.$wrapperEl; if (t.virtualTranslate) return i ? -s : s; if (t.cssMode) return s; var r = T(a[0], e); return i && (r = -r), r || 0 }, setTranslate: function (e, t) { var i = this.rtlTranslate, s = this.params, a = this.$wrapperEl, r = this.wrapperEl, n = this.progress, l = 0, o = 0; this.isHorizontal() ? l = i ? -e : e : o = e, s.roundLengths && (l = Math.floor(l), o = Math.floor(o)), s.cssMode ? r[this.isHorizontal() ? "scrollLeft" : "scrollTop"] = this.isHorizontal() ? -l : -o : s.virtualTranslate || a.transform("translate3d(" + l + "px, " + o + "px, 0px)"), this.previousTranslate = this.translate, this.translate = this.isHorizontal() ? l : o; var d = this.maxTranslate() - this.minTranslate(); (0 === d ? 0 : (e - this.minTranslate()) / d) !== n && this.updateProgress(e), this.emit("setTranslate", this.translate, t) }, minTranslate: function () { return -this.snapGrid[0] }, maxTranslate: function () { return -this.snapGrid[this.snapGrid.length - 1] }, translateTo: function (e, t, i, s, a) { void 0 === e && (e = 0), void 0 === t && (t = this.params.speed), void 0 === i && (i = !0), void 0 === s && (s = !0); var r = this, n = r.params, l = r.wrapperEl; if (r.animating && n.preventInteractionOnTransition) return !1; var o, d = r.minTranslate(), h = r.maxTranslate(); if (o = s && e > d ? d : s && e < h ? h : e, r.updateProgress(o), n.cssMode) { var p, u = r.isHorizontal(); if (0 === t) l[u ? "scrollLeft" : "scrollTop"] = -o; else if (l.scrollTo) l.scrollTo(((p = {})[u ? "left" : "top"] = -o, p.behavior = "smooth", p)); else l[u ? "scrollLeft" : "scrollTop"] = -o; return !0 } return 0 === t ? (r.setTransition(0), r.setTranslate(o), i && (r.emit("beforeTransitionStart", t, a), r.emit("transitionEnd"))) : (r.setTransition(t), r.setTranslate(o), i && (r.emit("beforeTransitionStart", t, a), r.emit("transitionStart")), r.animating || (r.animating = !0, r.onTranslateToWrapperTransitionEnd || (r.onTranslateToWrapperTransitionEnd = function (e) { r && !r.destroyed && e.target === this && (r.$wrapperEl[0].removeEventListener("transitionend", r.onTranslateToWrapperTransitionEnd), r.$wrapperEl[0].removeEventListener("webkitTransitionEnd", r.onTranslateToWrapperTransitionEnd), r.onTranslateToWrapperTransitionEnd = null, delete r.onTranslateToWrapperTransitionEnd, i && r.emit("transitionEnd")) }), r.$wrapperEl[0].addEventListener("transitionend", r.onTranslateToWrapperTransitionEnd), r.$wrapperEl[0].addEventListener("webkitTransitionEnd", r.onTranslateToWrapperTransitionEnd))), !0 } }, transition: { setTransition: function (e, t) { this.params.cssMode || this.$wrapperEl.transition(e), this.emit("setTransition", e, t) }, transitionStart: function (e, t) { void 0 === e && (e = !0); var i = this.activeIndex, s = this.params, a = this.previousIndex; if (!s.cssMode) { s.autoHeight && this.updateAutoHeight(); var r = t; if (r || (r = i > a ? "next" : i < a ? "prev" : "reset"), this.emit("transitionStart"), e && i !== a) { if ("reset" === r) return void this.emit("slideResetTransitionStart"); this.emit("slideChangeTransitionStart"), "next" === r ? this.emit("slideNextTransitionStart") : this.emit("slidePrevTransitionStart") } } }, transitionEnd: function (e, t) { void 0 === e && (e = !0); var i = this.activeIndex, s = this.previousIndex, a = this.params; if (this.animating = !1, !a.cssMode) { this.setTransition(0); var r = t; if (r || (r = i > s ? "next" : i < s ? "prev" : "reset"), this.emit("transitionEnd"), e && i !== s) { if ("reset" === r) return void this.emit("slideResetTransitionEnd"); this.emit("slideChangeTransitionEnd"), "next" === r ? this.emit("slideNextTransitionEnd") : this.emit("slidePrevTransitionEnd") } } } }, slide: { slideTo: function (e, t, i, s) { void 0 === e && (e = 0), void 0 === t && (t = this.params.speed), void 0 === i && (i = !0); var a = this, r = e; r < 0 && (r = 0); var n = a.params, l = a.snapGrid, o = a.slidesGrid, d = a.previousIndex, h = a.activeIndex, p = a.rtlTranslate, u = a.wrapperEl; if (a.animating && n.preventInteractionOnTransition) return !1; var c = Math.min(a.params.slidesPerGroupSkip, r), v = c + Math.floor((r - c) / a.params.slidesPerGroup); v >= l.length && (v = l.length - 1), (h || n.initialSlide || 0) === (d || 0) && i && a.emit("beforeSlideChangeStart"); var f, m = -l[v]; if (a.updateProgress(m), n.normalizeSlideIndex) for (var g = 0; g < o.length; g += 1)-Math.floor(100 * m) >= Math.floor(100 * o[g]) && (r = g); if (a.initialized && r !== h) { if (!a.allowSlideNext && m < a.translate && m < a.minTranslate()) return !1; if (!a.allowSlidePrev && m > a.translate && m > a.maxTranslate() && (h || 0) !== r) return !1 } if (f = r > h ? "next" : r < h ? "prev" : "reset", p && -m === a.translate || !p && m === a.translate) return a.updateActiveIndex(r), n.autoHeight && a.updateAutoHeight(), a.updateSlidesClasses(), "slide" !== n.effect && a.setTranslate(m), "reset" !== f && (a.transitionStart(i, f), a.transitionEnd(i, f)), !1; if (n.cssMode) { var w, b = a.isHorizontal(), y = -m; if (p && (y = u.scrollWidth - u.offsetWidth - y), 0 === t) u[b ? "scrollLeft" : "scrollTop"] = y; else if (u.scrollTo) u.scrollTo(((w = {})[b ? "left" : "top"] = y, w.behavior = "smooth", w)); else u[b ? "scrollLeft" : "scrollTop"] = y; return !0 } return 0 === t ? (a.setTransition(0), a.setTranslate(m), a.updateActiveIndex(r), a.updateSlidesClasses(), a.emit("beforeTransitionStart", t, s), a.transitionStart(i, f), a.transitionEnd(i, f)) : (a.setTransition(t), a.setTranslate(m), a.updateActiveIndex(r), a.updateSlidesClasses(), a.emit("beforeTransitionStart", t, s), a.transitionStart(i, f), a.animating || (a.animating = !0, a.onSlideToWrapperTransitionEnd || (a.onSlideToWrapperTransitionEnd = function (e) { a && !a.destroyed && e.target === this && (a.$wrapperEl[0].removeEventListener("transitionend", a.onSlideToWrapperTransitionEnd), a.$wrapperEl[0].removeEventListener("webkitTransitionEnd", a.onSlideToWrapperTransitionEnd), a.onSlideToWrapperTransitionEnd = null, delete a.onSlideToWrapperTransitionEnd, a.transitionEnd(i, f)) }), a.$wrapperEl[0].addEventListener("transitionend", a.onSlideToWrapperTransitionEnd), a.$wrapperEl[0].addEventListener("webkitTransitionEnd", a.onSlideToWrapperTransitionEnd))), !0 }, slideToLoop: function (e, t, i, s) { void 0 === e && (e = 0), void 0 === t && (t = this.params.speed), void 0 === i && (i = !0); var a = e; return this.params.loop && (a += this.loopedSlides), this.slideTo(a, t, i, s) }, slideNext: function (e, t, i) { void 0 === e && (e = this.params.speed), void 0 === t && (t = !0); var s = this.params, a = this.animating, r = this.activeIndex < s.slidesPerGroupSkip ? 1 : s.slidesPerGroup; if (s.loop) { if (a && s.loopPreventsSlide) return !1; this.loopFix(), this._clientLeft = this.$wrapperEl[0].clientLeft } return this.slideTo(this.activeIndex + r, e, t, i) }, slidePrev: function (e, t, i) { void 0 === e && (e = this.params.speed), void 0 === t && (t = !0); var s = this.params, a = this.animating, r = this.snapGrid, n = this.slidesGrid, l = this.rtlTranslate; if (s.loop) { if (a && s.loopPreventsSlide) return !1; this.loopFix(), this._clientLeft = this.$wrapperEl[0].clientLeft } function o(e) { return e < 0 ? -Math.floor(Math.abs(e)) : Math.floor(e) } var d, h = o(l ? this.translate : -this.translate), p = r.map((function (e) { return o(e) })), u = (r[p.indexOf(h)], r[p.indexOf(h) - 1]); return void 0 === u && s.cssMode && r.forEach((function (e) { !u && h >= e && (u = e) })), void 0 !== u && (d = n.indexOf(u)) < 0 && (d = this.activeIndex - 1), this.slideTo(d, e, t, i) }, slideReset: function (e, t, i) { return void 0 === e && (e = this.params.speed), void 0 === t && (t = !0), this.slideTo(this.activeIndex, e, t, i) }, slideToClosest: function (e, t, i, s) { void 0 === e && (e = this.params.speed), void 0 === t && (t = !0), void 0 === s && (s = .5); var a = this.activeIndex, r = Math.min(this.params.slidesPerGroupSkip, a), n = r + Math.floor((a - r) / this.params.slidesPerGroup), l = this.rtlTranslate ? this.translate : -this.translate; if (l >= this.snapGrid[n]) { var o = this.snapGrid[n]; l - o > (this.snapGrid[n + 1] - o) * s && (a += this.params.slidesPerGroup) } else { var d = this.snapGrid[n - 1]; l - d <= (this.snapGrid[n] - d) * s && (a -= this.params.slidesPerGroup) } return a = Math.max(a, 0), a = Math.min(a, this.slidesGrid.length - 1), this.slideTo(a, e, t, i) }, slideToClickedSlide: function () { var e, t = this, i = t.params, s = t.$wrapperEl, a = "auto" === i.slidesPerView ? t.slidesPerViewDynamic() : i.slidesPerView, r = t.clickedIndex; if (i.loop) { if (t.animating) return; e = parseInt(m(t.clickedSlide).attr("data-swiper-slide-index"), 10), i.centeredSlides ? r < t.loopedSlides - a / 2 || r > t.slides.length - t.loopedSlides + a / 2 ? (t.loopFix(), r = s.children("." + i.slideClass + '[data-swiper-slide-index="' + e + '"]:not(.' + i.slideDuplicateClass + ")").eq(0).index(), E((function () { t.slideTo(r) }))) : t.slideTo(r) : r > t.slides.length - a ? (t.loopFix(), r = s.children("." + i.slideClass + '[data-swiper-slide-index="' + e + '"]:not(.' + i.slideDuplicateClass + ")").eq(0).index(), E((function () { t.slideTo(r) }))) : t.slideTo(r) } else t.slideTo(r) } }, loop: { loopCreate: function () { var e = this, t = r(), i = e.params, s = e.$wrapperEl; s.children("." + i.slideClass + "." + i.slideDuplicateClass).remove(); var a = s.children("." + i.slideClass); if (i.loopFillGroupWithBlank) { var n = i.slidesPerGroup - a.length % i.slidesPerGroup; if (n !== i.slidesPerGroup) { for (var l = 0; l < n; l += 1) { var o = m(t.createElement("div")).addClass(i.slideClass + " " + i.slideBlankClass); s.append(o) } a = s.children("." + i.slideClass) } } "auto" !== i.slidesPerView || i.loopedSlides || (i.loopedSlides = a.length), e.loopedSlides = Math.ceil(parseFloat(i.loopedSlides || i.slidesPerView, 10)), e.loopedSlides += i.loopAdditionalSlides, e.loopedSlides > a.length && (e.loopedSlides = a.length); var d = [], h = []; a.each((function (t, i) { var s = m(t); i < e.loopedSlides && h.push(t), i < a.length && i >= a.length - e.loopedSlides && d.push(t), s.attr("data-swiper-slide-index", i) })); for (var p = 0; p < h.length; p += 1)s.append(m(h[p].cloneNode(!0)).addClass(i.slideDuplicateClass)); for (var u = d.length - 1; u >= 0; u -= 1)s.prepend(m(d[u].cloneNode(!0)).addClass(i.slideDuplicateClass)) }, loopFix: function () { this.emit("beforeLoopFix"); var e, t = this.activeIndex, i = this.slides, s = this.loopedSlides, a = this.allowSlidePrev, r = this.allowSlideNext, n = this.snapGrid, l = this.rtlTranslate; this.allowSlidePrev = !0, this.allowSlideNext = !0; var o = -n[t] - this.getTranslate(); if (t < s) e = i.length - 3 * s + t, e += s, this.slideTo(e, 0, !1, !0) && 0 !== o && this.setTranslate((l ? -this.translate : this.translate) - o); else if (t >= i.length - s) { e = -i.length + t + s, e += s, this.slideTo(e, 0, !1, !0) && 0 !== o && this.setTranslate((l ? -this.translate : this.translate) - o) } this.allowSlidePrev = a, this.allowSlideNext = r, this.emit("loopFix") }, loopDestroy: function () { var e = this.$wrapperEl, t = this.params, i = this.slides; e.children("." + t.slideClass + "." + t.slideDuplicateClass + ",." + t.slideClass + "." + t.slideBlankClass).remove(), i.removeAttr("data-swiper-slide-index") } }, grabCursor: { setGrabCursor: function (e) { if (!(this.support.touch || !this.params.simulateTouch || this.params.watchOverflow && this.isLocked || this.params.cssMode)) { var t = this.el; t.style.cursor = "move", t.style.cursor = e ? "-webkit-grabbing" : "-webkit-grab", t.style.cursor = e ? "-moz-grabbin" : "-moz-grab", t.style.cursor = e ? "grabbing" : "grab" } }, unsetGrabCursor: function () { this.support.touch || this.params.watchOverflow && this.isLocked || this.params.cssMode || (this.el.style.cursor = "") } }, manipulation: { appendSlide: function (e) { var t = this.$wrapperEl, i = this.params; if (i.loop && this.loopDestroy(), "object" == typeof e && "length" in e) for (var s = 0; s < e.length; s += 1)e[s] && t.append(e[s]); else t.append(e); i.loop && this.loopCreate(), i.observer && this.support.observer || this.update() }, prependSlide: function (e) { var t = this.params, i = this.$wrapperEl, s = this.activeIndex; t.loop && this.loopDestroy(); var a = s + 1; if ("object" == typeof e && "length" in e) { for (var r = 0; r < e.length; r += 1)e[r] && i.prepend(e[r]); a = s + e.length } else i.prepend(e); t.loop && this.loopCreate(), t.observer && this.support.observer || this.update(), this.slideTo(a, 0, !1) }, addSlide: function (e, t) { var i = this.$wrapperEl, s = this.params, a = this.activeIndex; s.loop && (a -= this.loopedSlides, this.loopDestroy(), this.slides = i.children("." + s.slideClass)); var r = this.slides.length; if (e <= 0) this.prependSlide(t); else if (e >= r) this.appendSlide(t); else { for (var n = a > e ? a + 1 : a, l = [], o = r - 1; o >= e; o -= 1) { var d = this.slides.eq(o); d.remove(), l.unshift(d) } if ("object" == typeof t && "length" in t) { for (var h = 0; h < t.length; h += 1)t[h] && i.append(t[h]); n = a > e ? a + t.length : a } else i.append(t); for (var p = 0; p < l.length; p += 1)i.append(l[p]); s.loop && this.loopCreate(), s.observer && this.support.observer || this.update(), s.loop ? this.slideTo(n + this.loopedSlides, 0, !1) : this.slideTo(n, 0, !1) } }, removeSlide: function (e) { var t = this.params, i = this.$wrapperEl, s = this.activeIndex; t.loop && (s -= this.loopedSlides, this.loopDestroy(), this.slides = i.children("." + t.slideClass)); var a, r = s; if ("object" == typeof e && "length" in e) { for (var n = 0; n < e.length; n += 1)a = e[n], this.slides[a] && this.slides.eq(a).remove(), a < r && (r -= 1); r = Math.max(r, 0) } else a = e, this.slides[a] && this.slides.eq(a).remove(), a < r && (r -= 1), r = Math.max(r, 0); t.loop && this.loopCreate(), t.observer && this.support.observer || this.update(), t.loop ? this.slideTo(r + this.loopedSlides, 0, !1) : this.slideTo(r, 0, !1) }, removeAllSlides: function () { for (var e = [], t = 0; t < this.slides.length; t += 1)e.push(t); this.removeSlide(e) } }, events: { attachEvents: function () { var e = r(), t = this.params, i = this.touchEvents, s = this.el, a = this.wrapperEl, n = this.device, l = this.support; this.onTouchStart = O.bind(this), this.onTouchMove = A.bind(this), this.onTouchEnd = D.bind(this), t.cssMode && (this.onScroll = B.bind(this)), this.onClick = N.bind(this); var o = !!t.nested; if (!l.touch && l.pointerEvents) s.addEventListener(i.start, this.onTouchStart, !1), e.addEventListener(i.move, this.onTouchMove, o), e.addEventListener(i.end, this.onTouchEnd, !1); else { if (l.touch) { var d = !("touchstart" !== i.start || !l.passiveListener || !t.passiveListeners) && { passive: !0, capture: !1 }; s.addEventListener(i.start, this.onTouchStart, d), s.addEventListener(i.move, this.onTouchMove, l.passiveListener ? { passive: !1, capture: o } : o), s.addEventListener(i.end, this.onTouchEnd, d), i.cancel && s.addEventListener(i.cancel, this.onTouchEnd, d), H || (e.addEventListener("touchstart", X), H = !0) } (t.simulateTouch && !n.ios && !n.android || t.simulateTouch && !l.touch && n.ios) && (s.addEventListener("mousedown", this.onTouchStart, !1), e.addEventListener("mousemove", this.onTouchMove, o), e.addEventListener("mouseup", this.onTouchEnd, !1)) } (t.preventClicks || t.preventClicksPropagation) && s.addEventListener("click", this.onClick, !0), t.cssMode && a.addEventListener("scroll", this.onScroll), t.updateOnWindowResize ? this.on(n.ios || n.android ? "resize orientationchange observerUpdate" : "resize observerUpdate", G, !0) : this.on("observerUpdate", G, !0) }, detachEvents: function () { var e = r(), t = this.params, i = this.touchEvents, s = this.el, a = this.wrapperEl, n = this.device, l = this.support, o = !!t.nested; if (!l.touch && l.pointerEvents) s.removeEventListener(i.start, this.onTouchStart, !1), e.removeEventListener(i.move, this.onTouchMove, o), e.removeEventListener(i.end, this.onTouchEnd, !1); else { if (l.touch) { var d = !("onTouchStart" !== i.start || !l.passiveListener || !t.passiveListeners) && { passive: !0, capture: !1 }; s.removeEventListener(i.start, this.onTouchStart, d), s.removeEventListener(i.move, this.onTouchMove, o), s.removeEventListener(i.end, this.onTouchEnd, d), i.cancel && s.removeEventListener(i.cancel, this.onTouchEnd, d) } (t.simulateTouch && !n.ios && !n.android || t.simulateTouch && !l.touch && n.ios) && (s.removeEventListener("mousedown", this.onTouchStart, !1), e.removeEventListener("mousemove", this.onTouchMove, o), e.removeEventListener("mouseup", this.onTouchEnd, !1)) } (t.preventClicks || t.preventClicksPropagation) && s.removeEventListener("click", this.onClick, !0), t.cssMode && a.removeEventListener("scroll", this.onScroll), this.off(n.ios || n.android ? "resize orientationchange observerUpdate" : "resize observerUpdate", G) } }, breakpoints: { setBreakpoint: function () { var e = this.activeIndex, t = this.initialized, i = this.loopedSlides, s = void 0 === i ? 0 : i, a = this.params, r = this.$el, n = a.breakpoints; if (n && (!n || 0 !== Object.keys(n).length)) { var l = this.getBreakpoint(n); if (l && this.currentBreakpoint !== l) { var o = l in n ? n[l] : void 0; o && ["slidesPerView", "spaceBetween", "slidesPerGroup", "slidesPerGroupSkip", "slidesPerColumn"].forEach((function (e) { var t = o[e]; void 0 !== t && (o[e] = "slidesPerView" !== e || "AUTO" !== t && "auto" !== t ? "slidesPerView" === e ? parseFloat(t) : parseInt(t, 10) : "auto") })); var d = o || this.originalParams, h = a.slidesPerColumn > 1, p = d.slidesPerColumn > 1; h && !p ? (r.removeClass(a.containerModifierClass + "multirow " + a.containerModifierClass + "multirow-column"), this.emitContainerClasses()) : !h && p && (r.addClass(a.containerModifierClass + "multirow"), "column" === d.slidesPerColumnFill && r.addClass(a.containerModifierClass + "multirow-column"), this.emitContainerClasses()); var u = d.direction && d.direction !== a.direction, c = a.loop && (d.slidesPerView !== a.slidesPerView || u); u && t && this.changeDirection(), S(this.params, d), S(this, { allowTouchMove: this.params.allowTouchMove, allowSlideNext: this.params.allowSlideNext, allowSlidePrev: this.params.allowSlidePrev }), this.currentBreakpoint = l, c && t && (this.loopDestroy(), this.loopCreate(), this.updateSlides(), this.slideTo(e - s + this.loopedSlides, 0, !1)), this.emit("breakpoint", d) } } }, getBreakpoint: function (e) { var t = l(); if (e) { var i = !1, s = Object.keys(e).map((function (e) { if ("string" == typeof e && 0 === e.indexOf("@")) { var i = parseFloat(e.substr(1)); return { value: t.innerHeight * i, point: e } } return { value: e, point: e } })); s.sort((function (e, t) { return parseInt(e.value, 10) - parseInt(t.value, 10) })); for (var a = 0; a < s.length; a += 1) { var r = s[a], n = r.point; r.value <= t.innerWidth && (i = n) } return i || "max" } } }, checkOverflow: { checkOverflow: function () { var e = this.params, t = this.isLocked, i = this.slides.length > 0 && e.slidesOffsetBefore + e.spaceBetween * (this.slides.length - 1) + this.slides[0].offsetWidth * this.slides.length; e.slidesOffsetBefore && e.slidesOffsetAfter && i ? this.isLocked = i <= this.size : this.isLocked = 1 === this.snapGrid.length, this.allowSlideNext = !this.isLocked, this.allowSlidePrev = !this.isLocked, t !== this.isLocked && this.emit(this.isLocked ? "lock" : "unlock"), t && t !== this.isLocked && (this.isEnd = !1, this.navigation && this.navigation.update()) } }, classes: { addClasses: function () { var e = this.classNames, t = this.params, i = this.rtl, s = this.$el, a = this.device, r = []; r.push("initialized"), r.push(t.direction), t.freeMode && r.push("free-mode"), t.autoHeight && r.push("autoheight"), i && r.push("rtl"), t.slidesPerColumn > 1 && (r.push("multirow"), "column" === t.slidesPerColumnFill && r.push("multirow-column")), a.android && r.push("android"), a.ios && r.push("ios"), t.cssMode && r.push("css-mode"), r.forEach((function (i) { e.push(t.containerModifierClass + i) })), s.addClass(e.join(" ")), this.emitContainerClasses() }, removeClasses: function () { var e = this.$el, t = this.classNames; e.removeClass(t.join(" ")), this.emitContainerClasses() } }, images: { loadImage: function (e, t, i, s, a, r) { var n, o = l(); function d() { r && r() } m(e).parent("picture")[0] || e.complete && a ? d() : t ? ((n = new o.Image).onload = d, n.onerror = d, s && (n.sizes = s), i && (n.srcset = i), t && (n.src = t)) : d() }, preloadImages: function () { var e = this; function t() { null != e && e && !e.destroyed && (void 0 !== e.imagesLoaded && (e.imagesLoaded += 1), e.imagesLoaded === e.imagesToLoad.length && (e.params.updateOnImagesReady && e.update(), e.emit("imagesReady"))) } e.imagesToLoad = e.$el.find("img"); for (var i = 0; i < e.imagesToLoad.length; i += 1) { var s = e.imagesToLoad[i]; e.loadImage(s, s.currentSrc || s.getAttribute("src"), s.srcset || s.getAttribute("srcset"), s.sizes || s.getAttribute("sizes"), !0, t) } } } }, F = {}, W = function () { function t() { for (var e, i, s = arguments.length, a = new Array(s), r = 0; r < s; r++)a[r] = arguments[r]; 1 === a.length && a[0].constructor && a[0].constructor === Object ? i = a[0] : (e = a[0], i = a[1]), i || (i = {}), i = S({}, i), e && !i.el && (i.el = e); var n = this; n.support = z(), n.device = P({ userAgent: i.userAgent }), n.browser = k(), n.eventsListeners = {}, n.eventsAnyListeners = [], Object.keys(V).forEach((function (e) { Object.keys(V[e]).forEach((function (i) { t.prototype[i] || (t.prototype[i] = V[e][i]) })) })), void 0 === n.modules && (n.modules = {}), Object.keys(n.modules).forEach((function (e) { var t = n.modules[e]; if (t.params) { var s = Object.keys(t.params)[0], a = t.params[s]; if ("object" != typeof a || null === a) return; if (!(s in i) || !("enabled" in a)) return; !0 === i[s] && (i[s] = { enabled: !0 }), "object" != typeof i[s] || "enabled" in i[s] || (i[s].enabled = !0), i[s] || (i[s] = { enabled: !1 }) } })); var l = S({}, Y); n.useParams(l), n.params = S({}, l, F, i), n.originalParams = S({}, n.params), n.passedParams = S({}, i), n.params && n.params.on && Object.keys(n.params.on).forEach((function (e) { n.on(e, n.params.on[e]) })), n.$ = m; var o = m(n.params.el); if (e = o[0]) { if (o.length > 1) { var d = []; return o.each((function (e) { var s = S({}, i, { el: e }); d.push(new t(s)) })), d } var h, p, u; return e.swiper = n, e && e.shadowRoot && e.shadowRoot.querySelector ? (h = m(e.shadowRoot.querySelector("." + n.params.wrapperClass))).children = function (e) { return o.children(e) } : h = o.children("." + n.params.wrapperClass), S(n, { $el: o, el: e, $wrapperEl: h, wrapperEl: h[0], classNames: [], slides: m(), slidesGrid: [], snapGrid: [], slidesSizesGrid: [], isHorizontal: function () { return "horizontal" === n.params.direction }, isVertical: function () { return "vertical" === n.params.direction }, rtl: "rtl" === e.dir.toLowerCase() || "rtl" === o.css("direction"), rtlTranslate: "horizontal" === n.params.direction && ("rtl" === e.dir.toLowerCase() || "rtl" === o.css("direction")), wrongRTL: "-webkit-box" === h.css("display"), activeIndex: 0, realIndex: 0, isBeginning: !0, isEnd: !1, translate: 0, previousTranslate: 0, progress: 0, velocity: 0, animating: !1, allowSlideNext: n.params.allowSlideNext, allowSlidePrev: n.params.allowSlidePrev, touchEvents: (p = ["touchstart", "touchmove", "touchend", "touchcancel"], u = ["mousedown", "mousemove", "mouseup"], n.support.pointerEvents && (u = ["pointerdown", "pointermove", "pointerup"]), n.touchEventsTouch = { start: p[0], move: p[1], end: p[2], cancel: p[3] }, n.touchEventsDesktop = { start: u[0], move: u[1], end: u[2] }, n.support.touch || !n.params.simulateTouch ? n.touchEventsTouch : n.touchEventsDesktop), touchEventsData: { isTouched: void 0, isMoved: void 0, allowTouchCallbacks: void 0, touchStartTime: void 0, isScrolling: void 0, currentTranslate: void 0, startTranslate: void 0, allowThresholdMove: void 0, formElements: "input, select, option, textarea, button, video, label", lastClickTime: x(), clickTimeout: void 0, velocities: [], allowMomentumBounce: void 0, isTouchEvent: void 0, startMoving: void 0 }, allowClick: !0, allowTouchMove: n.params.allowTouchMove, touches: { startX: 0, startY: 0, currentX: 0, currentY: 0, diff: 0 }, imagesToLoad: [], imagesLoaded: 0 }), n.useModules(), n.emit("_swiper"), n.params.init && n.init(), n } } var i, s, a, r = t.prototype; return r.emitContainerClasses = function () { var e = this; if (e.params._emitClasses && e.el) { var t = e.el.className.split(" ").filter((function (t) { return 0 === t.indexOf("swiper-container") || 0 === t.indexOf(e.params.containerModifierClass) })); e.emit("_containerClasses", t.join(" ")) } }, r.emitSlidesClasses = function () { var e = this; e.params._emitClasses && e.el && e.slides.each((function (t) { var i = t.className.split(" ").filter((function (t) { return 0 === t.indexOf("swiper-slide") || 0 === t.indexOf(e.params.slideClass) })); e.emit("_slideClass", t, i.join(" ")) })) }, r.slidesPerViewDynamic = function () { var e = this.params, t = this.slides, i = this.slidesGrid, s = this.size, a = this.activeIndex, r = 1; if (e.centeredSlides) { for (var n, l = t[a].swiperSlideSize, o = a + 1; o < t.length; o += 1)t[o] && !n && (r += 1, (l += t[o].swiperSlideSize) > s && (n = !0)); for (var d = a - 1; d >= 0; d -= 1)t[d] && !n && (r += 1, (l += t[d].swiperSlideSize) > s && (n = !0)) } else for (var h = a + 1; h < t.length; h += 1)i[h] - i[a] < s && (r += 1); return r }, r.update = function () { var e = this; if (e && !e.destroyed) { var t = e.snapGrid, i = e.params; i.breakpoints && e.setBreakpoint(), e.updateSize(), e.updateSlides(), e.updateProgress(), e.updateSlidesClasses(), e.params.freeMode ? (s(), e.params.autoHeight && e.updateAutoHeight()) : (("auto" === e.params.slidesPerView || e.params.slidesPerView > 1) && e.isEnd && !e.params.centeredSlides ? e.slideTo(e.slides.length - 1, 0, !1, !0) : e.slideTo(e.activeIndex, 0, !1, !0)) || s(), i.watchOverflow && t !== e.snapGrid && e.checkOverflow(), e.emit("update") } function s() { var t = e.rtlTranslate ? -1 * e.translate : e.translate, i = Math.min(Math.max(t, e.maxTranslate()), e.minTranslate()); e.setTranslate(i), e.updateActiveIndex(), e.updateSlidesClasses() } }, r.changeDirection = function (e, t) { void 0 === t && (t = !0); var i = this.params.direction; return e || (e = "horizontal" === i ? "vertical" : "horizontal"), e === i || "horizontal" !== e && "vertical" !== e || (this.$el.removeClass("" + this.params.containerModifierClass + i).addClass("" + this.params.containerModifierClass + e), this.emitContainerClasses(), this.params.direction = e, this.slides.each((function (t) { "vertical" === e ? t.style.width = "" : t.style.height = "" })), this.emit("changeDirection"), t && this.update()), this }, r.init = function () { this.initialized || (this.emit("beforeInit"), this.params.breakpoints && this.setBreakpoint(), this.addClasses(), this.params.loop && this.loopCreate(), this.updateSize(), this.updateSlides(), this.params.watchOverflow && this.checkOverflow(), this.params.grabCursor && this.setGrabCursor(), this.params.preloadImages && this.preloadImages(), this.params.loop ? this.slideTo(this.params.initialSlide + this.loopedSlides, 0, this.params.runCallbacksOnInit) : this.slideTo(this.params.initialSlide, 0, this.params.runCallbacksOnInit), this.attachEvents(), this.initialized = !0, this.emit("init")) }, r.destroy = function (e, t) { void 0 === e && (e = !0), void 0 === t && (t = !0); var i, s = this, a = s.params, r = s.$el, n = s.$wrapperEl, l = s.slides; return void 0 === s.params || s.destroyed || (s.emit("beforeDestroy"), s.initialized = !1, s.detachEvents(), a.loop && s.loopDestroy(), t && (s.removeClasses(), r.removeAttr("style"), n.removeAttr("style"), l && l.length && l.removeClass([a.slideVisibleClass, a.slideActiveClass, a.slideNextClass, a.slidePrevClass].join(" ")).removeAttr("style").removeAttr("data-swiper-slide-index")), s.emit("destroy"), Object.keys(s.eventsListeners).forEach((function (e) { s.off(e) })), !1 !== e && (s.$el[0].swiper = null, i = s, Object.keys(i).forEach((function (e) { try { i[e] = null } catch (e) { } try { delete i[e] } catch (e) { } }))), s.destroyed = !0), null }, t.extendDefaults = function (e) { S(F, e) }, t.installModule = function (e) { t.prototype.modules || (t.prototype.modules = {}); var i = e.name || Object.keys(t.prototype.modules).length + "_" + x(); t.prototype.modules[i] = e }, t.use = function (e) { return Array.isArray(e) ? (e.forEach((function (e) { return t.installModule(e) })), t) : (t.installModule(e), t) }, i = t, a = [{ key: "extendedDefaults", get: function () { return F } }, { key: "defaults", get: function () { return Y } }], (s = null) && e(i.prototype, s), a && e(i, a), t }(); W.use([$, I]); var R = { update: function (e) { var t = this, i = t.params, s = i.slidesPerView, a = i.slidesPerGroup, r = i.centeredSlides, n = t.params.virtual, l = n.addSlidesBefore, o = n.addSlidesAfter, d = t.virtual, h = d.from, p = d.to, u = d.slides, c = d.slidesGrid, v = d.renderSlide, f = d.offset; t.updateActiveIndex(); var m, g, w, b = t.activeIndex || 0; m = t.rtlTranslate ? "right" : t.isHorizontal() ? "left" : "top", r ? (g = Math.floor(s / 2) + a + o, w = Math.floor(s / 2) + a + l) : (g = s + (a - 1) + o, w = a + l); var y = Math.max((b || 0) - w, 0), E = Math.min((b || 0) + g, u.length - 1), x = (t.slidesGrid[y] || 0) - (t.slidesGrid[0] || 0); function T() { t.updateSlides(), t.updateProgress(), t.updateSlidesClasses(), t.lazy && t.params.lazy.enabled && t.lazy.load() } if (S(t.virtual, { from: y, to: E, offset: x, slidesGrid: t.slidesGrid }), h === y && p === E && !e) return t.slidesGrid !== c && x !== f && t.slides.css(m, x + "px"), void t.updateProgress(); if (t.params.virtual.renderExternal) return t.params.virtual.renderExternal.call(t, { offset: x, from: y, to: E, slides: function () { for (var e = [], t = y; t <= E; t += 1)e.push(u[t]); return e }() }), void (t.params.virtual.renderExternalUpdate && T()); var C = [], M = []; if (e) t.$wrapperEl.find("." + t.params.slideClass).remove(); else for (var z = h; z <= p; z += 1)(z < y || z > E) && t.$wrapperEl.find("." + t.params.slideClass + '[data-swiper-slide-index="' + z + '"]').remove(); for (var P = 0; P < u.length; P += 1)P >= y && P <= E && (void 0 === p || e ? M.push(P) : (P > p && M.push(P), P < h && C.push(P))); M.forEach((function (e) { t.$wrapperEl.append(v(u[e], e)) })), C.sort((function (e, t) { return t - e })).forEach((function (e) { t.$wrapperEl.prepend(v(u[e], e)) })), t.$wrapperEl.children(".swiper-slide").css(m, x + "px"), T() }, renderSlide: function (e, t) { var i = this.params.virtual; if (i.cache && this.virtual.cache[t]) return this.virtual.cache[t]; var s = i.renderSlide ? m(i.renderSlide.call(this, e, t)) : m('<div class="' + this.params.slideClass + '" data-swiper-slide-index="' + t + '">' + e + "</div>"); return s.attr("data-swiper-slide-index") || s.attr("data-swiper-slide-index", t), i.cache && (this.virtual.cache[t] = s), s }, appendSlide: function (e) { if ("object" == typeof e && "length" in e) for (var t = 0; t < e.length; t += 1)e[t] && this.virtual.slides.push(e[t]); else this.virtual.slides.push(e); this.virtual.update(!0) }, prependSlide: function (e) { var t = this.activeIndex, i = t + 1, s = 1; if (Array.isArray(e)) { for (var a = 0; a < e.length; a += 1)e[a] && this.virtual.slides.unshift(e[a]); i = t + e.length, s = e.length } else this.virtual.slides.unshift(e); if (this.params.virtual.cache) { var r = this.virtual.cache, n = {}; Object.keys(r).forEach((function (e) { var t = r[e], i = t.attr("data-swiper-slide-index"); i && t.attr("data-swiper-slide-index", parseInt(i, 10) + 1), n[parseInt(e, 10) + s] = t })), this.virtual.cache = n } this.virtual.update(!0), this.slideTo(i, 0) }, removeSlide: function (e) { if (null != e) { var t = this.activeIndex; if (Array.isArray(e)) for (var i = e.length - 1; i >= 0; i -= 1)this.virtual.slides.splice(e[i], 1), this.params.virtual.cache && delete this.virtual.cache[e[i]], e[i] < t && (t -= 1), t = Math.max(t, 0); else this.virtual.slides.splice(e, 1), this.params.virtual.cache && delete this.virtual.cache[e], e < t && (t -= 1), t = Math.max(t, 0); this.virtual.update(!0), this.slideTo(t, 0) } }, removeAllSlides: function () { this.virtual.slides = [], this.params.virtual.cache && (this.virtual.cache = {}), this.virtual.update(!0), this.slideTo(0, 0) } }, q = { name: "virtual", params: { virtual: { enabled: !1, slides: [], cache: !0, renderSlide: null, renderExternal: null, renderExternalUpdate: !0, addSlidesBefore: 0, addSlidesAfter: 0 } }, create: function () { M(this, { virtual: t(t({}, R), {}, { slides: this.params.virtual.slides, cache: {} }) }) }, on: { beforeInit: function (e) { if (e.params.virtual.enabled) { e.classNames.push(e.params.containerModifierClass + "virtual"); var t = { watchSlidesProgress: !0 }; S(e.params, t), S(e.originalParams, t), e.params.initialSlide || e.virtual.update() } }, setTranslate: function (e) { e.params.virtual.enabled && e.virtual.update() } } }, j = { handle: function (e) { var t = l(), i = r(), s = this.rtlTranslate, a = e; a.originalEvent && (a = a.originalEvent); var n = a.keyCode || a.charCode, o = this.params.keyboard.pageUpDown, d = o && 33 === n, h = o && 34 === n, p = 37 === n, u = 39 === n, c = 38 === n, v = 40 === n; if (!this.allowSlideNext && (this.isHorizontal() && u || this.isVertical() && v || h)) return !1; if (!this.allowSlidePrev && (this.isHorizontal() && p || this.isVertical() && c || d)) return !1; if (!(a.shiftKey || a.altKey || a.ctrlKey || a.metaKey || i.activeElement && i.activeElement.nodeName && ("input" === i.activeElement.nodeName.toLowerCase() || "textarea" === i.activeElement.nodeName.toLowerCase()))) { if (this.params.keyboard.onlyInViewport && (d || h || p || u || c || v)) { var f = !1; if (this.$el.parents("." + this.params.slideClass).length > 0 && 0 === this.$el.parents("." + this.params.slideActiveClass).length) return; var m = t.innerWidth, g = t.innerHeight, w = this.$el.offset(); s && (w.left -= this.$el[0].scrollLeft); for (var b = [[w.left, w.top], [w.left + this.width, w.top], [w.left, w.top + this.height], [w.left + this.width, w.top + this.height]], y = 0; y < b.length; y += 1) { var E = b[y]; E[0] >= 0 && E[0] <= m && E[1] >= 0 && E[1] <= g && (f = !0) } if (!f) return } this.isHorizontal() ? ((d || h || p || u) && (a.preventDefault ? a.preventDefault() : a.returnValue = !1), ((h || u) && !s || (d || p) && s) && this.slideNext(), ((d || p) && !s || (h || u) && s) && this.slidePrev()) : ((d || h || c || v) && (a.preventDefault ? a.preventDefault() : a.returnValue = !1), (h || v) && this.slideNext(), (d || c) && this.slidePrev()), this.emit("keyPress", n) } }, enable: function () { var e = r(); this.keyboard.enabled || (m(e).on("keydown", this.keyboard.handle), this.keyboard.enabled = !0) }, disable: function () { var e = r(); this.keyboard.enabled && (m(e).off("keydown", this.keyboard.handle), this.keyboard.enabled = !1) } }, _ = { name: "keyboard", params: { keyboard: { enabled: !1, onlyInViewport: !0, pageUpDown: !0 } }, create: function () { M(this, { keyboard: t({ enabled: !1 }, j) }) }, on: { init: function (e) { e.params.keyboard.enabled && e.keyboard.enable() }, destroy: function (e) { e.keyboard.enabled && e.keyboard.disable() } } }; var U = { lastScrollTime: x(), lastEventBeforeSnap: void 0, recentWheelEvents: [], event: function () { return l().navigator.userAgent.indexOf("firefox") > -1 ? "DOMMouseScroll" : function () { var e = r(), t = "onwheel" in e; if (!t) { var i = e.createElement("div"); i.setAttribute("onwheel", "return;"), t = "function" == typeof i.onwheel } return !t && e.implementation && e.implementation.hasFeature && !0 !== e.implementation.hasFeature("", "") && (t = e.implementation.hasFeature("Events.wheel", "3.0")), t }() ? "wheel" : "mousewheel" }, normalize: function (e) { var t = 0, i = 0, s = 0, a = 0; return "detail" in e && (i = e.detail), "wheelDelta" in e && (i = -e.wheelDelta / 120), "wheelDeltaY" in e && (i = -e.wheelDeltaY / 120), "wheelDeltaX" in e && (t = -e.wheelDeltaX / 120), "axis" in e && e.axis === e.HORIZONTAL_AXIS && (t = i, i = 0), s = 10 * t, a = 10 * i, "deltaY" in e && (a = e.deltaY), "deltaX" in e && (s = e.deltaX), e.shiftKey && !s && (s = a, a = 0), (s || a) && e.deltaMode && (1 === e.deltaMode ? (s *= 40, a *= 40) : (s *= 800, a *= 800)), s && !t && (t = s < 1 ? -1 : 1), a && !i && (i = a < 1 ? -1 : 1), { spinX: t, spinY: i, pixelX: s, pixelY: a } }, handleMouseEnter: function () { this.mouseEntered = !0 }, handleMouseLeave: function () { this.mouseEntered = !1 }, handle: function (e) { var t = e, i = this, s = i.params.mousewheel; i.params.cssMode && t.preventDefault(); var a = i.$el; if ("container" !== i.params.mousewheel.eventsTarget && (a = m(i.params.mousewheel.eventsTarget)), !i.mouseEntered && !a[0].contains(t.target) && !s.releaseOnEdges) return !0; t.originalEvent && (t = t.originalEvent); var r = 0, n = i.rtlTranslate ? -1 : 1, l = U.normalize(t); if (s.forceToAxis) if (i.isHorizontal()) { if (!(Math.abs(l.pixelX) > Math.abs(l.pixelY))) return !0; r = -l.pixelX * n } else { if (!(Math.abs(l.pixelY) > Math.abs(l.pixelX))) return !0; r = -l.pixelY } else r = Math.abs(l.pixelX) > Math.abs(l.pixelY) ? -l.pixelX * n : -l.pixelY; if (0 === r) return !0; if (s.invert && (r = -r), i.params.freeMode) { var o = { time: x(), delta: Math.abs(r), direction: Math.sign(r) }, d = i.mousewheel.lastEventBeforeSnap, h = d && o.time < d.time + 500 && o.delta <= d.delta && o.direction === d.direction; if (!h) { i.mousewheel.lastEventBeforeSnap = void 0, i.params.loop && i.loopFix(); var p = i.getTranslate() + r * s.sensitivity, u = i.isBeginning, c = i.isEnd; if (p >= i.minTranslate() && (p = i.minTranslate()), p <= i.maxTranslate() && (p = i.maxTranslate()), i.setTransition(0), i.setTranslate(p), i.updateProgress(), i.updateActiveIndex(), i.updateSlidesClasses(), (!u && i.isBeginning || !c && i.isEnd) && i.updateSlidesClasses(), i.params.freeModeSticky) { clearTimeout(i.mousewheel.timeout), i.mousewheel.timeout = void 0; var v = i.mousewheel.recentWheelEvents; v.length >= 15 && v.shift(); var f = v.length ? v[v.length - 1] : void 0, g = v[0]; if (v.push(o), f && (o.delta > f.delta || o.direction !== f.direction)) v.splice(0); else if (v.length >= 15 && o.time - g.time < 500 && g.delta - o.delta >= 1 && o.delta <= 6) { var w = r > 0 ? .8 : .2; i.mousewheel.lastEventBeforeSnap = o, v.splice(0), i.mousewheel.timeout = E((function () { i.slideToClosest(i.params.speed, !0, void 0, w) }), 0) } i.mousewheel.timeout || (i.mousewheel.timeout = E((function () { i.mousewheel.lastEventBeforeSnap = o, v.splice(0), i.slideToClosest(i.params.speed, !0, void 0, .5) }), 500)) } if (h || i.emit("scroll", t), i.params.autoplay && i.params.autoplayDisableOnInteraction && i.autoplay.stop(), p === i.minTranslate() || p === i.maxTranslate()) return !0 } } else { var b = { time: x(), delta: Math.abs(r), direction: Math.sign(r), raw: e }, y = i.mousewheel.recentWheelEvents; y.length >= 2 && y.shift(); var T = y.length ? y[y.length - 1] : void 0; if (y.push(b), T ? (b.direction !== T.direction || b.delta > T.delta || b.time > T.time + 150) && i.mousewheel.animateSlider(b) : i.mousewheel.animateSlider(b), i.mousewheel.releaseScroll(b)) return !0 } return t.preventDefault ? t.preventDefault() : t.returnValue = !1, !1 }, animateSlider: function (e) { var t = l(); return !(this.params.mousewheel.thresholdDelta && e.delta < this.params.mousewheel.thresholdDelta) && (!(this.params.mousewheel.thresholdTime && x() - this.mousewheel.lastScrollTime < this.params.mousewheel.thresholdTime) && (e.delta >= 6 && x() - this.mousewheel.lastScrollTime < 60 || (e.direction < 0 ? this.isEnd && !this.params.loop || this.animating || (this.slideNext(), this.emit("scroll", e.raw)) : this.isBeginning && !this.params.loop || this.animating || (this.slidePrev(), this.emit("scroll", e.raw)), this.mousewheel.lastScrollTime = (new t.Date).getTime(), !1))) }, releaseScroll: function (e) { var t = this.params.mousewheel; if (e.direction < 0) { if (this.isEnd && !this.params.loop && t.releaseOnEdges) return !0 } else if (this.isBeginning && !this.params.loop && t.releaseOnEdges) return !0; return !1 }, enable: function () { var e = U.event(); if (this.params.cssMode) return this.wrapperEl.removeEventListener(e, this.mousewheel.handle), !0; if (!e) return !1; if (this.mousewheel.enabled) return !1; var t = this.$el; return "container" !== this.params.mousewheel.eventsTarget && (t = m(this.params.mousewheel.eventsTarget)), t.on("mouseenter", this.mousewheel.handleMouseEnter), t.on("mouseleave", this.mousewheel.handleMouseLeave), t.on(e, this.mousewheel.handle), this.mousewheel.enabled = !0, !0 }, disable: function () { var e = U.event(); if (this.params.cssMode) return this.wrapperEl.addEventListener(e, this.mousewheel.handle), !0; if (!e) return !1; if (!this.mousewheel.enabled) return !1; var t = this.$el; return "container" !== this.params.mousewheel.eventsTarget && (t = m(this.params.mousewheel.eventsTarget)), t.off(e, this.mousewheel.handle), this.mousewheel.enabled = !1, !0 } }, K = { update: function () { var e = this.params.navigation; if (!this.params.loop) { var t = this.navigation, i = t.$nextEl, s = t.$prevEl; s && s.length > 0 && (this.isBeginning ? s.addClass(e.disabledClass) : s.removeClass(e.disabledClass), s[this.params.watchOverflow && this.isLocked ? "addClass" : "removeClass"](e.lockClass)), i && i.length > 0 && (this.isEnd ? i.addClass(e.disabledClass) : i.removeClass(e.disabledClass), i[this.params.watchOverflow && this.isLocked ? "addClass" : "removeClass"](e.lockClass)) } }, onPrevClick: function (e) { e.preventDefault(), this.isBeginning && !this.params.loop || this.slidePrev() }, onNextClick: function (e) { e.preventDefault(), this.isEnd && !this.params.loop || this.slideNext() }, init: function () { var e, t, i = this.params.navigation; (i.nextEl || i.prevEl) && (i.nextEl && (e = m(i.nextEl), this.params.uniqueNavElements && "string" == typeof i.nextEl && e.length > 1 && 1 === this.$el.find(i.nextEl).length && (e = this.$el.find(i.nextEl))), i.prevEl && (t = m(i.prevEl), this.params.uniqueNavElements && "string" == typeof i.prevEl && t.length > 1 && 1 === this.$el.find(i.prevEl).length && (t = this.$el.find(i.prevEl))), e && e.length > 0 && e.on("click", this.navigation.onNextClick), t && t.length > 0 && t.on("click", this.navigation.onPrevClick), S(this.navigation, { $nextEl: e, nextEl: e && e[0], $prevEl: t, prevEl: t && t[0] })) }, destroy: function () { var e = this.navigation, t = e.$nextEl, i = e.$prevEl; t && t.length && (t.off("click", this.navigation.onNextClick), t.removeClass(this.params.navigation.disabledClass)), i && i.length && (i.off("click", this.navigation.onPrevClick), i.removeClass(this.params.navigation.disabledClass)) } }, Z = { update: function () { var e = this.rtl, t = this.params.pagination; if (t.el && this.pagination.el && this.pagination.$el && 0 !== this.pagination.$el.length) { var i, s = this.virtual && this.params.virtual.enabled ? this.virtual.slides.length : this.slides.length, a = this.pagination.$el, r = this.params.loop ? Math.ceil((s - 2 * this.loopedSlides) / this.params.slidesPerGroup) : this.snapGrid.length; if (this.params.loop ? ((i = Math.ceil((this.activeIndex - this.loopedSlides) / this.params.slidesPerGroup)) > s - 1 - 2 * this.loopedSlides && (i -= s - 2 * this.loopedSlides), i > r - 1 && (i -= r), i < 0 && "bullets" !== this.params.paginationType && (i = r + i)) : i = void 0 !== this.snapIndex ? this.snapIndex : this.activeIndex || 0, "bullets" === t.type && this.pagination.bullets && this.pagination.bullets.length > 0) { var n, l, o, d = this.pagination.bullets; if (t.dynamicBullets && (this.pagination.bulletSize = d.eq(0)[this.isHorizontal() ? "outerWidth" : "outerHeight"](!0), a.css(this.isHorizontal() ? "width" : "height", this.pagination.bulletSize * (t.dynamicMainBullets + 4) + "px"), t.dynamicMainBullets > 1 && void 0 !== this.previousIndex && (this.pagination.dynamicBulletIndex += i - this.previousIndex, this.pagination.dynamicBulletIndex > t.dynamicMainBullets - 1 ? this.pagination.dynamicBulletIndex = t.dynamicMainBullets - 1 : this.pagination.dynamicBulletIndex < 0 && (this.pagination.dynamicBulletIndex = 0)), n = i - this.pagination.dynamicBulletIndex, o = ((l = n + (Math.min(d.length, t.dynamicMainBullets) - 1)) + n) / 2), d.removeClass(t.bulletActiveClass + " " + t.bulletActiveClass + "-next " + t.bulletActiveClass + "-next-next " + t.bulletActiveClass + "-prev " + t.bulletActiveClass + "-prev-prev " + t.bulletActiveClass + "-main"), a.length > 1) d.each((function (e) { var s = m(e), a = s.index(); a === i && s.addClass(t.bulletActiveClass), t.dynamicBullets && (a >= n && a <= l && s.addClass(t.bulletActiveClass + "-main"), a === n && s.prev().addClass(t.bulletActiveClass + "-prev").prev().addClass(t.bulletActiveClass + "-prev-prev"), a === l && s.next().addClass(t.bulletActiveClass + "-next").next().addClass(t.bulletActiveClass + "-next-next")) })); else { var h = d.eq(i), p = h.index(); if (h.addClass(t.bulletActiveClass), t.dynamicBullets) { for (var u = d.eq(n), c = d.eq(l), v = n; v <= l; v += 1)d.eq(v).addClass(t.bulletActiveClass + "-main"); if (this.params.loop) if (p >= d.length - t.dynamicMainBullets) { for (var f = t.dynamicMainBullets; f >= 0; f -= 1)d.eq(d.length - f).addClass(t.bulletActiveClass + "-main"); d.eq(d.length - t.dynamicMainBullets - 1).addClass(t.bulletActiveClass + "-prev") } else u.prev().addClass(t.bulletActiveClass + "-prev").prev().addClass(t.bulletActiveClass + "-prev-prev"), c.next().addClass(t.bulletActiveClass + "-next").next().addClass(t.bulletActiveClass + "-next-next"); else u.prev().addClass(t.bulletActiveClass + "-prev").prev().addClass(t.bulletActiveClass + "-prev-prev"), c.next().addClass(t.bulletActiveClass + "-next").next().addClass(t.bulletActiveClass + "-next-next") } } if (t.dynamicBullets) { var g = Math.min(d.length, t.dynamicMainBullets + 4), w = (this.pagination.bulletSize * g - this.pagination.bulletSize) / 2 - o * this.pagination.bulletSize, b = e ? "right" : "left"; d.css(this.isHorizontal() ? b : "top", w + "px") } } if ("fraction" === t.type && (a.find("." + t.currentClass).text(t.formatFractionCurrent(i + 1)), a.find("." + t.totalClass).text(t.formatFractionTotal(r))), "progressbar" === t.type) { var y; y = t.progressbarOpposite ? this.isHorizontal() ? "vertical" : "horizontal" : this.isHorizontal() ? "horizontal" : "vertical"; var E = (i + 1) / r, x = 1, T = 1; "horizontal" === y ? x = E : T = E, a.find("." + t.progressbarFillClass).transform("translate3d(0,0,0) scaleX(" + x + ") scaleY(" + T + ")").transition(this.params.speed) } "custom" === t.type && t.renderCustom ? (a.html(t.renderCustom(this, i + 1, r)), this.emit("paginationRender", a[0])) : this.emit("paginationUpdate", a[0]), a[this.params.watchOverflow && this.isLocked ? "addClass" : "removeClass"](t.lockClass) } }, render: function () { var e = this.params.pagination; if (e.el && this.pagination.el && this.pagination.$el && 0 !== this.pagination.$el.length) { var t = this.virtual && this.params.virtual.enabled ? this.virtual.slides.length : this.slides.length, i = this.pagination.$el, s = ""; if ("bullets" === e.type) { for (var a = this.params.loop ? Math.ceil((t - 2 * this.loopedSlides) / this.params.slidesPerGroup) : this.snapGrid.length, r = 0; r < a; r += 1)e.renderBullet ? s += e.renderBullet.call(this, r, e.bulletClass) : s += "<" + e.bulletElement + ' class="' + e.bulletClass + '"></' + e.bulletElement + ">"; i.html(s), this.pagination.bullets = i.find("." + e.bulletClass) } "fraction" === e.type && (s = e.renderFraction ? e.renderFraction.call(this, e.currentClass, e.totalClass) : '<span class="' + e.currentClass + '"></span> / <span class="' + e.totalClass + '"></span>', i.html(s)), "progressbar" === e.type && (s = e.renderProgressbar ? e.renderProgressbar.call(this, e.progressbarFillClass) : '<span class="' + e.progressbarFillClass + '"></span>', i.html(s)), "custom" !== e.type && this.emit("paginationRender", this.pagination.$el[0]) } }, init: function () { var e = this, t = e.params.pagination; if (t.el) { var i = m(t.el); 0 !== i.length && (e.params.uniqueNavElements && "string" == typeof t.el && i.length > 1 && (i = e.$el.find(t.el)), "bullets" === t.type && t.clickable && i.addClass(t.clickableClass), i.addClass(t.modifierClass + t.type), "bullets" === t.type && t.dynamicBullets && (i.addClass("" + t.modifierClass + t.type + "-dynamic"), e.pagination.dynamicBulletIndex = 0, t.dynamicMainBullets < 1 && (t.dynamicMainBullets = 1)), "progressbar" === t.type && t.progressbarOpposite && i.addClass(t.progressbarOppositeClass), t.clickable && i.on("click", "." + t.bulletClass, (function (t) { t.preventDefault(); var i = m(this).index() * e.params.slidesPerGroup; e.params.loop && (i += e.loopedSlides), e.slideTo(i) })), S(e.pagination, { $el: i, el: i[0] })) } }, destroy: function () { var e = this.params.pagination; if (e.el && this.pagination.el && this.pagination.$el && 0 !== this.pagination.$el.length) { var t = this.pagination.$el; t.removeClass(e.hiddenClass), t.removeClass(e.modifierClass + e.type), this.pagination.bullets && this.pagination.bullets.removeClass(e.bulletActiveClass), e.clickable && t.off("click", "." + e.bulletClass) } } }, J = { setTranslate: function () { if (this.params.scrollbar.el && this.scrollbar.el) { var e = this.scrollbar, t = this.rtlTranslate, i = this.progress, s = e.dragSize, a = e.trackSize, r = e.$dragEl, n = e.$el, l = this.params.scrollbar, o = s, d = (a - s) * i; t ? (d = -d) > 0 ? (o = s - d, d = 0) : -d + s > a && (o = a + d) : d < 0 ? (o = s + d, d = 0) : d + s > a && (o = a - d), this.isHorizontal() ? (r.transform("translate3d(" + d + "px, 0, 0)"), r[0].style.width = o + "px") : (r.transform("translate3d(0px, " + d + "px, 0)"), r[0].style.height = o + "px"), l.hide && (clearTimeout(this.scrollbar.timeout), n[0].style.opacity = 1, this.scrollbar.timeout = setTimeout((function () { n[0].style.opacity = 0, n.transition(400) }), 1e3)) } }, setTransition: function (e) { this.params.scrollbar.el && this.scrollbar.el && this.scrollbar.$dragEl.transition(e) }, updateSize: function () { if (this.params.scrollbar.el && this.scrollbar.el) { var e = this.scrollbar, t = e.$dragEl, i = e.$el; t[0].style.width = "", t[0].style.height = ""; var s, a = this.isHorizontal() ? i[0].offsetWidth : i[0].offsetHeight, r = this.size / this.virtualSize, n = r * (a / this.size); s = "auto" === this.params.scrollbar.dragSize ? a * r : parseInt(this.params.scrollbar.dragSize, 10), this.isHorizontal() ? t[0].style.width = s + "px" : t[0].style.height = s + "px", i[0].style.display = r >= 1 ? "none" : "", this.params.scrollbar.hide && (i[0].style.opacity = 0), S(e, { trackSize: a, divider: r, moveDivider: n, dragSize: s }), e.$el[this.params.watchOverflow && this.isLocked ? "addClass" : "removeClass"](this.params.scrollbar.lockClass) } }, getPointerPosition: function (e) { return this.isHorizontal() ? "touchstart" === e.type || "touchmove" === e.type ? e.targetTouches[0].clientX : e.clientX : "touchstart" === e.type || "touchmove" === e.type ? e.targetTouches[0].clientY : e.clientY }, setDragPosition: function (e) { var t, i = this.scrollbar, s = this.rtlTranslate, a = i.$el, r = i.dragSize, n = i.trackSize, l = i.dragStartPos; t = (i.getPointerPosition(e) - a.offset()[this.isHorizontal() ? "left" : "top"] - (null !== l ? l : r / 2)) / (n - r), t = Math.max(Math.min(t, 1), 0), s && (t = 1 - t); var o = this.minTranslate() + (this.maxTranslate() - this.minTranslate()) * t; this.updateProgress(o), this.setTranslate(o), this.updateActiveIndex(), this.updateSlidesClasses() }, onDragStart: function (e) { var t = this.params.scrollbar, i = this.scrollbar, s = this.$wrapperEl, a = i.$el, r = i.$dragEl; this.scrollbar.isTouched = !0, this.scrollbar.dragStartPos = e.target === r[0] || e.target === r ? i.getPointerPosition(e) - e.target.getBoundingClientRect()[this.isHorizontal() ? "left" : "top"] : null, e.preventDefault(), e.stopPropagation(), s.transition(100), r.transition(100), i.setDragPosition(e), clearTimeout(this.scrollbar.dragTimeout), a.transition(0), t.hide && a.css("opacity", 1), this.params.cssMode && this.$wrapperEl.css("scroll-snap-type", "none"), this.emit("scrollbarDragStart", e) }, onDragMove: function (e) { var t = this.scrollbar, i = this.$wrapperEl, s = t.$el, a = t.$dragEl; this.scrollbar.isTouched && (e.preventDefault ? e.preventDefault() : e.returnValue = !1, t.setDragPosition(e), i.transition(0), s.transition(0), a.transition(0), this.emit("scrollbarDragMove", e)) }, onDragEnd: function (e) { var t = this.params.scrollbar, i = this.scrollbar, s = this.$wrapperEl, a = i.$el; this.scrollbar.isTouched && (this.scrollbar.isTouched = !1, this.params.cssMode && (this.$wrapperEl.css("scroll-snap-type", ""), s.transition("")), t.hide && (clearTimeout(this.scrollbar.dragTimeout), this.scrollbar.dragTimeout = E((function () { a.css("opacity", 0), a.transition(400) }), 1e3)), this.emit("scrollbarDragEnd", e), t.snapOnRelease && this.slideToClosest()) }, enableDraggable: function () { if (this.params.scrollbar.el) { var e = r(), t = this.scrollbar, i = this.touchEventsTouch, s = this.touchEventsDesktop, a = this.params, n = this.support, l = t.$el[0], o = !(!n.passiveListener || !a.passiveListeners) && { passive: !1, capture: !1 }, d = !(!n.passiveListener || !a.passiveListeners) && { passive: !0, capture: !1 }; n.touch ? (l.addEventListener(i.start, this.scrollbar.onDragStart, o), l.addEventListener(i.move, this.scrollbar.onDragMove, o), l.addEventListener(i.end, this.scrollbar.onDragEnd, d)) : (l.addEventListener(s.start, this.scrollbar.onDragStart, o), e.addEventListener(s.move, this.scrollbar.onDragMove, o), e.addEventListener(s.end, this.scrollbar.onDragEnd, d)) } }, disableDraggable: function () { if (this.params.scrollbar.el) { var e = r(), t = this.scrollbar, i = this.touchEventsTouch, s = this.touchEventsDesktop, a = this.params, n = this.support, l = t.$el[0], o = !(!n.passiveListener || !a.passiveListeners) && { passive: !1, capture: !1 }, d = !(!n.passiveListener || !a.passiveListeners) && { passive: !0, capture: !1 }; n.touch ? (l.removeEventListener(i.start, this.scrollbar.onDragStart, o), l.removeEventListener(i.move, this.scrollbar.onDragMove, o), l.removeEventListener(i.end, this.scrollbar.onDragEnd, d)) : (l.removeEventListener(s.start, this.scrollbar.onDragStart, o), e.removeEventListener(s.move, this.scrollbar.onDragMove, o), e.removeEventListener(s.end, this.scrollbar.onDragEnd, d)) } }, init: function () { if (this.params.scrollbar.el) { var e = this.scrollbar, t = this.$el, i = this.params.scrollbar, s = m(i.el); this.params.uniqueNavElements && "string" == typeof i.el && s.length > 1 && 1 === t.find(i.el).length && (s = t.find(i.el)); var a = s.find("." + this.params.scrollbar.dragClass); 0 === a.length && (a = m('<div class="' + this.params.scrollbar.dragClass + '"></div>'), s.append(a)), S(e, { $el: s, el: s[0], $dragEl: a, dragEl: a[0] }), i.draggable && e.enableDraggable() } }, destroy: function () { this.scrollbar.disableDraggable() } }, Q = { setTransform: function (e, t) { var i = this.rtl, s = m(e), a = i ? -1 : 1, r = s.attr("data-swiper-parallax") || "0", n = s.attr("data-swiper-parallax-x"), l = s.attr("data-swiper-parallax-y"), o = s.attr("data-swiper-parallax-scale"), d = s.attr("data-swiper-parallax-opacity"); if (n || l ? (n = n || "0", l = l || "0") : this.isHorizontal() ? (n = r, l = "0") : (l = r, n = "0"), n = n.indexOf("%") >= 0 ? parseInt(n, 10) * t * a + "%" : n * t * a + "px", l = l.indexOf("%") >= 0 ? parseInt(l, 10) * t + "%" : l * t + "px", null != d) { var h = d - (d - 1) * (1 - Math.abs(t)); s[0].style.opacity = h } if (null == o) s.transform("translate3d(" + n + ", " + l + ", 0px)"); else { var p = o - (o - 1) * (1 - Math.abs(t)); s.transform("translate3d(" + n + ", " + l + ", 0px) scale(" + p + ")") } }, setTranslate: function () { var e = this, t = e.$el, i = e.slides, s = e.progress, a = e.snapGrid; t.children("[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y], [data-swiper-parallax-opacity], [data-swiper-parallax-scale]").each((function (t) { e.parallax.setTransform(t, s) })), i.each((function (t, i) { var r = t.progress; e.params.slidesPerGroup > 1 && "auto" !== e.params.slidesPerView && (r += Math.ceil(i / 2) - s * (a.length - 1)), r = Math.min(Math.max(r, -1), 1), m(t).find("[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y], [data-swiper-parallax-opacity], [data-swiper-parallax-scale]").each((function (t) { e.parallax.setTransform(t, r) })) })) }, setTransition: function (e) { void 0 === e && (e = this.params.speed); this.$el.find("[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y], [data-swiper-parallax-opacity], [data-swiper-parallax-scale]").each((function (t) { var i = m(t), s = parseInt(i.attr("data-swiper-parallax-duration"), 10) || e; 0 === e && (s = 0), i.transition(s) })) } }, ee = { getDistanceBetweenTouches: function (e) { if (e.targetTouches.length < 2) return 1; var t = e.targetTouches[0].pageX, i = e.targetTouches[0].pageY, s = e.targetTouches[1].pageX, a = e.targetTouches[1].pageY; return Math.sqrt(Math.pow(s - t, 2) + Math.pow(a - i, 2)) }, onGestureStart: function (e) { var t = this.support, i = this.params.zoom, s = this.zoom, a = s.gesture; if (s.fakeGestureTouched = !1, s.fakeGestureMoved = !1, !t.gestures) { if ("touchstart" !== e.type || "touchstart" === e.type && e.targetTouches.length < 2) return; s.fakeGestureTouched = !0, a.scaleStart = ee.getDistanceBetweenTouches(e) } a.$slideEl && a.$slideEl.length || (a.$slideEl = m(e.target).closest("." + this.params.slideClass), 0 === a.$slideEl.length && (a.$slideEl = this.slides.eq(this.activeIndex)), a.$imageEl = a.$slideEl.find("img, svg, canvas, picture, .swiper-zoom-target"), a.$imageWrapEl = a.$imageEl.parent("." + i.containerClass), a.maxRatio = a.$imageWrapEl.attr("data-swiper-zoom") || i.maxRatio, 0 !== a.$imageWrapEl.length) ? (a.$imageEl && a.$imageEl.transition(0), this.zoom.isScaling = !0) : a.$imageEl = void 0 }, onGestureChange: function (e) { var t = this.support, i = this.params.zoom, s = this.zoom, a = s.gesture; if (!t.gestures) { if ("touchmove" !== e.type || "touchmove" === e.type && e.targetTouches.length < 2) return; s.fakeGestureMoved = !0, a.scaleMove = ee.getDistanceBetweenTouches(e) } a.$imageEl && 0 !== a.$imageEl.length ? (t.gestures ? s.scale = e.scale * s.currentScale : s.scale = a.scaleMove / a.scaleStart * s.currentScale, s.scale > a.maxRatio && (s.scale = a.maxRatio - 1 + Math.pow(s.scale - a.maxRatio + 1, .5)), s.scale < i.minRatio && (s.scale = i.minRatio + 1 - Math.pow(i.minRatio - s.scale + 1, .5)), a.$imageEl.transform("translate3d(0,0,0) scale(" + s.scale + ")")) : "gesturechange" === e.type && s.onGestureStart(e) }, onGestureEnd: function (e) { var t = this.device, i = this.support, s = this.params.zoom, a = this.zoom, r = a.gesture; if (!i.gestures) { if (!a.fakeGestureTouched || !a.fakeGestureMoved) return; if ("touchend" !== e.type || "touchend" === e.type && e.changedTouches.length < 2 && !t.android) return; a.fakeGestureTouched = !1, a.fakeGestureMoved = !1 } r.$imageEl && 0 !== r.$imageEl.length && (a.scale = Math.max(Math.min(a.scale, r.maxRatio), s.minRatio), r.$imageEl.transition(this.params.speed).transform("translate3d(0,0,0) scale(" + a.scale + ")"), a.currentScale = a.scale, a.isScaling = !1, 1 === a.scale && (r.$slideEl = void 0)) }, onTouchStart: function (e) { var t = this.device, i = this.zoom, s = i.gesture, a = i.image; s.$imageEl && 0 !== s.$imageEl.length && (a.isTouched || (t.android && e.cancelable && e.preventDefault(), a.isTouched = !0, a.touchesStart.x = "touchstart" === e.type ? e.targetTouches[0].pageX : e.pageX, a.touchesStart.y = "touchstart" === e.type ? e.targetTouches[0].pageY : e.pageY)) }, onTouchMove: function (e) { var t = this.zoom, i = t.gesture, s = t.image, a = t.velocity; if (i.$imageEl && 0 !== i.$imageEl.length && (this.allowClick = !1, s.isTouched && i.$slideEl)) { s.isMoved || (s.width = i.$imageEl[0].offsetWidth, s.height = i.$imageEl[0].offsetHeight, s.startX = T(i.$imageWrapEl[0], "x") || 0, s.startY = T(i.$imageWrapEl[0], "y") || 0, i.slideWidth = i.$slideEl[0].offsetWidth, i.slideHeight = i.$slideEl[0].offsetHeight, i.$imageWrapEl.transition(0), this.rtl && (s.startX = -s.startX, s.startY = -s.startY)); var r = s.width * t.scale, n = s.height * t.scale; if (!(r < i.slideWidth && n < i.slideHeight)) { if (s.minX = Math.min(i.slideWidth / 2 - r / 2, 0), s.maxX = -s.minX, s.minY = Math.min(i.slideHeight / 2 - n / 2, 0), s.maxY = -s.minY, s.touchesCurrent.x = "touchmove" === e.type ? e.targetTouches[0].pageX : e.pageX, s.touchesCurrent.y = "touchmove" === e.type ? e.targetTouches[0].pageY : e.pageY, !s.isMoved && !t.isScaling) { if (this.isHorizontal() && (Math.floor(s.minX) === Math.floor(s.startX) && s.touchesCurrent.x < s.touchesStart.x || Math.floor(s.maxX) === Math.floor(s.startX) && s.touchesCurrent.x > s.touchesStart.x)) return void (s.isTouched = !1); if (!this.isHorizontal() && (Math.floor(s.minY) === Math.floor(s.startY) && s.touchesCurrent.y < s.touchesStart.y || Math.floor(s.maxY) === Math.floor(s.startY) && s.touchesCurrent.y > s.touchesStart.y)) return void (s.isTouched = !1) } e.cancelable && e.preventDefault(), e.stopPropagation(), s.isMoved = !0, s.currentX = s.touchesCurrent.x - s.touchesStart.x + s.startX, s.currentY = s.touchesCurrent.y - s.touchesStart.y + s.startY, s.currentX < s.minX && (s.currentX = s.minX + 1 - Math.pow(s.minX - s.currentX + 1, .8)), s.currentX > s.maxX && (s.currentX = s.maxX - 1 + Math.pow(s.currentX - s.maxX + 1, .8)), s.currentY < s.minY && (s.currentY = s.minY + 1 - Math.pow(s.minY - s.currentY + 1, .8)), s.currentY > s.maxY && (s.currentY = s.maxY - 1 + Math.pow(s.currentY - s.maxY + 1, .8)), a.prevPositionX || (a.prevPositionX = s.touchesCurrent.x), a.prevPositionY || (a.prevPositionY = s.touchesCurrent.y), a.prevTime || (a.prevTime = Date.now()), a.x = (s.touchesCurrent.x - a.prevPositionX) / (Date.now() - a.prevTime) / 2, a.y = (s.touchesCurrent.y - a.prevPositionY) / (Date.now() - a.prevTime) / 2, Math.abs(s.touchesCurrent.x - a.prevPositionX) < 2 && (a.x = 0), Math.abs(s.touchesCurrent.y - a.prevPositionY) < 2 && (a.y = 0), a.prevPositionX = s.touchesCurrent.x, a.prevPositionY = s.touchesCurrent.y, a.prevTime = Date.now(), i.$imageWrapEl.transform("translate3d(" + s.currentX + "px, " + s.currentY + "px,0)") } } }, onTouchEnd: function () { var e = this.zoom, t = e.gesture, i = e.image, s = e.velocity; if (t.$imageEl && 0 !== t.$imageEl.length) { if (!i.isTouched || !i.isMoved) return i.isTouched = !1, void (i.isMoved = !1); i.isTouched = !1, i.isMoved = !1; var a = 300, r = 300, n = s.x * a, l = i.currentX + n, o = s.y * r, d = i.currentY + o; 0 !== s.x && (a = Math.abs((l - i.currentX) / s.x)), 0 !== s.y && (r = Math.abs((d - i.currentY) / s.y)); var h = Math.max(a, r); i.currentX = l, i.currentY = d; var p = i.width * e.scale, u = i.height * e.scale; i.minX = Math.min(t.slideWidth / 2 - p / 2, 0), i.maxX = -i.minX, i.minY = Math.min(t.slideHeight / 2 - u / 2, 0), i.maxY = -i.minY, i.currentX = Math.max(Math.min(i.currentX, i.maxX), i.minX), i.currentY = Math.max(Math.min(i.currentY, i.maxY), i.minY), t.$imageWrapEl.transition(h).transform("translate3d(" + i.currentX + "px, " + i.currentY + "px,0)") } }, onTransitionEnd: function () { var e = this.zoom, t = e.gesture; t.$slideEl && this.previousIndex !== this.activeIndex && (t.$imageEl && t.$imageEl.transform("translate3d(0,0,0) scale(1)"), t.$imageWrapEl && t.$imageWrapEl.transform("translate3d(0,0,0)"), e.scale = 1, e.currentScale = 1, t.$slideEl = void 0, t.$imageEl = void 0, t.$imageWrapEl = void 0) }, toggle: function (e) { var t = this.zoom; t.scale && 1 !== t.scale ? t.out() : t.in(e) }, in: function (e) { var t, i, s, a, r, n, l, o, d, h, p, u, c, v, f, m, g = this.zoom, w = this.params.zoom, b = g.gesture, y = g.image; (b.$slideEl || (this.params.virtual && this.params.virtual.enabled && this.virtual ? b.$slideEl = this.$wrapperEl.children("." + this.params.slideActiveClass) : b.$slideEl = this.slides.eq(this.activeIndex), b.$imageEl = b.$slideEl.find("img, svg, canvas, picture, .swiper-zoom-target"), b.$imageWrapEl = b.$imageEl.parent("." + w.containerClass)), b.$imageEl && 0 !== b.$imageEl.length) && (b.$slideEl.addClass("" + w.zoomedSlideClass), void 0 === y.touchesStart.x && e ? (t = "touchend" === e.type ? e.changedTouches[0].pageX : e.pageX, i = "touchend" === e.type ? e.changedTouches[0].pageY : e.pageY) : (t = y.touchesStart.x, i = y.touchesStart.y), g.scale = b.$imageWrapEl.attr("data-swiper-zoom") || w.maxRatio, g.currentScale = b.$imageWrapEl.attr("data-swiper-zoom") || w.maxRatio, e ? (f = b.$slideEl[0].offsetWidth, m = b.$slideEl[0].offsetHeight, s = b.$slideEl.offset().left + f / 2 - t, a = b.$slideEl.offset().top + m / 2 - i, l = b.$imageEl[0].offsetWidth, o = b.$imageEl[0].offsetHeight, d = l * g.scale, h = o * g.scale, c = -(p = Math.min(f / 2 - d / 2, 0)), v = -(u = Math.min(m / 2 - h / 2, 0)), (r = s * g.scale) < p && (r = p), r > c && (r = c), (n = a * g.scale) < u && (n = u), n > v && (n = v)) : (r = 0, n = 0), b.$imageWrapEl.transition(300).transform("translate3d(" + r + "px, " + n + "px,0)"), b.$imageEl.transition(300).transform("translate3d(0,0,0) scale(" + g.scale + ")")) }, out: function () { var e = this.zoom, t = this.params.zoom, i = e.gesture; i.$slideEl || (this.params.virtual && this.params.virtual.enabled && this.virtual ? i.$slideEl = this.$wrapperEl.children("." + this.params.slideActiveClass) : i.$slideEl = this.slides.eq(this.activeIndex), i.$imageEl = i.$slideEl.find("img, svg, canvas, picture, .swiper-zoom-target"), i.$imageWrapEl = i.$imageEl.parent("." + t.containerClass)), i.$imageEl && 0 !== i.$imageEl.length && (e.scale = 1, e.currentScale = 1, i.$imageWrapEl.transition(300).transform("translate3d(0,0,0)"), i.$imageEl.transition(300).transform("translate3d(0,0,0) scale(1)"), i.$slideEl.removeClass("" + t.zoomedSlideClass), i.$slideEl = void 0) }, toggleGestures: function (e) { var t = this.zoom, i = t.slideSelector, s = t.passiveListener; this.$wrapperEl[e]("gesturestart", i, t.onGestureStart, s), this.$wrapperEl[e]("gesturechange", i, t.onGestureChange, s), this.$wrapperEl[e]("gestureend", i, t.onGestureEnd, s) }, enableGestures: function () { this.zoom.gesturesEnabled || (this.zoom.gesturesEnabled = !0, this.zoom.toggleGestures("on")) }, disableGestures: function () { this.zoom.gesturesEnabled && (this.zoom.gesturesEnabled = !1, this.zoom.toggleGestures("off")) }, enable: function () { var e = this.support, t = this.zoom; if (!t.enabled) { t.enabled = !0; var i = !("touchstart" !== this.touchEvents.start || !e.passiveListener || !this.params.passiveListeners) && { passive: !0, capture: !1 }, s = !e.passiveListener || { passive: !1, capture: !0 }, a = "." + this.params.slideClass; this.zoom.passiveListener = i, this.zoom.slideSelector = a, e.gestures ? (this.$wrapperEl.on(this.touchEvents.start, this.zoom.enableGestures, i), this.$wrapperEl.on(this.touchEvents.end, this.zoom.disableGestures, i)) : "touchstart" === this.touchEvents.start && (this.$wrapperEl.on(this.touchEvents.start, a, t.onGestureStart, i), this.$wrapperEl.on(this.touchEvents.move, a, t.onGestureChange, s), this.$wrapperEl.on(this.touchEvents.end, a, t.onGestureEnd, i), this.touchEvents.cancel && this.$wrapperEl.on(this.touchEvents.cancel, a, t.onGestureEnd, i)), this.$wrapperEl.on(this.touchEvents.move, "." + this.params.zoom.containerClass, t.onTouchMove, s) } }, disable: function () { var e = this.zoom; if (e.enabled) { var t = this.support; this.zoom.enabled = !1; var i = !("touchstart" !== this.touchEvents.start || !t.passiveListener || !this.params.passiveListeners) && { passive: !0, capture: !1 }, s = !t.passiveListener || { passive: !1, capture: !0 }, a = "." + this.params.slideClass; t.gestures ? (this.$wrapperEl.off(this.touchEvents.start, this.zoom.enableGestures, i), this.$wrapperEl.off(this.touchEvents.end, this.zoom.disableGestures, i)) : "touchstart" === this.touchEvents.start && (this.$wrapperEl.off(this.touchEvents.start, a, e.onGestureStart, i), this.$wrapperEl.off(this.touchEvents.move, a, e.onGestureChange, s), this.$wrapperEl.off(this.touchEvents.end, a, e.onGestureEnd, i), this.touchEvents.cancel && this.$wrapperEl.off(this.touchEvents.cancel, a, e.onGestureEnd, i)), this.$wrapperEl.off(this.touchEvents.move, "." + this.params.zoom.containerClass, e.onTouchMove, s) } } }, te = { loadInSlide: function (e, t) { void 0 === t && (t = !0); var i = this, s = i.params.lazy; if (void 0 !== e && 0 !== i.slides.length) { var a = i.virtual && i.params.virtual.enabled ? i.$wrapperEl.children("." + i.params.slideClass + '[data-swiper-slide-index="' + e + '"]') : i.slides.eq(e), r = a.find("." + s.elementClass + ":not(." + s.loadedClass + "):not(." + s.loadingClass + ")"); !a.hasClass(s.elementClass) || a.hasClass(s.loadedClass) || a.hasClass(s.loadingClass) || r.push(a[0]), 0 !== r.length && r.each((function (e) { var r = m(e); r.addClass(s.loadingClass); var n = r.attr("data-background"), l = r.attr("data-src"), o = r.attr("data-srcset"), d = r.attr("data-sizes"), h = r.parent("picture"); i.loadImage(r[0], l || n, o, d, !1, (function () { if (null != i && i && (!i || i.params) && !i.destroyed) { if (n ? (r.css("background-image", 'url("' + n + '")'), r.removeAttr("data-background")) : (o && (r.attr("srcset", o), r.removeAttr("data-srcset")), d && (r.attr("sizes", d), r.removeAttr("data-sizes")), h.length && h.children("source").each((function (e) { var t = m(e); t.attr("data-srcset") && (t.attr("srcset", t.attr("data-srcset")), t.removeAttr("data-srcset")) })), l && (r.attr("src", l), r.removeAttr("data-src"))), r.addClass(s.loadedClass).removeClass(s.loadingClass), a.find("." + s.preloaderClass).remove(), i.params.loop && t) { var e = a.attr("data-swiper-slide-index"); if (a.hasClass(i.params.slideDuplicateClass)) { var p = i.$wrapperEl.children('[data-swiper-slide-index="' + e + '"]:not(.' + i.params.slideDuplicateClass + ")"); i.lazy.loadInSlide(p.index(), !1) } else { var u = i.$wrapperEl.children("." + i.params.slideDuplicateClass + '[data-swiper-slide-index="' + e + '"]'); i.lazy.loadInSlide(u.index(), !1) } } i.emit("lazyImageReady", a[0], r[0]), i.params.autoHeight && i.updateAutoHeight() } })), i.emit("lazyImageLoad", a[0], r[0]) })) } }, load: function () { var e = this, t = e.$wrapperEl, i = e.params, s = e.slides, a = e.activeIndex, r = e.virtual && i.virtual.enabled, n = i.lazy, l = i.slidesPerView; function o(e) { if (r) { if (t.children("." + i.slideClass + '[data-swiper-slide-index="' + e + '"]').length) return !0 } else if (s[e]) return !0; return !1 } function d(e) { return r ? m(e).attr("data-swiper-slide-index") : m(e).index() } if ("auto" === l && (l = 0), e.lazy.initialImageLoaded || (e.lazy.initialImageLoaded = !0), e.params.watchSlidesVisibility) t.children("." + i.slideVisibleClass).each((function (t) { var i = r ? m(t).attr("data-swiper-slide-index") : m(t).index(); e.lazy.loadInSlide(i) })); else if (l > 1) for (var h = a; h < a + l; h += 1)o(h) && e.lazy.loadInSlide(h); else e.lazy.loadInSlide(a); if (n.loadPrevNext) if (l > 1 || n.loadPrevNextAmount && n.loadPrevNextAmount > 1) { for (var p = n.loadPrevNextAmount, u = l, c = Math.min(a + u + Math.max(p, u), s.length), v = Math.max(a - Math.max(u, p), 0), f = a + l; f < c; f += 1)o(f) && e.lazy.loadInSlide(f); for (var g = v; g < a; g += 1)o(g) && e.lazy.loadInSlide(g) } else { var w = t.children("." + i.slideNextClass); w.length > 0 && e.lazy.loadInSlide(d(w)); var b = t.children("." + i.slidePrevClass); b.length > 0 && e.lazy.loadInSlide(d(b)) } } }, ie = { LinearSpline: function (e, t) { var i, s, a, r, n, l = function (e, t) { for (s = -1, i = e.length; i - s > 1;)e[a = i + s >> 1] <= t ? s = a : i = a; return i }; return this.x = e, this.y = t, this.lastIndex = e.length - 1, this.interpolate = function (e) { return e ? (n = l(this.x, e), r = n - 1, (e - this.x[r]) * (this.y[n] - this.y[r]) / (this.x[n] - this.x[r]) + this.y[r]) : 0 }, this }, getInterpolateFunction: function (e) { this.controller.spline || (this.controller.spline = this.params.loop ? new ie.LinearSpline(this.slidesGrid, e.slidesGrid) : new ie.LinearSpline(this.snapGrid, e.snapGrid)) }, setTranslate: function (e, t) { var i, s, a = this, r = a.controller.control, n = a.constructor; function l(e) { var t = a.rtlTranslate ? -a.translate : a.translate; "slide" === a.params.controller.by && (a.controller.getInterpolateFunction(e), s = -a.controller.spline.interpolate(-t)), s && "container" !== a.params.controller.by || (i = (e.maxTranslate() - e.minTranslate()) / (a.maxTranslate() - a.minTranslate()), s = (t - a.minTranslate()) * i + e.minTranslate()), a.params.controller.inverse && (s = e.maxTranslate() - s), e.updateProgress(s), e.setTranslate(s, a), e.updateActiveIndex(), e.updateSlidesClasses() } if (Array.isArray(r)) for (var o = 0; o < r.length; o += 1)r[o] !== t && r[o] instanceof n && l(r[o]); else r instanceof n && t !== r && l(r) }, setTransition: function (e, t) { var i, s = this, a = s.constructor, r = s.controller.control; function n(t) { t.setTransition(e, s), 0 !== e && (t.transitionStart(), t.params.autoHeight && E((function () { t.updateAutoHeight() })), t.$wrapperEl.transitionEnd((function () { r && (t.params.loop && "slide" === s.params.controller.by && t.loopFix(), t.transitionEnd()) }))) } if (Array.isArray(r)) for (i = 0; i < r.length; i += 1)r[i] !== t && r[i] instanceof a && n(r[i]); else r instanceof a && t !== r && n(r) } }, se = { makeElFocusable: function (e) { return e.attr("tabIndex", "0"), e }, makeElNotFocusable: function (e) { return e.attr("tabIndex", "-1"), e }, addElRole: function (e, t) { return e.attr("role", t), e }, addElLabel: function (e, t) { return e.attr("aria-label", t), e }, disableEl: function (e) { return e.attr("aria-disabled", !0), e }, enableEl: function (e) { return e.attr("aria-disabled", !1), e }, onEnterKey: function (e) { var t = this.params.a11y; if (13 === e.keyCode) { var i = m(e.target); this.navigation && this.navigation.$nextEl && i.is(this.navigation.$nextEl) && (this.isEnd && !this.params.loop || this.slideNext(), this.isEnd ? this.a11y.notify(t.lastSlideMessage) : this.a11y.notify(t.nextSlideMessage)), this.navigation && this.navigation.$prevEl && i.is(this.navigation.$prevEl) && (this.isBeginning && !this.params.loop || this.slidePrev(), this.isBeginning ? this.a11y.notify(t.firstSlideMessage) : this.a11y.notify(t.prevSlideMessage)), this.pagination && i.is("." + this.params.pagination.bulletClass) && i[0].click() } }, notify: function (e) { var t = this.a11y.liveRegion; 0 !== t.length && (t.html(""), t.html(e)) }, updateNavigation: function () { if (!this.params.loop && this.navigation) { var e = this.navigation, t = e.$nextEl, i = e.$prevEl; i && i.length > 0 && (this.isBeginning ? (this.a11y.disableEl(i), this.a11y.makeElNotFocusable(i)) : (this.a11y.enableEl(i), this.a11y.makeElFocusable(i))), t && t.length > 0 && (this.isEnd ? (this.a11y.disableEl(t), this.a11y.makeElNotFocusable(t)) : (this.a11y.enableEl(t), this.a11y.makeElFocusable(t))) } }, updatePagination: function () { var e = this, t = e.params.a11y; e.pagination && e.params.pagination.clickable && e.pagination.bullets && e.pagination.bullets.length && e.pagination.bullets.each((function (i) { var s = m(i); e.a11y.makeElFocusable(s), e.a11y.addElRole(s, "button"), e.a11y.addElLabel(s, t.paginationBulletMessage.replace(/\{\{index\}\}/, s.index() + 1)) })) }, init: function () { this.$el.append(this.a11y.liveRegion); var e, t, i = this.params.a11y; this.navigation && this.navigation.$nextEl && (e = this.navigation.$nextEl), this.navigation && this.navigation.$prevEl && (t = this.navigation.$prevEl), e && (this.a11y.makeElFocusable(e), this.a11y.addElRole(e, "button"), this.a11y.addElLabel(e, i.nextSlideMessage), e.on("keydown", this.a11y.onEnterKey)), t && (this.a11y.makeElFocusable(t), this.a11y.addElRole(t, "button"), this.a11y.addElLabel(t, i.prevSlideMessage), t.on("keydown", this.a11y.onEnterKey)), this.pagination && this.params.pagination.clickable && this.pagination.bullets && this.pagination.bullets.length && this.pagination.$el.on("keydown", "." + this.params.pagination.bulletClass, this.a11y.onEnterKey) }, destroy: function () { var e, t; this.a11y.liveRegion && this.a11y.liveRegion.length > 0 && this.a11y.liveRegion.remove(), this.navigation && this.navigation.$nextEl && (e = this.navigation.$nextEl), this.navigation && this.navigation.$prevEl && (t = this.navigation.$prevEl), e && e.off("keydown", this.a11y.onEnterKey), t && t.off("keydown", this.a11y.onEnterKey), this.pagination && this.params.pagination.clickable && this.pagination.bullets && this.pagination.bullets.length && this.pagination.$el.off("keydown", "." + this.params.pagination.bulletClass, this.a11y.onEnterKey) } }, ae = { init: function () { var e = l(); if (this.params.history) { if (!e.history || !e.history.pushState) return this.params.history.enabled = !1, void (this.params.hashNavigation.enabled = !0); var t = this.history; t.initialized = !0, t.paths = ae.getPathValues(this.params.url), (t.paths.key || t.paths.value) && (t.scrollToSlide(0, t.paths.value, this.params.runCallbacksOnInit), this.params.history.replaceState || e.addEventListener("popstate", this.history.setHistoryPopState)) } }, destroy: function () { var e = l(); this.params.history.replaceState || e.removeEventListener("popstate", this.history.setHistoryPopState) }, setHistoryPopState: function () { this.history.paths = ae.getPathValues(this.params.url), this.history.scrollToSlide(this.params.speed, this.history.paths.value, !1) }, getPathValues: function (e) { var t = l(), i = (e ? new URL(e) : t.location).pathname.slice(1).split("/").filter((function (e) { return "" !== e })), s = i.length; return { key: i[s - 2], value: i[s - 1] } }, setHistory: function (e, t) { var i = l(); if (this.history.initialized && this.params.history.enabled) { var s; s = this.params.url ? new URL(this.params.url) : i.location; var a = this.slides.eq(t), r = ae.slugify(a.attr("data-history")); s.pathname.includes(e) || (r = e + "/" + r); var n = i.history.state; n && n.value === r || (this.params.history.replaceState ? i.history.replaceState({ value: r }, null, r) : i.history.pushState({ value: r }, null, r)) } }, slugify: function (e) { return e.toString().replace(/\s+/g, "-").replace(/[^\w-]+/g, "").replace(/--+/g, "-").replace(/^-+/, "").replace(/-+$/, "") }, scrollToSlide: function (e, t, i) { if (t) for (var s = 0, a = this.slides.length; s < a; s += 1) { var r = this.slides.eq(s); if (ae.slugify(r.attr("data-history")) === t && !r.hasClass(this.params.slideDuplicateClass)) { var n = r.index(); this.slideTo(n, e, i) } } else this.slideTo(0, e, i) } }, re = { onHashCange: function () { var e = r(); this.emit("hashChange"); var t = e.location.hash.replace("#", ""); if (t !== this.slides.eq(this.activeIndex).attr("data-hash")) { var i = this.$wrapperEl.children("." + this.params.slideClass + '[data-hash="' + t + '"]').index(); if (void 0 === i) return; this.slideTo(i) } }, setHash: function () { var e = l(), t = r(); if (this.hashNavigation.initialized && this.params.hashNavigation.enabled) if (this.params.hashNavigation.replaceState && e.history && e.history.replaceState) e.history.replaceState(null, null, "#" + this.slides.eq(this.activeIndex).attr("data-hash") || ""), this.emit("hashSet"); else { var i = this.slides.eq(this.activeIndex), s = i.attr("data-hash") || i.attr("data-history"); t.location.hash = s || "", this.emit("hashSet") } }, init: function () { var e = r(), t = l(); if (!(!this.params.hashNavigation.enabled || this.params.history && this.params.history.enabled)) { this.hashNavigation.initialized = !0; var i = e.location.hash.replace("#", ""); if (i) for (var s = 0, a = this.slides.length; s < a; s += 1) { var n = this.slides.eq(s); if ((n.attr("data-hash") || n.attr("data-history")) === i && !n.hasClass(this.params.slideDuplicateClass)) { var o = n.index(); this.slideTo(o, 0, this.params.runCallbacksOnInit, !0) } } this.params.hashNavigation.watchState && m(t).on("hashchange", this.hashNavigation.onHashCange) } }, destroy: function () { var e = l(); this.params.hashNavigation.watchState && m(e).off("hashchange", this.hashNavigation.onHashCange) } }, ne = { run: function () { var e = this, t = e.slides.eq(e.activeIndex), i = e.params.autoplay.delay; t.attr("data-swiper-autoplay") && (i = t.attr("data-swiper-autoplay") || e.params.autoplay.delay), clearTimeout(e.autoplay.timeout), e.autoplay.timeout = E((function () { e.params.autoplay.reverseDirection ? e.params.loop ? (e.loopFix(), e.slidePrev(e.params.speed, !0, !0), e.emit("autoplay")) : e.isBeginning ? e.params.autoplay.stopOnLastSlide ? e.autoplay.stop() : (e.slideTo(e.slides.length - 1, e.params.speed, !0, !0), e.emit("autoplay")) : (e.slidePrev(e.params.speed, !0, !0), e.emit("autoplay")) : e.params.loop ? (e.loopFix(), e.slideNext(e.params.speed, !0, !0), e.emit("autoplay")) : e.isEnd ? e.params.autoplay.stopOnLastSlide ? e.autoplay.stop() : (e.slideTo(0, e.params.speed, !0, !0), e.emit("autoplay")) : (e.slideNext(e.params.speed, !0, !0), e.emit("autoplay")), e.params.cssMode && e.autoplay.running && e.autoplay.run() }), i) }, start: function () { return void 0 === this.autoplay.timeout && (!this.autoplay.running && (this.autoplay.running = !0, this.emit("autoplayStart"), this.autoplay.run(), !0)) }, stop: function () { return !!this.autoplay.running && (void 0 !== this.autoplay.timeout && (this.autoplay.timeout && (clearTimeout(this.autoplay.timeout), this.autoplay.timeout = void 0), this.autoplay.running = !1, this.emit("autoplayStop"), !0)) }, pause: function (e) { this.autoplay.running && (this.autoplay.paused || (this.autoplay.timeout && clearTimeout(this.autoplay.timeout), this.autoplay.paused = !0, 0 !== e && this.params.autoplay.waitForTransition ? (this.$wrapperEl[0].addEventListener("transitionend", this.autoplay.onTransitionEnd), this.$wrapperEl[0].addEventListener("webkitTransitionEnd", this.autoplay.onTransitionEnd)) : (this.autoplay.paused = !1, this.autoplay.run()))) }, onVisibilityChange: function () { var e = r(); "hidden" === e.visibilityState && this.autoplay.running && this.autoplay.pause(), "visible" === e.visibilityState && this.autoplay.paused && (this.autoplay.run(), this.autoplay.paused = !1) }, onTransitionEnd: function (e) { this && !this.destroyed && this.$wrapperEl && e.target === this.$wrapperEl[0] && (this.$wrapperEl[0].removeEventListener("transitionend", this.autoplay.onTransitionEnd), this.$wrapperEl[0].removeEventListener("webkitTransitionEnd", this.autoplay.onTransitionEnd), this.autoplay.paused = !1, this.autoplay.running ? this.autoplay.run() : this.autoplay.stop()) } }, le = { setTranslate: function () { for (var e = this.slides, t = 0; t < e.length; t += 1) { var i = this.slides.eq(t), s = -i[0].swiperSlideOffset; this.params.virtualTranslate || (s -= this.translate); var a = 0; this.isHorizontal() || (a = s, s = 0); var r = this.params.fadeEffect.crossFade ? Math.max(1 - Math.abs(i[0].progress), 0) : 1 + Math.min(Math.max(i[0].progress, -1), 0); i.css({ opacity: r }).transform("translate3d(" + s + "px, " + a + "px, 0px)") } }, setTransition: function (e) { var t = this, i = t.slides, s = t.$wrapperEl; if (i.transition(e), t.params.virtualTranslate && 0 !== e) { var a = !1; i.transitionEnd((function () { if (!a && t && !t.destroyed) { a = !0, t.animating = !1; for (var e = ["webkitTransitionEnd", "transitionend"], i = 0; i < e.length; i += 1)s.trigger(e[i]) } })) } } }, oe = { setTranslate: function () { var e, t = this.$el, i = this.$wrapperEl, s = this.slides, a = this.width, r = this.height, n = this.rtlTranslate, l = this.size, o = this.browser, d = this.params.cubeEffect, h = this.isHorizontal(), p = this.virtual && this.params.virtual.enabled, u = 0; d.shadow && (h ? (0 === (e = i.find(".swiper-cube-shadow")).length && (e = m('<div class="swiper-cube-shadow"></div>'), i.append(e)), e.css({ height: a + "px" })) : 0 === (e = t.find(".swiper-cube-shadow")).length && (e = m('<div class="swiper-cube-shadow"></div>'), t.append(e))); for (var c = 0; c < s.length; c += 1) { var v = s.eq(c), f = c; p && (f = parseInt(v.attr("data-swiper-slide-index"), 10)); var g = 90 * f, w = Math.floor(g / 360); n && (g = -g, w = Math.floor(-g / 360)); var b = Math.max(Math.min(v[0].progress, 1), -1), y = 0, E = 0, x = 0; f % 4 == 0 ? (y = 4 * -w * l, x = 0) : (f - 1) % 4 == 0 ? (y = 0, x = 4 * -w * l) : (f - 2) % 4 == 0 ? (y = l + 4 * w * l, x = l) : (f - 3) % 4 == 0 && (y = -l, x = 3 * l + 4 * l * w), n && (y = -y), h || (E = y, y = 0); var T = "rotateX(" + (h ? 0 : -g) + "deg) rotateY(" + (h ? g : 0) + "deg) translate3d(" + y + "px, " + E + "px, " + x + "px)"; if (b <= 1 && b > -1 && (u = 90 * f + 90 * b, n && (u = 90 * -f - 90 * b)), v.transform(T), d.slideShadows) { var C = h ? v.find(".swiper-slide-shadow-left") : v.find(".swiper-slide-shadow-top"), S = h ? v.find(".swiper-slide-shadow-right") : v.find(".swiper-slide-shadow-bottom"); 0 === C.length && (C = m('<div class="swiper-slide-shadow-' + (h ? "left" : "top") + '"></div>'), v.append(C)), 0 === S.length && (S = m('<div class="swiper-slide-shadow-' + (h ? "right" : "bottom") + '"></div>'), v.append(S)), C.length && (C[0].style.opacity = Math.max(-b, 0)), S.length && (S[0].style.opacity = Math.max(b, 0)) } } if (i.css({ "-webkit-transform-origin": "50% 50% -" + l / 2 + "px", "-moz-transform-origin": "50% 50% -" + l / 2 + "px", "-ms-transform-origin": "50% 50% -" + l / 2 + "px", "transform-origin": "50% 50% -" + l / 2 + "px" }), d.shadow) if (h) e.transform("translate3d(0px, " + (a / 2 + d.shadowOffset) + "px, " + -a / 2 + "px) rotateX(90deg) rotateZ(0deg) scale(" + d.shadowScale + ")"); else { var M = Math.abs(u) - 90 * Math.floor(Math.abs(u) / 90), z = 1.5 - (Math.sin(2 * M * Math.PI / 360) / 2 + Math.cos(2 * M * Math.PI / 360) / 2), P = d.shadowScale, k = d.shadowScale / z, $ = d.shadowOffset; e.transform("scale3d(" + P + ", 1, " + k + ") translate3d(0px, " + (r / 2 + $) + "px, " + -r / 2 / k + "px) rotateX(-90deg)") } var L = o.isSafari || o.isWebView ? -l / 2 : 0; i.transform("translate3d(0px,0," + L + "px) rotateX(" + (this.isHorizontal() ? 0 : u) + "deg) rotateY(" + (this.isHorizontal() ? -u : 0) + "deg)") }, setTransition: function (e) { var t = this.$el; this.slides.transition(e).find(".swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left").transition(e), this.params.cubeEffect.shadow && !this.isHorizontal() && t.find(".swiper-cube-shadow").transition(e) } }, de = { setTranslate: function () { for (var e = this.slides, t = this.rtlTranslate, i = 0; i < e.length; i += 1) { var s = e.eq(i), a = s[0].progress; this.params.flipEffect.limitRotation && (a = Math.max(Math.min(s[0].progress, 1), -1)); var r = -180 * a, n = 0, l = -s[0].swiperSlideOffset, o = 0; if (this.isHorizontal() ? t && (r = -r) : (o = l, l = 0, n = -r, r = 0), s[0].style.zIndex = -Math.abs(Math.round(a)) + e.length, this.params.flipEffect.slideShadows) { var d = this.isHorizontal() ? s.find(".swiper-slide-shadow-left") : s.find(".swiper-slide-shadow-top"), h = this.isHorizontal() ? s.find(".swiper-slide-shadow-right") : s.find(".swiper-slide-shadow-bottom"); 0 === d.length && (d = m('<div class="swiper-slide-shadow-' + (this.isHorizontal() ? "left" : "top") + '"></div>'), s.append(d)), 0 === h.length && (h = m('<div class="swiper-slide-shadow-' + (this.isHorizontal() ? "right" : "bottom") + '"></div>'), s.append(h)), d.length && (d[0].style.opacity = Math.max(-a, 0)), h.length && (h[0].style.opacity = Math.max(a, 0)) } s.transform("translate3d(" + l + "px, " + o + "px, 0px) rotateX(" + n + "deg) rotateY(" + r + "deg)") } }, setTransition: function (e) { var t = this, i = t.slides, s = t.activeIndex, a = t.$wrapperEl; if (i.transition(e).find(".swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left").transition(e), t.params.virtualTranslate && 0 !== e) { var r = !1; i.eq(s).transitionEnd((function () { if (!r && t && !t.destroyed) { r = !0, t.animating = !1; for (var e = ["webkitTransitionEnd", "transitionend"], i = 0; i < e.length; i += 1)a.trigger(e[i]) } })) } } }, he = { setTranslate: function () { for (var e = this.width, t = this.height, i = this.slides, s = this.slidesSizesGrid, a = this.params.coverflowEffect, r = this.isHorizontal(), n = this.translate, l = r ? e / 2 - n : t / 2 - n, o = r ? a.rotate : -a.rotate, d = a.depth, h = 0, p = i.length; h < p; h += 1) { var u = i.eq(h), c = s[h], v = (l - u[0].swiperSlideOffset - c / 2) / c * a.modifier, f = r ? o * v : 0, g = r ? 0 : o * v, w = -d * Math.abs(v), b = a.stretch; "string" == typeof b && -1 !== b.indexOf("%") && (b = parseFloat(a.stretch) / 100 * c); var y = r ? 0 : b * v, E = r ? b * v : 0, x = 1 - (1 - a.scale) * Math.abs(v); Math.abs(E) < .001 && (E = 0), Math.abs(y) < .001 && (y = 0), Math.abs(w) < .001 && (w = 0), Math.abs(f) < .001 && (f = 0), Math.abs(g) < .001 && (g = 0), Math.abs(x) < .001 && (x = 0); var T = "translate3d(" + E + "px," + y + "px," + w + "px)  rotateX(" + g + "deg) rotateY(" + f + "deg) scale(" + x + ")"; if (u.transform(T), u[0].style.zIndex = 1 - Math.abs(Math.round(v)), a.slideShadows) { var C = r ? u.find(".swiper-slide-shadow-left") : u.find(".swiper-slide-shadow-top"), S = r ? u.find(".swiper-slide-shadow-right") : u.find(".swiper-slide-shadow-bottom"); 0 === C.length && (C = m('<div class="swiper-slide-shadow-' + (r ? "left" : "top") + '"></div>'), u.append(C)), 0 === S.length && (S = m('<div class="swiper-slide-shadow-' + (r ? "right" : "bottom") + '"></div>'), u.append(S)), C.length && (C[0].style.opacity = v > 0 ? v : 0), S.length && (S[0].style.opacity = -v > 0 ? -v : 0) } } }, setTransition: function (e) { this.slides.transition(e).find(".swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left").transition(e) } }, pe = { init: function () { var e = this.params.thumbs; if (this.thumbs.initialized) return !1; this.thumbs.initialized = !0; var t = this.constructor; return e.swiper instanceof t ? (this.thumbs.swiper = e.swiper, S(this.thumbs.swiper.originalParams, { watchSlidesProgress: !0, slideToClickedSlide: !1 }), S(this.thumbs.swiper.params, { watchSlidesProgress: !0, slideToClickedSlide: !1 })) : C(e.swiper) && (this.thumbs.swiper = new t(S({}, e.swiper, { watchSlidesVisibility: !0, watchSlidesProgress: !0, slideToClickedSlide: !1 })), this.thumbs.swiperCreated = !0), this.thumbs.swiper.$el.addClass(this.params.thumbs.thumbsContainerClass), this.thumbs.swiper.on("tap", this.thumbs.onThumbClick), !0 }, onThumbClick: function () { var e = this.thumbs.swiper; if (e) { var t = e.clickedIndex, i = e.clickedSlide; if (!(i && m(i).hasClass(this.params.thumbs.slideThumbActiveClass) || null == t)) { var s; if (s = e.params.loop ? parseInt(m(e.clickedSlide).attr("data-swiper-slide-index"), 10) : t, this.params.loop) { var a = this.activeIndex; this.slides.eq(a).hasClass(this.params.slideDuplicateClass) && (this.loopFix(), this._clientLeft = this.$wrapperEl[0].clientLeft, a = this.activeIndex); var r = this.slides.eq(a).prevAll('[data-swiper-slide-index="' + s + '"]').eq(0).index(), n = this.slides.eq(a).nextAll('[data-swiper-slide-index="' + s + '"]').eq(0).index(); s = void 0 === r ? n : void 0 === n ? r : n - a < a - r ? n : r } this.slideTo(s) } } }, update: function (e) { var t = this.thumbs.swiper; if (t) { var i = "auto" === t.params.slidesPerView ? t.slidesPerViewDynamic() : t.params.slidesPerView, s = this.params.thumbs.autoScrollOffset, a = s && !t.params.loop; if (this.realIndex !== t.realIndex || a) { var r, n, l = t.activeIndex; if (t.params.loop) { t.slides.eq(l).hasClass(t.params.slideDuplicateClass) && (t.loopFix(), t._clientLeft = t.$wrapperEl[0].clientLeft, l = t.activeIndex); var o = t.slides.eq(l).prevAll('[data-swiper-slide-index="' + this.realIndex + '"]').eq(0).index(), d = t.slides.eq(l).nextAll('[data-swiper-slide-index="' + this.realIndex + '"]').eq(0).index(); r = void 0 === o ? d : void 0 === d ? o : d - l == l - o ? l : d - l < l - o ? d : o, n = this.activeIndex > this.previousIndex ? "next" : "prev" } else n = (r = this.realIndex) > this.previousIndex ? "next" : "prev"; a && (r += "next" === n ? s : -1 * s), t.visibleSlidesIndexes && t.visibleSlidesIndexes.indexOf(r) < 0 && (t.params.centeredSlides ? r = r > l ? r - Math.floor(i / 2) + 1 : r + Math.floor(i / 2) - 1 : r > l && (r = r - i + 1), t.slideTo(r, e ? 0 : void 0)) } var h = 1, p = this.params.thumbs.slideThumbActiveClass; if (this.params.slidesPerView > 1 && !this.params.centeredSlides && (h = this.params.slidesPerView), this.params.thumbs.multipleActiveThumbs || (h = 1), h = Math.floor(h), t.slides.removeClass(p), t.params.loop || t.params.virtual && t.params.virtual.enabled) for (var u = 0; u < h; u += 1)t.$wrapperEl.children('[data-swiper-slide-index="' + (this.realIndex + u) + '"]').addClass(p); else for (var c = 0; c < h; c += 1)t.slides.eq(this.realIndex + c).addClass(p) } } }, ue = [q, _, { name: "mousewheel", params: { mousewheel: { enabled: !1, releaseOnEdges: !1, invert: !1, forceToAxis: !1, sensitivity: 1, eventsTarget: "container", thresholdDelta: null, thresholdTime: null } }, create: function () { M(this, { mousewheel: { enabled: !1, lastScrollTime: x(), lastEventBeforeSnap: void 0, recentWheelEvents: [], enable: U.enable, disable: U.disable, handle: U.handle, handleMouseEnter: U.handleMouseEnter, handleMouseLeave: U.handleMouseLeave, animateSlider: U.animateSlider, releaseScroll: U.releaseScroll } }) }, on: { init: function (e) { !e.params.mousewheel.enabled && e.params.cssMode && e.mousewheel.disable(), e.params.mousewheel.enabled && e.mousewheel.enable() }, destroy: function (e) { e.params.cssMode && e.mousewheel.enable(), e.mousewheel.enabled && e.mousewheel.disable() } } }, { name: "navigation", params: { navigation: { nextEl: null, prevEl: null, hideOnClick: !1, disabledClass: "swiper-button-disabled", hiddenClass: "swiper-button-hidden", lockClass: "swiper-button-lock" } }, create: function () { M(this, { navigation: t({}, K) }) }, on: { init: function (e) { e.navigation.init(), e.navigation.update() }, toEdge: function (e) { e.navigation.update() }, fromEdge: function (e) { e.navigation.update() }, destroy: function (e) { e.navigation.destroy() }, click: function (e, t) { var i, s = e.navigation, a = s.$nextEl, r = s.$prevEl; !e.params.navigation.hideOnClick || m(t.target).is(r) || m(t.target).is(a) || (a ? i = a.hasClass(e.params.navigation.hiddenClass) : r && (i = r.hasClass(e.params.navigation.hiddenClass)), !0 === i ? e.emit("navigationShow") : e.emit("navigationHide"), a && a.toggleClass(e.params.navigation.hiddenClass), r && r.toggleClass(e.params.navigation.hiddenClass)) } } }, { name: "pagination", params: { pagination: { el: null, bulletElement: "span", clickable: !1, hideOnClick: !1, renderBullet: null, renderProgressbar: null, renderFraction: null, renderCustom: null, progressbarOpposite: !1, type: "bullets", dynamicBullets: !1, dynamicMainBullets: 1, formatFractionCurrent: function (e) { return e }, formatFractionTotal: function (e) { return e }, bulletClass: "swiper-pagination-bullet", bulletActiveClass: "swiper-pagination-bullet-active", modifierClass: "swiper-pagination-", currentClass: "swiper-pagination-current", totalClass: "swiper-pagination-total", hiddenClass: "swiper-pagination-hidden", progressbarFillClass: "swiper-pagination-progressbar-fill", progressbarOppositeClass: "swiper-pagination-progressbar-opposite", clickableClass: "swiper-pagination-clickable", lockClass: "swiper-pagination-lock" } }, create: function () { M(this, { pagination: t({ dynamicBulletIndex: 0 }, Z) }) }, on: { init: function (e) { e.pagination.init(), e.pagination.render(), e.pagination.update() }, activeIndexChange: function (e) { (e.params.loop || void 0 === e.snapIndex) && e.pagination.update() }, snapIndexChange: function (e) { e.params.loop || e.pagination.update() }, slidesLengthChange: function (e) { e.params.loop && (e.pagination.render(), e.pagination.update()) }, snapGridLengthChange: function (e) { e.params.loop || (e.pagination.render(), e.pagination.update()) }, destroy: function (e) { e.pagination.destroy() }, click: function (e, t) { e.params.pagination.el && e.params.pagination.hideOnClick && e.pagination.$el.length > 0 && !m(t.target).hasClass(e.params.pagination.bulletClass) && (!0 === e.pagination.$el.hasClass(e.params.pagination.hiddenClass) ? e.emit("paginationShow") : e.emit("paginationHide"), e.pagination.$el.toggleClass(e.params.pagination.hiddenClass)) } } }, { name: "scrollbar", params: { scrollbar: { el: null, dragSize: "auto", hide: !1, draggable: !1, snapOnRelease: !0, lockClass: "swiper-scrollbar-lock", dragClass: "swiper-scrollbar-drag" } }, create: function () { M(this, { scrollbar: t({ isTouched: !1, timeout: null, dragTimeout: null }, J) }) }, on: { init: function (e) { e.scrollbar.init(), e.scrollbar.updateSize(), e.scrollbar.setTranslate() }, update: function (e) { e.scrollbar.updateSize() }, resize: function (e) { e.scrollbar.updateSize() }, observerUpdate: function (e) { e.scrollbar.updateSize() }, setTranslate: function (e) { e.scrollbar.setTranslate() }, setTransition: function (e, t) { e.scrollbar.setTransition(t) }, destroy: function (e) { e.scrollbar.destroy() } } }, { name: "parallax", params: { parallax: { enabled: !1 } }, create: function () { M(this, { parallax: t({}, Q) }) }, on: { beforeInit: function (e) { e.params.parallax.enabled && (e.params.watchSlidesProgress = !0, e.originalParams.watchSlidesProgress = !0) }, init: function (e) { e.params.parallax.enabled && e.parallax.setTranslate() }, setTranslate: function (e) { e.params.parallax.enabled && e.parallax.setTranslate() }, setTransition: function (e, t) { e.params.parallax.enabled && e.parallax.setTransition(t) } } }, { name: "zoom", params: { zoom: { enabled: !1, maxRatio: 3, minRatio: 1, toggle: !0, containerClass: "swiper-zoom-container", zoomedSlideClass: "swiper-slide-zoomed" } }, create: function () { var e = this; M(e, { zoom: t({ enabled: !1, scale: 1, currentScale: 1, isScaling: !1, gesture: { $slideEl: void 0, slideWidth: void 0, slideHeight: void 0, $imageEl: void 0, $imageWrapEl: void 0, maxRatio: 3 }, image: { isTouched: void 0, isMoved: void 0, currentX: void 0, currentY: void 0, minX: void 0, minY: void 0, maxX: void 0, maxY: void 0, width: void 0, height: void 0, startX: void 0, startY: void 0, touchesStart: {}, touchesCurrent: {} }, velocity: { x: void 0, y: void 0, prevPositionX: void 0, prevPositionY: void 0, prevTime: void 0 } }, ee) }); var i = 1; Object.defineProperty(e.zoom, "scale", { get: function () { return i }, set: function (t) { if (i !== t) { var s = e.zoom.gesture.$imageEl ? e.zoom.gesture.$imageEl[0] : void 0, a = e.zoom.gesture.$slideEl ? e.zoom.gesture.$slideEl[0] : void 0; e.emit("zoomChange", t, s, a) } i = t } }) }, on: { init: function (e) { e.params.zoom.enabled && e.zoom.enable() }, destroy: function (e) { e.zoom.disable() }, touchStart: function (e, t) { e.zoom.enabled && e.zoom.onTouchStart(t) }, touchEnd: function (e, t) { e.zoom.enabled && e.zoom.onTouchEnd(t) }, doubleTap: function (e, t) { e.params.zoom.enabled && e.zoom.enabled && e.params.zoom.toggle && e.zoom.toggle(t) }, transitionEnd: function (e) { e.zoom.enabled && e.params.zoom.enabled && e.zoom.onTransitionEnd() }, slideChange: function (e) { e.zoom.enabled && e.params.zoom.enabled && e.params.cssMode && e.zoom.onTransitionEnd() } } }, { name: "lazy", params: { lazy: { enabled: !1, loadPrevNext: !1, loadPrevNextAmount: 1, loadOnTransitionStart: !1, elementClass: "swiper-lazy", loadingClass: "swiper-lazy-loading", loadedClass: "swiper-lazy-loaded", preloaderClass: "swiper-lazy-preloader" } }, create: function () { M(this, { lazy: t({ initialImageLoaded: !1 }, te) }) }, on: { beforeInit: function (e) { e.params.lazy.enabled && e.params.preloadImages && (e.params.preloadImages = !1) }, init: function (e) { e.params.lazy.enabled && !e.params.loop && 0 === e.params.initialSlide && e.lazy.load() }, scroll: function (e) { e.params.freeMode && !e.params.freeModeSticky && e.lazy.load() }, resize: function (e) { e.params.lazy.enabled && e.lazy.load() }, scrollbarDragMove: function (e) { e.params.lazy.enabled && e.lazy.load() }, transitionStart: function (e) { e.params.lazy.enabled && (e.params.lazy.loadOnTransitionStart || !e.params.lazy.loadOnTransitionStart && !e.lazy.initialImageLoaded) && e.lazy.load() }, transitionEnd: function (e) { e.params.lazy.enabled && !e.params.lazy.loadOnTransitionStart && e.lazy.load() }, slideChange: function (e) { e.params.lazy.enabled && e.params.cssMode && e.lazy.load() } } }, { name: "controller", params: { controller: { control: void 0, inverse: !1, by: "slide" } }, create: function () { M(this, { controller: t({ control: this.params.controller.control }, ie) }) }, on: { update: function (e) { e.controller.control && e.controller.spline && (e.controller.spline = void 0, delete e.controller.spline) }, resize: function (e) { e.controller.control && e.controller.spline && (e.controller.spline = void 0, delete e.controller.spline) }, observerUpdate: function (e) { e.controller.control && e.controller.spline && (e.controller.spline = void 0, delete e.controller.spline) }, setTranslate: function (e, t, i) { e.controller.control && e.controller.setTranslate(t, i) }, setTransition: function (e, t, i) { e.controller.control && e.controller.setTransition(t, i) } } }, { name: "a11y", params: { a11y: { enabled: !0, notificationClass: "swiper-notification", prevSlideMessage: "Previous slide", nextSlideMessage: "Next slide", firstSlideMessage: "This is the first slide", lastSlideMessage: "This is the last slide", paginationBulletMessage: "Go to slide {{index}}" } }, create: function () { M(this, { a11y: t(t({}, se), {}, { liveRegion: m('<span class="' + this.params.a11y.notificationClass + '" aria-live="assertive" aria-atomic="true"></span>') }) }) }, on: { init: function (e) { e.params.a11y.enabled && (e.a11y.init(), e.a11y.updateNavigation()) }, toEdge: function (e) { e.params.a11y.enabled && e.a11y.updateNavigation() }, fromEdge: function (e) { e.params.a11y.enabled && e.a11y.updateNavigation() }, paginationUpdate: function (e) { e.params.a11y.enabled && e.a11y.updatePagination() }, destroy: function (e) { e.params.a11y.enabled && e.a11y.destroy() } } }, { name: "history", params: { history: { enabled: !1, replaceState: !1, key: "slides" } }, create: function () { M(this, { history: t({}, ae) }) }, on: { init: function (e) { e.params.history.enabled && e.history.init() }, destroy: function (e) { e.params.history.enabled && e.history.destroy() }, transitionEnd: function (e) { e.history.initialized && e.history.setHistory(e.params.history.key, e.activeIndex) }, slideChange: function (e) { e.history.initialized && e.params.cssMode && e.history.setHistory(e.params.history.key, e.activeIndex) } } }, { name: "hash-navigation", params: { hashNavigation: { enabled: !1, replaceState: !1, watchState: !1 } }, create: function () { M(this, { hashNavigation: t({ initialized: !1 }, re) }) }, on: { init: function (e) { e.params.hashNavigation.enabled && e.hashNavigation.init() }, destroy: function (e) { e.params.hashNavigation.enabled && e.hashNavigation.destroy() }, transitionEnd: function (e) { e.hashNavigation.initialized && e.hashNavigation.setHash() }, slideChange: function (e) { e.hashNavigation.initialized && e.params.cssMode && e.hashNavigation.setHash() } } }, { name: "autoplay", params: { autoplay: { enabled: !1, delay: 3e3, waitForTransition: !0, disableOnInteraction: !0, stopOnLastSlide: !1, reverseDirection: !1 } }, create: function () { M(this, { autoplay: t(t({}, ne), {}, { running: !1, paused: !1 }) }) }, on: { init: function (e) { e.params.autoplay.enabled && (e.autoplay.start(), r().addEventListener("visibilitychange", e.autoplay.onVisibilityChange)) }, beforeTransitionStart: function (e, t, i) { e.autoplay.running && (i || !e.params.autoplay.disableOnInteraction ? e.autoplay.pause(t) : e.autoplay.stop()) }, sliderFirstMove: function (e) { e.autoplay.running && (e.params.autoplay.disableOnInteraction ? e.autoplay.stop() : e.autoplay.pause()) }, touchEnd: function (e) { e.params.cssMode && e.autoplay.paused && !e.params.autoplay.disableOnInteraction && e.autoplay.run() }, destroy: function (e) { e.autoplay.running && e.autoplay.stop(), r().removeEventListener("visibilitychange", e.autoplay.onVisibilityChange) } } }, { name: "effect-fade", params: { fadeEffect: { crossFade: !1 } }, create: function () { M(this, { fadeEffect: t({}, le) }) }, on: { beforeInit: function (e) { if ("fade" === e.params.effect) { e.classNames.push(e.params.containerModifierClass + "fade"); var t = { slidesPerView: 1, slidesPerColumn: 1, slidesPerGroup: 1, watchSlidesProgress: !0, spaceBetween: 0, virtualTranslate: !0 }; S(e.params, t), S(e.originalParams, t) } }, setTranslate: function (e) { "fade" === e.params.effect && e.fadeEffect.setTranslate() }, setTransition: function (e, t) { "fade" === e.params.effect && e.fadeEffect.setTransition(t) } } }, { name: "effect-cube", params: { cubeEffect: { slideShadows: !0, shadow: !0, shadowOffset: 20, shadowScale: .94 } }, create: function () { M(this, { cubeEffect: t({}, oe) }) }, on: { beforeInit: function (e) { if ("cube" === e.params.effect) { e.classNames.push(e.params.containerModifierClass + "cube"), e.classNames.push(e.params.containerModifierClass + "3d"); var t = { slidesPerView: 1, slidesPerColumn: 1, slidesPerGroup: 1, watchSlidesProgress: !0, resistanceRatio: 0, spaceBetween: 0, centeredSlides: !1, virtualTranslate: !0 }; S(e.params, t), S(e.originalParams, t) } }, setTranslate: function (e) { "cube" === e.params.effect && e.cubeEffect.setTranslate() }, setTransition: function (e, t) { "cube" === e.params.effect && e.cubeEffect.setTransition(t) } } }, { name: "effect-flip", params: { flipEffect: { slideShadows: !0, limitRotation: !0 } }, create: function () { M(this, { flipEffect: t({}, de) }) }, on: { beforeInit: function (e) { if ("flip" === e.params.effect) { e.classNames.push(e.params.containerModifierClass + "flip"), e.classNames.push(e.params.containerModifierClass + "3d"); var t = { slidesPerView: 1, slidesPerColumn: 1, slidesPerGroup: 1, watchSlidesProgress: !0, spaceBetween: 0, virtualTranslate: !0 }; S(e.params, t), S(e.originalParams, t) } }, setTranslate: function (e) { "flip" === e.params.effect && e.flipEffect.setTranslate() }, setTransition: function (e, t) { "flip" === e.params.effect && e.flipEffect.setTransition(t) } } }, { name: "effect-coverflow", params: { coverflowEffect: { rotate: 50, stretch: 0, depth: 100, scale: 1, modifier: 1, slideShadows: !0 } }, create: function () { M(this, { coverflowEffect: t({}, he) }) }, on: { beforeInit: function (e) { "coverflow" === e.params.effect && (e.classNames.push(e.params.containerModifierClass + "coverflow"), e.classNames.push(e.params.containerModifierClass + "3d"), e.params.watchSlidesProgress = !0, e.originalParams.watchSlidesProgress = !0) }, setTranslate: function (e) { "coverflow" === e.params.effect && e.coverflowEffect.setTranslate() }, setTransition: function (e, t) { "coverflow" === e.params.effect && e.coverflowEffect.setTransition(t) } } }, { name: "thumbs", params: { thumbs: { swiper: null, multipleActiveThumbs: !0, autoScrollOffset: 0, slideThumbActiveClass: "swiper-slide-thumb-active", thumbsContainerClass: "swiper-container-thumbs" } }, create: function () { M(this, { thumbs: t({ swiper: null, initialized: !1 }, pe) }) }, on: { beforeInit: function (e) { var t = e.params.thumbs; t && t.swiper && (e.thumbs.init(), e.thumbs.update(!0)) }, slideChange: function (e) { e.thumbs.swiper && e.thumbs.update() }, update: function (e) { e.thumbs.swiper && e.thumbs.update() }, resize: function (e) { e.thumbs.swiper && e.thumbs.update() }, observerUpdate: function (e) { e.thumbs.swiper && e.thumbs.update() }, setTransition: function (e, t) { var i = e.thumbs.swiper; i && i.setTransition(t) }, beforeDestroy: function (e) { var t = e.thumbs.swiper; t && e.thumbs.swiperCreated && t && t.destroy() } } }]; return W.use(ue), W }));
//# sourceMappingURL=swiper-bundle.min.js.map;
(function () {
    'use strict';
    // Added constant for Bulk Order Messages
    window.app.constant('BULKORDER_CONSTANTS', {
        'STOCK_UNAVAILABLE': 'QP01',
        'STOCK_AVAILABLE': 'QP02',
        'SUCCESS': 'C001',
        'POSTCODE': 'POSTCODE',
        'ITEM_STOCK_UNAVAILABLE': 'C002',
        'PREORDER_ITEM_STOCK_AVAILABLE': 'C003'
    });
    ;
    window.app.constant("PERSONALISATION", {
        'ENABLED': "PersonalisationEnabled",
        'MANDATORY': 'PersonalisationMandatory'
    });
    window.app.constant("CURRENCYCOOKIE", {
        'CurrencyCode': "_ctcc"
    });
    window.app.constant("VOUCHERSTATUS", {
        'CLAIMED': "Claimed",
        'UNCLAIMED': 'Unclaimed',
        'IN_TRANSITION': 'InTransition',
    });
    window.app.constant("MULTIFILFILLMENT", {
        'URL_POPULATE_DELIVERY_PLANS': "/basket/populate-delivery-plans",
        'URL_FIX_DELIVERY_PLANS': "/basket/fix-delivery-plans",
    });
    window.app.constant("MEMBERSHIP", {
        'URL_UPGRADE_OPTIONS': "/my-tfs-membership/upgrade-options",
        'URL_SIGNUP_OPTIONS': "/my-tfs-membership/signup-options",
        'URL_SIGNUP_ADD': "/Basket/AddMembership",
    });
    // ADD CONSTANT FOR THEME DEFAULT IMAGE
    window.DEFAULT_IMAGE_URL = '/assets/theme/tfs/images/noimagefound.jpg';
    window.app.controller('globalCtrl', globalCtrl);
    globalCtrl.$inject = [
        '$scope',
        '$timeout',
        'globalConfig',
        'loader',
        '$http',
        'CapturePlus',
        'scriptLoader',
        'BULKORDER_CONSTANTS',
        'Recommendation',
        'PERSONALISATION',
        'REGEX_CONSTANTS',
        'alerts',
        'CURRENCYCOOKIE',
        'VOUCHERSTATUS',
        'vcRecaptchaService',
        'MULTIFILFILLMENT',
        'MEMBERSHIP'
    ];

    function globalCtrl(
        $scope,
        $timeout,
        globalConfig,
        $http,
        loader,
        CapturePlus,
        scriptLoader,
        BULKORDER_CONSTANTS,
        Recommendation,
        PERSONALISATION,
        REGEX_CONSTANTS,
        alerts,
        CURRENCYCOOKIE,
        VOUCHERSTATUS,
        vcRecaptchaService,
        MULTIFILFILLMENT,
        MEMBERSHIP
    ) {
        var gm = this;
        gm.model = {};
        $scope.personalisation = /^[a-zA-Z0-9 \n!"£$%^&*(){};:@'#~?/.>,<|_+=`\-\\\[\]]+$/;
        $scope.ribbonPersonalisation = /^[a-zA-Z0-9 ]+$/;

        gm.defaultCurrency = "£";

        gm.errorMessage == null;
        gm.stockErrorMessage == null;
        gm.saving = false;
        gm.success = false;
        gm.basketResponse = null;
        gm.updateQtyAndAdd = updateQtyAndAdd;
        gm.basketExtraInfo = [];
        gm.miniBasketSize = 3;
        gm.lineItemTotal = 0;
        gm.shippingMethods = [];
        gm.maximumBasketItemError = false;
        gm.invalidpromo = false;
        gm.blogReponse = [];
        gm.emailinvalid = false;
        gm.subssuccess = false;
        gm.customerEmail = '';
        gm.alreadySubscribed = false;
        gm.emptyGuid = '00000000-0000-0000-0000-000000000000';
        gm.activeMemebershipPlanId = '00000000-0000-0000-0000-000000000000';
        gm.openQuickBasketModal = openQuickBasketModal;
        gm.nRows = nRows;
        gm.userName = '';
        gm.incVat = ($.cookie('incVat') === undefined) ? false : ($.cookie('incVat') == 'true');
        gm.isChecked = !gm.incVat;
        $scope.signin = false;
        $scope.register = false;
        $scope.global_login = false;
        gm.basketData = null;
        gm.isPasswordPolicyMeet = isPasswordPolicyMeet;
        gm.customError = customError;
        gm.basketContainsMembership = false;
        gm.basketContainsSubscription = false;
        gm.basketContainsVirtual = false;
        gm.checkBasketContainsMembership = checkBasketContainsMembership;
        gm.hasOnlyMembershipProducts = hasOnlyMembershipProducts;
        gm.potentialSavings = 0;
        gm.isShipFromStoreProduct = false;

        //methods
        gm.userLogin = userLogin;
        gm.registration = registration;
        gm.contactForm = contactForm;
        gm.currencySettings = currencySettings;
        gm.initBasket = initBasket;
        gm.showShippingGrid = showShippingGrid;
        gm.addToBasket = addToBasket;
        gm.getPaymentMethods = getPaymentMethods;
        gm.getShippingMethods = getShippingMethods;
        gm.updateShipping = updateShipping;
        gm.applyPromoCode = applyPromoCode;
        gm.getallblogs = getallblogs;
        gm.getallblogsbycategory = getallblogsbycategory;
        gm.getBlogByCategory = getBlogByCategory;
        gm.initblogs = initblogs;
        gm.login = login;
        gm.passwordCheckTimeout1 = null;
        gm.passwordCheckTimeout2 = null;
        gm.globalLogin = globalLogin;
        gm.newsLetterSubscription = newsLetterSubscription;
        gm.showBasket = showBasket;
        gm.removePromoCode = removePromoCode;
        gm.forgotPassword = forgotPassword;
        gm.addProductsExcel = addProductsExcel;
        gm.registerCompanyRequest = registerCompanyRequest;
        gm.productPrice = productPrice;
        gm.socialSignIn = socialSignIn;
        gm.getSocialSettings = getSocialSettings;
        gm.getBillingCountries = getBillingCountries;
        gm.basketDetails = basketDetails;
        gm.hideBasketDetail = hideBasketDetail;
        gm.checkForSpecificAttribute = checkForSpecificAttribute;
        gm.onTextFocus = onTextFocus;
        gm.checkPassword = checkPassword;
        gm.isPasswordValid = false;
        gm.returnUrl = '';
        var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
        var eventer = window[eventMethod];
        var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
        gm.addQuoteToBasket = addQuoteToBasket;
        gm.removeQuoteBasket = removeQuoteBasket;
        gm.basketAction = basketAction;
        gm.cancelChangePostCode = cancelChangePostCode;
        gm.serializedData = serializedData;
        gm.forPaymentUpdate = false;
        gm.formReset = formReset;
        gm.removeProductToWishlist = removeProductToWishlist;
        gm.initLookbooks = initLookbooks;
        gm.addLookbookToCart = addLookbookToCart;
        gm.fetchLookbookByGroup = fetchLookbookByGroup;
        gm.updateBasketQty = updateBasketQty;
        gm.getRecommendations = getRecommendations;
        gm.addSampleLookbookToCart = addSampleLookbookToCart;
        gm.activeClass = '';
        let greetingCardsLoaded = false;

        //login screens
        gm.emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/;
        gm.minPasswordLength = 6;
        gm.maxPasswordLength = 50;
        gm.loginTab = loginTab;
        gm.createAccountTab = createAccountTab;
        gm.signing = false;
        gm.registering = false;
        gm.resettingPassword = false;
        gm.passwordResetSuccess = false;

        //Engraving Section Starts
        gm.applyPersonalisation = applyPersonalisation;
        gm.editPersonalisation = editPersonalisation;
        gm.removePersonalisation = removePersonalisation;
        gm.range = range;
        gm.engravingFailedAction = 'remove';
        gm.engravingProduct = null;
        gm.closeEngravingFailedModal = closeEngravingFailedModal;
        gm.engravingColour = 'WHITE'; //default engraving colour
        gm.engravingRegex = REGEX_CONSTANTS.LETTERS_AND_NUMBERS_ONLY; //default engraving colour
        gm.engravingSubmitInProgress = false;
        //Engraving Section Ends

        //Gift wrapping section 
        gm.selectedGiftWrapOption = {};
        gm.sourceProcess = 'NEWSLETTER';
        gm.selectedLineItem = {};
        gm.isGiftWrapApplied = false;
        gm.giftWrapError = false;
        gm.addGiftButtonClicked = false;
        gm.addGiftWrapSelected = addGiftWrapSelected;
        gm.addGiftWrap = addGiftWrap;
        gm.addPersonalisedRibbon = addPersonalisedRibbon;
        gm.addPersonalisedRibbonForm = addPersonalisedRibbonForm;
        gm.addRibbon = addRibbon;
        gm.updateRibbon = updateRibbon;
        gm.editRibbon = editRibbon;
        gm.removeRibbon = removeRibbon;
        gm.checkGiftWrap = checkGiftWrap;
        gm.removeGiftWrap = removeGiftWrap;
        gm.updateBasketBadgeCount = updateBasketBadgeCount;
        gm.changeBaseCurrency = changeBaseCurrency;
        gm.showEditRibbon = false;
        gm.backGiftWrapModal = backGiftWrapModal;
        gm.closeGiftWrapModal = closeGiftWrapModal;
        gm.selectedRibbonOption = {};
        gm.giftWrapRibbonPrice = giftWrapRibbonPrice;
        gm.basketContainShipFromStoreItems = false;

        //ADDONS
        gm.addonsActionPending = false;

        //Greeting cards section
        gm.selectedGreetingCardOption = {};
        gm.selectedGreetingCard = {};
        gm.isGreetingCardApplied = false;
        gm.selectedCardItem = {};
        gm.addGreetingCard = addGreetingCard;
        gm.addGreetingCardPersonalisation = addGreetingCardPersonalisation;
        $scope.tsCsChecked = false;
        gm.openGreetingCardModal = openGreetingCardModal;
        gm.closeGreetingCardModal = closeGreetingCardModal;
        gm.backGreetingCardModal = backGreetingCardModal;
        gm.editGreetingCard = editGreetingCard;
        gm.hideGreetingCard = hideGreetingCard;
        gm.saveEditGreetingCard = saveEditGreetingCard;
        gm.removeGreetingCard = removeGreetingCard;
        gm.greetingCardOptions = [];
        gm.greetingCardSelected = [];
        gm.greetingCardOption = [];
        gm.addGreetingCardButtonClicked = false;

        /*******below code is for recomendation**********/
        gm.recomendations = {};
        gm.openGiftModal = openGiftModal;
        gm.editGiftModal = editGiftModal;
        gm.saveRibbon = saveRibbon;
        // data used to generate qty dropdown in basket 
        gm.basketQtyDropdown = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

        //subscription block starts
        gm.removeSubscription = removeSubscription;
        gm.unsubscribedNewsletter = unsubscribedNewsletter;

        //This variable is used to show static offer recommendation for beauty[Indulge] and SA segment
        gm.offerCategoryName = "";
        gm.isNewsLetterSubscribed = $.cookie("NewsLetterSubscribed");
        gm.isProductExist = false;
        gm.couponProvider = '';
        gm.showCurrencyPopUp = showCurrencyPopUp;
        gm.memberShipAlert = null;
        gm.setCookie = setCookie;
        gm.initMembershipPlans = initMembershipPlans;
        gm.getUnClaimedVouchers = getUnClaimedVouchers;
        gm.applyMembershipVoucher = applyMembershipVoucher;
        gm.checkVoucherApplied = checkVoucherApplied;
        gm.deletedPromoCode = '';
        gm.membershipVoucherApplied = false;
        //fragrance match
        gm.currentlySelectedProductId = '00000000-0000-0000-0000-000000000000';

        //Multifulfillment
        //NEW TFS properties used to determine if we are showing the modals to the user
        gm.tfsBasketDataValidation = {
            validBasket: true,
            validAddons: true,
            validProducts: true,
            disableGiftWrap: false
        }
        gm.shipFromStoreModalInitial = true;
        gm.apiPendingTfs = false;
        gm.isBasketPage = window.location.pathname.toLowerCase() === '/basket';
        gm.isAccountMembershipPage = window.location.pathname.indexOf('/Account/membership') > -1;
        gm.isMembershipLandingPage = window.location.pathname.indexOf('/my-tfs-membership') > -1;
        gm.proceedToCheckout = proceedToCheckout;
        gm.fixDeliveryPlans = fixDeliveryPlans;

        gm.deliveryPlanApiPending = false;
        gm.checkApisStatus = checkApisPending;
        gm.showBasketWarning = false;
        gm.showMembershipWarning = false;

        //reCAPTCHA
        gm.widgetId = null;
        gm.setWidgetId = setWidgetId;

        //validate membership and membership basket
        gm.validateMembership = validateMembership;
        gm.userHasMembership = 0;
        gm.showMembershipBasketErrorMsg = false;
        gm.applyMembershipVoucherAfterRedirect = false;

        //subscription block ends
        function removeSubscription() {
            if (gm.subscriptionItems != null && gm.subscriptionItems != undefined && gm.subscriptionItems.length > 0) {
                var model = [];
                angular.forEach(gm.subscriptionItems, function (item) {
                    model.push({
                        basketId: gm.basketResponse.id,
                        productId: item.productId,
                        qty: 0,
                        stockCode: item.stockCode,
                        isSubscription: item.isSubscription
                    });
                });
                $http.post(globalConfig.bulkAddproduct, { model: model }).then(function (success) {
                    updateBasket(success.data);
                    extractSubscription();
                }, function (error) {
                });
            }
        }

        gm.changeSubscriptionBasketDisplayOrder = {
            update: function (e, ui) {
                //perform before sort math. 
            },
            stop: function (e, ui) {
                //perform after sort math. 
                var lines = [];
                angular.forEach(gm.subscriptionItems, function (item, key) {
                    item.displayOrder = key + 1;
                    lines.push({ id: item.id, displayOrder: key + 1 })
                });
                //add other basket items.
                $http.post(globalConfig.updateLineDisplayOrder, {
                    basketId: gm.basketResponse.id,
                    lines: lines
                }).then(function (sucess) {

                }, function (error) {
                });
            }
        }
        //function initPCALookup() {
        //    if (globalConfig.pcaAccessCode != undefined && globalConfig.pcaAccessCode != '') {
        //        window.setTimeout(function () {
        //            if (!gm.defaultCountry) {
        //                $http.post(globalConfig.getDefaultCountryUrl)
        //                    .success(function (country) { gm.defaultCountry = country; });
        //            }
        //            // address PCA Predict
        //            var optionsBilling = {
        //                key: globalConfig.pcaAccessCode,
        //                countries: {
        //                    codeList: gm.defaultCountry
        //                }
        //            };

        //            var fieldsBilling = [
        //                { element: 'gm.model.company.address1', field: 'Line1' },
        //                { element: 'gm.model.company.address2', field: 'Line2', mode: pca.fieldMode.POPULATE },
        //                { element: 'gm.model.company.city', field: 'City', mode: pca.fieldMode.POPULATE },
        //                { element: 'gm.model.company.state', field: 'Province', mode: pca.fieldMode.POPULATE },
        //                { element: 'gm.model.company.postCode', field: 'PostalCode' }
        //            ];

        //            var controlBilling = new pca.Address(fieldsBilling, optionsBilling);

        //            controlBilling.listen('options', function (options) {
        //                options.countries = options.countries || {};
        //                options.countries.codesList = "GB" //document.getElementById('gm.model.countryCode').value;
        //            });

        //            controlBilling.listen('populate', function (address, variations) {
        //                CapturePlusCallback();
        //            });

        //            controlBilling.load();
        //        }, 1500);
        //    }
        //}

        function loginTab() {
            if (!gm.loginAccount && gm.createAccount) {
                gm.errorMessage = null;
                gm.loginAccount = true;
                gm.createAccount = false;
            }
        }

        function createAccountTab() {
            if (gm.loginAccount && !gm.createAccount) {
                gm.errorMessage = null;
                gm.loginAccount = false;
                gm.createAccount = true;
            }
        }


        function checkForSpecificAttribute(attributeCode, attributevalue, item) {
            //search in specific line item
            if (item != null && item != undefined) {
                var attributesJson = JSON.parse(item.attributesJson);
                if (attributesJson.Attributes != null || attributesJson.Attributes != undefined) {
                    for (var i = 0; i < attributesJson.Attributes.length; i++) {
                        if (attributesJson.Attributes[i].FieldCode == attributeCode && attributesJson.Attributes[i].FieldValue == attributevalue) {
                            return true;
                        }
                    }
                }
                return false;
            }//search in all line items
            else {
                var flag = false;
                if (gm.basketResponse.lineItems != null) {
                    angular.forEach(gm.basketResponse.lineItems, function (line) {
                        var parsedJSON = eval('(' + line.attributesJson + ')');
                        var attr = parsedJSON.Attributes;
                        if (attr != null) {
                            for (i = 0; i < attr.length; i++) {
                                // this can be a string or null
                                var FieldCode = attr[i].FieldCode;
                                var FieldValue = attr[i].FieldValue;
                                if (FieldCode != null && FieldCode != "" && FieldCode == attributeCode) {
                                    //line.customInfo1 = FieldCode + "" + FieldValue;
                                    if (FieldValue != null && FieldValue == attributevalue) {
                                        flag = true;
                                        break;
                                    }
                                }
                            }
                        }
                        if (flag)
                            return flag;
                    });
                    return flag;
                }
            }
        }


        function contactForm(model) {
            $(".alertBlock").fadeIn();
            $http.post(globalConfig.setContactForm, { model: model })
                .success(function (data) {
                    if (!data.isValid != null && typeof data.errorMessages != 'undefined' && data.errorMessages.length > 0) {
                        gm.errorMessage = data.errorMessages;
                        $timeout(function () {
                            $(".alertBlock").fadeOut();
                        }, 10000);
                        return;
                    }
                    gm.errorMessage = null;
                    gm.success = true;
                })
                .error(function (msg) {
                    gm.errorMessage = msg.errorMessages;
                })
                .finally(function () {
                    gm.saving = false;
                    $timeout(function () {
                        $(".alertBlock").fadeOut();
                    }, 10000);
                });
        }

        //#region Basket
        function applyPromoCode(basketId, promoCode) {
            gm.apiPendingTfs = true;
            var membershipBenefits = null;
            if (gm.basketResponse != null && gm.basketResponse.membershipBenefits != null && gm.basketResponse.membershipBenefits.length > 0) {
                membershipBenefits = gm.basketResponse.membershipBenefits;
            }
            if ($.trim(promoCode) != "") {
                gm.model.Id = basketId;
                gm.invalidpromo = false;
                gm.showCustomMsg = false;
                gm.model.promoCode = promoCode;
                $http.post(globalConfig.applyPromoCode, gm.model).success(function (data) {
                    gm.apiPendingTfs = false;
                    //remove the automatic application of the vouchers regardless of the response - to prevent double calling
                    sessionStorage.removeItem(gm.applyMembershipVoucherAfterRedirect);
                    if (data != null && data == "false") {
                        if (data != "false") {
                            gm.showCustomMsg = true;
                            gm.customMsg = data;
                        }
                        gm.invalidpromo = true;
                        $('.promo').show(0).delay(2000).hide(0);
                        return;
                    }
                    $scope.promoCode = null;
                    gm.invalidpromo = false;
                    gm.validpromo = true;
                    $('.promovalid').show(0).delay(2000).hide(0);
                    var dataResult = gm.serializedData(data.result.basket);
                    gm.basketResponse = dataResult;
                    //add prop which is missing from returned api data
                    addPropToShipFromStoreLineItem('disableGiftWrap');
                    if (gm.basketResponse != null && membershipBenefits != null && membershipBenefits.length > 0 && (gm.basketResponse.membershipBenefits == null || gm.basketResponse.membershipBenefits.length == 0)) {
                        gm.basketResponse.membershipBenefits = membershipBenefits;
                    }
                    initBasket(dataResult);
                })
                    .error(function (msg) {
                        if (msg.errorMessage != "false") {
                            gm.showCustomMsg = true;
                            gm.customMsg = msg.errorMessage;
                        }
                        gm.apiPendingTfs = false;
                        gm.invalidpromo = true;
                        $('.promo').show(0).delay(2000).hide(0);
                    })
                    .finally(function () {
                    });
            } else {
                gm.promonull = true;
                $('.promonull').show(0).delay(1200).hide(0);
            }
        }

        gm.physicalStoreStringConst = 'PhysicalStore';
        function addPropToShipFromStoreLineItem(prop) {
            angular.forEach(gm.basketResponse.deliveryPlans, function (plan) {
                if (plan.deliveryCenter.code == gm.physicalStoreStringConst) {
                    angular.forEach(plan.lineItems, function (planLineItem) {
                        angular.forEach(gm.basketResponse.lineItems, function (basketLineItem) {
                            if (planLineItem.productId.toLowerCase() == basketLineItem.productId.toLowerCase()) {
                                basketLineItem[prop] = true;
                            }
                        });
                    });
                }
            });
        }

        function cancelChangePostCode() {
            gm.basketResponse.postCode = $.cookie(BULKORDER_CONSTANTS.POSTCODE);
        }

        //Method to show the shipping methods after entering the valid Post code
        function showShippingGrid(countryCode, basketId, postCode, appliedShippingId) {
            $.cookie(BULKORDER_CONSTANTS.POSTCODE, postCode, { path: '/' });
            //var postCode_regex = /^[a-zA-Z0-9_/-]+$/;
            if (postCode != null && postCode != "") {
                //if (postCode_regex.test(postCode)) {
                $http.post(globalConfig.getDeliverysByPostCode, {
                    countryCode: countryCode,
                    basketId: basketId,
                    postCode: postCode,
                    appliedShippingId: appliedShippingId
                })
                    .success(function (data) {
                        $scope.postCodeSelected = true;
                        var dataResult = gm.serializedData(data);
                        gm.basketResponse = dataResult;
                        gm.basketResponse.postCode = $.cookie(BULKORDER_CONSTANTS.POSTCODE);
                    })
                    .error(function (msg) {
                    })
                    .finally(function () {
                    });

                //}
                //else {
                //    $scope.shippingSelected = false;
                //    $scope.postCodeSelected = false;
                //    ck.hideShippingAddress = true;
                //    ck.wrongPostCode = true;
                //    $timeout(function () { ck.wrongPostCode = false; }, 10000);

                //}
            }
        }
        function initBasket(basket) {
            loadGreetingCards();
            gm.unClaimedMembershipVouchers = [];
            if (basket == null || basket == undefined) {
                if (gm.basketResponse == null || gm.basketResponse == undefined) {
                    $http.post(globalConfig.getBasketUrl)
                        .success(function (data) {
                            gm.basketResponse = data;
                            initAddToBagQty();
                            gm.getUnClaimedVouchers();
                            gm.postCode = $.cookie(BULKORDER_CONSTANTS.POSTCODE);
                            if (gm.basketResponse != null && gm.basketResponse != undefined) {
                                angular.forEach(gm.basketResponse.lineItems, function (line) {
                                    var json = eval('(' + line.attributesJson + ')');
                                    line.slug = json.Slug;
                                    if (isJSON(line.customInfo2)) {
                                        line.customInfo2 = JSON.parse(line.customInfo2);
                                        line.parentProductId = line.customInfo2.ParentProductId;
                                    }
                                    line.updatedqty = line.qty;
                                    if (line.isGiftWrapApplied) {
                                        //line.giftWrappingInfo = gm.basketResponse.giftWrapOption.filter(x => x.id == line.giftWrapId.toUpperCase());
                                        line.giftWrappingInfo = [];
                                        angular.forEach(gm.basketResponse.giftWrapOption, function (opt) {
                                            if (opt.id.toUpperCase() == line.giftWrapId.toUpperCase()) {
                                                line.giftWrappingInfo.push(opt);
                                            }
                                        });
                                    }
                                });
                                gm.count = gm.basketResponse.lineItemCount;
                                gm.currencyCookie = $.cookie(CURRENCYCOOKIE.CurrencyCode);
                                gm.changeBaseCurrency(gm.currencyCookie, false);
                                membershipDiscountPrice();
                                extractSubscription();
                                extractCustomInfo(gm.basketResponse);
                                updateBasketBadgeCount();
                                initGreetingCards();
                                initRibbons();

                                //NEW MULTI FULFILLMENT FUNCTIONALITY (Shipt From Store)
                                //ONLY if EnableShipFromStore == true (web.config)
                                if (isShipFromStoreEnabled() && gm.count > 0) {
                                    //add shipfromstore prop
                                    lineItemsAddPropShipFromStore();
                                    populateDeliveryPlans();
                                }

                                //paypal messaging refresh
                                renderPaypalMessaging();

                                //clearpay messaging render
                                renderClearpayMessaging();

                                gm.basketContainsMembership = checkBasketContainsMembership();
                                gm.basketContainsSubscription = checkBasketContainsSubscription();
                                gm.basketContainsVirtual = checkBasketContainsVirtual();

                                gm.potentialSavings = getBasketDiscountAmount();

                                gm.basketContainShipFromStoreItems = checkBasketContainShipFromStoreItems();

                                if (gm.isMultiFulfilmentEnabled) {
                                    gm.allItemsOOS = allItemsOOS();
                                    gm.someItemsOOS = someItemsOOS();
                                }

                                //check if membership discount needs to be applied
                                if (sessionStorage.getItem(gm.applyMembershipVoucherAfterRedirect) !== null) {
                                    applyMembershipVoucher();
                                }
                            }

                        })
                        .error(function (msg) {
                            // vm.errorMessage = msg.errorMessages;
                        })
                        .finally(function () {
                            // vm.saving = false;
                            //$("html, body").animate({ scrollTop: 0 }, "slow");
                        });
                }

            } else {
                gm.basketResponse = basket;
                if (gm.basketResponse != null && gm.basketResponse != undefined) {
                    angular.forEach(gm.basketResponse.lineItems, function (line) {
                        if (isJSON(line.customInfo2)) {
                            line.customInfo2 = JSON.parse(line.customInfo2);
                            line.parentProductId = line.customInfo2.ParentProductId;
                        }
                        line.updatedqty = line.qty;
                        if (line.isGiftWrapApplied) {
                            //line.giftWrappingInfo = gm.basketResponse.giftWrapOption.filter(x => x.id == line.giftWrapId.toUpperCase());
                            line.giftWrappingInfo = [];
                            angular.forEach(gm.basketResponse.giftWrapOption, function (opt) {
                                if (opt.id.toUpperCase() == line.giftWrapId.toUpperCase()) {
                                    line.giftWrappingInfo.push(opt);
                                }
                            });
                        }
                        if (line.isGreetingCardApplied) {
                            //line.greetingCardInfo = gm.basketResponse.greetingCardOption.filter(x => x.id == line.greetingCardId.toUpperCase());
                            line.greetingCardInfo = [];
                            angular.forEach(gm.basketResponse.greetingCardOption, function (opt) {
                                if (opt.id.toUpperCase() == line.greetingCardId.toUpperCase()) {
                                    line.greetingCardInfo.push(opt);
                                }
                            });
                        }

                    });
                    initAddToBagQty();
                    gm.getUnClaimedVouchers();
                    gm.count = gm.basketResponse.lineItemCount;
                    gm.postCode = $.cookie(BULKORDER_CONSTANTS.POSTCODE);
                    gm.currencyCookie = $.cookie(CURRENCYCOOKIE.CurrencyCode);
                    gm.changeBaseCurrency(gm.currencyCookie, false);
                    membershipDiscountPrice();
                    extractCustomInfo(gm.basketResponse);
                    initGreetingCards();
                    initRibbons();

                    //paypal messaging refresh
                    renderPaypalMessaging();

                    //clearpay messaging render
                    renderClearpayMessaging();

                    //zip messaging
                    renderZipMessaging(gm.basketResponse.totalWithoutShipping.raw.withTax);

                    gm.basketContainsMembership = checkBasketContainsMembership();

                    gm.basketContainShipFromStoreItems = checkBasketContainShipFromStoreItems();

                    //add shipfromstore prop
                    lineItemsAddPropShipFromStore();

                    if (gm.isMultiFulfilmentEnabled) {
                        gm.allItemsOOS = allItemsOOS();
                        gm.someItemsOOS = someItemsOOS();
                    }

                    //check if membership discount needs to be applied
                    if (sessionStorage.getItem(gm.applyMembershipVoucherAfterRedirect) !== null) {
                        applyMembershipVoucher();
                    }
                }
            }
        }

        function membershipDiscountPrice() {
            if (gm.basketResponse.membershipBenefits == null) {
                gm.selectedCurrencySymbol = "£";
                gm.membershipDiscountAmt = gm.selectedCurrencySymbol + ((gm.basketResponse.subTotal.raw.withTax / 100) * 20).toFixed(2);
            }
        }

        //multifillment FixDeliveryPlans
        function fixDeliveryPlans(goToCheckout = false, target = '') {
            //do nothing if we are not on a basket page
            if (!gm.isBasketPage) return;

            //return if already pending
            if (gm.apiPendingTfs) {
                return;
            }
            gm.apiPendingTfs = true;

            $http.get(MULTIFILFILLMENT.URL_FIX_DELIVERY_PLANS)
                .success(function (basketData) {
                    if (basketData != null && basketData != undefined) {
                        //set new props on the existing basket
                        setTfsBasketDataValidation(basketData);

                        //check if we need to redirect user to the checkout
                        if (goToCheckout && gm.tfsBasketDataValidation.validBasket) {
                            window.location.href = target;
                            return;
                        }
                        shipFromStoreModalHide();

                        //we initialise the basket to make sure the page is rendered as expected
                        //if changes where made
                        initBasket(basketData);

                        //populate line items with addons ON/OFF prop
                        lineItemsAddonsProp();
                    }
                })
                .error(function (msg) {

                })
                .finally(function () {
                    gm.apiPendingTfs = false;
                });
        }

        //multifillment PopulateDeliveryPlans
        function populateDeliveryPlans() {
            //do nothing if we are not on a basket page
            if (!gm.isBasketPage) return;

            gm.deliveryPlanApiPending = true;

            // basket before deliveryplan fetch
            var snapShotBasket = createBasketSnapshot(gm.basketResponse);

            $http.get(MULTIFILFILLMENT.URL_POPULATE_DELIVERY_PLANS)
                .success(function (basketData) {
                    if (basketData != null && basketData != undefined) {
                        //set new props on the existing basket
                        setTfsBasketDataValidation(basketData);
                        //we initialise the basket to make sure the page is rendered as expected
                        //if changes where made
                        initBasket(basketData);

                        //check if modal needs to be shown to the customer on basket load
                        //will show if needed on initial page load
                        if (!gm.tfsBasketDataValidation.validBasket && gm.shipFromStoreModalInitial && !gm.isMultiFulfilmentEnabled) {
                            //show addons modal
                            shipFromStoreModalShow();
                        }

                        //if multifulfilment is enabled we want to group invalid products and not show modal
                        if (!gm.tfsBasketDataValidation.validBasket && gm.shipFromStoreModalInitial && gm.isMultiFulfilmentEnabled) {
                            collectOutOfStockProducts(basketData);
                            fixDeliveryPlans();
                        }

                        if (gm.isMultiFulfilmentEnabled) {
                            if (!gm.tfsBasketDataValidation.validBasket) {
                                fixDeliveryPlans();
                            }
                            createSnapShotOfAddons(snapShotBasket, gm.basketResponse);
                        }

                        //populate line items with addons ON/OFF prop
                        lineItemsAddonsProp();
                    }
                })
                .error(function (msg) {

                })
                .finally(function () {
                    gm.deliveryPlanApiPending = false;
                    gm.showBasketWarning = showBasketWarning();
                });
        }

        gm.outofStockProducts = null;
        function collectOutOfStockProducts(basket) {
            let outofStockProducts = [];
            angular.forEach(basket.deliveryPlans, function (plan) {
                if (plan.deliveryCenter.code == "SupplierLocation") {
                    angular.forEach(plan.lineItems, function (item) {
                        outofStockProducts.push(item);
                    });
                }
            });
            gm.outofStockProducts = outofStockProducts;
        }

        gm.snapShotAddons = null;
        gm.basketTouched = false;
        function createSnapShotOfAddons(oldBasket, newBasket) {
            let oldAddons = [];
            angular.forEach(oldBasket.lineItems, function (oldLine) {
                angular.forEach(newBasket.lineItems, function (newLine) {
                    if (oldLine.productId.toLowerCase() == newLine.productId.toLowerCase() && typeof oldLine.isShipFromStore != 'undefined' && typeof newLine.isShipFromStore != 'undefined' && oldLine.isShipFromStore !== newLine.isShipFromStore) {
                        angular.forEach(oldBasket.lineItems, function (item) {
                            if (item.parentProductId == newLine.productId) {
                                oldAddons.push(item);
                                gm.basketTouched = true;
                            }
                        });
                    }
                });
            });
            gm.snapShotAddons = oldAddons;
        }

        function createBasketSnapshot(basket) {
            return JSON.parse(JSON.stringify(basket));
        }

        function checkApisPending() {
            return gm.apiPendingTfs || gm.deliveryPlanApiPending;
        }

        function setTfsBasketDataValidation(newBasket) {
            gm.tfsBasketDataValidation.validBasket = newBasket.validBasket;
            gm.tfsBasketDataValidation.validAddons = newBasket.validAddons;
            gm.tfsBasketDataValidation.validProducts = newBasket.validProducts;
            gm.tfsBasketDataValidation.disableGiftWrap = newBasket.disableGiftWrap;
        }

        function shipFromStoreModalShow() {
            $("#shipFromStoreModal").on('shown.bs.modal', function () {
                //adjust the backdrop
                $('.modal-backdrop.in').css({
                    "z-index": 9999998,
                });
            });
            $("#shipFromStoreModal").modal('show').on('hidden.bs.modal', function () {
                $("#shipFromStoreModal").off('hidden.bs.modal');
                gm.shipFromStoreModalInitial = false;
            });
        }

        function shipFromStoreModalHide() {
            $("#shipFromStoreModal").modal('hide');
        }

        //to add the quantity of product from dropdown
        function initAddToBagQty() {
            if (gm.maximumAddToBasketLimit > 0) {
                gm.basketQtyDropdown = [];
                for (var i = 1; i <= gm.maximumAddToBasketLimit; i++) {
                    gm.basketQtyDropdown.push(i);
                }
            }
        }

        gm.addMixLookbookToCart = addMixLookbookToCart;
        function addMixLookbookToCart(simpleProducts, subscriptionProductList, qty) {
            var model = [];
            if (subscriptionProductList != null && subscriptionProductList.length > 0) {
                $http.get("/Subscription/GetSubscriptionPlan?productId=" + subscriptionProductList[0].RecordId).then(function (success) {
                    gm.subscriptionPlan = success.data.result;
                    angular.forEach(subscriptionProductList, function (data, index) {
                        model.push({ stockCode: data.StockCode, productId: data.RecordId, qty: qty, subscriptionPlanId: gm.subscriptionPlan.recordId, isSubscription: true, displayOrder: index });
                    });
                    angular.forEach(simpleProducts, function (data, index) {
                        model.push({ stockCode: data.StockCode, productId: data.RecordId, qty: qty, displayOrder: index });
                    });
                    gm.addToLookBook(model);
                }, function (error) { });
            }
            else {
                angular.forEach(simpleProducts, function (data, index) {
                    model.push({ stockCode: data.StockCode, productId: data.RecordId, qty: qty, displayOrder: index });
                });
                gm.addToLookBook(model);
            }
        }
        gm.addToLookBook = addToLookBook;
        function addToLookBook(model) {
            var isAlreadyExistInBasket = false;
            $http.post(globalConfig.bulkAddproduct, model)
                .success(function (data) {
                    var dataResult = gm.serializedData(data.result);
                    if (data.messageCode == 'C002') {
                        gm.errorMessage = data.message;
                        $('.alert').show(0).delay(4000).hide(0);
                    }
                    gm.basketResponse = dataResult;
                    PubSub.publish("addToCartBulk", gm.basketResponse);
                    var count = 0;
                    if (gm.basketResponse != null) {
                        if (gm.basketResponse.lineItems != null) {
                            angular.forEach(gm.basketResponse.lineItems, function (line) {
                                if (line.parentProductId == gm.emptyGuid) {
                                    count = count + line.qty;
                                }
                                var json = eval('(' + line.attributesJson + ')');
                                line.slug = json.Slug;
                                isAlreadyExistInBasket = false;
                            });
                            gm.count = gm.basketResponse.lineItemCount;
                        }
                    }
                    redirectToOffers(gm.basketResponse.id, isAlreadyExistInBasket);
                }).error(function () {
                    gm.wrongFormatMessage = true;
                    $('.wrongFormatError').show(0).delay(3000).hide(0);
                });
        }
        function addLookbookToCart(data, qty) {
            var isAlreadyExistInBasket = false;
            var model = [];
            angular.forEach(data, function (stockCode) {
                model.push({ stockCode: stockCode, qty: qty })
            });

            $http.post(globalConfig.bulkAddproduct, model)
                .success(function (data) {
                    var dataResult = gm.serializedData(data.result);
                    if (data.messageCode == 'C002') {
                        gm.errorMessage = data.message;
                        $('.alert').show(0).delay(4000).hide(0);
                    }
                    gm.basketResponse = dataResult;
                    PubSub.publish("addToCartBulk", gm.basketResponse);
                    var count = 0;
                    if (gm.basketResponse != null) {
                        if (gm.basketResponse.lineItems != null) {
                            angular.forEach(gm.basketResponse.lineItems, function (line) {
                                if (line.parentProductId == gm.emptyGuid) {
                                    count = count + line.qty;
                                }
                                var json = eval('(' + line.attributesJson + ')');
                                line.slug = json.Slug;
                                isAlreadyExistInBasket = false;
                            });
                            gm.count = gm.basketResponse.lineItemCount;
                        }
                    }
                    redirectToOffers(gm.basketResponse.id, isAlreadyExistInBasket);
                }).error(function () {
                    gm.wrongFormatMessage = true;
                    $('.wrongFormatError').show(0).delay(3000).hide(0);
                });
        }

        function pushEventToOmnilytics(eventName, data) {

            if (eventName == 'addToBasket' && data != null) {
                // in this case data is the server response of the add to basket calls
                // in case the item is removed or qty reduced, data would also contain product field having the product which was removed. 

                if (data.lineItems != null && data.lineItems.length > 0) {
                    var eventData = {
                        product: data.productRemoved,
                        basket: { id: null, lines: [], totalCost: null, totalItems: null, tax: null }
                    };
                    eventData.id = data.id;
                    eventData.basket.totalItems = data.lineItemCount;
                    eventData.basket.totalCost = data.subTotal.raw.withoutTax;
                    eventData.basket.tax = data.grandTotal.raw.tax;
                    angular.forEach(data.lineItems, function (line) {
                        var li = {
                            id: line.id,
                            basketId: data.id,
                            stockCode: line.stockCode,
                            name: line.name,
                            qty: line.qty,
                            price: line.price.raw.withoutTax,
                            tax: line.price.raw.tax,
                            manufacturer: line.Manufacture,
                            'img': line.image
                        };
                        eventData.basket.lines.push(li);
                        if (line.productId.toLowerCase() == data.product.productId.toLowerCase() && data.productRemoved == null) {
                            var prodDetail = angular.copy(line);
                            prodDetail.qty = data.product.qty /// set the actual qty that was requested to be aded instead of final  item qty
                            prodDetail.basketId = data.product.basketId;
                            eventData.product = prodDetail;
                        }
                        PubSub.publish("addToCart", eventData);
                    });
                }
            }
        }

        function addToBasket(recordId, qty, displayOrder, isSubscription, isMembership = 0, redirect = false, membershipUpgrade = false) {
            gm.apiPendingTfs = true;
            if (gm.currentlySelectedProductId !== gm.emptyGuid) {
                recordId = gm.currentlySelectedProductId;
                $('section.pdp-modal-product button.cart-add-btn').prop('disabled', true);
            }

            if (gm.memberShipAlert != null && gm.memberShipAlert.length > 0) {
                alerts.error(gm.memberShipAlert);
                $('section.pdp-modal-product button.cart-add-btn').prop('disabled', false);
                return;
            }

            if (isSubscription == undefined)
                isSubscription = false;
            if ($scope.addToBagInProgress) {
                $('section.pdp-modal-product button.cart-add-btn').prop('disabled', false);
                return;
            }
            $scope.addToBagInProgress = true;

            //variable to check if product to be added is already exist in basket or not
            //to be used in finally block when redirecting it to offer page. 
            //if product already exists in basket that means it's a qty update or deletion hence no offer page redirection. 
            var isAlreadyExistInBasket = false;

            if (displayOrder >= 0) {
                gm.displayOrder = displayOrder;
            } else {
                gm.displayOrder = gm.basketResponse.lineItems.length + 1;
            }
            var basketId = gm.basketResponse != null ? gm.basketResponse.id : "";
            var itemType = 0;
            var prodInBasket = null;
            if (gm.basketResponse != null) {
                if (gm.basketResponse.lineItems != null) {
                    angular.forEach(gm.basketResponse.lineItems, function (line) {
                        if (line.productId.toLowerCase() == recordId.toLowerCase()) {
                            itemType = line.itemType;
                            // this line is used in omnilytics  incase of product removal from basket
                            prodInBasket = {
                                'id': line.productId,
                                'name': line.name,
                                basketId: basketId,
                                'stockCode': line.stockCode,
                                'price': line.price,
                                'manufacturer': line.manufacturer,
                                'category': line.category,
                                'qty': qty,
                                'image': line.image
                            };
                            isAlreadyExistInBasket = true;
                        }
                    });
                }
            }
            initAddToBagQty();
            var itemGroupId = 0;
            if (gm.couponProvider == 'Givex')
                itemGroupId = 7;
            var prod = {
                "basketId": basketId,
                "productId": recordId,
                "qty": qty,
                "displayOrder": gm.displayOrder,
                "itemType": itemType,
                "issubscription": isSubscription,
                "isMembership": isMembership,
                "itemGroupId": itemGroupId
            };
            gm.couponProvider = '';
            //var eventData = { product: prodInBasket, basket: { id: null, lines: [], totalCost: null, totalItems: null, tax: null } };
            $http.post(globalConfig.addToBasket, prod)
                .success(function (data) {
                    $scope.addToBagInProgress = false;
                    //validate the basket and return false if  basket item is greater than the count set in basket settings
                    if (data != null && data.isValid == false) {
                        gm.maximumBasketItemError = true;
                        alerts.error(data.message);
                        //retain the old basket quantity when item exceeds the required qty
                        angular.forEach(gm.basketResponse.lineItems, function (line) {
                            if (line.productId == recordId) {
                                line.qty = line.updatedqty;
                                // this line is used in omnilytics  incase of product removal from basket 
                            }
                        });
                        $('section.pdp-modal-product button.cart-add-btn').prop('disabled', false);
                        return;
                    }
                    if (data != null && data != false) {
                        if (data.messageCode != null && data.messageCode.length > 0 && (data.messageCode == BULKORDER_CONSTANTS.ITEM_STOCK_UNAVAILABLE || data.messageCode == BULKORDER_CONSTANTS.ITEM_STOCK_UNAVAILABLE)) {
                            alerts.error(data.message);
                            $('section.pdp-modal-product button.cart-add-btn').prop('disabled', false);
                            if (data == null || data.result == null || data.result.lineItems == null || data.result.lineItems.length == 0) {
                                return;
                            } else {
                                angular.forEach(data.result.lineItems, function (value, key) {
                                    if (value.stockCode == value.stockCode) {
                                        gm.isProductExist = true;
                                    }
                                });
                            }

                        }
                    }
                    updateBasket(data);
                    //gm.removeProductToWishlist(recordId);
                    //PubSub.publish("addToCart", eventData);
                    gm.basketResponse.productRemoved = prodInBasket /// this is assigned in case of basket item removal since the response would not have any product 
                    gm.basketResponse.product = { productId: recordId, qty: qty, basketId: basketId };/// this is assigned to pass the actual qty change.
                    pushEventToOmnilytics('addToBasket', gm.basketResponse);
                    if (typeof _itq != "undefined") {
                        if (qty < 1) {
                            _itq.push(["_trackUserEvent", "remove from basket",
                                {
                                    Product: {
                                        ID: recordId
                                    }
                                },
                                "Remove from Basket"
                            ]);
                        } else {
                            if (gm.basketResponse != null && gm.basketResponse.lineItems != null && gm.basketResponse.lineItems.length > 0) {
                                gm.addToBasketProduct = null;
                                angular.forEach(gm.basketResponse.lineItems, function (value, key) {
                                    if (value.productId != null && recordId != null && value.productId.toLowerCase() == recordId.toLowerCase()) {
                                        gm.addToBasketProduct = value;
                                        $('section.pdp-modal-product button.cart-add-btn').prop('disabled', false);
                                        return;
                                    }
                                });
                                if (gm.addToBasketProduct != null) {
                                    _itq.push(["_trackUserEvent", "add to basket",
                                        {
                                            Product: {
                                                ID: gm.addToBasketProduct.productId,
                                                Image: gm.addToBasketProduct.image,
                                                Price: gm.addToBasketProduct.price.formatted.withTax,
                                                Subbrand: gm.addToBasketProduct.subbrand,
                                                Productname: gm.addToBasketProduct.name,
                                                Brand: gm.addToBasketProduct.brand
                                            }
                                        },
                                        "Add to Basket"
                                    ]);
                                }
                            }
                        }
                    }

                    //check if we need to stay in the basket
                    //this is for membership upgrades from basket page
                    if (membershipUpgrade) {
                        isAlreadyExistInBasket = true; //this is to not trigger redirect to offers page
                    }

                    //redirect to offer page
                    if (data.messageCode != 'C002' || gm.isProductExist || gm.engravingFailedAction === 'continue') {
                        if (gm.isProductExist) {
                            $timeout(function () {
                                redirectToOffers(recordId, isAlreadyExistInBasket, redirect);
                            }, 3000);
                        } else {
                            redirectToOffers(recordId, isAlreadyExistInBasket, redirect);
                        }
                        gm.isProductExist = false;
                    }

                    //engraving failed modal actions
                    if (gm.engravingFailedAction === 'remove' && gm.engravingProduct) {
                        engravingFiledActions();
                    }
                    if (isMembership) {
                        window.location.reload();
                        return;
                    }
                    //UPDATE BASKET IF SHIP BASKET PAGE AND SHIP FROM STORE ENABLED
                    if (isShipFromStoreEnabled() && gm.count > 0) {
                        populateDeliveryPlans();
                    }

                    gm.basketContainsMembership = checkBasketContainsMembership();

                    //if we are upgrading from account area we need to redirect user to basket once done
                    if (membershipUpgrade && data.messageCode != 'C002') {
                        window.location.href = "/Basket";
                    }

                    gm.apiPendingTfs = false;
                })
                .error(function (msg) {
                    $('section.pdp-modal-product button.cart-add-btn').prop('disabled', false);
                    gm.apiPendingTfs = false;
                })
                .finally(function () {
                    gm.currencyCookie = $.cookie(CURRENCYCOOKIE.CurrencyCode);
                    gm.changeBaseCurrency(gm.currencyCookie, false);
                    $('section.pdp-modal-product button.cart-add-btn').prop('disabled', false);
                    if (gm.isMultiFulfilmentEnabled) {
                        collectOutOfStockProducts(gm.basketResponse);
                    }
                });
        };


        function checkBasketContainsMembership() {
            var membershipLines = [];
            angular.forEach(gm.basketResponse.lineItems, function (line) {
                if (line.isMembership) {
                    membershipLines.push(line);
                }
            });
            return membershipLines.length > 0 ? true : false;
        }

        function checkBasketContainsSubscription() {
            var subLines = [];
            angular.forEach(gm.basketResponse.lineItems, function (line) {
                if (line.isSubscription) {
                    subLines.push(line);
                }
            });
            return subLines.length > 0 ? true : false;
        }

        function checkBasketContainsVirtual() {
            var virLines = [];
            angular.forEach(gm.basketResponse.lineItems, function (line) {
                if (line.itemGroupId == 7) {
                    virLines.push(line);
                }
            });
            return virLines.length > 0 ? true : false;
        }

        function redirectToOffers(productId, isAlreadyExistInBasket, redirect = false) {
            if (!isAlreadyExistInBasket || gm.engravingFailedAction === 'continue' || redirect) {
                if (gm.basketResponse != null && gm.basketResponse != undefined && gm.basketResponse.lineItems != null && gm.basketResponse.lineItems.length > 0) {
                    //get the last added item sub-brand 
                    //var lastAddedItem = gm.basketResponse.lineItems.find(i => i.productId.toLowerCase() == productId.toLowerCase());
                    var lastAddedItem = '';
                    angular.forEach(gm.basketResponse.lineItems, function (line) {
                        if (line.productId.toLowerCase() == productId.toLowerCase())
                            lastAddedItem = line;
                    });
                    if (lastAddedItem) {
                        //store sub-brand in cookie
                        $.cookie("_stk", lastAddedItem.stockCode, { path: '/' });
                    }
                }
                //redirect to offer page
                if (gm.offerCategoryName != null && gm.offerCategoryName != "")
                    window.location.href = globalConfig.offerUrl + "/?categoryType=" + gm.offerCategoryName;
                else
                    window.location.href = globalConfig.offerUrl;
            }
        }

        function removeProductToWishlist(recordId) {
            $http.post(globalConfig.removeProductFromWishlist, { id: recordId })
                .success(function (data) {
                    PubSub.publish("wishListData", data);
                    //window.location.reload();
                })
                .error(function (msg) {
                })
                .finally(function () {
                });
        };

        function getShippingMethods(countryCode) {

            $http.post(globalConfig.getShippingMethods, { 'countryCode': countryCode })
                .success(function (data) {
                    gm.basketResponse.shippingMethods = data;
                })
                .error(function (msg) {
                    // vm.errorMessage = msg.errorMessages;
                })
                .finally(function () {
                    // vm.saving = false;
                    //$("html, body").animate({ scrollTop: 0 }, "slow");
                });
        }

        function updateQtyAndAdd(productId, newQty, oldQty, displayOrder) {
            gm.updateQty = 0;
            if (newQty == oldQty || !oldQty) {
                return gm.basketResponse;
            } else {
                if (newQty > oldQty) {
                    gm.updateQty = newQty - oldQty;
                } else {
                    gm.updateQty = -(oldQty - newQty);
                }
                gm.addToBasket(productId, gm.updateQty, displayOrder);
            }
        };

        function updateShipping(id) {
            $http.post(globalConfig.updateShipping, { id: gm.basketResponse.id, shippingId: id, nominatedDelivery: null })
                .success(function (data) {
                    var dataResult = gm.serializedData(data.basket);
                    gm.basketResponse = dataResult;
                    angular.forEach(data.basket.shippingMethods, function (obj, key) {
                        if (obj.id == id) {
                            gm.basketResponse.isPriceOnRequest = obj.isPriceOnRequest;
                        }
                    });
                })
                .error(function (msg) {
                    // vm.errorMessage = msg.errorMessages;
                })
                .finally(function () {
                    // vm.saving = false;
                    //$("html, body").animate({ scrollTop: 0 }, "slow");
                });
        };

        function removePromoCode(id, promoCode) {
            var membershipBenefits = null;
            gm.deletedPromoCode = promoCode;
            if (gm.basketResponse != null && gm.basketResponse.membershipBenefits != null && gm.basketResponse.membershipBenefits.length > 0) {
                membershipBenefits = gm.basketResponse.membershipBenefits;
            }

            $http.post(globalConfig.removePromoCode, { id: id, promoCode: promoCode })
                .success(function (data) {
                    gm.validpromo = false;
                    var dataResult = gm.serializedData(data.result.basket);
                    gm.basketResponse = dataResult;
                    //add prop which is not returned but required by html
                    addPropToShipFromStoreLineItem('disableGiftWrap');
                    if (gm.basketResponse != null && membershipBenefits != null && membershipBenefits.length > 0 && (gm.basketResponse.membershipBenefits == null || gm.basketResponse.membershipBenefits.length == 0)) {
                        gm.basketResponse.membershipBenefits = membershipBenefits;
                    }
                    initBasket(dataResult);
                })
                .error(function (msg) {
                })
                .finally(function () {
                });
        };

        function addProductsExcel(line) {
            gm.errorMessage = '';
            gm.wrongFormatError = '';
            gm.basketMessage = '';
            gm.stockUnavailable = false;
            $scope.bulkOrder = [];
            var rows = line.split("\n");
            angular.forEach(rows, function (value, key) {
                $scope.bulkOrder.push({ stockCode: rows[key].split(",")[0], qty: rows[key].split(",")[1], basketId: "" })
            });
            angular.forEach($scope.bulkOrder, function (item, key) {
                if (item != undefined) {
                    angular.forEach($scope.bulkOrder, function (i, k) {
                        if (i != undefined && item.stockCode == i.stockCode && key != k) {
                            gm.errorMessage = " ";
                        }
                    });
                }
            });
            if (gm.errorMessage) {
                $('.stockError').show(0).delay(3000).hide(0);
                return;
            }
            $http.post(globalConfig.bulkAddproduct, $scope.bulkOrder)
                .success(function (data) {
                    var dataResult = gm.serializedData(data.result);
                    gm.basketResponse = dataResult;
                    var count = 0;
                    if (gm.basketResponse != null) {
                        if (gm.basketResponse.lineItems != null) {
                            angular.forEach(gm.basketResponse.lineItems, function (line) {
                                if (line.parentProductId == gm.emptyGuid) {
                                    count = count + line.qty;
                                }
                                var json = eval('(' + line.attributesJson + ')');
                                line.slug = json.Slug;
                            });
                            gm.count = gm.basketResponse.lineItemCount;
                        }
                    }
                    $("#AddToBasketModel").modal("hide");
                    $("#bulkOrderMessage").modal();
                    if (data.message != null && data.message.length > 0)
                        gm.notFoundLength = data.message.split(",").length;
                    if (data.messageCode == BULKORDER_CONSTANTS.STOCK_UNAVAILABLE) {
                        gm.stockUnavailable = true;
                        $('.stockUnavailable').show(0).delay(3000).hide(0);
                    }
                    if (data.message) {
                        if (data.messageCode == BULKORDER_CONSTANTS.STOCK_AVAILABLE) {
                            gm.basketMessage = data.message;
                        }
                        if (data.message) {
                            if (data.messageCode == BULKORDER_CONSTANTS.SUCCESS)
                                gm.basketMessage = data.message
                        } else {
                            gm.basketMessage = data.message;
                        }
                        return;
                    }
                }).error(function () {
                    gm.wrongFormatMessage = true;
                    $('.wrongFormatError').show(0).delay(3000).hide(0);
                });
        };

        //#endregion
        gm.addToWishlistAction = false;
        gm.redeemSaVoucherAction = false;
        function userLogin(model, modal = false) {
            let url = globalConfig.signIn;
            if (modal) {
                url = '/TFSAccount/SignIn';
            }
            gm.saving = false;
            gm.errorMessage = null;
            gm.success = false;
            $(".alertBlock").hide();
            $http.post(url, model)
                .success(function (data) {
                    if (data) {
                        if (!data.isValid != null && typeof data.errorMessages != 'undefined' && data.errorMessages.length > 0) {
                            gm.errorMessage = data.errorMessages;
                            return;
                        }
                        if (typeof _itq != "undefined") {
                            _itq.push(["_trackUserEvent", "sign in",
                                {
                                    "Customer": { "Email": model.username }
                                },
                                "Sign In"
                            ]);
                        }

                        $timeout(function () {
                            gm.isChecked = $.cookie(model.username);
                        }, 10000);
                        $("#login-modal").modal('hide');
                        $.cookie('IsUserLoggedIn', true, { path: '/' });
                        if ($scope.global_login || gm.forPaymentUpdate || gm.addToWishlistAction || gm.redeemSaVoucherAction) {
                            if (gm.addToWishlistAction) {
                                sessionStorage.setItem('addToWishlist', true);
                            }
                            window.location.reload();
                        } else {
                            const returnUrl = 'returnUrl';
                            let params = getAllQuerryParams(window.location.search);
                            if (params.hasOwnProperty(returnUrl)) {
                                const url = params[returnUrl];
                                window.location.href = url;
                            }
                            else {
                                window.location.href = window.location.origin + '/myaccount';
                            }

                        }

                    }
                })
                .error(function (msg) {
                    gm.errorMessage = msg.errorMessages;
                })
                .finally(function () {
                    gm.saving = false;
                    gm.signing = false;
                });
        }

        //extract search params to array
        function getAllQuerryParams(search) {
            let paramsObj = {};
            let params = new URLSearchParams(search);
            for (let key of params.keys()) {
                paramsObj[key] = params.get(key)
            }
            return paramsObj;
        }

        function isPasswordPolicyMeet(flag, form, pwdId, cnfPwdId) {
            if (!flag)
                form[pwdId].$valid = false;
            else
                form[pwdId].$valid = true;
            if (form[pwdId].$modelValue != form[cnfPwdId].$modelValue)
                form[cnfPwdId].$valid = false;
            else
                form[cnfPwdId].$valid = true;
            if (form[pwdId].$valid && form[cnfPwdId].$valid)
                return true;
            else
                return false;
        }

        function checkPassword(form, pwdId, cnfPwdId) {
            $timeout.cancel(gm.passwordCheckTimeout1);
            $timeout.cancel(gm.passwordCheckTimeout2);
            if (!gm.myPlugin) {
                gm.myPlugin = $("input[id='" + pwdId + "']").password_strength();
            }
            var resp = false;
            gm.passwordCheckTimeout1 = $timeout(function () {
                resp = gm.myPlugin.metReq();
            }, 1500);
            gm.passwordCheckTimeout2 = $timeout(function () {
                gm.isPasswordPolicyMeet(resp, form, pwdId, cnfPwdId);
            }, 1500);
        }

        function registration(model, isRedeem) {
            $scope.global_login = false;
            $scope.signin = false;
            $scope.register = true;
            gm.registering = true;
            gm.saving = false;
            gm.errorMessage = null;
            gm.success = false;
            $(".alertBlock").hide();
            // if (!gm.isPasswordPolicyMeet)
            //     return false;

            gm.model.registerViewModel.NewsLetterSubscribed = gm.model.registerViewModel.notifyByEmail;
            $http.post(globalConfig.register, model)
                .success(function (data) {
                    if (data) {
                        if (!data.isValid != null && typeof data.errorMessages != 'undefined' && data.errorMessages.length > 0) {
                            gm.errorMessage = data.errorMessages;
                            return;
                        }
                        $.cookie('IsUserLoggedIn', true, { path: '/' });
                        if (isRedeem)
                            window.location.href = "/redeem";
                        else {
                            var returnStr = "?returnUrl=";
                            if (window.location.search != null && window.location.search.indexOf(returnStr) > -1) {
                                window.location.href = window.location.search.replace(returnStr, '');
                            }
                            else {
                                window.location.href = "/MyAccount";
                            }
                        }

                    }
                })
                .error(function (msg) {
                    gm.errorMessage = msg.errorMessages;
                })
                .finally(function () {
                    gm.registering = false;
                });
        }

        function setWidgetId(widgetId) {
            gm.widgetId = widgetId;
            vcRecaptchaService.execute(widgetId);
        }

        gm.captchaExpiration = captchaExpiration;

        function captchaExpiration() {
            vcRecaptchaService.reload(gm.widgetId);
            vcRecaptchaService.execute(gm.widgetId);
        }

        function login(model, captchaVerificationEnable, modal = false) {
            var allowuserLogin = true;
            if (captchaVerificationEnable == true) {
                allowuserLogin = false;
                var recapResponse = vcRecaptchaService.getResponse(gm.widgetId);
                if (recapResponse === "" || recapResponse.length == 0) {
                    allowuserLogin = false;
                    alerts.error('Please resolve the captcha and submit!');
                }
                else {
                    allowuserLogin = true;
                    model.captchaResponse = recapResponse;
                }
            }
            if (allowuserLogin) {
                $scope.signin = true;
                gm.signing = true;
                $scope.register = false;
                $scope.global_login = false;
                gm.userLogin(model, modal);
            }
        }

        function globalLogin(model) {
            $scope.signin = false;
            gm.signing = true;
            $scope.register = false;
            $scope.global_login = true;
            gm.userLogin(model);
        }

        function forgotPassword(model) {
            gm.resettingPassword = true;
            $(".alertBlock").hide();
            $http.post(globalConfig.forgotPassword, model)
                .success(function (data) {
                    gm.errorMessage = null;
                    if (data != null) {
                        if (!data.isValid && typeof data.errorMessages != 'undefined' && data.errorMessages.length > 0) {
                            gm.errorMessage = data.errorMessages;
                            return;
                        } else {
                            gm.passwordResetSuccess = true;
                        }
                    }
                })
                .error(function (msg) {
                    gm.errorMessage = msg.errorMessages;
                })
                .finally(function () {
                    gm.resettingPassword = false;
                });
        };

        function registerCompanyRequest(model) {
            if (model.country == undefined)
                model.country = gm.defaultCountry;
            $scope.changeForm.$setSubmitted();
            $scope.registrationAlert = true;
            gm.errorMessage = null;
            $(".alertBlock").fadeIn();
            if (!gm.isPasswordValid)
                return false;
            $http.post(globalConfig.companyRegisterUrl, model)
                .success(function (resp) {
                    if (resp.isValid) {
                        if (resp.message) {
                            gm.accountCreated = true;
                            $('.accountCreated').show(0).delay(3000).hide(0);
                        } else {
                            gm.requestSuccess = true;
                            $('.requestSuccess').show(0).delay(3000).hide(0);
                        }
                        $timeout(function () {
                            window.location.reload();
                        }, 5000);
                    }
                    ;
                })
                .error(function (msg) {
                    gm.errorMessage = msg.errorMessages;
                })
                .finally(function () {
                    $timeout(function () {
                        $(".alertBlock").fadeOut();
                    }, 10000);
                });
        }

        //#region blogs

        function getallblogs(page) {
            location.href = 'GetAllBlogs?currentpage=' + page + ''
        }

        function getallblogsbycategory(page, category) {

            location.href = 'GetBlogByCategory?category=' + category + '&currentpage=' + page + ''
        }

        function getBlogByCategory(id, page) {
            $http.post(globalConfig.getBlogByCategory, { category: id, currentpage: page })
                .success(function (data) {
                    var dataResult = gm.serializedData(data);
                    gm.basketResponse = dataResult;

                })
                .error(function (msg) {
                    // vm.errorMessage = msg.errorMessages;
                })
                .finally(function () {
                    // vm.saving = false;
                    //$("html, body").animate({ scrollTop: 0 }, "slow");
                });


        }

        //function getBlogByCategory(id, page) {

        //    $http.post(globalConfig.getBlogsbyCategory, {category: id, currentpage: page})
        //        .success(function (data) {

        //            gm.blogReponse = data;

        //        })
        //        .error(function (msg) {
        //            // vm.errorMessage = msg.errorMessages;
        //        })
        //        .finally(function () {
        //            // vm.saving = false;
        //            //$("html, body").animate({ scrollTop: 0 }, "slow");
        //        });


        //}

        function initblogs(id) {
            $http.post(globalConfig.getallblogs, { id: id })
                .success(function (data) {

                    gm.blogReponse = data;

                })
                .error(function (msg) {
                    // vm.errorMessage = msg.errorMessages;
                })
                .finally(function () {
                    // vm.saving = false;
                    //$("html, body").animate({ scrollTop: 0 }, "slow");
                });
        }

        //#endregion blogs

        function currencySettings(currencyCode) {
            var data = { currency: currencyCode };
            $http.post(globalConfig.currencySettingUrl, data)
                .success(function () {
                    window.location.reload();
                })
                .error(function (msg) {
                })
                .finally(function () {
                });
        };

        function getPaymentMethods() {
            $http.post(globalConfig.paymentMethodsUrl)
                .success(function (data) {
                    gm.paymentMethods = data;
                })
                .error(function (msg) {
                })
                .finally(function () {
                });
        };

        function newsLetterSubscription(email) {
            gm.emailinvalid = false;
            gm.subssuccess = false;
            var email_regex = /^[_a-z0-9]+(\.[_a-z0-9]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$/;
            if (!email_regex.test(email.toLowerCase())) {
                gm.emailinvalid = true;
                $('.newsletteralert').show(0).delay(2000).hide(0);
            }
            if (email == "" || email == null) {
                gm.emailinvalid = true;
                $('.newsletteralert').show(0).delay(2000).hide(0);
            }
            var model = { email: email, notifyByEmail: true, newsLetterSubscribed: true, sourceProcess: gm.sourceProcess }
            if (gm.emailinvalid == false) {
                $http.post(globalConfig.newsLetterSubscription, { newsletter: model })
                    .success(function (data) {
                        gm.customerEmail = '';
                        if (data == true) {
                            gm.subssuccess = true;
                            $.cookie("NewsLetterSubscribed", email, { path: '/', expires: 1000 });
                            gm.isNewsLetterSubscribed = $.cookie("NewsLetterSubscribed");
                        } else {
                            gm.alreadySubscribed = true;
                            $('.newsletteralready').show(0).delay(2000).hide(0);
                        }
                    })
                    .error(function (msg) {
                        gm.alreadySubscribed = true;
                        $('.newsletteralert').show(0).delay(2000).hide(0);
                    })
                    .finally(function () {

                    });
            }

        }

        function showBasket(value) {
            if (value)
                gm.activeClass = 'active';
            else
                gm.activeClass = '';
        }

        function openQuickBasketModal() {
            $("#AddToBasketModel").modal();
        };

        function nRows(num) {
            return new Array(num);
        }

        //loadPCAScript(scriptLoader, globalConfig.pcaAccessCode)

        function productPrice(isChecked) {
            gm.incVat = (isChecked) ? false : true;
            $.cookie('incVat', gm.incVat, { path: '/' });
        };

        function socialSignIn(provider) {
            //$http.post(globalConfig.socialSignInUrl, {provider: provider}).success(function (data) {

            //});

            var Form = document.createElement('form');
            Form.setAttribute('method', 'post');
            Form.setAttribute('action', '/Account/SocialSignIn');
            var providertag = document.createElement('input');
            providertag.setAttribute('type', 'hidden');
            providertag.setAttribute('name', 'provider');
            providertag.setAttribute('value', provider);
            Form.appendChild(providertag);

            document.getElementsByTagName('body')[0].appendChild(Form);
            Form.submit();
        };

        function getSocialSettings() {
            $http.post("/Account/GetSocialSettings").then(function (success) {
                gm.model.socialSettings = success.data;
            }, function (error) {
            });
        }

        function getBillingCountries() {
            $http.post(globalConfig.getBillingCountriesUrl)
                .success(function (data) {
                    if (data.length > 0) {
                        gm.countries = data;
                    }
                })
                .error(function (msg) {

                })
                .finally(function () {

                });
        }

        function basketDetails(basketId) {
            gm.basketDetailView = true;
            gm.currentBasket = gm.baskets.find(function (basket) {
                return basket.id == basketId
            });
        }

        function hideBasketDetail() {
            gm.basketDetailView = false;
        }

        PubSub.subscribe('addToCart', function (eventData) {
            if (eventData != null && dataLayer && typeof omnilytics != 'undefined' && omnilytics) {
                if (eventData.product != null) {
                    var prod = eventData.product
                    var data = dataLayer[0];
                    var entity = {
                        'basketId': prod.basketId,
                        'name': prod.name,
                        'id': prod.productId,
                        'stockCode': prod.stockCode,
                        'price': prod.price.raw.withTax,
                        'brand': prod.manufacturer,
                        'category': prod.category,
                        'quantity': prod.qty,
                        'img': prod.image
                    };
                    data["entity"] = JSON.stringify(entity);
                    data["entityId"] = prod.productId;
                    data["entityName"] = prod.name;
                    data["entityType"] = "product";
                    data["basketItems"] = JSON.stringify(eventData.basket.lines);
                    data["basketItemCount"] = eventData.basket.lines.length ? eventData.basket.totalItems : 0;
                    data["basketTotal"] = eventData.basket.totalCost;
                    data["tax"] = eventData.basket.tax;
                    dataLayer[0] = data;
                    data["action"] = "addToCart";
                    if (eventData.basket.lines.length == 0 || prod.qty < 1) {
                        data["eventType"] = "basketItemRemoved";
                        omnilytics.emit('basketItemRemoved', null);

                    } else {
                        data["eventType"] = "basketItemAdded";
                        omnilytics.emit('basketItemAdded', null);

                    }


                }
            }
        });
        PubSub.subscribe('registerUser', function (eventData) {
            if (eventData != null && dataLayer && omnilytics && gm.publishPubSub) {
                if (eventData.email != null) {
                    var user = eventData
                    var data = dataLayer[0];
                    var entity = {
                        'email': user.email,
                        'recordId': user.recordId,
                        'notifyNone': user.notifyNone,
                        'notifyBySms': user.notifyBySMS,
                        'notifyEmail': user.notifyByEmail,
                        'notifyPost': user.notifyByPost
                    };
                    data["entity"] = JSON.stringify(entity);
                    data["entityName"] = user.email;
                    data["entityType"] = "customer";
                    data["action"] = "registerUser";
                    data["eventType"] = "customerCreated";
                    omnilytics.emit('customerCreated', null);
                }
            }
            gm.publishPubSub = false;
        });

        function onTextFocus(event) {
            event.target.select();
        }

        function addQuoteToBasket(id, action) {
            if (gm.basketResponse != null && gm.basketResponse.lineItems.length != 0) {
                $("#quoteDetailModal").modal("hide");
                $("#mergeBasketModal").modal();
                return;
            }
            gm.basketAction(id, action);
        }

        function basketAction(quoteId, action) {
            $http.post(globalConfig.addQuoteToBasketUrl, { basketId: quoteId, basketAction: action })
                .success(function (data) {
                    var dataResult = gm.serializedData(data);
                    gm.basketResponse = dataResult;
                    $("#quoteDetailModal").modal("hide");
                    $("#mergeBasketModal").modal("hide");
                    if (gm.basketResponse != null && gm.basketResponse != undefined) {
                        gm.count = gm.basketResponse.lineItemCount;
                        var scroll = $(window).scrollTop();
                        if (scroll >= 200) {
                            $("#miniBasket").addClass("fix-to-top");
                        } else {
                            $("#miniBasket").removeClass("fix-to-top");
                        }
                        $('.cartopen').addClass('active');
                        $timeout(function () {
                            $(".cartopen").removeClass("active");
                            $("#miniBasket").removeClass("fix-to-top");
                        }, 10000);
                    }
                }).finally(function () {
                });
        }

        function removeQuoteBasket() {
            $http.post(globalConfig.removeQuoteBasketUrl)
                .success(function (resp) {
                    location.reload();
                });
        }

        function serializedData(data) {
            if (data != null) {
                if (data.lineItems != null) {
                    angular.forEach(data.lineItems, function (line) {
                        if (isJSON(line.customInfo2)) {
                            line.customInfo2 = JSON.parse(line.customInfo2);
                            line.parentProductId = line.customInfo2.ParentProductId;
                        }
                    });
                }
            }
            return data;
        }

        function formReset(form) {
            if (form) {
                form.$setPristine();
                form.$setUntouched();
            }
        }

        function initLookbooks(data) {
            gm.model = data;
            gm.allLooks = angular.copy(data);
        }

        function fetchLookbookByGroup() {
            if (gm.selectedGroup != undefined && gm.selectedGroup != '' && gm.selectedGroup != null) {
                if (gm.selectedGroup == "All") {
                    gm.model.DynamicLists = gm.allLooks.DynamicLists;
                } else {
                    //gm.model.DynamicLists = gm.allLooks.DynamicLists.filter(i => i.DisplayGroupName == gm.selectedGroup);
                    angular.forEach(gm.allLooks.DynamicLists, function (list) {
                        if (list.DisplayGroupName == gm.selectedGroup) {
                            gm.model.DynamicLists.push(list);
                        }
                    });
                }

            }

        }

        function updateBasketQty(productId, newQty, oldQty, displayOrder) {
            gm.updateQty = 0;
            if (newQty == oldQty || !oldQty) {
                return gm.basketResponse;
            } else {
                if (newQty > oldQty) {
                    gm.updateQty = newQty - oldQty;
                } else {
                    gm.updateQty = -(oldQty - newQty);
                }
                gm.addToBasket(productId, gm.updateQty, displayOrder);
            }
        }

        function getRecommendations() {
            Recommendation.getRecommendation().then(function (resp) {
                if (resp) {
                    gm.recomendations.products = resp;
                    $("#bubbleOption").modal();
                }
            });
        }

        function getAllcurrencyandCountries() {
            $http.post(globalConfig.getAllcurrencySetting)
                .success(function (data) {
                    if (data) {
                        gm.currencies = data.currencies;
                        gm.countries = data.countries;
                    }
                })
                .error(function (msg) {
                })
                .finally(function () {
                });
        };

        function openGiftModal() {
            $(".gift-wrap-itm input.greetingCardsItems").prop("checked", false);
            $(".gift-wrap-modal .step-1").show();
            $(".gift-wrap-modal .step-2").hide();
            $(".personalise-ribbon").show();
            $(".gift-wrap-modal .step-3").hide();
            $(".gift-wrap-modal .step-1 button").text("Continue");

            // Enabled button toggle
            $(".gift-wrap-modal .inr .step-1 .btn-primary").attr("disabled", "disabled").css({ "background-color": "#CCC", "border-color": "#CCC" });
            $(".gift-wrap-modal .gift-wrap-itm input").click(function () {
                if ($(this).is(":checked")) {
                    $(".customise-modal .inr .step-1 .btn-primary").removeAttr("disabled").css({ "background-color": "#1d1258", "border-color": "#1d1258" });
                }
            });

            // Clear ribbon info
            $scope.tsCsChecked = false;
            $scope.personaliseRibbon = "";

            $(".tfs-lds-ring").hide();
            //if (isSelected) {
            $(".gift-wrap-modal").show();
            $(".gift-wrap-modal .close-personalisation").click(function (e) {
                $(".gift-wrap-modal .step-3").hide();
                $(".gift-wrap-modal .personalise-ribbon").show();
                $(".gift-wrap-modal .step-2 button").show();
            });
            $(".gift-wrap-modal .ts-cs a").click(function (e) {
                e.preventDefault();
                $(".gift-wrap-modal .close").hide();
                $(".gift-wrap-modal .step-2").hide();
                $(".gift-wrap-modal .ts-cs-overlay").show();
                $(".ts-cs-overlay .close-ts-cs").click(function () {
                    $(".ts-cs-overlay").hide();
                    $(".gift-wrap-modal .step-2").show();
                    $(".gift-wrap-modal .close").show();
                });
            });
            //}
        }

        // Back gift wrap modal
        function backGiftWrapModal() {
            $(".gift-wrap-modal .step-1").show();
            $(".gift-wrap-modal .step-2").hide();
            gm.addGiftButtonClicked = false;
        }

        // Close gift wrap modal
        function closeGiftWrapModal() {
            $(".gift-wrap-modal").hide();
            $('input#gifts').prop('checked', false);
            $("html").css("overflow-y", "auto");
            $(".gift-wrap-modal .step-1").show();
            $(".gift-wrap-modal .step-2").hide();
            //$(".greeting-card-modal .gift-wrap-itm").remove();
        }

        function editGiftModal() {

        }

        function saveRibbon() {

        }

        function extractSubscription() {
            if (gm.basketResponse != null && gm.basketResponse != undefined && gm.basketResponse.lineItems.length > 0) {
                //extract subscription plan
                var subscriptionItem = '';
                //var subscriptionItem = gm.basketResponse.lineItems.find(i => i.subscriptionUserSettings.subscriptionPlanId != gm.emptyGuid);
                angular.forEach(gm.basketResponse.lineItems, function (item) {
                    if (item.subscriptionUserSettings.subscriptionPlanId != gm.emptyGuid) {
                        subscriptionItem = item;
                    }
                });
                if (subscriptionItem != undefined && subscriptionItem != null && subscriptionItem != '') {
                    gm.subscriptionPlan = JSON.parse(subscriptionItem.subscriptionUserSettings.subscriptionJson);
                    var subscriptionItems = [];
                    if (gm.basketResponse != null && gm.basketResponse != undefined && gm.basketResponse.lineItems.length > 0) {
                        angular.forEach(gm.basketResponse.lineItems, function (item) {
                            if (item.subscriptionUserSettings.subscriptionPlanId == gm.subscriptionPlan.RecordId) {
                                subscriptionItems.push(item);
                            }
                        });
                    }
                    //sort items by thier display order.
                    var sortedItems = subscriptionItems.sort(function (i, j) {
                        return i.displayOrder - j.displayOrder
                    });
                    gm.subscriptionItems = sortedItems;
                } else {
                    gm.subscriptionItems = [];
                }
            } else {
                gm.subscriptionItems = [];
            }

        }


        //Personalisation Section Starts
        function applyPersonalisation(product) {
            gm.engravingSubmitInProgress = true;
            if (product != null && product != undefined) {
                var basketId = '';
                if (gm.basketResponse)
                    basketId = gm.basketResponse.id;
                var engravingModel = {
                    basketId: basketId,
                    productId: product.recordId,
                    stockCode: product.stockCode,
                    Qty: 1,
                    engravingProductId: product.engravingAttributes.productId,
                    engravingStockCode: product.engravingAttributes.stockCode,
                    engravingLines: gm.engravingMsg,
                    engravingColour: gm.engravingColour,
                    engravingAttributes: product.engravingAttributes
                };
                $http.post("/TFSBasket/ApplyPersonalisation", { model: engravingModel }).then(function (success) {
                    if (success != null && success.data != null) {
                        savePersonalisationInfo(success.data, engravingModel);
                    } else {
                        gm.engravingSubmitInProgress = false;
                    }
                }, function (error) {
                    gm.engravingSubmitInProgress = false;
                });
            }
        }

        function savePersonalisationInfo(data, model) {
            if (data) {
                var engravingLineItem = data.result.lineItems.filter(function (itm) {
                    return (itm.parentProductId.toLowerCase() === model.productId.toLowerCase() && itm.productId.toLowerCase() === model.engravingProductId.toLowerCase());
                });
                if (engravingLineItem && engravingLineItem.length > 0) {
                    $http.post("/TFSBasket/SavePersonalisationInfo",
                        {
                            basketId: data.result.id,
                            basketLineModel: engravingLineItem[0],
                            model: model
                        }).then(function (success) {
                            $("#Engraving").modal('hide');
                            //assign updated basket. 
                            updateBasket(success.data);
                            //redirect to offer page
                            redirectToOffers(model.productId, false);
                        },
                            function (error) {
                                gm.basketResponse = data.result;
                                gm.engravingProduct = data.result.lineItems.find(e => e.productId.toLowerCase() === model.productId.toLowerCase());
                                //engraving couldn't be saved. Remove from basket
                                gm.addToBasket(gm.engravingProduct.productId, 0, gm.engravingProduct.displayOrder);
                            });
                } else {
                    gm.basketResponse = data.result;
                    gm.engravingProduct = data.result.lineItems.find(e => e.productId.toLowerCase() === model.productId.toLowerCase());
                    gm.addToBasket(gm.engravingProduct.productId, 0, gm.engravingProduct.displayOrder);
                }
            }
        }

        function engravingFiledActions() {
            $('#Engraving').modal('hide');
            $('#engraving-failed').modal('show').on('hide.bs.modal', function () {
                $("#engraving-failed").off('hide.bs.modal');
                // engraving failed modal closed
                if (gm.engravingFailedAction === 'again') { // user wants to try again
                    $('#Engraving').modal('show');
                    gm.engravingFailedAction = 'remove';
                } else if (gm.engravingFailedAction === 'continue') { // user wants to continue without engraving
                    gm.addToBasket(gm.engravingProduct.productId, 1, 0);
                } else { //none of the above. Close the modal and cancel engraving
                    gm.engravingProduct = null;
                }
                gm.engravingSubmitInProgress = false;
            });
        }


        function closeEngravingFailedModal() {
            $('#engraving-failed').modal('hide');
        }

        function range(length) {
            if (length > 0) {
                return new Array(length);
            }
        }

        function editPersonalisation(item) {
            if (item.customInfo1 != null && item.customInfo1 != undefined && item.customInfo1 != '') {
                var isValid = true;
                var regex = new RegExp(REGEX_CONSTANTS.LETTERS_AND_NUMBERS_ONLY);
                angular.forEach(item.customInfo1.personalisation, function (lines) {
                    if (!regex.test(lines.lines.join(''))) {
                        isValid = false;
                    }
                });
                if (isValid) {
                    var model = {
                        basketId: gm.basketResponse.id,
                        LineInfo: [{
                            productId: item.productId,
                            parentProductId: item.parentProductId,
                            stockCode: item.stockCode,
                            customInfo1: JSON.stringify(item.customInfo1)
                        }]
                    }
                    $http.post("/TFSBasket/UpdatePersonalisationInfo", { customInfo: model }).then(function (success) {
                        updateBasket(success.data);
                        gm.editMsg = false;
                    }, function (error) {
                    });
                } else {
                    gm.regexError = true;
                    $timeout(function () {
                        gm.regexError = false;
                    }, 10000);
                }


            }
        }


        //Engraving Section End

        function updateBasket(data) {

            if (data.messageCode == 'C002' && !gm.isProductExist)
                gm.errorMessage = data.message;
            var giftWrapOption = gm.basketResponse ? gm.basketResponse.giftWrapOption : null;
            var greetingCardOption = gm.basketResponse ? gm.basketResponse.greetingCardOption : null;

            //check if we already have memebrship benefits availabe. reuse them if we do
            let currentBenefits = null;
            if (gm.basketResponse != null && gm.basketResponse.membershipBenefits != null && gm.basketResponse.membershipBenefits.length > 0) {
                currentBenefits = gm.basketResponse.membershipBenefits;
            }

            gm.basketResponse = data.result;
            //reasign benefits
            gm.basketResponse.membershipBenefits = currentBenefits;

            //reset giftwarp options
            if (giftWrapOption && data.result.giftWrapOption === null) {
                gm.basketResponse.giftWrapOption = giftWrapOption;
            }
            //reset greetingcard options
            if (greetingCardOption && data.result.greetingCardOption === null) {
                gm.basketResponse.greetingCardOption = greetingCardOption;
            }
            //var count = 0;
            if (gm.basketResponse != null) {
                if (gm.basketResponse.membershipBenefits != null && gm.basketResponse.membershipBenefits.length > 0 && gm.basketResponse.subTotal != null) {
                    gm.membershipDiscountAmt = gm.selectedCurrencySymbol + ((gm.basketResponse.membershipBenefits[0].discountPct / 100) * gm.basketResponse.subTotal.raw.withTax).toFixed(2);
                }
                if (gm.basketResponse.lineItems != null) {
                    //var eventData = { product: {}, basket: { id: null, lines: [], totalCost: null, totalItems: null, tax: null } };
                    //eventData.id = gm.basketResponse.id;
                    //eventData.basket.totalItems = gm.basketResponse.lineItemCount;
                    //eventData.basket.totalCost = gm.basketResponse.subTotal.raw.withoutTax;
                    //eventData.basket.tax = gm.basketResponse.grandTotal.raw.tax;
                    angular.forEach(gm.basketResponse.lineItems, function (line) {
                        //var li = { id: line.id, basketId: gm.basketResponse.id, stockCode: line.stockCode, name: line.name, qty: line.qty, price: line.price.raw.withoutTax, tax: line.price.raw.tax, manufacturer: line.Manufacture, 'img': line.image };
                        //eventData.basket.lines.push(li);
                        //if (line.parentProductId == gm.emptyGuid) {
                        //    count = count + line.qty;
                        //}
                        if (line.isGiftWrapApplied) {
                            line.giftWrappingInfo = [];
                            //line.giftWrappingInfo = gm.basketResponse.giftWrapOption.filter(x => x.id == line.giftWrapId.toUpperCase());
                            angular.forEach(gm.basketResponse.giftWrapOption, function (opt) {
                                if (opt.id.toUpperCase() == line.giftWrapId.toUpperCase()) {
                                    line.giftWrappingInfo.push(opt);
                                }
                            });
                        }
                        if (line.isGreetingCardApplied) {
                            line.greetingCardInfo = [];
                            //line.greetingCardInfo = gm.basketResponse.greetingCardOption.filter(x => x.id == line.greetingCardId.toUpperCase());
                            angular.forEach(gm.basketResponse.greetingCardOption, function (opt) {
                                if (opt.id.toUpperCase() == line.greetingCardId.toUpperCase()) {
                                    line.greetingCardInfo.push(opt);
                                }
                            });
                        }
                        line.updatedqty = line.qty;
                        //var json = eval('(' + line.attributesJson + ')');
                        //line.slug = json.Slug;
                        //if (line.productId.toLowerCase() == prod.productId.toLowerCase()) {
                        //    var prodDetail = angular.copy(line);
                        //    prodDetail.qty = qty /// set the actual qty that was requested to be aded instead of final  item qty
                        //    prodDetail.basketId = basketId;
                        //    //eventData.product = prodDetail;
                        //}

                    });
                    extractCustomInfo(gm.basketResponse);
                    extractSubscription();
                    initGreetingCards();
                    initRibbons();
                    membershipDiscountPrice();

                    if (isShipFromStoreEnabled() && gm.count > 0) {
                        //add shipfromstore prop
                        lineItemsAddPropShipFromStore();
                    }
                }
                gm.count = gm.basketResponse.lineItemCount;
                if (gm.count > 0) {
                    $(".basketItemCount").removeClass('tfs-bag-badge-hidden').html(gm.count);
                } else {
                    $(".basketItemCount").addClass('tfs-bag-badge-hidden').html(0);
                }

                //paypal messaging refresh
                renderPaypalMessaging();

                //clearpay messaging render
                renderClearpayMessaging();

                //zip messaging
                renderZipMessaging((gm.basketResponse && gm.basketResponse.totalWithoutShipping) ? gm.basketResponse.totalWithoutShipping.raw.withTax : 0);

                //update the min basket badge dynamically
                //var basketCountElem = document.getElementById('headerBasketCountBadge');
                //if (basketCountElem != null && basketCountElem != undefined) {
                // document.getElementById('headerBasketCountBadge').innerHTML = gm.count;
                // }

                //window.setTimeout(function () { imgix.init({ force: true }); }, 1000);
            }
            window.setTimeout(function () {
                gm.errorMessage = null;
            }, 10000);

            if (true) {
                var scroll = $(window).scrollTop();
                if (scroll >= 200) {
                    $("#miniBasket").addClass("fix-to-top");
                } else {
                    $('.cartopen').addClass('active');
                    $("#miniBasket").removeClass("fix-to-top");
                }
                //$("html, body").animate({ scrollTop: 0 }, "slow");
                $('.cartopen').addClass('active');
                $timeout(function () {
                    $(".cartopen").removeClass("active");
                }, 10000);
            }
            //PubSub.publish("addToCart", eventData);

        }

        function updateBasketBadgeCount() {
            if (gm.basketResponse != null && gm.basketResponse != undefined) {
                if (gm.basketResponse.lineItemCount > 0) {
                    $(".basketItemCount").removeClass('tfs-bag-badge-hidden').html(gm.basketResponse.lineItemCount);
                } else {
                    $(".basketItemCount").addClass('tfs-bag-badge-hidden').html(0);
                }
            }

        }

        //Method to Remove Engraving
        function removePersonalisation(product, index) {
            if (product != null) {
                gm.qtyToRemove = 0;
                if (product.qty > 1 && product.customInfo1 != null) {
                    gm.qtyToRemove = -1;
                    product.customInfo1.personalisation.splice(index, 1);
                }
                var basketModel = {
                    basketId: gm.basketResponse.id,
                    productId: product.productId.toLowerCase(),
                    stockCode: product.stockCode,
                    qty: gm.qtyToRemove,
                    parentProductId: product.parentProductId.toLowerCase(),
                    itemType: product.itemType,
                    customInfo1: JSON.stringify(product.customInfo1)
                }
                $http.post(globalConfig.removePersonalisation, { model: basketModel }).then(function (success) {
                    if (success != null && success.data != null)
                        removePersonalisationInfo(success.data.result.id, basketModel)
                }, function (error) {
                });
            }
        }

        function removePersonalisationInfo(basketId, model) {
            if (basketId != null && model != null) {
                $http.post("/TFSBasket/RemovePersonalisationInfo", {
                    basketId: basketId,
                    model: model
                }).then(function (success) {
                    updateBasket(success.data);
                    gm.editMsg = false;
                }, function (error) {
                });
            }
        }

        //Add gift warpping
        function addGiftWrap(selectedGiftOption) {
            if (!gm.addGiftButtonClicked && selectedGiftOption != null && Object.keys(selectedGiftOption) != 0) {
                if (gm.addonsActionPending) return;
                gm.addonsActionPending = true;
                $(".gift-wrap-modal .inr").append("<div class='tfs-lds-ring'><div></div><div></div><div></div><div></div></div>");
                gm.addGiftButtonClicked = true;
                var model = {
                    basketId: gm.basketResponse.id,
                    productId: selectedGiftOption.productId,
                    stockCode: selectedGiftOption.stockCode,
                    Qty: 1,
                    isGiftWrapApplied: true,
                    giftWrapId: selectedGiftOption.id,
                    parentProductId: gm.selectedLineItem.productId,
                };
                $http.post("/Basket/AddGiftWrap", { model: model }).then(function (success) {
                    gm.selectedGiftWrapOption = {};
                    //assign updated basket. 
                    updateBasket(success.data);
                    gm.addGiftButtonClicked = false;
                    gm.addonsActionPending = false;
                    gm.currencyCookie = $.cookie(CURRENCYCOOKIE.CurrencyCode);
                    gm.changeBaseCurrency(gm.currencyCookie, false);
                    if ($scope.personaliseRibbon.length === 0) {
                        $(".gift-wrap-modal").hide();
                        $(".gift-wrap-modal .inr .tfs-lds-ring").remove();
                    }

                    // add ribbon after gift wrap
                    gm.selectedLineItem.giftWrapId = selectedGiftOption.id;
                    gm.selectedLineItem.isGiftWrapApplied = true;
                    if ($scope.personaliseRibbon.length > 0) {
                        //set seletced ribbon to correct option based on gift wrap
                        const relatedRibbon = findRelatedRibbon(selectedGiftOption.productId);
                        if (!relatedRibbon) {
                            //couldn't find related ribbon
                            //show error
                            return false;
                        };
                        addRibbon(relatedRibbon);
                    }
                }, function (error) {
                    gm.closeGiftWrapModal();
                    gm.giftWrapError = true;
                    gm.addGiftButtonClicked = false;
                    gm.addonsActionPending = false;
                });
            } else {
                gm.giftWrapError = true;
                gm.addGiftButtonClicked = false;
                gm.addonsActionPending = false;
                $timeout(function () {
                    gm.giftWrapError = false;
                }, 10000);
            }
        }

        function giftWrapRibbonPrice(giftWrap) {
            let price = giftWrap.price.raw.withTax;
            const ribbon = getAppliedRibbon(giftWrap.parentProductId);
            //we need to check if the ribbon is applied or not
            //if ribbon is not return just the gift wrap price
            if (!ribbon) return numberToFixed(price);
            //we have a ribbon and need to return it's price added to gift wrap
            price = giftWrap.price.raw.withTax + ribbon.price.raw.withTax;
            return numberToFixed(price);
        }

        function numberToFixed(number) {
            if (typeof number !== 'number') return 0.00;
            return Number(number).toFixed(2);
        }

        function getAppliedRibbon(giftWrapParentProductId) {
            const lineItems = gm.basketResponse['lineItems'];
            if (lineItems.length === 0) return false;
            //find the ribbon wiht the same parentProductId & customInfo3.text property
            const ribbon = lineItems.find(o => o['parentProductId'].toLowerCase() === giftWrapParentProductId.toLowerCase() && o['customInfo3'].hasOwnProperty('text'));
            //return true if we have the ribbon
            if (!ribbon) return null;
            return ribbon;
        }

        function findRelatedRibbon(giftWrapProductId) {
            return gm.ribbbonOptions.find(option => {
                if (option['relatedProducts'].length === 0) return false;
                //we need to check for each ralated product to find the correct match
                return option['relatedProducts'].find(p => {
                    return p['productId'].toLowerCase() === giftWrapProductId.toLowerCase();
                });
            });
        }

        function addGiftWrapSelected(selectedGiftWrap) {
            gm.selectedGiftWrapOption = selectedGiftWrap;
            const relatedRibbon = findRelatedRibbon(selectedGiftWrap.productId);
            if (!relatedRibbon) {
                $(".gift-wrap-modal .step-1 button").text("Add gift wrap");
            } else {
                $(".gift-wrap-modal .step-1 button").text("Continue");
            }
        }

        //Add personalised ribbon
        function addPersonalisedRibbon(selectedGiftOption) {
            const relatedRibbon = findRelatedRibbon(selectedGiftOption.productId);
            if (!relatedRibbon) {
                //couldn't find related ribbon
                //show error
                addGiftWrap(selectedGiftOption);
            } else {
                $(".gift-wrap-modal .step-1").hide();
                $(".gift-wrap-modal .step-2").show();
                gm.selectedRibbonOption = relatedRibbon;
            }

            /* $.ajax({
                url: "/basket/get-ribbons",
                type: "GET",
                beforeSend: function (xhr) {
                    $(".greeting-card-modal .inr").append("<div class='loading-overlay'><img src='/assets/theme/tfs/images/loader.svg' /></div>")
                },
                success: function (data) {
                    $scope.$apply(function () {
                        data = JSON.parse(data);
                        $(".loading-overlay").remove();
                    });
                },
                complete: function () {
                },
                dataType: "html"
            }); */
        }

        function addPersonalisedRibbonForm() {
            $(".gift-wrap-modal .step-3").show();
            $(".gift-wrap-modal .step-2 button").hide();
            $(".gift-wrap-modal .step-2 .step-3 button").show();
            $(".gift-wrap-modal .personalise-ribbon").hide();
        }

        //Remove gift wrapping
        function removeGiftWrap(selectedGiftOption) {
            if (selectedGiftOption != null) {
                let loaderDiv = "<div class='tfs-lds-ring'><div></div><div></div><div></div><div></div></div>";
                gm.apiPendingTfs = true;
                var model = {
                    basketId: gm.basketResponse.id,
                    productId: selectedGiftOption.productId,
                    stockCode: selectedGiftOption.stockCode,
                    Qty: 0,
                    isGiftWrapApplied: false,
                    giftWrapId: selectedGiftOption.id,
                    parentProductId: gm.selectedLineItem.productId,
                    itemType: selectedGiftOption.itemType
                }
                $http.post("/Basket/RemoveGiftWrap", { model: model }).then(function (success) {
                    $("#giftChoose").modal('hide');
                    gm.apiPendingTfs = false;
                    gm.selectedGiftWrapOption = {};
                    //assign updated basket.
                    updateBasket(success.data);
                    gm.currencyCookie = $.cookie(CURRENCYCOOKIE.CurrencyCode);
                    gm.changeBaseCurrency(gm.currencyCookie, false);
                    isGiftWrapApplied: false;
                    //$(".ribbon-info").addClass("hidden");
                    // Show in basket
                    $(".gift-wrap-modal .step-1").show();
                    $(".gift-wrap-modal .step-2").hide();

                    gm.selectedLineItem.giftWrapId = gm.emptyGuid;
                    gm.selectedLineItem.isGiftWrapApplied = false;

                    //set seletced ribbon to correct option based on gift wrap
                    const relatedRibbon = findRelatedRibbon(selectedGiftOption.productId);
                    if (!relatedRibbon) {
                        //couldn't find related ribbon
                        //show error
                        return false;
                    };

                    removeRibbon(relatedRibbon);
                }, function (error) {
                    gm.apiPendingTfs = false;
                });
            } else {
                //give error msg.
            }
        }

        //Handle closed gift dialog when no options were selected
        function checkGiftWrap() {
            if (gm.addGiftButtonClicked === false) {
                $scope.$apply(function () {
                    angular.forEach(gm.basketResponse.lineItems, function (line) {
                        line.giftWrappingInfo = [];
                        angular.forEach(gm.basketResponse.giftWrapOption, function (opt) {
                            if (opt.id.toUpperCase() == line.giftWrapId.toUpperCase()) {
                                line.giftWrappingInfo.push(opt);
                            }
                        });
                        line.updatedqty = line.qty;
                        line.isGiftWrapApplied = line.giftWrappingInfo.length > 0;
                    });
                });
            }
        }

        function unsubscribedNewsletter() {
            $http.post(globalConfig.unsubscribeNewsletter)
                .success(function (data) {
                    gm.errorMessage = null;
                    gm.isValid = data.isValid;
                    gm.isValiduser = !data.isValid;
                    gm.unsubssuccess = true;
                    $('.newsletterunsuccess').show(0).delay(2000).hide(0);
                    $timeout(function () {
                        gm.isValiduser = false;
                        gm.isValid = false;
                        window.location.reload();
                    }, 3000);
                })
                .error(function (msg) {
                    gm.errorMessage = msg.errorMessages;
                    $timeout(function () {
                        gm.isValiduser = false;
                        $(".alertBlock").fadeOut();
                    }, 2000);
                })
                .finally(function () {
                });
        };
        gm.showChangedCurrency = false;
        function changeBaseCurrency(changeToCurrencyCode, doReload) {
            if (changeToCurrencyCode == null) {
                changeToCurrencyCode = $.cookie(CURRENCYCOOKIE.CurrencyCode);
            }
            if (changeToCurrencyCode) {
                $http.get('/Home/GetCurrencyExchangeRate' + "?changeToCurrencyCode=" + changeToCurrencyCode).then(function (resp) {
                    if (resp != null && resp.data != false && resp.data.rate != 1) {
                        gm.showChangedCurrency = true;
                        gm.selectedCurrencySymbol = resp.data.currencySymbol;
                        gm.defaultCurrency = resp.data.currencySymbol;
                        gm.currencyExchangeRate = resp.data.resp;

                        // Discount amount if not a member/logged in
                        if (gm.basketResponse.membershipBenefits == null) {
                            gm.membershipDiscountAmt = gm.selectedCurrencySymbol + ((gm.basketResponse.subTotal.raw.withTax / 100) * 20 * resp.data.rate).toFixed(2);
                        }

                        // Saving amount if active membership
                        if (gm.basketResponse != null && gm.basketResponse.membershipBenefits != null && gm.basketResponse.membershipBenefits.length > 0) {
                            var membershipProductAmount = 0;
                            angular.forEach(gm.basketResponse.lineItems, function (line) {
                                if (line.isMembership)
                                    membershipProductAmount = membershipProductAmount + line.price.raw.withTax;
                            });
                            gm.membershipDiscountAmt = gm.selectedCurrencySymbol + ((gm.basketResponse.membershipBenefits[0].discountPct / 100) * (gm.basketResponse.subTotal.raw.withTax - membershipProductAmount) * resp.data.rate).toFixed(2);
                        }

                        // Saving amount on Membership landing page
                        gm.potentialSavings = gm.selectedCurrencySymbol + (gm.basketResponse.grandTotal.raw.withTax * 0.2 * resp.data.rate).toFixed(2);

                        if (gm.basketResponse != null && gm.basketResponse.lineItems) {
                            angular.forEach(gm.basketResponse.lineItems, function (item) {
                                item.currencyExchangedPriceRaw = item.price.raw.withTax * resp.data.rate;
                                item.currencyExchangedPriceFormatted = gm.selectedCurrencySymbol + item.currencyExchangedPriceRaw.toFixed(2);
                                if (item.isGiftWrapApplied && item.giftWrappingInfo.length > 0)
                                    item.currencyExchangedItemGiftWrapPrice = gm.selectedCurrencySymbol + (item.giftWrappingInfo[0].price.raw.withoutTax * resp.data.rate).toFixed(2);
                                if (item.isGreetingCardApplied && item.greetingCardInfo.length > 0)
                                    item.currencyExchangedItemGreetingCardPrice = gm.selectedCurrencySymbol + (item.greetingCardInfo[0].price.raw.withoutTax * resp.data.rate).toFixed(2);
                            });
                            angular.forEach(gm.basketResponse.promotionsApplied, function (promo) {
                                promo.currencyExchangedDiscountAmt = gm.selectedCurrencySymbol + (promo.discountAmt.raw.withoutTax * resp.data.rate).toFixed(2);
                            });
                            if (gm.basketResponse.giftWrapOption) {
                                angular.forEach(gm.basketResponse.giftWrapOption, function (gift) {
                                    gift.currencyExchangeGiftWrapPrice = gm.selectedCurrencySymbol + (gift.price.raw.withoutTax * resp.data.rate).toFixed(2);
                                });
                            }
                            if (gm.basketResponse.greetingCardOption) {
                                angular.forEach(gm.basketResponse.greetingCardption, function (card) {
                                    card.currencyExchangeGreetingCardPrice = gm.selectedCurrencySymbol + (card.price.raw.withoutTax * resp.data.rate).toFixed(2);
                                });
                            }
                            gm.currencyExchangedSubtotalFormatted = gm.selectedCurrencySymbol + (gm.basketResponse.subTotal.raw.withTax * resp.data.rate).toFixed(2);
                            gm.currencyExchangedtotalWithoutShippingFormatted = gm.selectedCurrencySymbol + (gm.basketResponse.totalWithoutShipping.raw.withTax * resp.data.rate).toFixed(2);
                        }
                    }
                    else
                        gm.showChangedCurrency = false;
                    if (changeToCurrencyCode != $.cookie(CURRENCYCOOKIE.CurrencyCode)) {
                        $.cookie("_ctcc", changeToCurrencyCode, { path: '/', expires: 1000 });
                    }
                    if (doReload) {
                        window.location.reload();
                    }
                }, function (error) {
                });
            }
        };
        function showCurrencyPopUp() {
            $("#currency-modal").modal();
        }

        function setCookie(cookieName, value) {
            var now = new Date();
            var exp = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1);
            $.cookie(cookieName, value, { path: '/', expires: exp });
        }
        function addSampleLookbookToCart(data) {
            var isAlreadyExistInBasket = false;
            $http.post(globalConfig.bulkAddproduct, data)
                .success(function (data) {
                    var dataResult = gm.serializedData(data.result);
                    if (data.messageCode == 'C002') {
                        gm.errorMessage = data.message;
                        $('.alert').show(0).delay(4000).hide(0);
                    }
                    gm.basketResponse = dataResult;
                    PubSub.publish("addToCartBulk", gm.basketResponse);
                    var count = 0;
                    if (gm.basketResponse != null) {
                        if (gm.basketResponse.lineItems != null) {
                            angular.forEach(gm.basketResponse.lineItems, function (line) {
                                if (line.parentProductId == gm.emptyGuid) {
                                    count = count + line.qty;
                                }
                                var json = eval('(' + line.attributesJson + ')');
                                line.slug = json.Slug;
                                isAlreadyExistInBasket = false;
                            });
                            gm.count = gm.basketResponse.lineItemCount;
                        }
                    }
                    redirectToOffers(gm.basketResponse.id, isAlreadyExistInBasket);
                }).error(function () {
                    gm.wrongFormatMessage = true;
                    $('.wrongFormatError').show(0).delay(3000).hide(0);
                });
        }

        gm.hasMembership = globalConfig.hasMembership;
        function initMembershipPlans(data) {
            gm.membershipList = data;
            // harcode the number of vouchers per Tier :-(
            // TODO: this need to be populated from the API!!!
            angular.forEach(gm.membershipList, function (benefit) {
                if (benefit['stockCode'] === "53241") {
                    benefit['voucherCount'] = 3;
                    benefit['voucherImg'] = "https://the-fragrance-shop.imgix.net/UX/content/membership/my-tfs-logo-sparkle.svg";
                }
                if (benefit['stockCode'] === "53221") {
                    benefit['voucherCount'] = 5;
                    benefit['voucherImg'] = "https://the-fragrance-shop.imgix.net/UX/content/membership/my-tfs-plus-logo-sparkle.svg";
                }
                if (benefit['stockCode'] === "53222") {
                    benefit['voucherCount'] = "UNLIMITED";
                    benefit['voucherImg'] = "https://the-fragrance-shop.imgix.net/UX/content/membership/my-tfs-family-logo-sparkle.svg";
                }
            });
        }

        gm.unClaimedMembershipVouchers = [];
        gm.membershipDiscountAmt = 0;
        gm.membershipDiscountPercentage = 0;
        function getUnClaimedVouchers() {
            gm.checkVoucherApplied();
            if (gm.basketResponse != null && gm.basketResponse.membershipBenefits != null && gm.basketResponse.membershipBenefits.length > 0) {
                angular.forEach(gm.basketResponse.membershipBenefits, function (benefit) {
                    if (
                        (typeof benefit.status === 'string' && benefit.status.toLowerCase() == VOUCHERSTATUS.UNCLAIMED.toLowerCase()) ||
                        (typeof benefit.status === 'string' && benefit.status.toLowerCase() == VOUCHERSTATUS.IN_TRANSITION.toLowerCase() && gm.basketResponse.isMembershipUpgrade)
                    ) {
                        gm.unClaimedMembershipVouchers.push(benefit);
                    }
                    if (benefit.voucher.toLowerCase() == gm.deletedPromoCode.toLowerCase()) {
                        gm.membershipVoucherApplied = false;
                        gm.unClaimedMembershipVouchers.push(benefit);
                    }
                });

                gm.deletedPromoCode = '';
                gm.activeMemebershipPlanId = angular.copy(gm.basketResponse.membershipBenefits[0].siteUserMembershipId);
                var membershipProductAmount = 0;
                angular.forEach(gm.basketResponse.lineItems, function (line) {
                    if (line.isMembership)
                        membershipProductAmount = membershipProductAmount + line.price.raw.withTax;
                });
                gm.selectedCurrencySymbol = "£";
                gm.membershipDiscountAmt = gm.selectedCurrencySymbol + ((gm.basketResponse.membershipBenefits[0].discountPct / 100) * (gm.basketResponse.subTotal.raw.withTax - membershipProductAmount)).toFixed(2);
                gm.membershipDiscountPercentage = gm.basketResponse.membershipBenefits[0].discountPct;
            }
        }

        gm.isMembershipUpgradeAvailable = isMembershipUpgradeAvailable;
        function isMembershipUpgradeAvailable() {
            if (typeof enableMembershipUpgrade !== 'undefined' && enableMembershipUpgrade === false) return false;
            if (gm.basketContainsMembership) return false;
            if (gm.membershipUpgradeOptions.length === 0) return false;
            return true;
        }

        gm.isMembershipUpgradeAllowed = isMembershipUpgradeAllowed;
        function isMembershipUpgradeAllowed() {
            if (typeof enableMembershipUpgrade !== 'undefined' && enableMembershipUpgrade === false) return false;
            if (gm.membershipUpgradeOptions.length === 0) return false;
            return true;
        }


        if ((gm.isBasketPage || gm.isAccountMembershipPage || gm.isMembershipLandingPage) && typeof enableMembershipUpgrade !== 'undefined' && enableMembershipUpgrade === true) {
            getMembershipUpgradeOptions();
        }

        gm.currentMembershipPlanName = null;
        function getActiveMembershipName() {
            //do not know why it is contianed within each optional upgrade 
            angular.forEach(gm.membershipUpgradeOptions, function (membership) {
                gm.currentMembershipPlanName = membership.upgradeFromMembershipName;
            });
        }

        function addLogosForMembershipUpgradeOptions() {
            if (gm.membershipUpgradeOptions.length == 0) return;
            angular.forEach(gm.membershipUpgradeOptions, function (option) {
                if (option['stockCode'] === "54270") {
                    option['voucherImg'] = "https://the-fragrance-shop.imgix.net/UX/content/membership/my-tfs-plus-logo-sparkle.svg";
                }
                if (option['stockCode'] === "54271" || option['stockCode'] === "54272") {
                    option['noOfVouchers'] = "UNLIMITED";
                    option['voucherImg'] = "https://the-fragrance-shop.imgix.net/UX/content/membership/my-tfs-family-logo-sparkle.svg";
                }
            });
        }

        gm.membershipUpgradeOptions = [];
        gm.membershipUpgradeSelectedOption = null;
        function getMembershipUpgradeOptions() {
            //let's check if member is eligible for upgrade
            $http.get(MEMBERSHIP.URL_UPGRADE_OPTIONS)
                .success(function (res) {
                    if (!res.canUpgrade) return;
                    //we can upgrade. Assign options to global array
                    gm.membershipUpgradeOptions = res.options;
                    addLogosForMembershipUpgradeOptions();
                    getActiveMembershipName();
                })
                .error(function (error) {
                    console.log('Error fetching membership upgrade options.');
                })
                .finally(function () {
                    console.log('Membership upgrade options fetched.');
                });
        }

        function checkVoucherApplied() {
            if (gm.basketResponse != null && gm.basketResponse.promotionsApplied != null && gm.basketResponse.membershipBenefits != null) {
                angular.forEach(gm.basketResponse.promotionsApplied, function (promo) {
                    angular.forEach(gm.basketResponse.membershipBenefits, function (benefit) {
                        if (benefit.voucher.toLowerCase() == promo.promoCode.toLowerCase()) {
                            benefit.status = VOUCHERSTATUS.CLAIMED;
                            gm.membershipVoucherApplied = true;
                        }
                    });
                });
            }
        }

        function applyMembershipVoucher() {
            var promoCode = gm.unClaimedMembershipVouchers[0].voucher;
            gm.unClaimedMembershipVouchers[0].status = VOUCHERSTATUS.CLAIMED;
            gm.applyPromoCode(gm.basketResponse.id, promoCode);
        }
        function customError() {
            $timeout(function () {
                $(".alertBlock").fadeOut();
            }, 10000);
        }

        function showMembershipModal(targetLocation) {
            $(".modal-reminder").show();
            const closeMembershipModal = $(".modal-reminder .top .close, .modal-reminder .btn");
            $(closeMembershipModal).click(function () {
                $(".modal-reminder").hide();
            });
            $(".modal-reminder .btm .close").click(function () {
                window.location.href = targetLocation;
            });
        };

        function isOnlyMembershipInTheBasket() {
            return gm.basketResponse.lineItems.every(a => !0 === a.isMembership)
        }

        gm.isOnlySubInTheBasket = isOnlySubInTheBasket;

        function isOnlySubInTheBasket() {
            return gm.basketResponse.lineItems.every(a => !0 === a.isSubscription)
        }


        gm.isOnlyVirtualInTheBasket = isOnlyVirtualInTheBasket;
        function isOnlyVirtualInTheBasket() {
            return gm.basketResponse.lineItems.every(a => a.itemGroupId === 7)
        }

        function hasOnlyMembershipProducts() {
            var membershipLines = [];
            var subLines = [];
            angular.forEach(gm.basketResponse.lineItems, function (line) {
                if (line.isMembership) {
                    membershipLines.push(line);
                }
                if (line.isSubscription) {
                    subLines.push(line);
                }
            });
            return (subLines.length > 0 && membershipLines.length > 0 && gm.basketResponse.lineItems.length == membershipLines.length + subLines.length) ? true : false;
        }

        //THIS IS THE MAIN METHOD WHICH IS NOW USED TO PROCEED TO CHECKOUT
        function proceedToCheckout(e) {
            e.preventDefault();

            //prevent double membership purchases
            var membershipBasket = false;
            if (gm.userHasMembership == 1 && gm.basketResponse != null) {
                angular.forEach(gm.basketResponse.lineItems, function (item) {
                    if (item != null && item.isMembership == true && item.itemType == 2) {
                        membershipBasket = true;
                    }
                });

                if (membershipBasket == true) {
                    $(".membershipBasketErrorMsg").fadeIn();
                    gm.showMembershipBasketErrorMsg = true;
                    $timeout(function () {
                        $(".membershipBasketErrorMsg").fadeOut();
                        gm.showMembershipBasketErrorMsg = false;
                    }, 10000);
                    membershipBasket = false;
                    return;
                }
            }

            //prevent user to proceed to basket if it is not valid
            if (isShipFromStoreEnabled() && !gm.tfsBasketDataValidation.validBasket) {
                shipFromStoreModalShow();
                return;
            }

            //do not allow the checkout if we have a pending API
            if (gm.apiPendingTfs) {
                return;
            }

            const targetLocation = e.target.dataset.href;
            //check if we need to show membershiop modal
            if (typeof enableMembershipOnline !== 'undefined' && enableMembershipOnline === true && gm.unClaimedMembershipVouchers.length > 0 && gm.membershipVoucherApplied === false && !isOnlyMembershipInTheBasket() && !hasOnlyMembershipProducts() && !isOnlySubInTheBasket() && !isOnlyVirtualInTheBasket() && gm.validpromo !== true) {
                showMembershipModal(targetLocation);
                //check if we have scentaddict redemption in the basket.
                //If true show the old checkout to the user
            } else if (isScentaddictRedemptionBasket()) {
                window.location.href = `/checkout/2/${gm.basketResponse.id}`;
            } else {
                window.location.href = targetLocation;
            }
        }

        function lineItemsAddonsProp() {
            angular.forEach(gm.basketResponse.lineItems, function (item) {
                item['disableGiftWrap'] = gm.tfsBasketDataValidation.disableGiftWrap;
                if (gm.isMultiFulfilmentEnabled) {
                    //check what type deliveryPlan item is on
                    angular.forEach(gm.basketResponse.deliveryPlans, function (dp) {
                        angular.forEach(dp['lineItems'], function (dpi) {
                            if (dpi['productId'].toLowerCase() === item['productId'].toLowerCase() && dp['deliveryCenter']['code'] === 'Warehouse') {
                                item['disableGiftWrap'] = false;
                            }
                        });
                    });
                }
            });
        }

        function lineItemsAddPropShipFromStore() {
            angular.forEach(gm.basketResponse.lineItems, function (item) {
                item['isShipFromStore'] = gm.isShipFromStoreProduct;
                if (gm.isMultiFulfilmentEnabled) {
                    //check what type deliveryPlan item is on
                    angular.forEach(gm.basketResponse.deliveryPlans, function (dp) {
                        angular.forEach(dp['lineItems'], function (dpi) {
                            if (dpi['productId'].toLowerCase() === item['productId'].toLowerCase() && dp['deliveryCenter']['code'] === "PhysicalStore") {
                                item['isShipFromStore'] = true;
                            }
                        });
                    });
                }
            });
        }

        function isShipFromStoreEnabled() {
            return (typeof enableShipFromStore !== 'undefined' && enableShipFromStore === true);
        }

        gm.isMultiFulfilmentEnabled = isMultiFulfilmentEnabled();
        function isMultiFulfilmentEnabled() {
            return (typeof enableMultiFulfilment !== 'undefined' && enableMultiFulfilment === true);
        }

        function isScentaddictRedemptionBasket() {
            return hasScentaddictCouponCode && (gm.subscriptionItems != null && gm.subscriptionItems != undefined && gm.subscriptionItems.length > 0);
        }

        // Greeting Cards
        // Load greeting cards
        function loadGreetingCards() {
            if (greetingCardsLoaded == false && gm.isBasketPage && enableGreetingCards) {
                $.ajax({
                    url: "/basket/get-greeting-cards",
                    type: "GET",
                    beforeSend: function (xhr) {
                        //$(".greeting-card-modal .inr").append("<div class='tfs-lds-ring'><div></div><div></div><div></div><div></div></div>");
                    },
                    success: function (data) {
                        greetingCardsLoaded = true;
                        $scope.$apply(function () {
                            data = JSON.parse(data);
                            if (data.length > 0) {

                                angular.forEach(data, function (card) {
                                    gm.greetingCardOptions.push(card);
                                });
                                //data.forEach(card => {
                                //    gm.greetingCardOptions.
                                //    appendGreetingCards(card)
                                //});
                            }

                            //function appendGreetingCards(cardDetails) {
                            //    const greetingCard = $("<div class='gift-wrap-itm'><div class='lhs'><label ng-click='gm.selectedGreetingCardOption()' class='control control--radio mt-30px m-no-margin-top'><input id='greetingCard' name='greetingCard' type='radio' /><div class='control__indicator__basket'></div></label><img src='https://the-fragrance-shop.imgix.net/product/" + cardDetails.stockCode + "-1.jpg?h=260&w=260&max-w=260" + cardDetails.image + "' /></div><div class='rhs'><p class='name'>" + cardDetails.name + "</p><p class='price'>" + cardDetails.price.formatted.withTax + "</p></div></div>");
                            //    $scope.$apply(function () {
                            //        $(".step-1").prepend(greetingCard);
                            //    });
                            //}
                            $(".loading-overlay").remove();
                        });
                    },
                    complete: function () {
                    },
                    dataType: "html"
                });
            }
        }

        // Open Greeting Card Modal
        function openGreetingCardModal() {
            $(".greeting-card-modal").show();
            if (typeof MagicZoom !== 'undefined') {
                MagicZoom.refresh();
            };
            $(".tfs-lds-ring").hide();
            $("html").css({ "overflow-y": "hidden", "touch-action": "none", "-ms-touch-action": "none" });

            // Enabled button toggle
            $(".customise-modal .inr .step-1 .btn-primary").attr("disabled", "disabled").css({ "background-color": "#CCC", "border-color": "#CCC" });
            $(".greeting-card-modal .gift-wrap-itm input").click(function () {
                if ($(this).is(":checked")) {
                    $(".customise-modal .inr .step-1 .btn-primary").removeAttr("disabled").css({ "background-color": "#1d1258", "border-color": "#1d1258" });
                }
            });

            // Clear greeting card info
            $scope.tsCsChecked = false;
            $scope.greetingCardMessage = "";
            $scope.greetingCardEnvelope = "";

            // Open Ts & Cs
            $(".greeting-card-modal .ts-cs a").click(function (e) {
                e.preventDefault();
                $(".greeting-card-modal .close").hide();
                $(".greeting-card-modal .step-2").hide();
                $(".greeting-card-modal .ts-cs-overlay").show();
                $(".ts-cs-overlay .close-ts-cs").click(function () {
                    $(".ts-cs-overlay").hide();
                    $(".greeting-card-modal .step-2").show();
                    $(".greeting-card-modal .close").show();
                });
            });
        }

        // Close greeting card modal
        function closeGreetingCardModal() {
            $(".greeting-card-modal").hide();
            $('#greetingCard').prop('checked', false);
            $("html").css("overflow-y", "auto");
            $(".greeting-card-modal .step-1").show();
            $(".greeting-card-modal .step-2").hide();
            $(".gift-wrap-itm input.greetingCardsItems").prop("checked", false);
            //$(".greeting-card-modal .gift-wrap-itm").remove();
        }

        // Back greeting card modal
        function backGreetingCardModal() {
            $(".greeting-card-modal .step-1").show();
            $(".greeting-card-modal .step-2").hide();
            gm.addGreetingCardButtonClicked = false;
        }

        // Add greeting card
        function addGreetingCard(selectedCardOption) {
            if (gm.addonsActionPending) return;
            gm.addonsActionPending = true;
            $(".greeting-card-summary").removeClass("hidden");
            $(".greeting-card-item").removeClass("hidden");
            $(".greeting-card-modal .inr").append("<div class='tfs-lds-ring'><div></div><div></div><div></div><div></div></div>");
            $("html").css("overflow-y", "auto");
            //if (!gm.addGreetingCardButtonClicked && selectedCardOption != null && Object.keys(selectedCardOption) != 0) {
            gm.addGreetingCardButtonClicked = true;
            var greetingCardModel = {
                basketId: gm.basketResponse.id,
                parentProductId: gm.selectedLineItem.productId,
                Qty: 1,
                greetingCardId: selectedCardOption.recordId,
                greetingCardStockCode: selectedCardOption.stockCode,
                greetingCardText: $(".greeting-card-modal .step-2 textarea").val(),
                greetingCardEnvelope: $(".greeting-card-modal .step-2 input[type='text']").val()
            };
            $http.post("/basket/add-greeting-card", { model: greetingCardModel, lineItem: gm.selectedLineItem }).then(function (success) {
                gm.addonsActionPending = false;
                gm.selectedGreetingCardOption = {};
                //    //assign updated basket. 
                updateBasket(success.data);
                //    gm.addGreetingCardButtonClicked = false;
                gm.addGreetingCardButtonClicked = false;
                gm.currencyCookie = $.cookie(CURRENCYCOOKIE.CurrencyCode);
                gm.changeBaseCurrency(gm.currencyCookie, false);
                $(".greeting-card-modal").hide();
                //$(".greeting-card-items").removeClass("hidden");
                $(".greeting-card-modal .inr .tfs-lds-ring").remove();
                // Show in basket
                $(".greeting-card-modal .step-1").show();
                $(".greeting-card-modal .step-2").hide();

                //uncheck radios
                $(".gift-wrap-itm input.greetingCardsItems").prop("checked", false);

                //set greeting card to true
                gm.selectedLineItem.isGreetingCardApplied = true;
            }, function (error) {
                gm.addonsActionPending = false;
            });
            //}
            gm.addGreetingCardButtonClicked = true;
        }

        function addGreetingCardPersonalisation(selectedCard) {
            if (!gm.addGreetingCardButtonClicked && selectedCard != null && Object.keys(selectedCard) != 0) {
                gm.addGreetingCardButtonClicked = true;
                $(".greeting-card-modal .step-1").hide();
                $(".greeting-card-modal .step-2").show();
            } else {
                gm.addGreetingCardButtonClicked = false;
            }
        }

        // Edit greeting card
        function editGreetingCard(target) {
            $(`#summary_${target.productId}_${target.parentProductId}`).hide();
            $(`#form_${target.productId}_${target.parentProductId}`).removeClass("hidden");

            $(".greeting-card-info .form-control").each(function () {
                let inputLimit = $(this).attr("maxlength")
                $(this).on("keyup", function () {
                    $(this).siblings().find(".character-count").text(this.value.length + " / " + inputLimit);
                });
            });
        }

        // Hide greeting card
        function hideGreetingCard(target) {
            $(`#summary_${target.productId}_${target.parentProductId}`).show();
            $(`#form_${target.productId}_${target.parentProductId}`).addClass("hidden");
        }

        // Save edited greeting card
        function saveEditGreetingCard(greetingCard) {

            const greetingCardMessage = $(`#info4_${greetingCard.productId}_${greetingCard.parentProductId}`).val();
            const greetingCardEnvelope = $(`#info5_${greetingCard.productId}_${greetingCard.parentProductId}`).val();

            var model = {
                basketId: gm.basketResponse.id,
                LineInfo: [{
                    productId: greetingCard.productId,
                    parentProductId: greetingCard.parentProductId,
                    stockCode: greetingCard.stockCode,
                    customInfo4: JSON.stringify({ text: greetingCardMessage }),
                    customInfo5: JSON.stringify({ text: greetingCardEnvelope })
                }]
            }

            gm.apiPendingTfs = true;

            $http.post("basket/update-greeting-card", { customInfo: model }).then(function (response) {
                $(`#summary_${greetingCard.productId}_${greetingCard.parentProductId}`).show();
                $(`#form_${greetingCard.productId}_${greetingCard.parentProductId}`).addClass("hidden");
                gm.apiPendingTfs = false;

                updateBasket(response.data);
            }, function (error) {
                gm.apiPendingTfs = false;
            });
        }

        // Remove greeting card
        function removeGreetingCard(greetingCard) {
            var greetingCardModel = {
                basketId: gm.basketResponse.id,
                parentProductId: gm.selectedLineItem.productId,
                Qty: 0,
                greetingCardId: greetingCard.productId,
                greetingCardStockCode: greetingCard.stockCode,
            };
            gm.apiPendingTfs = true;
            $http.post("/basket/remove-greeting-card-info", { model: greetingCardModel, lineItem: gm.selectedLineItem }).then(function (response) {
                updateBasket(response.data);
                gm.apiPendingTfs = false;
            }, function (error) {
                gm.apiPendingTfs = false;
            });
        }

        // Add ribbon
        if (gm.isBasketPage && enableRibbons) {
            getRibbons();
        }

        gm.ribbbonOptions = [];

        function getRibbons() {
            $http.post("basket/get-ribbons").then(function (response) {
                //THIS IS TEMPORARY JUST FETCHING SINGLE RIBBON
                if (response['data'] && response['data'].length > 0) {
                    gm.ribbbonOptions = response['data'];
                }

                //attach ribbions to gift wrap options
            }, function (error) {
            });
        }

        function addRibbon(selectedRibbon) {
            //if (!gm.addGreetingCardButtonClicked && selectedCardOption != null && Object.keys(selectedCardOption) != 0) {
            gm.addGreetingCardButtonClicked = true;
            if (gm.addonsActionPending) return;
            gm.addonsActionPending = true;

            var ribbonModel = {
                basketId: gm.basketResponse.id,
                parentProductId: gm.selectedLineItem.productId,
                Qty: 1,
                ribbonId: selectedRibbon.recordId,
                ribbonStockCode: selectedRibbon.stockCode,
                ribbonText: $(".gift-wrap-modal input.ribbon-text").val(),
            };
            $http.post("/basket/add-ribbon", { model: ribbonModel, lineItem: gm.selectedLineItem }).then(function (success) {
                //    //assign updated basket. 
                updateBasket(success.data);
                //    gm.addGreetingCardButtonClicked = false;
                gm.addRibbonButtonClicked = false;
                gm.addonsActionPending = false;
                gm.currencyCookie = $.cookie(CURRENCYCOOKIE.CurrencyCode);
                gm.changeBaseCurrency(gm.currencyCookie, false);
                $(".gift-wrap-modal").hide();
                $(".gift-wrap-modal .inr .tfs-lds-ring").remove();
                //$(".greeting-card-items").removeClass("hidden");

                // Show in basket
                $(".gift-wrap-modal .step-1").show();
                $(".gift-wrap-modal .step-2").hide();
            }, function (error) {
                gm.addonsActionPending = false;
            });
            //}
            gm.addRibbonButtonClicked = true;
        }

        function editRibbon(target) {
            $(`#ribbon-summary_${target.productId}_${target.parentProductId}`).addClass("hidden");
            $(`#ribbon-form_${target.productId}_${target.parentProductId}`).removeClass("hidden");

            $(".edit-ribbon .ribbon-controls span").click(function () {
                $(".ribbon-info").removeClass("hidden");
                $(".edit-ribbon.ribbon-info").addClass("hidden");
            });

            $(".edit-ribbon .form-control").each(function () {
                let inputLimit = $(this).attr("maxlength")
                $(this).on("keyup", function () {
                    $(this).siblings().find(".character-count").text(this.value.length + " / " + inputLimit);
                });
            });
        }

        // Update ribbon
        function updateRibbon(ribbon) {

            const personaliseRibbon = $(`#info3_${ribbon.productId}_${ribbon.parentProductId}`).val();

            var model = {
                basketId: gm.basketResponse.id,
                LineInfo: [{
                    productId: ribbon.productId,
                    parentProductId: ribbon.parentProductId,
                    stockCode: ribbon.stockCode,
                    customInfo3: JSON.stringify({ text: personaliseRibbon }),
                }]
            }

            gm.apiPendingTfs = true;

            $http.post("basket/update-ribbon", { customInfo: model }).then(function (response) {
                updateBasket(response.data);
                $(".ribbon-info").removeClass("hidden");
                $(".edit-ribbon.ribbon-info").addClass("hidden");
                gm.apiPendingTfs = false;
            }, function (error) {
                gm.apiPendingTfs = false;
            });
        }

        function removeRibbon(ribbon) {
            var ribbonModel = {
                basketId: gm.basketResponse.id,
                parentProductId: gm.selectedLineItem.productId,
                Qty: 0,
                ribbonId: ribbon.productId,
                ribbonStockCode: ribbon.stockCode,
            };
            gm.apiPendingTfs = true;
            $http.post("/basket/remove-ribbon", { model: ribbonModel, lineItem: gm.selectedLineItem }).then(function (response) {
                updateBasket(response.data);
                gm.apiPendingTfs = false;
            }, function (error) {
                gm.apiPendingTfs = false;
            });
        }

        function initGreetingCards() {
            angular.forEach(gm.basketResponse.lineItems, function (greetingCardLine) {
                if (greetingCardLine.customInfo4 != null) {
                    angular.forEach(gm.basketResponse.lineItems, function (parentLine) {
                        if (parentLine.productId.toUpperCase() == greetingCardLine.parentProductId.toUpperCase() && greetingCardLine.itemType != 7 && greetingCardLine.customInfo1 == '' && greetingCardLine.customInfo4.text) {
                            parentLine.isGreetingCardApplied = true;
                        }
                    });
                }
            });
        }

        function initRibbons() {
            angular.forEach(gm.basketResponse.lineItems, function (ribbonLine) {
                if (ribbonLine.customInfo3 != null) {
                    angular.forEach(gm.basketResponse.lineItems, function (parentLine) {
                        if (parentLine.productId.toUpperCase() == ribbonLine.parentProductId.toUpperCase() && ribbonLine.itemType != 7 && ribbonLine.customInfo1 == '' && ribbonLine.customInfo3.text) {
                            parentLine.isRibbonApplied = true;
                        }
                    });
                }
            });
        }

        function renderPaypalMessaging() {
            if (typeof window.paypal === "undefined" && gm.isBasketPage && typeof payPalClientId === 'string') {
                const ppJs = document.createElement('script');
                ppJs.src = "https://www.paypal.com/sdk/js?components=messages&currency=GBP&client-id=" + payPalClientId;
                document.body.append(ppJs);
            }
        }

        function renderClearpayMessaging() {
            if (typeof window.Afterpay === "undefined" && gm.isBasketPage && typeof enableClearpayMessaging !== "undefined" && enableClearpayMessaging === true) {
                const cpJS = document.createElement('script');
                cpJS.src = "https://js.afterpay.com/afterpay-1.x.js";
                cpJS.dataset.min = "1.00";
                cpJS.dataset.max = "1000.00";
                cpJS.async = true;
                document.body.append(cpJS);
            }
        }

        gm.renderZipMessaging = renderZipMessaging;
        function renderZipMessaging(amount = 0) {
            if (gm.isBasketPage && enableZipMessaging) {
                //add CSS overwrites
                const zipStyles = document.getElementById('zip-styles-head');
                //check is CSS is already attached
                if (!zipStyles) {
                    const css = `#zip-messaging-container #partPayCalculatorWidget {padding: 0;width: 100%;background-color: transparent;display: flex;} #zip-messaging-container #partPayCalculatorWidget #partPayCalculatorWidgetLogo {display: inline; float: unset;order: 1;flex: 0 0 auto;} #zip-messaging-container #partPayCalculatorWidget #partPayCalculatorWidgetLogo img {height: 1.5rem;display: inline-block;margin-top: 0;margin-left: 0.5rem;} #zip-messaging-container #partPayCalculatorWidget #partPayCalculatorWidgetText {display: inline;font-size: 14px;} #zip-messaging-container #partPayCalculatorWidget #partPayCalculatorWidgetText br {display: none;} #zip-messaging-container #partPayCalculatorWidget #partPayCalculatorWidgetText #partPayCalculatorWidgetTextFromCopy {margin-right: 0;}`;
                    const style = document.createElement('style');
                    document.head.appendChild(style);
                    style.type = 'text/css';
                    style.id = 'zip-styles-head';
                    style.appendChild(document.createTextNode(css));
                }

                const zipScript = document.createElement('script');
                const holder = document.getElementById('zip-messaging-container');
                //we need to check if the JS is already appended or not - to prevent double widget being loaded
                if (!holder || (holder && holder.firstChild && holder.firstChild.src)) return;
                holder.innerHTML = '';
                zipScript.async = true;
                zipScript.src = `https://widgets.partpay.co.nz/zip-widget-classic-v3.0.0.js?type=calculator&min=0&max=1000&amount=${amount}&locale=uk`;
                holder.appendChild(zipScript);
            }
        }

        function getBasketDiscountAmount() {
            return gm.basketResponse.currencySymbol + (gm.basketResponse.grandTotal.raw.withTax * 0.2).toFixed(2);
        }

        function checkBasketContainShipFromStoreItems() {
            return gm.basketResponse.deliveryPlans.length > 0 ? true : false;
        }

        function validateMembership() {
            var membershipBasket = false;
            if (gm.userHasMembership == 1 && gm.basketResponse != null) {
                angular.forEach(gm.basketResponse.lineItems, function (item) {
                    if (item != null && item.isMembership == true && item.itemType == 2) {
                        membershipBasket = true;
                    }
                });

                if (membershipBasket == true) {
                    $(".membershipBasketErrorMsg").fadeIn();
                    gm.showMembershipBasketErrorMsg = true;
                    $timeout(function () {
                        $(".membershipBasketErrorMsg").fadeOut();
                        gm.showMembershipBasketErrorMsg = false;
                    }, 10000);
                    membershipBasket = false;
                    return;
                }
            }
        }

        function showBasketWarning() {
            return ((gm.basketContainShipFromStoreItems && gm.basketTouched) || (gm.outofStockProducts != null && gm.outofStockProducts.length > 0)) && gm.isMultiFulfilmentEnabled ? true : false;
        }

        function allItemsOOS() {
            return (gm.outofStockProducts != null && gm.outofStockProducts.length == (gm.basketResponse.lineItems.length + gm.outofStockProducts.length)) ? true : false;
        }

        function someItemsOOS() {
            return (gm.outofStockProducts != null && gm.outofStockProducts.length > 0 && gm.outofStockProducts.length != (gm.basketResponse.lineItems.length + gm.outofStockProducts.length)) ? true : false;
        }

        gm.getDeliveryPlansSorted = getDeliveryPlansSorted;
        function getDeliveryPlansSorted(deliveryPlans) {
            return deliveryPlans.sort(sortDeliveryPlansByType);
        }

        gm.WAREHOUSE = 'warehouse';
        function sortDeliveryPlansByType(a, b) {
            if ((a.deliveryCenter.code.toLowerCase().indexOf(gm.WAREHOUSE) > -1) && (b.deliveryCenter.code.toLowerCase().indexOf(gm.WAREHOUSE) > -1)) {
                return 0;
            } else if (a.deliveryCenter.code.toLowerCase().indexOf(gm.WAREHOUSE) > -1) {
                return -1;
            } else {
                return 1;
            }
        }

        // MEMBERSHIP SIGNUP
        gm.membershipSignupOptions = [];
        gm.membershipSignupSelectedOption = null;
        gm.memSignApplyDiscounCode = false;
        gm.fetchingSignupOptions = false;
        gm.currentMembership = typeof currentMembership != "undefined" ? currentMembership : null;

        if (gm.isBasketPage) {
            getMembershipSignupOptions();
        }

        function getMembershipSignupOptions() {
            if (gm.fetchingSignupOptions) return;
            gm.fetchingSignupOptions = true;
            $http.get(MEMBERSHIP.URL_SIGNUP_OPTIONS)
                .success(function (res) {
                    if (res && res.length === 0) return;
                    //we can signup. Assign options to global array
                    gm.membershipSignupOptions = res;

                    //override the top tier voucher count
                    angular.forEach(gm.membershipSignupOptions, function (benefit) {
                        if (benefit['stockCode'] === "53222") {
                            benefit['noOfVouchers'] = "UNLIMITED";
                        }
                    });

                    //assign modal listeners
                    $('#tfs-membership-signup-modal').on('show.bs.modal', function () {
                        document.documentElement.style.overflowY = "hidden";
                        resetMembershipSignupModal();
                    })

                    $('#tfs-membership-signup-modal').on('hide.bs.modal', function () {
                        document.documentElement.style.overflowY = "unset";
                        resetMembershipSignupModal();
                    })
                })
                .error(function (error) {
                    console.log('Error fetching membership signup options.');
                })
                .finally(function () {
                    gm.fetchingSignupOptions = false;
                    console.log('Membership signup options fetched.');
                });
        }

        function resetMembershipSignupModal() {
            // This happens outside of angularJS, we wrap it in a timeout 
            $timeout(function () {
                gm.membershipSignupSelectedOption = null;
            })
        }

        gm.addMembershipToBag = addMembershipToBag;
        function addMembershipToBag(stockCode) {
            if (gm.apiPendingTfs) return;
            gm.apiPendingTfs = true;
            $http.get(`${MEMBERSHIP.URL_SIGNUP_ADD}?sku=${stockCode}`)
                .success(function (res) {
                    if (!res.isValid) {
                        gm.apiPendingTfs = false;
                        tfsNewAlert("Something went wrong. Try again.", "error");
                        return;
                    };
                    //check if we need to apply the first discount or not
                    if (gm.memSignApplyDiscounCode) {
                        sessionStorage.setItem(gm.applyMembershipVoucherAfterRedirect, true);
                    }
                    window.location.reload();
                })
                .error(function (error) {
                    gm.apiPendingTfs = false;
                    tfsNewAlert("Something went wrong. Try again.", "error")
                })
                .finally(function () {
                    console.log('Membership added to basket.');
                });
        }

    };
})();
;
(function () {
    'use strict';
    window.app.controller('productCtrl', productCtrl);
    window.app.constant("CURRENCYCOOKIE", {
        'CurrencyCode': "_ctcc"
    });
    productCtrl.$inject = ['$scope', '$timeout', 'productConfig', 'model', '$http', '$q', '$sce', 'CURRENCYCOOKIE', 'loader'];

    function productCtrl($scope, $timeout, productConfig, model, $http, $q, $sce, CURRENCYCOOKIE) {
        var pm = this;
        pm.model = model;
        pm.addToBag = false;
        pm.productResponse = {};
        pm.searchCriteria = {};
        pm.itemsPerPage = 12;
        pm.currentPage = 0;
        pm.productCount = 1;
        pm.priceWithEngraving = 0;
        pm.productTosearch = productTosearch;
        pm.searchproductfilter = [];
        pm.initProducts = initProducts;
        pm.initCollectionProducts = initCollectionProducts;
        pm.searchProducts = searchProducts;
        pm.searchAddProduct = searchAddProduct;
        pm.clearAddProduct = clearAddProduct;
        //pm.variantDetail = variantDetail;
        pm.productDetail = productDetail;
        pm.productQty = productQty;
        pm.initBrandListing = initBrandListing;
        pm.filterBrandListing = filterBrandListing;
        pm.fetchSubBrandProductList = fetchSubBrandProductList;
        pm.filterBrands = filterBrands;
        pm.getUrl = getUrl;
        pm.paging = paging;
        pm.temp = 0;
        pm.addToWishlist = addToWishlist;
        pm.wishlistexistserror = false;
        pm.WishlistFilter = { id: '' };
        pm.wishlistsaved = false;
        pm.wishlisterror = false;
        pm.removeFilter = removeFilter;
        pm.selectionGroup = [];
        pm.selectedKey = ""
        pm.item = [];
        $scope.noRecord = false;
        pm.subBrandProducts = [];
        pm.selectedRecord = '';
        pm.setRating = setRating;
        pm.removeChar = removeChar;
        pm.userLogin = userLogin;
        pm.registration = registration;
        pm.reviewAsGuest = reviewAsGuest;
        pm.cancel = cancel;
        pm.addReview = addReview;
        pm.configRating = configRating;
        pm.addMultipleToWishlist = addMultipleToWishlist;
        pm.addMultipleToBasket = addMultipleToBasket;
        pm.showAllbrand = false;
        pm.hideQickView = hideQickView;
        pm.subBrandPagination = subBrandPagination;
        pm.initProductVariant = initProductVariant;
        pm.getToWishlist = getToWishlist;
        pm.checkForWishlist = checkForWishlist;
        pm.getBasketRelatedProducts = getBasketRelatedProducts;
        pm.getAvailableAttributeValues = getAvailableAttributeValues;
        pm.relatedProducts = [];
        pm.GetDynamicReviewConfig = GetDynamicReviewConfig;
        pm.beginQuestionnaire = beginQuestionnaire;
        pm.submitSurvey = submitSurvey;
        pm.rotateImage = rotateImage;
        pm.degree = 0;
        pm.onTextFocus = onTextFocus;
        pm.checkForSpecificAttributeinProductList = checkForSpecificAttributeinProductList;
        pm.IsUserLoggedIn = ($.cookie('IsUserLoggedIn') === undefined) ? false : ($.cookie('IsUserLoggedIn') == 'true');
        pm.COOKIE_LIMIT = 15;
        pm.PRODUCT_COOKIE = '_rvp';
        pm.PRODUCT_COOKIE_LIST = '_rvpList';
        pm.getGrid = getGrid;
        pm.getList = getList;
        pm.getView = true;
        pm.getHtml = getHtml;
        pm.videoPopupModal = videoPopupModal;
        pm.getStoreStockAvailability = getStoreStockAvailability;
        pm.deletedFromWishlist = deletedFromWishlist;
        pm.getProductReview = getProductReview;
        pm.productAvgRating = 0;
        pm.showAddToBag = true;
        pm.showAddToQueue = false;
        pm.showAddToSubscriptionList = false;
        pm.slugifyUrl = slugifyUrl;
        pm.EngravingItemType = '10';
        pm.evalButtonVisibility = evalButtonVisibility;
        pm.checkStockAvailabilityStatus = checkStockAvailabilityStatus;
        pm.IsDeletedFromWishlist = false;
        pm.searchCollectionProducts = searchCollectionProducts;
        pm.collectionProuducts = null;
        pm.collectionList = [];
        pm.searchPaginated = searchPaginated;
        pm.emptyGuid = '00000000-0000-0000-0000-000000000000';
        pm.fetchMoreReviews = fetchMoreReviews;
        pm.hideGiftCardMsg = hideGiftCardMsg;
        pm.changeBaseCurrency = changeBaseCurrency;
        pm.changeCurrecyValueForEngraving = changeCurrecyValueForEngraving;
        pm.brandCarousels = brandCarousels;


        if (pm.model.recordId) {
            var recentProducts = $.cookie(pm.PRODUCT_COOKIE);
            if (recentProducts) {
                var itemsInCookies = recentProducts.split(",");
                if (itemsInCookies) {
                    var flag = 1;
                    angular.forEach(itemsInCookies, function (value, key) {
                        if (value == pm.model.recordId) {
                            flag = 0;
                        }
                    });
                    if (flag) {
                        if (itemsInCookies.length > pm.COOKIE_LIMIT) {
                            angular.forEach(itemsInCookies, function (value, key) {
                                itemsInCookies[key] = itemsInCookies[key + 1];
                            });
                            itemsInCookies[itemsInCookies.length - 1] = pm.model.recordId;
                            recentProducts = itemsInCookies.join(',');
                        }
                        else {
                            itemsInCookies.push(pm.model.recordId);
                            recentProducts = itemsInCookies.join(',');
                        }
                        $.removeCookie(pm.PRODUCT_COOKIE);
                        $.cookie(pm.PRODUCT_COOKIE, recentProducts, { path: '/' });
                    }
                }
            }
            else {
                $.cookie(pm.PRODUCT_COOKIE, pm.model.recordId, { path: '/' });
            }
        }

        //For Product Recommendation
        if (pm.model.stockCode) {
            var recentProductsList = $.cookie(pm.PRODUCT_COOKIE_LIST);
            if (recentProductsList) {
                var itemsInCookies = recentProductsList.split(",");
                if (itemsInCookies) {
                    var flag = 1;
                    angular.forEach(itemsInCookies, function (value, key) {
                        if (value == pm.model.stockCode) {
                            flag = 0;
                        }
                    });
                    if (flag) {
                        if (itemsInCookies.length > pm.COOKIE_LIMIT) {
                            angular.forEach(itemsInCookies, function (value, key) {
                                itemsInCookies[key] = itemsInCookies[key + 1];
                            });
                            itemsInCookies[itemsInCookies.length - 1] = pm.model.stockCode;
                            recentProductsList = itemsInCookies.join(',');
                        }
                        else {
                            itemsInCookies.push(pm.model.stockCode);
                            recentProductsList = itemsInCookies.join(',');
                        }
                        $.removeCookie(pm.PRODUCT_COOKIE_LIST);
                        $.cookie(pm.PRODUCT_COOKIE_LIST, recentProductsList, { path: '/' });
                    }
                }
            }
            else {
                $.cookie(pm.PRODUCT_COOKIE_LIST, pm.model.stockCode, { path: '/' });
            }
        }


        function getBasketRelatedProducts(basketId) {
            $http.post(productConfig.basketRelatedProducts + '/' + basketId).success(function (resp) {
                if (resp != null) {
                    pm.relatedProducts = resp;
                }
            })
        };
        function checkForSpecificAttributeinProductList(attributeCode, attributevalue, grp, list) {
            var flag = false;
            if (list != null) {
                angular.forEach(list, function (line) {
                    if (line.groupName.includes(grp)) {
                        var attr = line.attributes
                        if (attr != null) {
                            for (i = 0; i < attr.length; i++) {
                                // this can be a string or null
                                var FieldCode = attr[i].key;
                                var FieldValue = attr[i].value;
                                if (FieldCode != null && FieldCode != "" && FieldCode == attributeCode) {
                                    //line.customInfo1 = FieldCode + "" + FieldValue;
                                    if (FieldValue != null && FieldValue == attributevalue) {
                                        flag = true;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    if (flag)
                        return flag;
                });
                return flag;
            }
        }


        function initProducts(responseModel) {
            if (responseModel == null) {
                responseModel = pm.model;
            }
            pm.productResponse = responseModel;
            //bind gradient value with product 
            //angular.forEach(pm.productResponse.results, function (item) {
            //    angular.forEach(item.attributes, function (attr) {
            //        if (attr.key == "gradient") {
            //            item.title = attr.value;
            //        }
            //    });
            //});
            pm.searchCriteria = responseModel.searchCriteria;
            //if (pm.productResponse.customFieldValue != null && pm.productResponse.customFieldValue != "")
            //    pm.sortItems = JSON.parse(pm.productResponse.customFieldValue);
            pm.itemsPerPage = pm.searchCriteria.pageSize;
            pm.currentPage = pm.searchCriteria.currentPage;
            pm.sortByList = responseModel.sortList;
            pm.searchCriteria.sortBy = responseModel.sortBy;
            pm.currencyCookie = $.cookie(CURRENCYCOOKIE.CurrencyCode);
            pm.changeBaseCurrency(pm.currencyCookie);
        };

        function initCollectionProducts(responseModel) {
            pm.productResponse = responseModel.collectionResult;
            if (pm.productResponse == null || pm.productResponse.results == null)
                $scope.noRecord = true;
            if (pm.productResponse != null) {
                pm.searchCriteria = responseModel.collectionResult.searchCriteria;
                pm.itemsPerPage = pm.searchCriteria.pageSize;
                pm.currentPage = pm.searchCriteria.currentPage;
                pm.sortByList = responseModel.collectionResult.sortByList;

            }
        };
        function removeFilter(filter) {
            if (filter.freeText == undefined) {
                productTosearch({ key: filter.key, name: filter.name }, { name: filter.value, isSelected: false });
            } else {
                pm.searchCriteria.freeText = '';
                pm.searchAddProduct();
            }
        }
        function productTosearch(filter, item) {
            pm.selectedKey = '';
            if (item.isSelected) {
                pm.selectedKey = filter.key;
                pm.searchproductfilter.push({ "key": filter.key, "value": item.name, "isSelected": true, name: filter.name });
            }
            else {
                for (var i = 0; i < pm.searchproductfilter.length; i++) {
                    if (pm.searchproductfilter[i].key == filter.key && pm.searchproductfilter[i].value == item.name) {
                        pm.searchproductfilter.splice(i, 1);
                    }
                }
            }
            pm.selectionGroup = [];
            for (var i = 0; i < pm.searchproductfilter.length; i++) {
                if (pm.selectionGroup.indexOf(pm.searchproductfilter[i].name) == -1) {
                    pm.selectionGroup.push(pm.searchproductfilter[i].name);
                }
            }
            pm.searchAddProduct();
        };


        function searchAddProduct() {
            pm.searchfilter = { "currentPage": 1, "collectionId": pm.searchCriteria.collectionId, "pageSize": pm.searchCriteria.pageSize, "filters": pm.searchproductfilter, "freeText": pm.searchCriteria.freeText, "sortBy": pm.searchCriteria.sortBy, "allowFacet": "true", "categoryIds": pm.searchCriteria.categoryIds, "brandId": pm.searchCriteria.brandId, "facet": pm.searchCriteria.facet, "categoryId": pm.searchCriteria.categoryId, "excludedBrandIds": pm.searchCriteria.excludedBrandIds, "excludedCategoryIds": pm.searchCriteria.excludedCategoryIds };
            pm.searchProducts(pm.searchfilter);
        };


        function clearAddProduct(fieldId) {
            pm.selectedKey = '';
            pm.selectionGroup = [];
            $scope.fieldId = false;
            for (var i = 0; i < pm.searchproductfilter.length; i++) {
                if (pm.searchproductfilter[i].key == fieldId) {
                    pm.searchproductfilter.splice(i, 1);
                    i = i - 1;
                } else {
                    if (pm.selectionGroup.indexOf(pm.searchproductfilter[i].name) == -1) {
                        pm.selectionGroup.push(pm.searchproductfilter[i].name);
                    }
                }
            }

            pm.searchAddProduct();
        };

        function paging(pagination) {
            pm.searchCriteria = { "filters": pm.searchproductfilter, "currentPage": pagination.currentPage, "pageSize": pagination.pageSize, "categoryIds": pm.searchCriteria.categoryIds, "categoryId": pm.searchCriteria.categoryId };
            Products(pm.searchCriteria);
        };

        function productDetail(id) {
            $scope.productmodal = false;
            $http.post(productConfig.productUrl, { id: id })
                .success(function (data) {
                    pm.model = data;
                    pm.variants = data != null ? data.variant : null;
                    if (pm.variants != null) {
                        pm.initProductVariant(pm.variants);
                    }
                    if (data != null)
                        pm.productId = data.recordId;
                    $scope.productmodal = true;
                    pm.model.bulkQty = 1;
                    pm.checkForWishlist();
                    $timeout(function () { $("#qtyBox").focus().select(); $("#qtyBoxBundle").focus().select(); }, 2000);
                })
                .error(function (msg) {
                    pm.errorMessage = msg.errorMessages;
                })
                .finally(function () {
                    pm.saving = false;
                });
        };

        function searchPaginated(filter) {
            if ((filter.collectionId == pm.emptyGuid || filter.collectionId == null || filter.collectionId == "") &&
                (filter.brandId == pm.emptyGuid || filter.brandId == null || filter.brandId == ""))
                window.location = '/search?page=' + filter.currentPage
            else {
                searchProducts(filter);
            }

        }

        function searchProducts(searchFilter) {
            $http.post(productConfig.searchProductUrl, searchFilter)
                .success(function (data) {
                    $('html,body').animate({ scrollTop: 0 }, 'slow');
                    pm.productResponse.results = data.results;
                    //bind gradient value with product 
                    angular.forEach(pm.productResponse.results, function (item) {
                        angular.forEach(item.attributes, function (attr) {
                            if (attr.key == "gradient") {
                                item.title = attr.value;
                            }
                        });
                    });

                    if (typeof (data.groups) !== undefined && data.groups !== null) {
                        pm.productResponse.productGroupModel.groups = data.groups;
                    }
                    angular.forEach(pm.productResponse.results, function (pro) {
                        pro.bulkQty = 1;
                    });
                    pm.productResponse.total = data.total;
                    pm.searchCriteria = data.searchCriteria;
                    pm.itemsPerPage = pm.searchCriteria.pageSize;
                    pm.currentPage = pm.searchCriteria.currentPage;
                    if (data.results.length == 0)
                        $scope.noRecord = true;
                    else
                        $scope.noRecord = false;
                    var filter = {};
                    angular.forEach(pm.productResponse.filters, function (value, i) {
                        if (pm.selectedKey == value.key) {
                            filter = value;
                        }
                    });
                    pm.productResponse.filters = data.filters;
                    //pm.productResponse.groupsWithProducts = [];
                    //if (pm.productResponse.productGroupModel && pm.productResponse.productGroupModel.groups && pm.productResponse.productGroupModel.groups.length <= 0) {
                    //    pm.productResponse.groupsWithProducts.push({ groupName: "", products: pm.productResponse.results });
                    //}
                    //else {
                    //    var groups = [];
                    //    if (pm.sortItems != undefined) {
                    //        angular.forEach(pm.sortItems, function (sortGrp) {
                    //            angular.forEach(pm.productResponse.filterCriteria, function (grp) {
                    //                if (sortGrp.key == grp.attributeValue) {
                    //                    groups.push(sortGrp.value);
                    //                }
                    //            });
                    //        });
                    //    }
                    //}
                    //if (groups.length > 0)
                    //    pm.productResponse.productGroupModel.groups = groups;

                    //if (pm.productResponse.productGroupModel) {
                    //    for (var i = 0; i < pm.productResponse.productGroupModel.groups.length; i++) {
                    //        var products = [];
                    //        for (var j = 0; j < pm.productResponse.results.length; j++) {
                    //            if (pm.productResponse.productGroupModel.groups[i] == pm.productResponse.results[j].groupName) {
                    //                products.push(pm.productResponse.results[j]);
                    //            }
                    //            var grpName = [];
                    //            grpName = pm.productResponse.results[j].groupName.split(',');
                    //            if (grpName && grpName.length > 1) {
                    //                if (grpName.find(ele => ele == pm.productResponse.productGroupModel.groups[i])) {
                    //                    products.push(pm.productResponse.results[j]);
                    //                }
                    //            }
                    //        }
                    //        if (products.length > 0)
                    //            pm.productResponse.groupsWithProducts.push({ groupName: pm.productResponse.productGroupModel.groups[i], products: products });
                    //    }
                    //}
                    //else {
                    //    if (pm.productResponse.results != null) {
                    //        pm.productResponse.groupsWithProducts.push({ groupName: "", 'products': pm.productResponse.results });
                    //    }

                    //}
                    //window.setTimeout(function () { imgix.init({ force: true });}, 1000);

                    //PubSub.publish("search", prodDetail);


                })
                .error(function (msg) {

                })
                .finally(function () {
                });
        };

        if (sessionStorage.getItem('addToWishlist') !== null) {
            addToWishlist(pm.model.recordId);
        }

        function addToWishlist(id) {
            pm.WishlistFilter.id = id;
            $(".add-wishlist-btn").attr("disabled", "true");
            $http.post(productConfig.addToWishlistUrl, pm.WishlistFilter).success(function (resp) {
                //$(".wishdiv").fadeIn();
                if (resp) {
                    pm.wishlistsaved = true;
                }
                else {
                    pm.wishlistexistserror = true;
                    pm.wishlisterror = false;
                }
                $timeout(function () {
                    $(".wishdiv").fadeOut();
                    pm.checkForWishlist();
                    pm.wishlistsaved = false;
                    pm.wishlistexistserror = false;
                }, 2000);
            }).error(function (msg) {
                //$(".wishdiv").fadeIn();
                pm.wishlisterror = true;
                //$timeout(function () {
                //    $(".wishdiv").fadeOut();
                //}, 2000);
            }).finally(function (data) {
                sessionStorage.removeItem('addToWishlist');
                $(".add-wishlist-btn").removeAttr("disabled");
            });;
        };

        function initBrandListing() {
            $('#brandContainer').html($('#ALL').html());
            $('#brandContainer').quicksand($('#ALL').find('div[parent=1]'), { duration: 1, attribute: 'data-id', adjustHeight: 'dynamic' });
        };

        function filterBrandListing(letter) {
            if (letter == 'ALL') {
                pm.showAllbrand = true;
                $('#brandContainer').quicksand($('#ALL').find('div[parent=1]'), { duration: 1, attribute: 'data-id', adjustHeight: 'dynamic' });
            }

            else {
                pm.showAllbrand = false;
                var test = $('div:contains("' + letter + '")');
                $('#brandContainer').quicksand($('#ALL').find('div[firstchar="' + letter + '"]'), { duration: 1, attribute: 'data-id', adjustHeight: 'dynamic' });
                pm.result = $('#ALL').find(test);
            }
        };

        function filterBrands(letter) {
            if (letter == null || letter.length == 0) {
                pm.showAllbrand = true;
                $('#brandContainer').html($('#ALL').html());
                $('#brandContainer').quicksand($('#ALL').find('div[parent=1]'), { duration: 1, attribute: 'data-id', adjustHeight: 'dynamic' });
            }
            if (letter == null || letter.length < 2) return;
            pm.selectedRecord = letter;
            pm.showAllbrand = false;
            if (letter == '#') { letter = ''; }
            letter = letter.toUpperCase();
            letter = letter.charAt(0).toLowerCase() + letter.slice(1);
            if (!isNaN(letter.charAt(0)) || letter.indexOf('+') !== -1) {
                letter = '#' + letter;
            }
            var test = $('div:contains("' + letter + '")');
            $('#brandContainer').quicksand($('#ALL').find(test), { duration: 1, attribute: 'data-id', adjustHeight: 'dynamic' });
            pm.result = $('#ALL').find(test);

        };
        function getUrl() {
            pm.url = window.location.origin;
        };

        function fetchSubBrandProductList(subBrand, parentBrand) {
            $http.post(productConfig.fetchSubBrandProducts, { id: parentBrand, subBrandId: subBrand }).success(function (resp) {
                pm.subBrandProducts = resp[0].products;
                pm.subBrandProducts.currentPage = 1;
                pm.subBrandProducts.pageSize = 12;
                pm.subBrandProducts.total = pm.subBrandProducts.length;
                pm.subBrandPaginated = pm.subBrandProducts.slice(0, pm.subBrandProducts.pageSize);
                //$timeout(function () { $(".wishdiv").fadeOut(); }, 2000);
            })
                .error(function (msg) {
                    //pm.wishlisterror = true;
                    //$timeout(function () {
                    //    $(".wishdiv").fadeOut();
                    //}, 2000);
                })
                .finally(function () {
                });

        };

        function subBrandPagination(subBrandProducts) {

            pm.subBrandPaginated = pm.subBrandProducts.slice((subBrandProducts.pageSize * subBrandProducts.currentPage) - subBrandProducts.pageSize, subBrandProducts.pageSize * subBrandProducts.currentPage);
        }

        function setRating(value, isActive) {
            pm.rate = [];
            if (isActive == 1) {
                for (var i = 1; i <= value; i++) {
                    pm.rate.push(i);
                }
            }
            else {
                for (var i = value; i < 5; i++) {
                    pm.rate.push(i);
                }
            }
            return pm.rate;

        };
        function removeChar(fielId, name) {
            var value = fielId.replace(/[^a-zA-Z0-9]/g, '') + name.replace(/[^a-zA-Z0-9]/g, '');
            return value;
        };

        function registration(model) {
            pm.errorMessage = null;
            pm.registerErrors = true;
            pm.loginErrors = false;
            $http.post(productConfig.register, model)
                .success(function (data) {
                    if (data) {
                        $("#productReviewLogin").modal('hide');
                        pm.writeReview = true;
                        pm.reviewAsGuest();
                    }
                })
                .error(function (msg) {
                    pm.errorMessage = msg.errorMessages;
                })
                .finally(function () {
                    $timeout(function () { $(".alertBlock").fadeOut(); }, 3000);
                });
        };

        function userLogin(model) {
            pm.errorMessage = null;
            pm.loginErrors = true;
            pm.registerErrors = false;
            $(".alertBlock").fadeIn();
            $http.post(productConfig.signIn, model)
                .success(function (data) {
                    if (data) {
                        $("#productReviewLogin").modal('hide');
                        pm.writeReview = true;
                        pm.reviewAsGuest();
                    }
                })
                .error(function (msg) {
                    pm.errorMessage = msg.errorMessages;
                    $timeout(function () {
                        $(".alertBlock").fadeOut();
                    }, 3000);

                })
                .finally(function () {
                });
        };

        function reviewAsGuest() {
            $('html,body').animate({ scrollTop: 980 }, 'slow');
            $("#collapse1").removeClass("in");
            $("#collapse3").addClass("in");
        };

        function cancel() {
            $('html,body').animate({ scrollTop: 300 }, 'slow');
            $("#collapse3").removeClass("in");
            $("#collapse1").addClass("in");
        };

        function addReview(id, model, form) {
            if (form.$invalid) {
                return;
            }
            model.reviewSections = pm.reviewSections;
            model.section = pm.reviewSections[0];
            $http.post(productConfig.addReview, { id: id, productReview: model })
                .success(function (data) {
                    $("#SuccessAlert").modal();
                    form.$setPristine();
                    form.$setUntouched();
                    pm.model.review = {};
                    pm.writeReview = false;
                    $timeout(function () {
                        $("#SuccessAlert").modal('hide');
                        $("#collapse3").removeClass("in");
                        $("#collapse1").addClass("in");
                    }, 2000);
                    $timeout(function () {
                        window.location.reload();
                    }, 3000);
                })
                .error(function (msg) {
                    //pm.errorMessage = msg.errorMessages;
                    //$timeout(function () {
                    //    $(".alertBlock").fadeOut();
                    //}, 3000);

                })
                .finally(function () {
                });
        };
        function configRating(value) {
            pm.trueRating = pm.setRating(value, 1);
            pm.falseRating = pm.setRating(5 - value, 1);
        };

        function GetDynamicReviewConfig() {
            $http.post(productConfig.reviewConfig).then(function (success) {
                pm.reviewSections = success.data;
            }, function (error) { });
        }

        function addMultipleToWishlist(products, isMultiple) {
            pm.modelList = [];
            if (isMultiple == 1) {
                pm.modelList.push({ "productId": products.productId, "qty": 0, "displayOrder": 0 });
                $scope.$parent.gm.addToBasket(products.productId, 0);
            }
            else {
                for (var i = 0; i < products.length; i++) {
                    pm.modelList.push({ "productId": products[i].productId, "qty": 0, "displayOrder": 0 });
                    $scope.$parent.gm.addToBasket(products[i].productId, 0);
                }
            }
            $http.post(productConfig.basketToWishlist, pm.modelList).success(function (resp) {
                if (resp) {
                    pm.wishlistsaved = true;
                }
                else {
                    pm.wishlistexistserror = true;
                }
                $("html, body").animate({ scrollTop: 0 }, "slow");
                $timeout(function () { window.location.reload(); }, 3000);
            })
                .error(function (msg) {
                })
                .finally(function () {
                    pm.getToWishlist(pm.productResponse.results);
                });
        };
        function checkForWishlist() {
            pm.IsUserLoggedIn = $.cookie('IsUserLoggedIn');
            $http.post(productConfig.getWishlist).success(function (resp) {
                if (resp != null && pm.productId != null) {
                    angular.forEach(resp, function (resp, key) {
                        if (pm.productId == resp.recordId) {
                            pm.model.inWishList = true;
                        }
                    });
                }
            })
                .finally(function () {
                });
        };

        function getToWishlist(products) {
            $http.post(productConfig.getWishlist).success(function (resp) {
                if (resp != null && products != null) {
                    angular.forEach(products, function (product, key) {
                        angular.forEach(resp, function (resp, key) {
                            if (product.id == resp.id) {
                                product.inWishList = true;
                            }
                        });
                    });
                }
            })
                .finally(function () {
                });
        };
        function addMultipleToBasket(products, memberShipAlert) {
            if (memberShipAlert != null && memberShipAlert.length > 0) {
                $("#wishListModal").modal('hide');
                pm.membershipAlreadyAdded = true;
                $timeout(function () {
                    $(".membershipAlreadyAdded").fadeOut();
                    pm.membershipAlreadyAdded = false;
                }, 2000);
                return;
            }
            pm.modelList = [];
            for (var i = 0; i < products.length; i++) {
                pm.modelList.push({ "productId": products[i].recordId, "qty": 1, "displayOrder": 0, isSubscription: products[i].subscriptionEnabled });
            }
            $http.post(productConfig.wishlistToBasket, pm.modelList).success(function (resp) {
                window.location.reload();
            })
                .error(function (msg) {
                })
                .finally(function () {
                });
        };

        function hideQickView() {
            $("#product-quick-view-modal").modal("hide");
        }

        //gets the possible attribute values for the selected attribute & its value. Uses the pm.model.variantProducts
        //sample call getAvailableAttributeValues('size', '6', products);      //=> {size: ['6'], color: ['black', 'blue']}
        function getAvailableAttributeValues(attrCode, attrValue, isSelected, independentUrl) {
            pm.addToBag = false;
            if (isSelected) { return; }
            var selectedValues = [];
            //angular.forEach();
            //1. Set attributes available = false & selected = false for all 
            pm.model.variantProductsAttribute.forEach(function (attr) {
                attr.fieldValues.forEach(function (val) {
                    val.available = false;
                    if (attr.fieldCode == attrCode) {
                        if (val.fieldValue == attrValue) {
                            val.selected = true;
                        } else {
                            val.selected = false;
                        }
                    }
                    if (val.selected == true)
                        selectedValues.push(val.fieldValue);
                })
            });

            //2. pick up all the proudcts that match the attrCode & attrValue passed. 
            var availableAttrs = [];
            var matchedProd = [];
            pm.model.variantProducts.forEach(function (prod) {
                var matchedAttrAndValue = prod.variantAttributes.filter(function (pAttr) {
                    return pAttr.fieldCode === attrCode & pAttr.fieldValue === attrValue;
                })

                if (matchedAttrAndValue.length > 0) {

                    //console.log(MoviesCtrl(selectedValues, prod.variantAttributes));
                    //if (selectedValues.every(function (val) { return prod.variantAttributes.indexOf(val) >= 0; }))
                    //    matchedProd.push(prod);
                    var matchedAttribute = [];
                    prod.variantAttributes.forEach(function (pAttr) {
                        selectedValues.filter(function (pAttr1) {
                            pAttr.selected = pAttr1;
                            if (pAttr1 === pAttr.fieldValue) { matchedAttribute.push(pAttr1) } return matchedAttribute;
                        })
                        //TODO: check that the same attribute & value does not exist already in the array before pushing it in
                        availableAttrs.push(pAttr);
                    })
                    if (matchedAttribute.length == prod.variantAttributes.length) { matchedProd.push(prod); }
                }
            });

            //3. pick up all the attributes + values (other than the clicked one) from products and set their isAvailable = true in MasterAttributes array
            pm.model.variantProductsAttribute.forEach(function (attr) {
                //the attribute passed in selection, shoudl have all the values as "avaialble" and clicked item to be "selected"
                if (attr.fieldCode === attrCode) {
                    attr.fieldValues.forEach(function (val) {
                        val.available = true;
                        if (val.fieldValue == attrValue) val.selected = true;
                        if (val.selected == true) {
                            if (val.available == true) {
                                attr.selectedValue = val.fieldValue;

                            }
                            else {
                                attr.selectedValue = "";
                                pm.addToBag = true;
                            }
                        }
                    });
                }
                else {
                    attr.fieldValues.forEach(function (val) {
                        if (availableAttrs.filter(function (availAttr) {
                            return availAttr.fieldCode === attr.fieldCode & availAttr.fieldValue === val.fieldValue;
                        }).length > 0) {
                            val.available = true;
                        }
                        if (val.selected == true) {
                            if (val.available == true) {
                                attr.selectedValue = val.fieldValue;

                            }
                            else {
                                attr.selectedValue = "";
                                pm.addToBag = true;
                            }
                        }
                    })
                }
            });

            if (matchedProd.length > 0) {
                $scope.productId = matchedProd[0].productId;
                $http.post(productConfig.productUrl + "/" + $scope.productId).success(function (resp) {
                    if (resp !== null) {
                        //if (pm.model.classification.mainCategoryName != null && pm.model.classification.mainCategoryName.toLowerCase() == 'scent addict') {
                        //    pm.showAddToBag = attrValue == 'one-time-purchase' ? true : false;
                        //}
                        if (independentUrl) {
                            window.location.href = "/" + resp.link;
                        }
                        else {
                            pm.productId = $scope.productId;
                            var attributes = pm.model.variantProductsAttribute;
                            var variantProducts = pm.model.variantProducts;
                            pm.model = resp;
                            pm.model.reviews = pm.reviews;
                            pm.model.variantProductsAttribute = attributes;
                            pm.model.variantProducts = variantProducts;
                            pm.image = pm.model !== null ? pm.model.image : null;
                            pm.model.engravingProduct = [];
                            angular.forEach(pm.model.relatedProductList, function (prod) {
                                if (prod.itemType == pm.EngravingItemType) {
                                    pm.model.engravingProduct.push(prod);
                                }
                            });
                            pm.priceWithEngraving = pm.model.price.raw.withTax + pm.model.engravingProduct[0].price.raw.withTax;
                            pm.evalButtonVisibility();
                            changeCurrecyValueForEngraving(pm.priceWithEngraving);
                        }
                    }
                });
            }
        }
        function evalButtonVisibility() {
            pm.showAddToBag = false;
            pm.showAddToQueue = false;
            pm.showAddToSubscriptionList = false;

            if (!pm.model.subscriptionEnabled) {
                pm.showAddToBag = true;
            }
            else {
                var isOtp = -1;
                //var isOtp = pm.model.variantProducts.findIndex(i => i.stockCode == pm.model.stockCode && i.variantAttributes[0].fieldValue == 'one-time-purchase');
                angular.forEach(pm.model.variantProducts, function (value, key) {
                    if (vProd.stockCode == pm.model.stockCode && vProd.variantAttributes[0].fieldValue == 'one-time-purchase') {
                        isOtp = key;
                    }
                });
                if (pm.model.variantProducts.length > 0 && isOtp == -1) {
                    pm.showAddToQueue = true;
                }
                else if (isOtp == -1) {
                    pm.showAddToSubscriptionList = true;
                }
                else {
                    pm.showAddToBag = true;
                }
            }
            pm.checkStockAvailabilityStatus();
        }
        function checkStockAvailabilityStatus() {
            if (pm.model.stockAvailability == 'Instock') {
                pm.stockAvailabilityMsg = 'In Stock';
            }
            else if (pm.model.stockAvailability == 'OutOfStock') {
                pm.stockAvailabilityMsg = 'Out of Stock';
            }
            else if (pm.model.stockAvailability == 'ClickNCollectOnly') {
                pm.stockAvailabilityMsg = 'Out of Stock - Available for Click & Collect';
            }
        }
        function initProductVariant() {
            pm.model.variantProductsAttribute.forEach(function (attr) {
                attr.fieldValues.forEach(function (val) { val.available = true; })
            });
            pm.model.engravingProduct = [];
            //pm.model.engravingProduct = pm.model.relatedProductList.filter(x => x.itemType == pm.EngravingItemType);
            angular.forEach(pm.model.relatedProductList, function (prod) {
                if (prod.itemType == pm.EngravingItemType) {
                    pm.model.engravingProduct.push(prod);
                }
            });
            pm.priceWithEngraving = pm.model.price.raw.withTax + pm.model.engravingProduct[0].price.raw.withTax;
            changeCurrecyValueForEngraving(pm.priceWithEngraving);
            var selectedProduct = pm.model.variantProducts.filter(function (p) { return p.stockCode === pm.model.stockCode; })[0];
            if (selectedProduct != undefined) {
                selectedProduct.variantAttributes.forEach(function (pAttr) {
                    var attrFromMaster = pm.model.variantProductsAttribute.filter(function (attr) { return attr.fieldCode === pAttr.fieldCode })[0];
                    var matchedAttr = attrFromMaster.fieldValues.filter(function (fieldVal) { return fieldVal.fieldValue === pAttr.fieldValue })[0];
                    matchedAttr.selected = true;
                    attrFromMaster.selectedValue = matchedAttr.fieldValue;
                });
            }
        }

        function productQty(qty) {
            if (pm.productCount == 1 && qty == -1) { return; }
            pm.productCount = parseInt(pm.productCount) + qty;
        }

        function beginQuestionnaire(productId, questionnaireCode) {
            pm.model.survey = {};
            $http.post(productConfig.questionnaireCode, { questionnaireCode: questionnaireCode }).success(function (resp) {
                pm.model.survey = resp;
                $('#QualifyingQuestionnaire').modal('show');
            });
        }

        function submitSurvey(productId) {

            //this is where we submit the whole survey using AJAX call.
            pm.surveyCompleted = true;
            var answers = []; var multipleAnswers = "";
            pm.model.survey.result.wrongOptionCount = 0;
            //save answers in an array
            angular.forEach(pm.model.survey.result.questions, function (value, key) {
                multipleAnswers = "";
                if (value.selectedOptionValue == "" || value.showHelpText == true) {
                    pm.model.survey.result.wrongOptionCount = (pm.model.survey.result.wrongOptionCount + 1);
                }
                if (multipleAnswers != "") {
                    answers.push({ "questionId": value.recordId, "question": value.question, "selectedAnswer": multipleAnswers });
                }
                else {
                    answers.push({ "questionId": value.recordId, "question": value.question, "selectedAnswer": value.selectedOptionValue });
                }
            });

            //save survey.
            if (pm.model.survey.result.wrongOptionCount == 0) {
                $http.post("/Survey/SaveAnswerBulk", { surveyId: pm.model.survey.result.recordId, answers: answers, productId: productId }).then(function (success) {
                    $('#QualifyingQuestionnaire').modal('hide');
                    pm.model.canAddToBag = true;
                }, function (error) { })
            }
        }

        function rotateImage(deg) {
            if (pm.degree == 270) {
                $(".magnify-image").removeClass("rotate" + pm.degree);
                pm.degree = 0;
            }
            else {
                $(".magnify-image").removeClass("rotate" + pm.degree);
                pm.degree += deg;
                $(".magnify-image").addClass("rotate" + pm.degree);
            }

        }
        function onTextFocus(event) {
            event.target.select();
        }
        function getGrid() {
            $("#view").addClass('gridView');
            $("#view").removeClass('listView');
            pm.getView = true;
        }
        function getList() {
            $("#view").removeClass('gridView');
            $("#view").addClass('listView');
            pm.getView = false;
        }

        PubSub.subscribe('wishListData', function (wishlistData) {
            pm.productModel = wishlistData;
        });

        function getStoreStockAvailability() {
            if (pm.postCode != null) {
                pm.noStore = false;
                pm.postCodeInValid = false;
                $http.post(productConfig.stockAvailabilityUrl, { stockCode: pm.model.stockCode, postCode: pm.postCode }).success(function (resp) {
                    pm.stores = resp;
                    if (pm.stores != null && pm.stores.length > 0) {
                        pm.showStoresOnMap(pm.stores);
                        $('#storeInfo').modal('show');
                        if (pm.stores != null) {
                            angular.forEach(pm.stores, function (store) {
                                store.distanceFromPostCode = Math.ceil(store.distanceFromPostCode);
                            });
                        }
                    }
                    else {
                        pm.noStore = true;
                    }
                });
            }
            else {
                pm.postCodeInValid = false;
                pm.postCodeInValid = true;
            }
        }
        pm.createMap = createMap;
        pm.showStoresOnMap = showStoresOnMap;
        function createMap() {
            var mapOptions = {
                zoom: 9,
                mapTypeId: google.maps.MapTypeId.ROADMAP
            };
            pm.map = new google.maps.Map(document.getElementById('map'), mapOptions);
        }
        function showStoresOnMap(stores) {
            pm.markers = [];
            var mapOptions = {
                zoom: 9,
                center: new google.maps.LatLng(stores[0].latitude, stores[0].longitude),
                mapTypeId: google.maps.MapTypeId.ROADMAP
            };
            pm.map = new google.maps.Map(document.getElementById('map'), mapOptions);
            var bounds = new google.maps.LatLngBounds();
            var infoWindow = new google.maps.InfoWindow();
            var pinImage = new google.maps.MarkerImage('/assets/theme/tfs/images/map-pin.png');
            angular.forEach(stores, function (store) {
                var latLng = new google.maps.LatLng(store.latitude, store.longitude);
                var marker = new google.maps.Marker({
                    map: pm.map,
                    position: latLng,
                    title: store.name,
                    icon: pinImage
                });
                marker.content = '<div class="infoWindowContent">' + store.name + '</div>';
                google.maps.event.addListener(marker, 'click', function () {
                    infoWindow.setContent('<h2>' + marker.title + '</h2>' + marker.content);
                    infoWindow.open(pm.map, marker);
                });

                bounds.extend(latLng);
                pm.markers.push(marker);
            });
            pm.map.fitBounds(bounds);
            pm.map.panToBounds(bounds);
            var listener = google.maps.event.addListener(pm.map, "idle", function () {
                pm.map.setZoom(9);
                google.maps.event.removeListener(listener);
            });
        }
        function getHtml(content) {
            return $sce.trustAsHtml(content);
        };
        function videoPopupModal() {
            $('#videoPopupModal').modal('show');
        }
        function deletedFromWishlist(productId) {
            $http.post("/TFSAccount/RemoveWishList", { id: productId }).then(function (resp) {
                pm.productModel = resp.data;
                pm.IsDeletedFromWishlist = true;
                $timeout(function () {
                    $(".deleteWishdiv").fadeOut();
                    pm.IsDeletedFromWishlist = false;
                }, 2000);
            }, function (error) { });
        }
        function getProductReview() {
            pm.model.reviews = [];
            if (pm.model.hideReviews) {
                return;
            }
            var stockCodes = [];
            stockCodes.push(pm.model.stockCode);
            if (pm.model.variantProducts != null && pm.model.variantProducts.length > 0) {
                angular.forEach(pm.model.variantProducts, function (variant) {
                    stockCodes.push(variant.stockCode);
                });
            }
            $http.post(productConfig.getProductReviewsUrl, stockCodes).success(function (resp) {
                if (resp != null) {
                    var ratingTotal = 0;
                    pm.reviews = resp;
                    pm.model.reviews = resp;
                    angular.forEach(pm.model.reviews, function (review) {
                        ratingTotal += review.rating.avgRating;
                    });
                    pm.productAvgRating = (ratingTotal / pm.model.reviews.length) * 20;
                }
            }, function (error) { });
        }

        function fetchMoreReviews(stocks) {
            $http.post("/TFSProduct/FetchMoreReviews", { currentPage: 1, stockCodes: stocks, pageSize: 100 }).success(function (resp) {
                $("#feefoReview").remove();
                $("#reviewContainer").append($(resp));
            });
        };



        function slugifyUrl(url) {
            url = url || '';
            return url.replace(/ /g, '-').toLowerCase();
        }

        function brandCarousels() {
            setTimeout(function () {
                if (typeof Swiper !== 'undefined') {
                    let spaceBetween = 30;
                    if (typeof luxuryTemplateV2 !== 'undefined' && luxuryTemplateV2 === true) {
                        spaceBetween = 10;
                    }
                    new Swiper('.swiper-container', {
                        slidesPerView: 2,
                        slidesPerGroup: 2,
                        spaceBetween: spaceBetween,
                        navigation: {
                            nextEl: '.swiper-button-next',
                            prevEl: '.swiper-button-prev',
                        },
                        observer: true,
                        observeParents: true,
                        breakpoints: {
                            768: {
                                slidesPerView: 3,
                                slidesPerGroup: 3,
                            },
                            992: {
                                slidesPerView: 4,
                                slidesPerGroup: 4,
                            },
                        }
                    });
                }
            }, 500);
        }

        function searchCollectionProducts(manufacturerSettings) {
            pm.collectionListTemp = [];
            angular.forEach(manufacturerSettings.split(','), function (value, key) {
                var resp = value.split(':');
                if (resp != null && resp[0].toLowerCase() != 'displayorder' && resp[0].toLowerCase() != 'morevideo') {
                    if (resp.length > 1) {
                        var tempData = resp[1].split('__');
                        var tempHeading = null;
                        if (tempData != null && tempData.length > 2) {
                            tempHeading = tempData[2];
                        }
                        if (tempData != null && tempData.length > 1) {
                            pm.collectionList.push({ key: resp[0], value: tempData[1], heading: tempHeading });
                            pm.collectionListTemp.push({ key: resp[0], value: tempData[1] });
                        }
                    }
                }
            });
            $http.post(productConfig.getCollectionProductsUrl, pm.collectionListTemp)
                .success(function (data) {
                    brandCarousels();
                    if (data != null) {
                        pm.collectionProuducts = data;
                        if (pm.collectionProuducts != null) {
                            angular.forEach(pm.collectionList, function (value, key) {
                                if (pm.collectionProuducts.bestseller != null && pm.collectionProuducts.bestseller.searchCriteria.collectionId.toLowerCase() == value.value.toLowerCase()) {
                                    pm.collectionProuducts.bestseller.heading = value.heading;
                                }
                                else if (pm.collectionProuducts.bestsellerwomen && pm.collectionProuducts.bestsellerwomen.searchCriteria.collectionId.toLowerCase() == value.value.toLowerCase()) {
                                    pm.collectionProuducts.bestsellerwomen.heading = value.heading;
                                }
                                else if (pm.collectionProuducts.bestsellermen && pm.collectionProuducts.bestsellermen.searchCriteria.collectionId.toLowerCase() == value.value.toLowerCase()) {
                                    pm.collectionProuducts.bestsellermen.heading = value.heading;
                                }
                                else if (pm.collectionProuducts.newrelease && pm.collectionProuducts.newrelease.searchCriteria.collectionId.toLowerCase() == value.value.toLowerCase()) {
                                    pm.collectionProuducts.newrelease.heading = value.heading;
                                }
                            });
                            var noOfItemInRow = 4;
                            if (window != null && window.innerWidth != null && window.innerWidth <= 767) {
                                noOfItemInRow = 2;
                            }
                            if (pm.collectionProuducts.bestsellerwomen != null && pm.collectionProuducts.bestsellerwomen.results != null) {
                                var tempCount = pm.collectionProuducts.bestsellerwomen.results.length / noOfItemInRow;
                                var tempList = [];
                                var tempCounter = 0;
                                var count = 0;
                                var tempArray = [];
                                var totalProcessedItem = 0;
                                angular.forEach(pm.collectionProuducts.bestsellerwomen.results, function (value, key) {

                                    tempArray.push(value);
                                    count = count + 1;
                                    totalProcessedItem = totalProcessedItem + 1;
                                });
                                pm.collectionProuducts.bestsellerwomen.productSet = tempArray;
                            }
                            if (pm.collectionProuducts.bestsellermen != null && pm.collectionProuducts.bestsellermen.results != null) {
                                var tempCount = pm.collectionProuducts.bestsellermen.results.length / noOfItemInRow;
                                var tempList = [];
                                var tempCounter = 0;
                                var count = 0;
                                var tempArray = [];
                                var totalProcessedItem = 0;
                                angular.forEach(pm.collectionProuducts.bestsellermen.results, function (value, key) {
                                    tempArray.push(value);
                                    count = count + 1;
                                    totalProcessedItem = totalProcessedItem + 1;
                                });
                                pm.collectionProuducts.bestsellermen.productSet = tempArray;
                            }
                        }
                    }
                })
                .error(function (msg) {
                })
                .finally(function () {
                    pm.currencyCookie = $.cookie(CURRENCYCOOKIE.CurrencyCode);
                    pm.changeBaseCurrency(pm.currencyCookie);
                });
        }

        function hideGiftCardMsg() {
            $timeout(function () {
                $(".giftCardMsg").fadeOut();
            }, 3000);
        }
        pm.showChangedCurrency = false;
        function changeBaseCurrency(changeToCurrencyCode) {
            if (changeToCurrencyCode == null)
                changeToCurrencyCode = $.cookie(CURRENCYCOOKIE.CurrencyCode);
            if (changeToCurrencyCode) {
                $http.get(productConfig.currencyExchangeRate + "?changeToCurrencyCode=" + changeToCurrencyCode).then(function (resp) {
                    if (resp != null && resp.data != false && resp.data.rate != 1) {
                        pm.showChangedCurrency = true;
                        pm.selectedCurrencySymbol = resp.data.currencySymbol;
                        pm.currencyExchangeRate = resp.data.rate;
                        if (pm.productResponse != null && pm.productResponse.results) {
                            angular.forEach(pm.productResponse.results, function (product) {
                                product.currencyExchangedPriceRaw = product.price.raw.withTax * resp.data.rate;
                                product.currencyExchangedPriceFormatted = pm.selectedCurrencySymbol + product.currencyExchangedPriceRaw.toFixed(2);
                                product.currencyExchangedListPriceFormatted = pm.selectedCurrencySymbol + (product.listPrice.raw.withTax * resp.data.rate).toFixed(2);
                                product.currencyExchangedPriceFromFormatted = pm.selectedCurrencySymbol + (product.priceFrom.raw.withTax * resp.data.rate).toFixed(2);
                                product.currencyExchangedRRP = pm.selectedCurrencySymbol + ((product.listPrice.raw.withTax - product.price.raw.withTax) * resp.data.rate).toFixed(2);
                            });
                        }
                        if (pm.collectionProuducts != null && pm.collectionProuducts.bestsellerwomen != null && pm.collectionProuducts.bestsellerwomen.productSet != null) {
                            angular.forEach(pm.collectionProuducts.bestsellerwomen.productSet, function (prodSetWomen) {
                                angular.forEach(prodSetWomen.productsList, function (prodWomen) {
                                    prodWomen.currencyExchangedPriceFrom = pm.selectedCurrencySymbol + (prodWomen.priceFrom.raw.withTax * resp.data.rate).toFixed(2);
                                    prodWomen.currencyExchangedPrice = pm.selectedCurrencySymbol + (prodWomen.price.raw.withTax * resp.data.rate).toFixed(2);
                                    prodWomen.currencyExchangedListPriceFormatted = pm.selectedCurrencySymbol + (prodWomen.listPrice.raw.withTax * resp.data.rate).toFixed(2);
                                    prodWomen.currencyExchangedSavingFormatted = pm.selectedCurrencySymbol + ((prodWomen.listPrice.raw.withTax - prodWomen.price.raw.withTax) * resp.data.rate).toFixed(2);
                                });
                            });
                        }
                        if (pm.collectionProuducts != null && pm.collectionProuducts.bestsellermen != null && pm.collectionProuducts.bestsellermen.productSet != null) {
                            angular.forEach(pm.collectionProuducts.bestsellermen.productSet, function (prodSetMen) {
                                angular.forEach(prodSetMen.productsList, function (prodMen) {
                                    prodMen.currencyExchangedPriceFrom = pm.selectedCurrencySymbol + (prodMen.priceFrom.raw.withTax * resp.data.rate).toFixed(2);
                                    prodMen.currencyExchangedPrice = pm.selectedCurrencySymbol + (prodMen.price.raw.withTax * resp.data.rate).toFixed(2);
                                    prodMen.currencyExchangedListPriceFormatted = pm.selectedCurrencySymbol + (prodMen.listPrice.raw.withTax * resp.data.rate).toFixed(2);
                                    prodMen.currencyExchangedSavingFormatted = pm.selectedCurrencySymbol + ((prodMen.listPrice.raw.withTax - prodMen.price.raw.withTax) * resp.data.rate).toFixed(2);
                                });
                            });
                        }
                    }
                    else
                        pm.showChangedCurrency = false;
                    $.cookie("_ctcc", changeToCurrencyCode, { path: '/', expires: 1000 });
                }, function (error) {
                });
            }
        }

        function changeCurrecyValueForEngraving(priceWithEngraving) {
            var currencyCookie = $.cookie("_ctcc");
            var isSubscriptionEnabled = $(".subscriptionEnabled").val();
            if (currencyCookie != null && !isSubscriptionEnabled) {
                $.get('/Home/GetCurrencyExchangeRate' + "?changeToCurrencyCode=" + currencyCookie, function (data) {
                    if (data != null && data != false && data.rate != 1) {
                        var engravingPrice = $(".proEngravingPriceRaw").val();
                        if (engravingPrice.length == 0 && pm.model.engravingProduct != null && pm.model.engravingProduct.length > 0) {
                            engravingPrice = pm.model.engravingProduct[0].price.raw.withTax;
                        }
                        var selectedCurrencyData = data;
                        var currencyExchangeEngravingPrice = selectedCurrencyData.currencySymbol + (engravingPrice * selectedCurrencyData.rate).toFixed(2);
                        var currencyEngravePriceExchangePrice = selectedCurrencyData.currencySymbol + (priceWithEngraving * selectedCurrencyData.rate).toFixed(2);
                        $(".engravePriceFormatted").html(currencyEngravePriceExchangePrice);
                        $(".proEngravingPriceFormatted").html(currencyExchangeEngravingPrice);
                    }
                });
            }
        }
    };
})();
;
(function ($, undefined) {
    'use strict';
    var defaults = {
        item: 3,
        autoWidth: false,
        slideMove: 1,
        slideMargin: 10,
        addClass: '',
        mode: 'slide',
        useCSS: true,
        cssEasing: 'ease', //'cubic-bezier(0.25, 0, 0.25, 1)',
        easing: 'linear', //'for jquery animation',//
        speed: 400, //ms'
        auto: false,
        pauseOnHover: false,
        loop: false,
        slideEndAnimation: true,
        pause: 2000,
        keyPress: false,
        controls: true,
        prevHtml: '',
        nextHtml: '',
        rtl: false,
        adaptiveHeight: false,
        vertical: false,
        verticalHeight: 500,
        vThumbWidth: 100,
        thumbItem: 10,
        pager: true,
        gallery: false,
        galleryMargin: 5,
        thumbMargin: 5,
        currentPagerPosition: 'middle',
        enableTouch: true,
        enableDrag: true,
        freeMove: true,
        swipeThreshold: 40,
        responsive: [],
        /* jshint ignore:start */
        onBeforeStart: function ($el) {},
        onSliderLoad: function ($el) {},
        onBeforeSlide: function ($el, scene) {},
        onAfterSlide: function ($el, scene) {},
        onBeforeNextSlide: function ($el, scene) {},
        onBeforePrevSlide: function ($el, scene) {}
        /* jshint ignore:end */
    };
    $.fn.lightSlider = function (options) {
        if (this.length === 0) {
            return this;
        }

        if (this.length > 1) {
            this.each(function () {
                $(this).lightSlider(options);
            });
            return this;
        }

        var plugin = {},
            settings = $.extend(true, {}, defaults, options),
            settingsTemp = {},
            $el = this;
        plugin.$el = this;

        if (settings.mode === 'fade') {
            settings.vertical = false;
        }
        var $children = $el.children(),
            windowW = $(window).width(),
            breakpoint = null,
            resposiveObj = null,
            length = 0,
            w = 0,
            on = false,
            elSize = 0,
            $slide = '',
            scene = 0,
            property = (settings.vertical === true) ? 'height' : 'width',
            gutter = (settings.vertical === true) ? 'margin-bottom' : 'margin-right',
            slideValue = 0,
            pagerWidth = 0,
            slideWidth = 0,
            thumbWidth = 0,
            interval = null,
            isTouch = ('ontouchstart' in document.documentElement);
        var refresh = {};

        refresh.chbreakpoint = function () {
            windowW = $(window).width();
            if (settings.responsive.length) {
                var item;
                if (settings.autoWidth === false) {
                    item = settings.item;
                }
                if (windowW < settings.responsive[0].breakpoint) {
                    for (var i = 0; i < settings.responsive.length; i++) {
                        if (windowW < settings.responsive[i].breakpoint) {
                            breakpoint = settings.responsive[i].breakpoint;
                            resposiveObj = settings.responsive[i];
                        }
                    }
                }
                if (typeof resposiveObj !== 'undefined' && resposiveObj !== null) {
                    for (var j in resposiveObj.settings) {
                        if (resposiveObj.settings.hasOwnProperty(j)) {
                            if (typeof settingsTemp[j] === 'undefined' || settingsTemp[j] === null) {
                                settingsTemp[j] = settings[j];
                            }
                            settings[j] = resposiveObj.settings[j];
                        }
                    }
                }
                if (!$.isEmptyObject(settingsTemp) && windowW > settings.responsive[0].breakpoint) {
                    for (var k in settingsTemp) {
                        if (settingsTemp.hasOwnProperty(k)) {
                            settings[k] = settingsTemp[k];
                        }
                    }
                }
                if (settings.autoWidth === false) {
                    if (slideValue > 0 && slideWidth > 0) {
                        if (item !== settings.item) {
                            scene = Math.round(slideValue / ((slideWidth + settings.slideMargin) * settings.slideMove));
                        }
                    }
                }
            }
        };

        refresh.calSW = function () {
            if (settings.autoWidth === false) {
                slideWidth = (elSize - ((settings.item * (settings.slideMargin)) - settings.slideMargin)) / settings.item;
            }
        };

        refresh.calWidth = function (cln) {
            var ln = cln === true ? $slide.find('.lslide').length : $children.length;
            if (settings.autoWidth === false) {
                w = ln * (slideWidth + settings.slideMargin);
            } else {
                w = 0;
                for (var i = 0; i < ln; i++) {
                    w += (parseInt($children.eq(i).width()) + settings.slideMargin);
                }
            }
            return w;
        };
        plugin = {
            doCss: function () {
                var support = function () {
                    var transition = ['transition', 'MozTransition', 'WebkitTransition', 'OTransition', 'msTransition', 'KhtmlTransition'];
                    var root = document.documentElement;
                    for (var i = 0; i < transition.length; i++) {
                        if (transition[i] in root.style) {
                            return true;
                        }
                    }
                };
                if (settings.useCSS && support()) {
                    return true;
                }
                return false;
            },
            keyPress: function () {
                if (settings.keyPress) {
                    $(document).on('keyup.lightslider', function (e) {
                        if (!$(':focus').is('input, textarea')) {
                            if (e.preventDefault) {
                                e.preventDefault();
                            } else {
                                e.returnValue = false;
                            }
                            if (e.keyCode === 37) {
                                $el.goToPrevSlide();
                            } else if (e.keyCode === 39) {
                                $el.goToNextSlide();
                            }
                        }
                    });
                }
            },
            controls: function () {
                if (settings.controls) {
                    $el.after('<div class="lSAction"><a class="lSPrev">' + settings.prevHtml + '</a><a class="lSNext">' + settings.nextHtml + '</a></div>');
                    if (!settings.autoWidth) {
                        if (length <= settings.item) {
                            $slide.find('.lSAction').hide();
                        }
                    } else {
                        if (refresh.calWidth(false) < elSize) {
                            $slide.find('.lSAction').hide();
                        }
                    }
                    $slide.find('.lSAction a').on('click', function (e) {
                        if (e.preventDefault) {
                            e.preventDefault();
                        } else {
                            e.returnValue = false;
                        }
                        if ($(this).attr('class') === 'lSPrev') {
                            $el.goToPrevSlide();
                        } else {
                            $el.goToNextSlide();
                        }
                        return false;
                    });
                }
            },
            initialStyle: function () {
                var $this = this;
                if (settings.mode === 'fade') {
                    settings.autoWidth = false;
                    settings.slideEndAnimation = false;
                }
                if (settings.auto) {
                    settings.slideEndAnimation = false;
                }
                if (settings.autoWidth) {
                    settings.slideMove = 1;
                    settings.item = 1;
                }
                if (settings.loop) {
                    settings.slideMove = 1;
                    settings.freeMove = false;
                }
                settings.onBeforeStart.call(this, $el);
                refresh.chbreakpoint();
                $el.addClass('lightSlider').wrap('<div class="lSSlideOuter ' + settings.addClass + '"><div class="lSSlideWrapper"></div></div>');
                $slide = $el.parent('.lSSlideWrapper');
                if (settings.rtl === true) {
                    $slide.parent().addClass('lSrtl');
                }
                if (settings.vertical) {
                    $slide.parent().addClass('vertical');
                    elSize = settings.verticalHeight;
                    $slide.css('height', elSize + 'px');
                } else {
                    elSize = $el.outerWidth();
                }
                $children.addClass('lslide');
                if (settings.loop === true && settings.mode === 'slide') {
                    refresh.calSW();
                    refresh.clone = function () {
                        if (refresh.calWidth(true) > elSize) {
                            /**/
                            var tWr = 0,
                                tI = 0;
                            for (var k = 0; k < $children.length; k++) {
                                tWr += (parseInt($el.find('.lslide').eq(k).width()) + settings.slideMargin);
                                tI++;
                                if (tWr >= (elSize + settings.slideMargin)) {
                                    break;
                                }
                            }
                            var tItem = settings.autoWidth === true ? tI : settings.item;

                            /**/
                            if (tItem < $el.find('.clone.left').length) {
                                for (var i = 0; i < $el.find('.clone.left').length - tItem; i++) {
                                    $children.eq(i).remove();
                                }
                            }
                            if (tItem < $el.find('.clone.right').length) {
                                for (var j = $children.length - 1; j > ($children.length - 1 - $el.find('.clone.right').length); j--) {
                                    scene--;
                                    $children.eq(j).remove();
                                }
                            }
                            /**/
                            for (var n = $el.find('.clone.right').length; n < tItem; n++) {
                                $el.find('.lslide').eq(n).clone().removeClass('lslide').addClass('clone right').appendTo($el);
                                scene++;
                            }
                            for (var m = $el.find('.lslide').length - $el.find('.clone.left').length; m > ($el.find('.lslide').length - tItem); m--) {
                                $el.find('.lslide').eq(m - 1).clone().removeClass('lslide').addClass('clone left').prependTo($el);
                            }
                            $children = $el.children();
                        } else {
                            if ($children.hasClass('clone')) {
                                $el.find('.clone').remove();
                                $this.move($el, 0);
                            }
                        }
                    };
                    refresh.clone();
                }
                refresh.sSW = function () {
                    length = $children.length;
                    if (settings.rtl === true && settings.vertical === false) {
                        gutter = 'margin-left';
                    }
                    if (settings.autoWidth === false) {
                        $children.css(property, slideWidth + 'px');
                    }
                    $children.css(gutter, settings.slideMargin + 'px');
                    w = refresh.calWidth(false);
                    $el.css(property, w + 'px');
                    if (settings.loop === true && settings.mode === 'slide') {
                        if (on === false) {
                            scene = $el.find('.clone.left').length;
                        }
                    }
                };
                refresh.calL = function () {
                    $children = $el.children();
                    length = $children.length;
                };
                if (this.doCss()) {
                    $slide.addClass('usingCss');
                }
                refresh.calL();
                if (settings.mode === 'slide') {
                    refresh.calSW();
                    refresh.sSW();
                    if (settings.loop === true) {
                        slideValue = $this.slideValue();
                        this.move($el, slideValue);
                    }
                    if (settings.vertical === false) {
                        this.setHeight($el, false);
                    }

                } else {
                    this.setHeight($el, true);
                    $el.addClass('lSFade');
                    if (!this.doCss()) {
                        $children.fadeOut(0);
                        $children.eq(scene).fadeIn(0);
                    }
                }
                if (settings.loop === true && settings.mode === 'slide') {
                    $children.eq(scene).addClass('active');
                } else {
                    $children.first().addClass('active');
                }
            },
            pager: function () {
                var $this = this;
                refresh.createPager = function () {
                    thumbWidth = (elSize - ((settings.thumbItem * (settings.thumbMargin)) - settings.thumbMargin)) / settings.thumbItem;
                    var $children = $slide.find('.lslide');
                    var length = $slide.find('.lslide').length;
                    var i = 0,
                        pagers = '',
                        v = 0;
                    for (i = 0; i < length; i++) {
                        if (settings.mode === 'slide') {
                            // calculate scene * slide value
                            if (!settings.autoWidth) {
                                v = i * ((slideWidth + settings.slideMargin) * settings.slideMove);
                            } else {
                                v += ((parseInt($children.eq(i).width()) + settings.slideMargin) * settings.slideMove);
                            }
                        }
                        var thumb = $children.eq(i * settings.slideMove).attr('data-thumb');
                        if (settings.gallery === true) {
                            pagers += '<li style="width:100%;' + property + ':' + thumbWidth + 'px;' + gutter + ':' + settings.thumbMargin + 'px"><a href="#"><img src="' + thumb + '" /></a></li>';
                        } else {
                            pagers += '<li><a href="#">' + (i + 1) + '</a></li>';
                        }
                        if (settings.mode === 'slide') {
                            if ((v) >= w - elSize - settings.slideMargin) {
                                i = i + 1;
                                var minPgr = 2;
                                if (settings.autoWidth) {
                                    pagers += '<li><a href="#">' + (i + 1) + '</a></li>';
                                    minPgr = 1;
                                }
                                if (i < minPgr) {
                                    pagers = null;
                                    $slide.parent().addClass('noPager');
                                } else {
                                    $slide.parent().removeClass('noPager');
                                }
                                break;
                            }
                        }
                    }
                    var $cSouter = $slide.parent();
                    $cSouter.find('.lSPager').html(pagers); 
                    if (settings.gallery === true) {
                        if (settings.vertical === true) {
                            // set Gallery thumbnail width
                            $cSouter.find('.lSPager').css('width', settings.vThumbWidth + 'px');
                        }
                        pagerWidth = (i * (settings.thumbMargin + thumbWidth)) + 0.5;
                        $cSouter.find('.lSPager').css({
                            property: pagerWidth + 'px',
                            'transition-duration': settings.speed + 'ms'
                        });
                        if (settings.vertical === true) {
                            $slide.parent().css('padding-right', (settings.vThumbWidth + settings.galleryMargin) + 'px');
                        }
                        $cSouter.find('.lSPager').css(property, pagerWidth + 'px');
                    }
                    var $pager = $cSouter.find('.lSPager').find('li');
                    $pager.first().addClass('active');
                    $pager.on('click', function () {
                        if (settings.loop === true && settings.mode === 'slide') {
                            scene = scene + ($pager.index(this) - $cSouter.find('.lSPager').find('li.active').index());
                        } else {
                            scene = $pager.index(this);
                        }
                        $el.mode(false);
                        if (settings.gallery === true) {
                            $this.slideThumb();
                        }
                        return false;
                    });
                };
                if (settings.pager) {
                    var cl = 'lSpg';
                    if (settings.gallery) {
                        cl = 'lSGallery';
                    }
                    $slide.after('<ul class="lSPager ' + cl + '"></ul>');
                    var gMargin = (settings.vertical) ? 'margin-left' : 'margin-top';
                    $slide.parent().find('.lSPager').css(gMargin, settings.galleryMargin + 'px');
                    refresh.createPager();
                }

                setTimeout(function () {
                    refresh.init();
                }, 0);
            },
            setHeight: function (ob, fade) {
                var obj = null,
                    $this = this;
                if (settings.loop) {
                    obj = ob.children('.lslide ').first();
                } else {
                    obj = ob.children().first();
                }
                var setCss = function () {
                    var tH = obj.outerHeight(),
                        tP = 0,
                        tHT = tH;
                    if (fade) {
                        tH = 0;
                        tP = ((tHT) * 100) / elSize;
                    }
                    ob.css({
                        'height': tH + 'px',
                        'padding-bottom': tP + '%'
                    });
                };
                setCss();
                if (obj.find('img').length) {
                    if ( obj.find('img')[0].complete) {
                        setCss();
                        if (!interval) {
                            $this.auto();
                        }   
                    }else{
                        obj.find('img').on('load', function () {
                            setTimeout(function () {
                                setCss();
                                if (!interval) {
                                    $this.auto();
                                }
                            }, 100);
                        });
                    }
                }else{
                    if (!interval) {
                        $this.auto();
                    }
                }
            },
            active: function (ob, t) {
                if (this.doCss() && settings.mode === 'fade') {
                    $slide.addClass('on');
                }
                var sc = 0;
                if (scene * settings.slideMove < length) {
                    ob.removeClass('active');
                    if (!this.doCss() && settings.mode === 'fade' && t === false) {
                        ob.fadeOut(settings.speed);
                    }
                    if (t === true) {
                        sc = scene;
                    } else {
                        sc = scene * settings.slideMove;
                    }
                    //t === true ? sc = scene : sc = scene * settings.slideMove;
                    var l, nl;
                    if (t === true) {
                        l = ob.length;
                        nl = l - 1;
                        if (sc + 1 >= l) {
                            sc = nl;
                        }
                    }
                    if (settings.loop === true && settings.mode === 'slide') {
                        //t === true ? sc = scene - $el.find('.clone.left').length : sc = scene * settings.slideMove;
                        if (t === true) {
                            sc = scene - $el.find('.clone.left').length;
                        } else {
                            sc = scene * settings.slideMove;
                        }
                        if (t === true) {
                            l = ob.length;
                            nl = l - 1;
                            if (sc + 1 === l) {
                                sc = nl;
                            } else if (sc + 1 > l) {
                                sc = 0;
                            }
                        }
                    }

                    if (!this.doCss() && settings.mode === 'fade' && t === false) {
                        ob.eq(sc).fadeIn(settings.speed);
                    }
                    ob.eq(sc).addClass('active');
                } else {
                    ob.removeClass('active');
                    ob.eq(ob.length - 1).addClass('active');
                    if (!this.doCss() && settings.mode === 'fade' && t === false) {
                        ob.fadeOut(settings.speed);
                        ob.eq(sc).fadeIn(settings.speed);
                    }
                }
            },
            move: function (ob, v) {
                if (settings.rtl === true) {
                    v = -v;
                }
                if (this.doCss()) {
                    if (settings.vertical === true) {
                        ob.css({
                            'transform': 'translate3d(0px, ' + (-v) + 'px, 0px)',
                            '-webkit-transform': 'translate3d(0px, ' + (-v) + 'px, 0px)'
                        });
                    } else {
                        ob.css({
                            'transform': 'translate3d(' + (-v) + 'px, 0px, 0px)',
                            '-webkit-transform': 'translate3d(' + (-v) + 'px, 0px, 0px)',
                        });
                    }
                } else {
                    if (settings.vertical === true) {
                        ob.css('position', 'relative').animate({
                            top: -v + 'px'
                        }, settings.speed, settings.easing);
                    } else {
                        ob.css('position', 'relative').animate({
                            left: -v + 'px'
                        }, settings.speed, settings.easing);
                    }
                }
                var $thumb = $slide.parent().find('.lSPager').find('li');
                this.active($thumb, true);
            },
            fade: function () {
                this.active($children, false);
                var $thumb = $slide.parent().find('.lSPager').find('li');
                this.active($thumb, true);
            },
            slide: function () {
                var $this = this;
                refresh.calSlide = function () {
                    if (w > elSize) {
                        slideValue = $this.slideValue();
                        $this.active($children, false);
                        if ((slideValue) > w - elSize - settings.slideMargin) {
                            slideValue = w - elSize - settings.slideMargin;
                        } else if (slideValue < 0) {
                            slideValue = 0;
                        }
                        $this.move($el, slideValue);
                        if (settings.loop === true && settings.mode === 'slide') {
                            if (scene >= (length - ($el.find('.clone.left').length / settings.slideMove))) {
                                $this.resetSlide($el.find('.clone.left').length);
                            }
                            if (scene === 0) {
                                $this.resetSlide($slide.find('.lslide').length);
                            }
                        }
                    }
                };
                refresh.calSlide();
            },
            resetSlide: function (s) {
                var $this = this;
                $slide.find('.lSAction a').addClass('disabled');
                setTimeout(function () {
                    scene = s;
                    $slide.css('transition-duration', '0ms');
                    slideValue = $this.slideValue();
                    $this.active($children, false);
                    plugin.move($el, slideValue);
                    setTimeout(function () {
                        $slide.css('transition-duration', settings.speed + 'ms');
                        $slide.find('.lSAction a').removeClass('disabled');
                    }, 50);
                }, settings.speed + 100);
            },
            slideValue: function () {
                var _sV = 0;
                if (settings.autoWidth === false) {
                    _sV = scene * ((slideWidth + settings.slideMargin) * settings.slideMove);
                } else {
                    _sV = 0;
                    for (var i = 0; i < scene; i++) {
                        _sV += (parseInt($children.eq(i).width()) + settings.slideMargin);
                    }
                }
                return _sV;
            },
            slideThumb: function () {
                var position;
                switch (settings.currentPagerPosition) {
                case 'left':
                    position = 0;
                    break;
                case 'middle':
                    position = (elSize / 2) - (thumbWidth / 2);
                    break;
                case 'right':
                    position = elSize - thumbWidth;
                }
                var sc = scene - $el.find('.clone.left').length;
                var $pager = $slide.parent().find('.lSPager');
                if (settings.mode === 'slide' && settings.loop === true) {
                    if (sc >= $pager.children().length) {
                        sc = 0;
                    } else if (sc < 0) {
                        sc = $pager.children().length;
                    }
                }
                var thumbSlide = sc * ((thumbWidth + settings.thumbMargin)) - (position);
                if ((thumbSlide + elSize) > pagerWidth) {
                    thumbSlide = pagerWidth - elSize - settings.thumbMargin;
                }
                if (thumbSlide < 0) {
                    thumbSlide = 0;
                }
                this.move($pager, thumbSlide);
            },
            auto: function () {
                if (settings.auto) {
                    clearInterval(interval);
                    interval = setInterval(function () {
                        $el.goToNextSlide();
                    }, settings.pause);
                }
            },
            pauseOnHover: function(){
                var $this = this;
                if (settings.auto && settings.pauseOnHover) {
                    $slide.on('mouseenter', function(){
                        $(this).addClass('ls-hover');
                        $el.pause();
                        settings.auto = true;
                    });
                    $slide.on('mouseleave',function(){
                        $(this).removeClass('ls-hover');
                        if (!$slide.find('.lightSlider').hasClass('lsGrabbing')) {
                            $this.auto();
                        }
                    });
                }
            },
            touchMove: function (endCoords, startCoords) {
                $slide.css('transition-duration', '0ms');
                if (settings.mode === 'slide') {
                    var distance = endCoords - startCoords;
                    var swipeVal = slideValue - distance;
                    if ((swipeVal) >= w - elSize - settings.slideMargin) {
                        if (settings.freeMove === false) {
                            swipeVal = w - elSize - settings.slideMargin;
                        } else {
                            var swipeValT = w - elSize - settings.slideMargin;
                            swipeVal = swipeValT + ((swipeVal - swipeValT) / 5);

                        }
                    } else if (swipeVal < 0) {
                        if (settings.freeMove === false) {
                            swipeVal = 0;
                        } else {
                            swipeVal = swipeVal / 5;
                        }
                    }
                    this.move($el, swipeVal);
                }
            },

            touchEnd: function (distance) {
                $slide.css('transition-duration', settings.speed + 'ms');
                if (settings.mode === 'slide') {
                    var mxVal = false;
                    var _next = true;
                    slideValue = slideValue - distance;
                    if ((slideValue) > w - elSize - settings.slideMargin) {
                        slideValue = w - elSize - settings.slideMargin;
                        if (settings.autoWidth === false) {
                            mxVal = true;
                        }
                    } else if (slideValue < 0) {
                        slideValue = 0;
                    }
                    var gC = function (next) {
                        var ad = 0;
                        if (!mxVal) {
                            if (next) {
                                ad = 1;
                            }
                        }
                        if (!settings.autoWidth) {
                            var num = slideValue / ((slideWidth + settings.slideMargin) * settings.slideMove);
                            scene = parseInt(num) + ad;
                            if (slideValue >= (w - elSize - settings.slideMargin)) {
                                if (num % 1 !== 0) {
                                    scene++;
                                }
                            }
                        } else {
                            var tW = 0;
                            for (var i = 0; i < $children.length; i++) {
                                tW += (parseInt($children.eq(i).width()) + settings.slideMargin);
                                scene = i + ad;
                                if (tW >= slideValue) {
                                    break;
                                }
                            }
                        }
                    };
                    if (distance >= settings.swipeThreshold) {
                        gC(false);
                        _next = false;
                    } else if (distance <= -settings.swipeThreshold) {
                        gC(true);
                        _next = false;
                    }
                    $el.mode(_next);
                    this.slideThumb();
                } else {
                    if (distance >= settings.swipeThreshold) {
                        $el.goToPrevSlide();
                    } else if (distance <= -settings.swipeThreshold) {
                        $el.goToNextSlide();
                    }
                }
            },



            enableDrag: function () {
                var $this = this;
                if (!isTouch) {
                    var startCoords = 0,
                        endCoords = 0,
                        isDraging = false;
                    $slide.find('.lightSlider').addClass('lsGrab');
                    $slide.on('mousedown', function (e) {
                        if (w < elSize) {
                            if (w !== 0) {
                                return false;
                            }
                        }
                        if ($(e.target).attr('class') !== ('lSPrev') && $(e.target).attr('class') !== ('lSNext')) {
                            startCoords = (settings.vertical === true) ? e.pageY : e.pageX;
                            isDraging = true;
                            if (e.preventDefault) {
                                e.preventDefault();
                            } else {
                                e.returnValue = false;
                            }
                            // ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
                            $slide.scrollLeft += 1;
                            $slide.scrollLeft -= 1;
                            // *
                            $slide.find('.lightSlider').removeClass('lsGrab').addClass('lsGrabbing');
                            clearInterval(interval);
                        }
                    });
                    $(window).on('mousemove', function (e) {
                        if (isDraging) {
                            endCoords = (settings.vertical === true) ? e.pageY : e.pageX;
                            $this.touchMove(endCoords, startCoords);
                        }
                    });
                    $(window).on('mouseup', function (e) {
                        if (isDraging) {
                            $slide.find('.lightSlider').removeClass('lsGrabbing').addClass('lsGrab');
                            isDraging = false;
                            endCoords = (settings.vertical === true) ? e.pageY : e.pageX;
                            var distance = endCoords - startCoords;
                            if (Math.abs(distance) >= settings.swipeThreshold) {
                                $(window).on('click.ls', function (e) {
                                    if (e.preventDefault) {
                                        e.preventDefault();
                                    } else {
                                        e.returnValue = false;
                                    }
                                    e.stopImmediatePropagation();
                                    e.stopPropagation();
                                    $(window).off('click.ls');
                                });
                            }

                            $this.touchEnd(distance);

                        }
                    });
                }
            },




            enableTouch: function () {
                var $this = this;
                if (isTouch) {
                    var startCoords = {},
                        endCoords = {};
                    $slide.on('touchstart', function (e) {
                        endCoords = e.originalEvent.targetTouches[0];
                        startCoords.pageX = e.originalEvent.targetTouches[0].pageX;
                        startCoords.pageY = e.originalEvent.targetTouches[0].pageY;
                        clearInterval(interval);
                    });
                    $slide.on('touchmove', function (e) {
                        if (w < elSize) {
                            if (w !== 0) {
                                return false;
                            }
                        }
                        var orig = e.originalEvent;
                        endCoords = orig.targetTouches[0];
                        var xMovement = Math.abs(endCoords.pageX - startCoords.pageX);
                        var yMovement = Math.abs(endCoords.pageY - startCoords.pageY);
                        if (settings.vertical === true) {
                            if ((yMovement * 3) > xMovement) {
                                e.preventDefault();
                            }
                            $this.touchMove(endCoords.pageY, startCoords.pageY);
                        } else {
                            if ((xMovement * 3) > yMovement) {
                                e.preventDefault();
                            }
                            $this.touchMove(endCoords.pageX, startCoords.pageX);
                        }

                    });
                    $slide.on('touchend', function () {
                        if (w < elSize) {
                            if (w !== 0) {
                                return false;
                            }
                        }
                        var distance;
                        if (settings.vertical === true) {
                            distance = endCoords.pageY - startCoords.pageY;
                        } else {
                            distance = endCoords.pageX - startCoords.pageX;
                        }
                        $this.touchEnd(distance);
                    });
                }
            },
            build: function () {
                var $this = this;
                $this.initialStyle();
                if (this.doCss()) {

                    if (settings.enableTouch === true) {
                        $this.enableTouch();
                    }
                    if (settings.enableDrag === true) {
                        $this.enableDrag();
                    }
                }

                $(window).on('focus', function(){
                    $this.auto();
                });
                
                $(window).on('blur', function(){
                    clearInterval(interval);
                });

                $this.pager();
                $this.pauseOnHover();
                $this.controls();
                $this.keyPress();
            }
        };
        plugin.build();
        refresh.init = function () {
            refresh.chbreakpoint();
            if (settings.vertical === true) {
                if (settings.item > 1) {
                    elSize = settings.verticalHeight;
                } else {
                    elSize = $children.outerHeight();
                }
                $slide.css('height', elSize + 'px');
            } else {
                elSize = $slide.outerWidth();
            }
            if (settings.loop === true && settings.mode === 'slide') {
                refresh.clone();
            }
            refresh.calL();
            if (settings.mode === 'slide') {
                $el.removeClass('lSSlide');
            }
            if (settings.mode === 'slide') {
                refresh.calSW();
                refresh.sSW();
            }
            setTimeout(function () {
                if (settings.mode === 'slide') {
                    $el.addClass('lSSlide');
                }
            }, 1000);
            if (settings.pager) {
                refresh.createPager();
            }
            if (settings.adaptiveHeight === true && settings.vertical === false) {
                $el.css('height', $children.eq(scene).outerHeight(true));
            }
            if (settings.adaptiveHeight === false) {
                if (settings.mode === 'slide') {
                    if (settings.vertical === false) {
                        plugin.setHeight($el, false);
                    }else{
                        plugin.auto();
                    }
                } else {
                    plugin.setHeight($el, true);
                }
            }
            if (settings.gallery === true) {
                plugin.slideThumb();
            }
            if (settings.mode === 'slide') {
                plugin.slide();
            }
            if (settings.autoWidth === false) {
                if ($children.length <= settings.item) {
                    $slide.find('.lSAction').hide();
                } else {
                    $slide.find('.lSAction').show();
                }
            } else {
                if ((refresh.calWidth(false) < elSize) && (w !== 0)) {
                    $slide.find('.lSAction').hide();
                } else {
                    $slide.find('.lSAction').show();
                }
            }
        };
        $el.goToPrevSlide = function () {
            if (scene > 0) {
                settings.onBeforePrevSlide.call(this, $el, scene);
                scene--;
                $el.mode(false);
                if (settings.gallery === true) {
                    plugin.slideThumb();
                }
            } else {
                if (settings.loop === true) {
                    settings.onBeforePrevSlide.call(this, $el, scene);
                    if (settings.mode === 'fade') {
                        var l = (length - 1);
                        scene = parseInt(l / settings.slideMove);
                    }
                    $el.mode(false);
                    if (settings.gallery === true) {
                        plugin.slideThumb();
                    }
                } else if (settings.slideEndAnimation === true) {
                    $el.addClass('leftEnd');
                    setTimeout(function () {
                        $el.removeClass('leftEnd');
                    }, 400);
                }
            }
        };
        $el.goToNextSlide = function () {
            var nextI = true;
            if (settings.mode === 'slide') {
                var _slideValue = plugin.slideValue();
                nextI = _slideValue < w - elSize - settings.slideMargin;
            }
            if (((scene * settings.slideMove) < length - settings.slideMove) && nextI) {
                settings.onBeforeNextSlide.call(this, $el, scene);
                scene++;
                $el.mode(false);
                if (settings.gallery === true) {
                    plugin.slideThumb();
                }
            } else {
                if (settings.loop === true) {
                    settings.onBeforeNextSlide.call(this, $el, scene);
                    scene = 0;
                    $el.mode(false);
                    if (settings.gallery === true) {
                        plugin.slideThumb();
                    }
                } else if (settings.slideEndAnimation === true) {
                    $el.addClass('rightEnd');
                    setTimeout(function () {
                        $el.removeClass('rightEnd');
                    }, 400);
                }
            }
        };
        $el.mode = function (_touch) {
            if (settings.adaptiveHeight === true && settings.vertical === false) {
                $el.css('height', $children.eq(scene).outerHeight(true));
            }
            if (on === false) {
                if (settings.mode === 'slide') {
                    if (plugin.doCss()) {
                        $el.addClass('lSSlide');
                        if (settings.speed !== '') {
                            $slide.css('transition-duration', settings.speed + 'ms');
                        }
                        if (settings.cssEasing !== '') {
                            $slide.css('transition-timing-function', settings.cssEasing);
                        }
                    }
                } else {
                    if (plugin.doCss()) {
                        if (settings.speed !== '') {
                            $el.css('transition-duration', settings.speed + 'ms');
                        }
                        if (settings.cssEasing !== '') {
                            $el.css('transition-timing-function', settings.cssEasing);
                        }
                    }
                }
            }
            if (!_touch) {
                settings.onBeforeSlide.call(this, $el, scene);
            }
            if (settings.mode === 'slide') {
                plugin.slide();
            } else {
                plugin.fade();
            }
            if (!$slide.hasClass('ls-hover')) {
                plugin.auto();
            }
            setTimeout(function () {
                if (!_touch) {
                    settings.onAfterSlide.call(this, $el, scene);
                }
            }, settings.speed);
            on = true;
        };
        $el.play = function () {
            $el.goToNextSlide();
            settings.auto = true;
            plugin.auto();
        };
        $el.pause = function () {
            settings.auto = false;
            clearInterval(interval);
        };
        $el.refresh = function () {
            refresh.init();
        };
        $el.getCurrentSlideCount = function () {
            var sc = scene;
            if (settings.loop) {
                var ln = $slide.find('.lslide').length,
                    cl = $el.find('.clone.left').length;
                if (scene <= cl - 1) {
                    sc = ln + (scene - cl);
                } else if (scene >= (ln + cl)) {
                    sc = scene - ln - cl;
                } else {
                    sc = scene - cl;
                }
            }
            return sc + 1;
        }; 
        $el.getTotalSlideCount = function () {
            return $slide.find('.lslide').length;
        };
        $el.goToSlide = function (s) {
            if (settings.loop) {
                scene = (s + $el.find('.clone.left').length - 1);
            } else {
                scene = s;
            }
            $el.mode(false);
            if (settings.gallery === true) {
                plugin.slideThumb();
            }
        };
        $el.destroy = function () {
            if ($el.lightSlider) {
                $el.goToPrevSlide = function(){};
                $el.goToNextSlide = function(){};
                $el.mode = function(){};
                $el.play = function(){};
                $el.pause = function(){};
                $el.refresh = function(){};
                $el.getCurrentSlideCount = function(){};
                $el.getTotalSlideCount = function(){};
                $el.goToSlide = function(){}; 
                $el.lightSlider = null;
                refresh = {
                    init : function(){}
                };
                $el.parent().parent().find('.lSAction, .lSPager').remove();
                $el.removeClass('lightSlider lSFade lSSlide lsGrab lsGrabbing leftEnd right').removeAttr('style').unwrap().unwrap();
                $el.children().removeAttr('style');
                $children.removeClass('lslide active');
                $el.find('.clone').remove();
                $children = null;
                interval = null;
                on = false;
                scene = 0;
            }

        };
        setTimeout(function () {
            settings.onSliderLoad.call(this, $el);
        }, 10);
        $(window).on('resize orientationchange', function (e) {
            setTimeout(function () {
                if (e.preventDefault) {
                    e.preventDefault();
                } else {
                    e.returnValue = false;
                }
                refresh.init();
            }, 200);
        });
        return this;
    };
}(jQuery));;
(function(e){var o="left",n="right",d="up",v="down",c="in",w="out",l="none",r="auto",k="swipe",s="pinch",x="tap",i="doubletap",b="longtap",A="horizontal",t="vertical",h="all",q=10,f="start",j="move",g="end",p="cancel",a="ontouchstart" in window,y="TouchSwipe";var m={fingers:1,threshold:75,cancelThreshold:null,pinchThreshold:20,maxTimeThreshold:null,fingerReleaseThreshold:250,longTapThreshold:500,doubleTapThreshold:200,swipe:null,swipeLeft:null,swipeRight:null,swipeUp:null,swipeDown:null,swipeStatus:null,pinchIn:null,pinchOut:null,pinchStatus:null,click:null,tap:null,doubleTap:null,longTap:null,triggerOnTouchEnd:true,triggerOnTouchLeave:false,allowPageScroll:"auto",fallbackToMouseEvents:true,excludedElements:"button, input, select, textarea, a, .noSwipe"};e.fn.swipe=function(D){var C=e(this),B=C.data(y);if(B&&typeof D==="string"){if(B[D]){return B[D].apply(this,Array.prototype.slice.call(arguments,1))}else{e.error("Method "+D+" does not exist on jQuery.swipe")}}else{if(!B&&(typeof D==="object"||!D)){return u.apply(this,arguments)}}return C};e.fn.swipe.defaults=m;e.fn.swipe.phases={PHASE_START:f,PHASE_MOVE:j,PHASE_END:g,PHASE_CANCEL:p};e.fn.swipe.directions={LEFT:o,RIGHT:n,UP:d,DOWN:v,IN:c,OUT:w};e.fn.swipe.pageScroll={NONE:l,HORIZONTAL:A,VERTICAL:t,AUTO:r};e.fn.swipe.fingers={ONE:1,TWO:2,THREE:3,ALL:h};function u(B){if(B&&(B.allowPageScroll===undefined&&(B.swipe!==undefined||B.swipeStatus!==undefined))){B.allowPageScroll=l}if(B.click!==undefined&&B.tap===undefined){B.tap=B.click}if(!B){B={}}B=e.extend({},e.fn.swipe.defaults,B);return this.each(function(){var D=e(this);var C=D.data(y);if(!C){C=new z(this,B);D.data(y,C)}})}function z(a0,aq){var av=(a||!aq.fallbackToMouseEvents),G=av?"touchstart":"mousedown",au=av?"touchmove":"mousemove",R=av?"touchend":"mouseup",P=av?null:"mouseleave",az="touchcancel";var ac=0,aL=null,Y=0,aX=0,aV=0,D=1,am=0,aF=0,J=null;var aN=e(a0);var W="start";var T=0;var aM=null;var Q=0,aY=0,a1=0,aa=0,K=0;var aS=null;try{aN.bind(G,aJ);aN.bind(az,a5)}catch(ag){e.error("events not supported "+G+","+az+" on jQuery.swipe")}this.enable=function(){aN.bind(G,aJ);aN.bind(az,a5);return aN};this.disable=function(){aG();return aN};this.destroy=function(){aG();aN.data(y,null);return aN};this.option=function(a8,a7){if(aq[a8]!==undefined){if(a7===undefined){return aq[a8]}else{aq[a8]=a7}}else{e.error("Option "+a8+" does not exist on jQuery.swipe.options")}};function aJ(a9){if(ax()){return}if(e(a9.target).closest(aq.excludedElements,aN).length>0){return}var ba=a9.originalEvent?a9.originalEvent:a9;var a8,a7=a?ba.touches[0]:ba;W=f;if(a){T=ba.touches.length}else{a9.preventDefault()}ac=0;aL=null;aF=null;Y=0;aX=0;aV=0;D=1;am=0;aM=af();J=X();O();if(!a||(T===aq.fingers||aq.fingers===h)||aT()){ae(0,a7);Q=ao();if(T==2){ae(1,ba.touches[1]);aX=aV=ap(aM[0].start,aM[1].start)}if(aq.swipeStatus||aq.pinchStatus){a8=L(ba,W)}}else{a8=false}if(a8===false){W=p;L(ba,W);return a8}else{ak(true)}}function aZ(ba){var bd=ba.originalEvent?ba.originalEvent:ba;if(W===g||W===p||ai()){return}var a9,a8=a?bd.touches[0]:bd;var bb=aD(a8);aY=ao();if(a){T=bd.touches.length}W=j;if(T==2){if(aX==0){ae(1,bd.touches[1]);aX=aV=ap(aM[0].start,aM[1].start)}else{aD(bd.touches[1]);aV=ap(aM[0].end,aM[1].end);aF=an(aM[0].end,aM[1].end)}D=a3(aX,aV);am=Math.abs(aX-aV)}if((T===aq.fingers||aq.fingers===h)||!a||aT()){aL=aH(bb.start,bb.end);ah(ba,aL);ac=aO(bb.start,bb.end);Y=aI();aE(aL,ac);if(aq.swipeStatus||aq.pinchStatus){a9=L(bd,W)}if(!aq.triggerOnTouchEnd||aq.triggerOnTouchLeave){var a7=true;if(aq.triggerOnTouchLeave){var bc=aU(this);a7=B(bb.end,bc)}if(!aq.triggerOnTouchEnd&&a7){W=ay(j)}else{if(aq.triggerOnTouchLeave&&!a7){W=ay(g)}}if(W==p||W==g){L(bd,W)}}}else{W=p;L(bd,W)}if(a9===false){W=p;L(bd,W)}}function I(a7){var a8=a7.originalEvent;if(a){if(a8.touches.length>0){C();return true}}if(ai()){T=aa}a7.preventDefault();aY=ao();Y=aI();if(a6()){W=p;L(a8,W)}else{if(aq.triggerOnTouchEnd||(aq.triggerOnTouchEnd==false&&W===j)){W=g;L(a8,W)}else{if(!aq.triggerOnTouchEnd&&a2()){W=g;aB(a8,W,x)}else{if(W===j){W=p;L(a8,W)}}}}ak(false)}function a5(){T=0;aY=0;Q=0;aX=0;aV=0;D=1;O();ak(false)}function H(a7){var a8=a7.originalEvent;if(aq.triggerOnTouchLeave){W=ay(g);L(a8,W)}}function aG(){aN.unbind(G,aJ);aN.unbind(az,a5);aN.unbind(au,aZ);aN.unbind(R,I);if(P){aN.unbind(P,H)}ak(false)}function ay(bb){var ba=bb;var a9=aw();var a8=aj();var a7=a6();if(!a9||a7){ba=p}else{if(a8&&bb==j&&(!aq.triggerOnTouchEnd||aq.triggerOnTouchLeave)){ba=g}else{if(!a8&&bb==g&&aq.triggerOnTouchLeave){ba=p}}}return ba}function L(a9,a7){var a8=undefined;if(F()||S()){a8=aB(a9,a7,k)}else{if((M()||aT())&&a8!==false){a8=aB(a9,a7,s)}}if(aC()&&a8!==false){a8=aB(a9,a7,i)}else{if(al()&&a8!==false){a8=aB(a9,a7,b)}else{if(ad()&&a8!==false){a8=aB(a9,a7,x)}}}if(a7===p){a5(a9)}if(a7===g){if(a){if(a9.touches.length==0){a5(a9)}}else{a5(a9)}}return a8}function aB(ba,a7,a9){var a8=undefined;if(a9==k){aN.trigger("swipeStatus",[a7,aL||null,ac||0,Y||0,T]);if(aq.swipeStatus){a8=aq.swipeStatus.call(aN,ba,a7,aL||null,ac||0,Y||0,T);if(a8===false){return false}}if(a7==g&&aR()){aN.trigger("swipe",[aL,ac,Y,T]);if(aq.swipe){a8=aq.swipe.call(aN,ba,aL,ac,Y,T);if(a8===false){return false}}switch(aL){case o:aN.trigger("swipeLeft",[aL,ac,Y,T]);if(aq.swipeLeft){a8=aq.swipeLeft.call(aN,ba,aL,ac,Y,T)}break;case n:aN.trigger("swipeRight",[aL,ac,Y,T]);if(aq.swipeRight){a8=aq.swipeRight.call(aN,ba,aL,ac,Y,T)}break;case d:aN.trigger("swipeUp",[aL,ac,Y,T]);if(aq.swipeUp){a8=aq.swipeUp.call(aN,ba,aL,ac,Y,T)}break;case v:aN.trigger("swipeDown",[aL,ac,Y,T]);if(aq.swipeDown){a8=aq.swipeDown.call(aN,ba,aL,ac,Y,T)}break}}}if(a9==s){aN.trigger("pinchStatus",[a7,aF||null,am||0,Y||0,T,D]);if(aq.pinchStatus){a8=aq.pinchStatus.call(aN,ba,a7,aF||null,am||0,Y||0,T,D);if(a8===false){return false}}if(a7==g&&a4()){switch(aF){case c:aN.trigger("pinchIn",[aF||null,am||0,Y||0,T,D]);if(aq.pinchIn){a8=aq.pinchIn.call(aN,ba,aF||null,am||0,Y||0,T,D)}break;case w:aN.trigger("pinchOut",[aF||null,am||0,Y||0,T,D]);if(aq.pinchOut){a8=aq.pinchOut.call(aN,ba,aF||null,am||0,Y||0,T,D)}break}}}if(a9==x){if(a7===p||a7===g){clearTimeout(aS);if(V()&&!E()){K=ao();aS=setTimeout(e.proxy(function(){K=null;aN.trigger("tap",[ba.target]);if(aq.tap){a8=aq.tap.call(aN,ba,ba.target)}},this),aq.doubleTapThreshold)}else{K=null;aN.trigger("tap",[ba.target]);if(aq.tap){a8=aq.tap.call(aN,ba,ba.target)}}}}else{if(a9==i){if(a7===p||a7===g){clearTimeout(aS);K=null;aN.trigger("doubletap",[ba.target]);if(aq.doubleTap){a8=aq.doubleTap.call(aN,ba,ba.target)}}}else{if(a9==b){if(a7===p||a7===g){clearTimeout(aS);K=null;aN.trigger("longtap",[ba.target]);if(aq.longTap){a8=aq.longTap.call(aN,ba,ba.target)}}}}}return a8}function aj(){var a7=true;if(aq.threshold!==null){a7=ac>=aq.threshold}return a7}function a6(){var a7=false;if(aq.cancelThreshold!==null&&aL!==null){a7=(aP(aL)-ac)>=aq.cancelThreshold}return a7}function ab(){if(aq.pinchThreshold!==null){return am>=aq.pinchThreshold}return true}function aw(){var a7;if(aq.maxTimeThreshold){if(Y>=aq.maxTimeThreshold){a7=false}else{a7=true}}else{a7=true}return a7}function ah(a7,a8){if(aq.allowPageScroll===l||aT()){a7.preventDefault()}else{var a9=aq.allowPageScroll===r;switch(a8){case o:if((aq.swipeLeft&&a9)||(!a9&&aq.allowPageScroll!=A)){a7.preventDefault()}break;case n:if((aq.swipeRight&&a9)||(!a9&&aq.allowPageScroll!=A)){a7.preventDefault()}break;case d:if((aq.swipeUp&&a9)||(!a9&&aq.allowPageScroll!=t)){a7.preventDefault()}break;case v:if((aq.swipeDown&&a9)||(!a9&&aq.allowPageScroll!=t)){a7.preventDefault()}break}}}function a4(){var a8=aK();var a7=U();var a9=ab();return a8&&a7&&a9}function aT(){return !!(aq.pinchStatus||aq.pinchIn||aq.pinchOut)}function M(){return !!(a4()&&aT())}function aR(){var ba=aw();var bc=aj();var a9=aK();var a7=U();var a8=a6();var bb=!a8&&a7&&a9&&bc&&ba;return bb}function S(){return !!(aq.swipe||aq.swipeStatus||aq.swipeLeft||aq.swipeRight||aq.swipeUp||aq.swipeDown)}function F(){return !!(aR()&&S())}function aK(){return((T===aq.fingers||aq.fingers===h)||!a)}function U(){return aM[0].end.x!==0}function a2(){return !!(aq.tap)}function V(){return !!(aq.doubleTap)}function aQ(){return !!(aq.longTap)}function N(){if(K==null){return false}var a7=ao();return(V()&&((a7-K)<=aq.doubleTapThreshold))}function E(){return N()}function at(){return((T===1||!a)&&(isNaN(ac)||ac===0))}function aW(){return((Y>aq.longTapThreshold)&&(ac<q))}function ad(){return !!(at()&&a2())}function aC(){return !!(N()&&V())}function al(){return !!(aW()&&aQ())}function C(){a1=ao();aa=event.touches.length+1}function O(){a1=0;aa=0}function ai(){var a7=false;if(a1){var a8=ao()-a1;if(a8<=aq.fingerReleaseThreshold){a7=true}}return a7}function ax(){return !!(aN.data(y+"_intouch")===true)}function ak(a7){if(a7===true){aN.bind(au,aZ);aN.bind(R,I);if(P){aN.bind(P,H)}}else{aN.unbind(au,aZ,false);aN.unbind(R,I,false);if(P){aN.unbind(P,H,false)}}aN.data(y+"_intouch",a7===true)}function ae(a8,a7){var a9=a7.identifier!==undefined?a7.identifier:0;aM[a8].identifier=a9;aM[a8].start.x=aM[a8].end.x=a7.pageX||a7.clientX;aM[a8].start.y=aM[a8].end.y=a7.pageY||a7.clientY;return aM[a8]}function aD(a7){var a9=a7.identifier!==undefined?a7.identifier:0;var a8=Z(a9);a8.end.x=a7.pageX||a7.clientX;a8.end.y=a7.pageY||a7.clientY;return a8}function Z(a8){for(var a7=0;a7<aM.length;a7++){if(aM[a7].identifier==a8){return aM[a7]}}}function af(){var a7=[];for(var a8=0;a8<=5;a8++){a7.push({start:{x:0,y:0},end:{x:0,y:0},identifier:0})}return a7}function aE(a7,a8){a8=Math.max(a8,aP(a7));J[a7].distance=a8}function aP(a7){return J[a7].distance}function X(){var a7={};a7[o]=ar(o);a7[n]=ar(n);a7[d]=ar(d);a7[v]=ar(v);return a7}function ar(a7){return{direction:a7,distance:0}}function aI(){return aY-Q}function ap(ba,a9){var a8=Math.abs(ba.x-a9.x);var a7=Math.abs(ba.y-a9.y);return Math.round(Math.sqrt(a8*a8+a7*a7))}function a3(a7,a8){var a9=(a8/a7)*1;return a9.toFixed(2)}function an(){if(D<1){return w}else{return c}}function aO(a8,a7){return Math.round(Math.sqrt(Math.pow(a7.x-a8.x,2)+Math.pow(a7.y-a8.y,2)))}function aA(ba,a8){var a7=ba.x-a8.x;var bc=a8.y-ba.y;var a9=Math.atan2(bc,a7);var bb=Math.round(a9*180/Math.PI);if(bb<0){bb=360-Math.abs(bb)}return bb}function aH(a8,a7){var a9=aA(a8,a7);if((a9<=45)&&(a9>=0)){return o}else{if((a9<=360)&&(a9>=315)){return o}else{if((a9>=135)&&(a9<=225)){return n}else{if((a9>45)&&(a9<135)){return v}else{return d}}}}}function ao(){var a7=new Date();return a7.getTime()}function aU(a7){a7=e(a7);var a9=a7.offset();var a8={left:a9.left,right:a9.left+a7.outerWidth(),top:a9.top,bottom:a9.top+a7.outerHeight()};return a8}function B(a7,a8){return(a7.x>a8.left&&a7.x<a8.right&&a7.y>a8.top&&a7.y<a8.bottom)}}})(jQuery);;
/**
 * @license angular-recaptcha build:2018-07-30
 * https://github.com/vividcortex/angular-recaptcha
 * Copyright (c) 2018 VividCortex
**/


!function (a) { "use strict"; a.module("vcRecaptcha", []) }(angular), function (a) { "use strict"; function b() { throw new Error('You need to set the "key" attribute to your public reCaptcha key. If you don\'t have a key, please get one from https://www.google.com/recaptcha/admin/create') } a.module("vcRecaptcha").provider("vcRecaptchaService", function () { var c = this, d = {}; c.onLoadFunctionName = "vcRecaptchaApiLoaded", c.setDefaults = function (b) { a.copy(b, d) }, c.setSiteKey = function (a) { d.key = a }, c.setTheme = function (a) { d.theme = a }, c.setStoken = function (a) { d.stoken = a }, c.setSize = function (a) { d.size = a }, c.setType = function (a) { d.type = a }, c.setLang = function (a) { d.lang = a }, c.setBadge = function (a) { d.badge = a }, c.setOnLoadFunctionName = function (a) { c.onLoadFunctionName = a }, c.$get = ["$rootScope", "$window", "$q", "$document", "$interval", function (e, f, g, h, i) { function j() { return m ? g.when(m) : o } function k() { if (!m) throw new Error("reCaptcha has not been loaded yet.") } function l() { return a.isFunction((f.grecaptcha || {}).render) } var m, n = g.defer(), o = n.promise, p = {}; f.vcRecaptchaApiLoadedCallback = f.vcRecaptchaApiLoadedCallback || []; var q = function () { m = f.grecaptcha, n.resolve(m) }; if (f.vcRecaptchaApiLoadedCallback.push(q), f[c.onLoadFunctionName] = function () { f.vcRecaptchaApiLoadedCallback.forEach(function (a) { a() }) }, l()) q(); else if (f.document.querySelector('script[src^="https://www.google.com/recaptcha/api.js"]')) var r = i(function () { l() && (i.cancel(r), q()) }, 25); else { var s = f.document.createElement("script"); s.async = !0, s.defer = !0, s.src = "https://www.google.com/recaptcha/api.js?onload=" + c.onLoadFunctionName + "&render=explicit", h.find("body")[0].appendChild(s) } return { create: function (a, c) { return c.sitekey = c.key || d.key, c.theme = c.theme || d.theme, c.stoken = c.stoken || d.stoken, c.size = c.size || d.size, c.type = c.type || d.type, c.hl = c.lang || d.lang, c.badge = c.badge || d.badge, c.sitekey || b(), j().then(function (b) { var d = b.render(a, c); return p[d] = a, d }) }, reload: function (a) { k(), m.reset(a), e.$broadcast("reCaptchaReset", a) }, execute: function (a) { k(), m.execute(a) }, useLang: function (a, b) { var c = p[a]; if (!c) throw new Error("reCaptcha Widget ID not exists", a); var d = c.querySelector("iframe"); if (!b) return d && d.src && /[?&]hl=\w+/.test(d.src) ? d.src.replace(/.+[?&]hl=(\w+)([^\w].+)?/, "$1") : null; if (d && d.src) { var e = d.src; /[?&]hl=/.test(e) ? e = e.replace(/([?&]hl=)\w+/, "$1" + b) : e += (-1 === e.indexOf("?") ? "?" : "&") + "hl=" + b, d.src = e } }, getResponse: function (a) { return k(), m.getResponse(a) }, getInstance: function (a) { return p[a] }, destroy: function (a) { delete p[a] } } }] }) }(angular), function (a) { "use strict"; a.module("vcRecaptcha").directive("vcRecaptcha", ["$document", "$timeout", "vcRecaptchaService", function (b, c, d) { return { restrict: "A", require: "?^^form", scope: { response: "=?ngModel", key: "=?", stoken: "=?", theme: "=?", size: "=?", type: "=?", lang: "=?", badge: "=?", tabindex: "=?", required: "=?", onCreate: "&", onSuccess: "&", onExpire: "&", onError: "&" }, link: function (e, f, g, h) { function i() { h && h.$setValidity("recaptcha", null), m() } function j() { c(function () { e.response = "", l(), e.onExpire({ widgetId: e.widgetId }) }) } function k() { var a = arguments; c(function () { e.response = "", l(), e.onError({ widgetId: e.widgetId, arguments: a }) }) } function l() { h && h.$setValidity("recaptcha", !1 === e.required ? null : Boolean(e.response)) } function m() { d.destroy(e.widgetId), a.element(b[0].querySelectorAll(".pls-container")).parent().remove() } e.widgetId = null, h && a.isDefined(g.required) && e.$watch("required", l); var n = e.$watch("key", function (b) { var h = function (a) { c(function () { e.response = a, l(), e.onSuccess({ response: a, widgetId: e.widgetId }) }) }; d.create(f[0], { callback: h, key: b, stoken: e.stoken || g.stoken || null, theme: e.theme || g.theme || null, type: e.type || g.type || null, lang: e.lang || g.lang || null, tabindex: e.tabindex || g.tabindex || null, size: e.size || g.size || null, badge: e.badge || g.badge || null, "expired-callback": j, "error-callback": g.onError ? k : void 0 }).then(function (b) { l(), e.widgetId = b, e.onCreate({ widgetId: b }), e.$on("$destroy", i), e.$on("reCaptchaReset", function (c, d) { (a.isUndefined(d) || b === d) && (e.response = "", l()) }) }), n() }) } } }]) }(angular);;
