(function () {
    'use strict';
    /* Initialize the main module */
    var Xapp = angular.module('btApp', ['bw.paging', 'btAutoComplete', 'ui.sortable', 'ordinal', 'btImageUtil', 'btimageutilcustom', 'numbersOnly', 'dropZone']);

    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 visible-xs" 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>' +
                                              '<div class="input-group-btn-search visible-xs" ng-click="headerSearch()"><i class="site-sprite search-icon-desktop active-search-icon hidden-xs"></i></div>' +
                                                '<div class="desktop-search-input">' +
                                                '<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" class="typeAheadSearchInput search-textbox search-textbox-mobile" ng-focus="resetHideResults()" ng-blur="hideResults()" />' +
                                                '<div class="input-group-btn-clear" ng-click="closeSearchDialog()" ng-if="searchStr.length > 0"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 15 15"><path fill="#000" 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()"><i class="active-search-icon top-header-icon search-header-icon sprite-icon sprite-search"></i></div>' +
                                                 '</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"><span class="searching-result">Searching...</span></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">' +
                                                    '<h4 class="search-title" ng-if="results.length>0">Brands</h4>' +
                                                    '<a ng-repeat="brand in brands" class="autocomplete-brands-item" href="{{ brand.slug }}">' +
                                                        'Shop all <span ng-bind-html="brand.title"></span>' +
                                                    '</a>' +
                                                '</div>' +
                                                //'<ul class="search-suggestion" ng-show="results.length != 0">' +
                                                //     '<li class="suggestion-info">' +
                                                //        '<a>' +
                                                //            '<span class="suggestionpro-name">Red Dress</span>' +
                                                //            '<span class="suggestionpro-count">84</span>' +
                                                //        '</a>' +
                                                //     '</li>' +
                                                //'</ul>' +
                                                '<button type="button" class="animate btn-primary width-full shop-all-search-btn" ng-click="headerSearch()" ng-keyup="$event.keyCode == 13 && headerSearch()" ng-show="results.length != 0">Shop all</button>' +
                                                '<ul class="searchresult-section">' +
                                                   //'<a class="side-search-icon" ng-click="headerSearch()"><i class="fa fa-chevron-right" aria-hidden="true"></i></a>' +

                                                    '<li ng-repeat="result in results" class="autocomplete-results col-sm-12 col-xs-12" ng-if="$index<10">' +
                                                        '<div class="">' +
                                                            '<a class="tfs-search-link" href="{{result.slug }}">' +
                                                                '<div class="autocomplete-image-holder" ng-if="imageField">' +
                                                                    '<img ng-if="result.image && result.image != \'\'" ng-src="{{result.image}}" class="autocomplete-image"/>' +
                                                                    '<div ng-if="!result.image && result.image != \'\'" class="autocomplete-image-default"></div>' +
                                                                '</div>' +
                                                                '<div class="autocomplete-title-holder">' +
                                                                    '<div class="autocomplete-title-result" ng-if="matchClass" ng-bind-html="result.title"></div>' +
                                                                    '<div class="autocomplete-title-result" ng-if="!matchClass">{{ result.title }}</div>' +
                                                               '</div>' +
                                                                '<div class="autocomplete-price-holder">' +
                                                                    '<div class="autocomplete-title-result">{{ result.price.formatted.withoutTax }}</div>' +
                                                                '</div>' +
                                                             '</a>' +
                                                        '</div>' +
                                                    '</li>' +
                                               '</ul>' +
                                              '<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="" 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 = 3;
                    $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.dynamicUrl = null;
                    $scope.dropdownHeight = { "height": "calc(100vh - 66px)" };
                    $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;
                        }  
                        //$scope.searchStr = encodeURIComponent($scope.searchStr);  
                        var searchfreetext = encodeURIComponent($scope.searchStr);
                        if (microCountry !== '') 
                            window.location = "//" + window.location.host + microCountry + "/search?freeText=" + searchfreetext.toLowerCase();
                        else
                            window.location = "//" + window.location.host + "/search?freeText=" + searchfreetext.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;
                                            link = microCountry + 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;
                                link = microCountry + link;
                                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) {
                        if (eventData != null && dataLayer && 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)" srcset="{{imageUrl}}?h={{imageUtil.HiRes_H}}&w={{imageUtil.HiRes_W}}&min-w={{imageUtil.HiRes_W}}&min-h={{imageUtil.HiRes_H}}"> ' +
                ' <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}}"> ' +
                ' <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}}"> ' +
                ' <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}}"> ' +
                ' <img ng-src="{{imageUrl}}?h={{imageUtil.Mobile_H}}&w={{imageUtil.Mobile_W}}&min-w={{imageUtil.Mobile_W}}&min-h={{imageUtil.Mobile_H}}" alt="{{itemName}}" class="image1 omni-img">' +
                '</picture> ' +
                '<img  ng-if="imageUrl==\'\'" src="/assets/theme/fub2c/images/noimagefound.jpg"  alt="{{itemName}}" class="img-responsive omni-img"/ >', 
                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('btimageutilcustom', [])
        .directive('btimageutilcustom', function ($parse, $http, $sce) {
            return {
                restrict: 'A',               
                template: '<picture> ' +
                ' <source media="(min-width: 1440px)" srcset="{{imageUrl}}?h={{imageUtil.HiRes_H}}&w={{imageUtil.HiRes_W}}"> ' + 
                            ' <source media="(min-width: 1200px)" srcset="{{imageUrl}}?h={{imageUtil.Desktop_H}}&w={{imageUtil.Desktop_W}}"> ' + 
                            ' <source media="(min-width: 768px)" srcset="{{imageUrl}}?h={{imageUtil.Tablet_H}}&w={{imageUtil.Tablet_W}}"> ' + 
                            ' <source media="(min-width: 480px)" srcset="{{imageUrl}}?h={{imageUtil.Mobile_H}}&w={{imageUtil.Mobile_W}}"> ' + 
                            ' <img ng-src="{{imageUrl}}?h={{imageUtil.Mobile_H}}&w={{imageUtil.Mobile_W}}" alt="{{itemName}}" class="image1 omni-img">' + 
                           '</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('dropZone', [])
        .directive("dropZone", function () {
            return {
                require: "ngModel",
                link: function postLink(scope, elem, attrs, ngModel) {
                    elem.on("change", function (e) {
                        var files = elem[0].files;
                        ngModel.$setViewValue(files);
                    })
                }
            }
        })
})();;
/*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/fub2c/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');
    }

});
;
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 LLLL yyyy');
    }
});
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';
    /* 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
        };
    });
}());;
//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;
    }
}

function base64ArrayBuffer(arrayBuffer) {
    var base64 = '';
    var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'

    var bytes = new Uint8Array(arrayBuffer);
    var byteLength = bytes.byteLength;
    var byteRemainder = byteLength % 3;
    var mainLength = byteLength - byteRemainder;

    var a, b, c, d;
    var chunk;

    // Main loop deals with bytes in chunks of 3
    for (var i = 0; i < mainLength; i = i + 3) {
        // Combine the three bytes into a single integer
        chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];

        // Use bitmasks to extract 6-bit segments from the triplet
        a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18
        b = (chunk & 258048) >> 12; // 258048   = (2^6 - 1) << 12
        c = (chunk & 4032) >> 6; // 4032     = (2^6 - 1) << 6
        d = chunk & 63;              // 63       = 2^6 - 1

        // Convert the raw binary segments to the appropriate ASCII encoding
        base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d];
    }

    // Deal with the remaining bytes and padding
    if (byteRemainder === 1) {
        chunk = bytes[mainLength];

        a = (chunk & 252) >> 2 // 252 = (2^6 - 1) << 2

        // Set the 4 least significant bits to zero
        b = (chunk & 3) << 4 // 3   = 2^2 - 1

        base64 += encodings[a] + encodings[b] + '==';
    } else if (byteRemainder === 2) {
        chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1]

        a = (chunk & 64512) >> 10; // 64512 = (2^6 - 1) << 10
        b = (chunk & 1008) >> 4; // 1008  = (2^6 - 1) << 4

        // Set the 2 least significant bits to zero
        c = (chunk & 15) << 2; // 15    = 2^4 - 1

        base64 += encodings[a] + encodings[b] + encodings[c] + '=';
    }

    return base64;
}

function getSupportedExtensions(ext) {
    switch (ext) {
        case "application/pdf": return "pdf";
        case "application/vnd.ms-excel": return "xls";
        case "application/vnd.ms-excel": return "xlsx";
        case "application/msword": return "doc";
        case "application/msword": return "docx";
        case "image/jpeg": return "jpeg";
        case "image/jpg": return "jpg";
        case "image/png": return "png";
        default:
            return null;
    }
};
/*

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 () {
    '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;
                }
            }
        };
    });
}());;
try {
    var SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
    var recognition = new SpeechRecognition();



var noteTextarea = $('.typeAheadSearchInput');
var instructions = $('#recording-instructions');
var notesList = $('ul#notes');

var noteContent = '';

// Get all notes from previous sessions and display them.
var notes = getAllNotes();
renderNotes(notes);



/*-----------------------------
      Voice Recognition 
------------------------------*/

// If false, the recording will stop after a few seconds of silence.
// When true, the silence period is longer (about 15 seconds),
// allowing us to keep recording even when the user pauses. 
recognition.continuous = true;

// This block is called every time the Speech APi captures a line. 
recognition.onresult = function (event) {

    // event is a SpeechRecognitionEvent object.
    // It holds all the lines we have captured so far. 
    // We only need the current one.
    var current = event.resultIndex;

    // Get a transcript of what was said.
    var transcript = event.results[current][0].transcript;

    // Add the current transcript to the contents of our Note.
    // There is a weird bug on mobile, where everything is repeated twice.
    // There is no official solution so far so we have to handle an edge case.
    var mobileRepeatBug = (current == 1 && transcript == event.results[0][0].transcript);

    if (!mobileRepeatBug) {
        noteContent += transcript;
        noteTextarea.val(noteContent);
        window.location = "//" + window.location.host + "/search?freeText=" + noteContent;
    }
};

    recognition.onstart = function () {
        // instructions.text('Voice recognition activated. Try speaking into the microphone.');
        noteTextarea = $('.typeAheadSearchInput');
        // alert('Voice recognition activated. Try speaking into the microphone.');
    };

    recognition.onspeechend = function () {
        //instructions.text('You were quiet for a while so voice recognition turned itself off.');
        // alert('You were quiet for a while so voice recognition turned itself off.');
    };

    recognition.onerror = function (event) {
        if (event.error == 'no-speech') {
            //instructions.text('No speech was detected. Try again.');
            // alert('No speech was detected. Try again.');
        };
    };



/*-----------------------------
      App buttons and input 
------------------------------*/

$('#voichSearch').on('click', function (e) {
    if (noteContent.length) {
        noteContent += ' ';
    }
    recognition.start();
});


$('#pause-record-btn').on('click', function (e) {
    recognition.stop();
    instructions.text('Voice recognition paused.');
});

// Sync the text inside the text area with the noteContent variable.
    noteTextarea.on('input', function () {
        noteContent = $(this).val();
    });


}
catch (e) {
    console.error(e);
    $('.no-browser-support').show();
    $('.app').hide();
}


/*-----------------------------
      Speech Synthesis 
------------------------------*/

function readOutLoud(message) {
    var speech = new SpeechSynthesisUtterance();

    // Set the text and voice attributes.
    speech.text = message;
    speech.volume = 1;
    speech.rate = 1;
    speech.pitch = 1;

    window.speechSynthesis.speak(speech);
}



/*-----------------------------
      Helper Functions 
------------------------------*/

function renderNotes(notes) {
    var html = '';
    if (notes.length) {
        notes.forEach(function (note) {
            html += `<li class="note">
        <p class="header">
          <span class="date">${note.date}</span>
          <a href="#" class="listen-note" title="Listen to Note">Listen to Note</a>
          <a href="#" class="delete-note" title="Delete">Delete</a>
        </p>
        <p class="content">${note.content}</p>
      </li>`;
        });
    }
    else {
        html = '<li><p class="content">You don\'t have any notes yet.</p></li>';
    }
    notesList.html(html);
}


function saveNote(dateTime, content) {
    localStorage.setItem('note-' + dateTime, content);
}


function getAllNotes() {
    var notes = [];
    var key;
    for (var i = 0; i < localStorage.length; i++) {
        key = localStorage.key(i);

        if (key.substring(0, 5) == 'note-') {
            notes.push({
                date: key.replace('note-', ''),
                content: localStorage.getItem(localStorage.key(i))
            });
        }
    }
    return notes;
}


function deleteNote(dateTime) {
    localStorage.removeItem('note-' + dateTime);
}

;
(function () {
    'use strict';

    window.app.constant('REGEX_CONSTANTS', {
        'LETTERS_AND_NUMBERS_ONLY': '^[a-zA-Z0-9 ]+$',
    });
})();;
(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('GLOBALATTRIBUES_CONSTANTS', {
        'COLOR': 'global.colour', 'SIZE': 'clothing.size', 'ATTACH_ADD': 'Attachment added', 'UNSPTD_FILE':'File type not supported'
    });
    window.app.constant("PERSONALISATION", { 'ENABLED': "PersonalisationEnabled", 'MANDATORY': 'PersonalisationMandatory' });
    // ADD CONSTANT FOR THEME DEFAULT IMAGE
    window.DEFAULT_IMAGE_URL = '/assets/theme/fub2c/images/noimagefound.jpg';
    window.app.controller('globalCtrl', globalCtrl);
    globalCtrl.$inject = ['$scope', '$timeout', 'globalConfig', '$http', 'scriptLoader', 'BULKORDER_CONSTANTS', 'GLOBALATTRIBUES_CONSTANTS', 'REGEX_CONSTANTS', 'alerts'];
    function globalCtrl($scope, $timeout, globalConfig, $http, scriptLoader, BULKORDER_CONSTANTS, GLOBALATTRIBUES_CONSTANTS, REGEX_CONSTANTS, alerts) {
       var gm = this;


        gm.model = {};


        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.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.globalIdeaBList = [];
        gm.prodMinForIB = {};
        gm.createBoard = false;
        gm.ideaboardName = "";
        gm.ideaboardGuestLogin = false;
        gm.groupedLookBooks = [];
        gm.productId = "";
        gm.hoverUrlLink = 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.getBlogByCategory = getBlogByCategory;
        gm.initblogs = initblogs;
        gm.login = login;
        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 = '';
        gm.isIdeaboardListLoaded = false;
        gm.shopByInspToBoard = false;
        gm.shopyByInspList = [];
        gm.groupedLookBookLoaded = false;
        gm.highlightBoardedProducts = highlightBoardedProducts;
        gm.authenticateSitePassword = authenticateSitePassword;

        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.closeOnScreenModal = closeOnScreenModal;
        gm.fetchLookbookByGroup = fetchLookbookByGroup;
        gm.updateBasketQty = updateBasketQty;
        //gm.getRecommendations = getRecommendations;
        gm.activeClass = '';
        gm.getUserIdeaBoards = getUserIdeaBoards;
        gm.getProdMinimalForIB = getProdMinimalForIB;
        gm.addItemToIBoard = addItemToIBoard;
        gm.createItemBoard = createItemBoard;
        gm.createProductDetailIB = createProductDetailIB;
        gm.getProductAccessories = getProductAccessories;

        //Engraving Section Starts
        gm.applyPersonalisation = applyPersonalisation;
        gm.editPersonalisation = editPersonalisation;
        gm.removePersonalisation = removePersonalisation;
        gm.range = range;
        //Engraving Section Ends

        //Gift wrapping section 
        gm.selectedGiftWrapOption = {};
        gm.selectedLineItem = {};
        gm.isGiftWrapApplied = false;
        gm.giftWrapError = false;
        gm.addGiftWrap = addGiftWrap;
        gm.removeGiftWrap = removeGiftWrap;
        gm.updateBasketBadgeCount = updateBasketBadgeCount;

        /*******below code is for recomendation**********/
        gm.recomendations = {};
        gm.openGiftModal = openGiftModal;
        // 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.generateCoupons = generateCoupons;

        gm.storeAddress = storeAddress;
        gm.openShare = openShare;
        gm.openGiftPanel = openGiftPanel;
        gm.discountShow = discountShow;
        gm.getGrid = getGrid;
        gm.getList = getList;
        gm.getView = true;
        gm.openIdeaBoardModal = openIdeaBoardModal;
        gm.closeBoardModal = closeBoardModal;
        gm.showRegistration = showRegistration;
        gm.showLoginModal = showLoginModal;
        gm.showTradingForm = showTradingForm;
        gm.addToWishlist = addToWishlist;
        gm.assignGuestIdeaBoard = assignGuestIdeaBoard;
        gm.checkIfBoarded = checkIfBoarded;
        gm.highlightBoardedProduct = highlightBoardedProduct;
        gm.updateBasketInfo = updateBasketInfo;
        gm.extractOrderCustomInfo = extractOrderCustomInfo;
        gm.groupLookBooks = groupLookBooks;
        gm.addbundleProductsInBasket = addbundleProductsInBasket;
        gm.bulkAddToBag = bulkAddToBag;
        gm.addontobeaddedinbasket = [];
        gm.bulkAddToBasket = bulkAddToBasket;
        gm.getLookbookProducts = getLookbookProducts;
        gm.checkIfProductExistInBoard = checkIfProductExistInBoard;
        gm.addBulkItemsToBoard = addBulkItemsToBoard;
        gm.addMultipleProductsInBasket = addMultipleProductsInBasket;
        gm.apierror = false;
        gm.updateVariantProductinbasket = updateVariantProductinbasket;
        //Contact Us Attachment
        gm.onFileSelected = onFileSelected;
        gm.deleteAttachment = deleteAttachment;
        gm.files = [];
        gm.uploadFiles = [];
        gm.fileIdCounter = 0;
        gm.showSubTotalIncShipping = showSubTotalIncShipping;   
        gm.checkActiveTab = checkActiveTab;
        gm.getColourfromStock = getColourfromStock;
        gm.addlookbookBulkProducts = addlookbookBulkProducts;
        gm.checkCountryredirect = checkCountryredirect;
        gm.isMiniBagRequest = false;
        gm.spopValue = false;
        gm.updateNewsletterPref = updateNewsletterPref;

        function checkCountryredirect(isMobile, cookieName, microSiteCookie) {
            if ($.cookie(microSiteCookie) || microCountry == '') {
                gm.showCountryredirect(isMobile, cookieName);
            } else {
                $http.get('/home/setmicrosite').success(function (resp) {

                    gm.showCountryredirect(isMobile, cookieName);
                });
            }
        }
        //this is a quick and dirty solution, Need a proper fix
        function getColourfromStock(line) {

            var stockColor = line.stockCode.split('-');
            line.colorName = stockColor[1];
            line.selectedColorVariantvalue = line.colorName;

            var matchedproduct = line.variantProducts.filter(function (pAttr) {
                return pAttr.stockCode.toLowerCase() === line.stockCode.toLowerCase();
            })
            if (matchedproduct != null && matchedproduct.length>0) {
                var matchedColourValue = matchedproduct[0].variantAttributes.filter(function (pAttr) {
                    return pAttr.fieldCode === GLOBALATTRIBUES_CONSTANTS.COLOR;
                })
                if (matchedColourValue != null) {
                    line.selectedColorVariantvalue = matchedColourValue[0].fieldValue;
                } 
            } 
        }

      
        function updateVariantProductinbasket(line) {
            $scope.bulkOrder = []; 
            var stockFound = false;
            line.variantProducts = line.variantProducts.filter((thing, index, self) =>
                index === self.findIndex((t) => (
                    t.stockCode === thing.stockCode
                ))
            );
            angular.forEach(line.variantProducts, function (prod) {
                var stockColor = prod.stockCode.split('-');
                var prodColor = '';
                var matchedColourValue = prod.variantAttributes.filter(function (pAttr) {
                    return pAttr.fieldCode === GLOBALATTRIBUES_CONSTANTS.COLOR;
                })
                if (matchedColourValue != null) {
                    prodColor = matchedColourValue[0].fieldValue;
                } 
                if (prod.size == line.selectedSizeVariantvalue && prodColor == line.selectedColorVariantvalue && stockFound == false) {
                    stockFound = true;
                    $http.post(globalConfig.getProductById + "/" + prod.productId).success(function (resp) {
                        if (resp != null) {
                            var prodInfo = resp;
                            if (prodInfo.currentStock <= 0) {
                                $("#OOSPopUp").modal('show');
                                return false;
                            } else {
                                $scope.bulkOrder.push({ stockCode: prod.stockCode, parentProductId: null, qty: line.qty, basketId: "" });
                                $scope.bulkOrder.push({ stockCode: line.stockCode, parentProductId: null, qty: 0, basketId: "" });
                                $scope.bulkOrder = $scope.bulkOrder.filter((thing, index, self) =>
                                    index === self.findIndex((t) => (
                                        t.stockCode === thing.stockCode
                                    ))
                                );
                                gm.bulkAddToBag();
                            }
                            return false;
                        }
                    });
                }
                //else { 
                //    $("#OOSPopUp").modal('show');
                //    return false;} 
            }); 
            if (!stockFound) { 
                $("#OOSPopUp").modal('show');
                return false;}

        }
        function addMultipleProductsInBasket(productList) {

            $scope.bulkOrder = [];
            angular.forEach(productList, function (linetiem) {
                $scope.bulkOrder.push({ stockCode: linetiem.stockCode, parentProductId: null, qty: 1, basketId: "" });
            });
            gm.bulkAddToBag();

        }
        //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. 
                console.log(gm.subscriptionItems);

            },
            stop: function (e, ui) {
                //perform after sort math. 
                console.log(gm.subscriptionItems);
                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 updateBasketInfo() {
            var lineInfo = [];
            if (gm.basketResponse.lineItems != null) {
                angular.forEach(gm.basketResponse.lineItems, function (item) {

                    var json = eval('(' + item.attributesJson + ')');

                    if (json.Attributes != null) {
                        angular.forEach(json.Attributes, function (opt) {
                            if (opt.FieldCode.toLowerCase() === "choose.size") {
                                item.customInfo1 = opt.FieldValue;
                            }
                        });
                    }
                    lineInfo.push({ productId: item.productId, customInfo1: item.customInfo1, customInfo2: item.customInfo2, customInfo3: item.customInfo3, customInfo4: item.customInfo4, customInfo5: item.customInfo5 });
                });
            }

            var model = { basketId: gm.basketResponse.id, lineInfo: lineInfo };
            $http.post("/Basket/UpdateBasketInfo", { model: model }).success(function (resp) {
            });
        }
        //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 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) { 
                    if (GLOBALATTRIBUES_CONSTANTS.COLOR == attributeCode) {
                        for (var i = 0; i < attributesJson.Attributes.length; i++) {
                            if (attributesJson.Attributes[i].FieldCode == attributeCode &&  attributesJson.Attributes[i].FieldValue == attributevalue ) {
                                item.selectedColorVariantvalue = attributevalue; 
                                item.selectedColorVariantName = attributesJson.Attributes[i].FieldValue;
                                return true;
                            }
                        } 
                    } 
                    if (GLOBALATTRIBUES_CONSTANTS.SIZE == attributeCode) {
                        item.selectedSizeVariantvalue = attributesJson.Size; 
                        //for (var i = 0; i < attributesJson.Attributes.length; i++) {
                        //    if (attributesJson.Attributes[i].FieldCode == attributeCode && attributesJson.Attributes[i].FieldValue == attributevalue && attributesJson.Attributes[i].UseForVariant == true) {
                                
                        //            item.selectedSizeVariantvalue = 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) {
                                        if (GLOBALATTRIBUES_CONSTANTS.COLOR == FieldCode) {
                                            line.selectedColorVariantvalue = FieldValue;
                                        }
                                        if (GLOBALATTRIBUES_CONSTANTS.SIZE == FieldCode) {
                                            line.selectedSizeVariantvalue = FieldValue;
                                        }
                                        flag = true;
                                        break;
                                    }
                                }
                            }
                        }
                        if (flag)
                            return flag;
                    });
                    return flag;
                }
            }
        }

        //Contact-us Form
        function contactForm(model) {
            if (!model.subject || model.subject =="Select subject") {
                alerts.error('Please select subject!');
                return;
            }
            if (!model.department || model.subject == "Select dept") {
                alerts.error('Please select department!');
                return;
            }
            var contactModel = {
                subject: model.subject,
                firstName: model.firstName,
                lastName: model.lastName,
                email: model.email,
                message: "Department: " + model.department + "<br> " + "Message: " + model.message,
                orderNo: model.orderNo
            };
            if (gm.files.length > 0) {
                contactModel.attachmentUrl = gm.files.map(function (elem) {return elem.url;}).join(",");;
            }
            $http.post(globalConfig.setContactForm, contactModel)
                .success(function (data) {
                    if (data != null) {
                        gm.subssuccess = true;
                        $('.contactussuccess').show(0).delay(3000).hide(0);
                        model.firstName = '';
                        model.department = '';
                        model.subject = '';
                        model.lastName = '';
                        model.email = '';
                        model.message = '';
                        model.orderNo = '';
                        gm.files = [];
                        gm.uploadFiles = [];
                    }
                    else {
                        gm.apierror = true;
                        $('.contactusalert').show(0).delay(3000).hide(0);
                    }
                })
                .error(function (msg) {
                    gm.errorMessage = msg.errorMessages;
                })
        }

        //#region Basket
        function applyPromoCode(basketId, promoCode) {

            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) {
                    $scope.promoCode = null;
                    if (data != "false") {
                        gm.validpromo = true;
                        $('.promovalid').show(0).delay(2000).hide(0);
                        var dataResult = gm.serializedData(data.result.basket);
                        gm.basketResponse = dataResult;
                        initBasket(dataResult);
                        $('#basket-promo-btn').addClass('btn-success');
                        $('#basket-promo-btn').removeClass('btn-primary');
                        $('#basket-promo-btn').text('APPLIED');
                        $timeout(function () {
                            $('#basket-promo-btn').addClass('btn-primary');
                            $('#basket-promo-btn').removeClass('btn-sucesss');
                            $('#basket-promo-btn').text('APPLY CODE');
                            $('.promo-container').hide();
                          
                        }, 3000);
                    }
                    else {
                        gm.invalidpromo = true;
                        $('.promo').show(0).delay(2000).hide(0);
                    }
                })
                    .error(function (msg) {
                        if (msg.errorMessage != "false") {
                            gm.showCustomMsg = true;
                            gm.customMsg = msg.errorMessage;
                        }
                    })
                    .finally(function () {
                    });
            }
            else {
                gm.promonull = true;
                $('.promonull').show(0).delay(1200).hide(0);
            }
        }
        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) {
            if (basket == null || basket == undefined) {
                if (gm.basketResponse == null || gm.basketResponse == undefined) {
                    $http.post(globalConfig.getBasketUrl)
                        .success(function (data) {
                            gm.basketResponse = data;
                            gm.updateBasketInfo();
                            initAddToBagQty();
                            var sumofListPrice = 0;
                            var sumofLineWiseDiscount = 0;
                            gm.postCode = $.cookie(BULKORDER_CONSTANTS.POSTCODE);
                            if (gm.basketResponse != null && gm.basketResponse != undefined) {
                                angular.forEach(gm.basketResponse.lineItems, function (line) {
                                    if (line.price.raw.withTax > 0 && line.parentProductId == gm.emptyGuid) {
                                        sumofListPrice = sumofListPrice + + (line.listPrice.raw.withTax) * line.qty;
                                        sumofLineWiseDiscount = sumofLineWiseDiscount + line.lineDiscount;
                                    }
                                    var json = eval('(' + line.attributesJson + ')');
                                    line.slug = json.Slug;
                                    //assign line fulfilmentChannel value from deliveryPlanLine
                                    if (gm.basketResponse.deliveryPlans != null && gm.basketResponse.deliveryPlans.length > 0) {
                                        angular.forEach(gm.basketResponse.deliveryPlans, function (plan) {
                                            angular.forEach(plan.lineItems, function (planLine) {
                                                if (line.productId.toLowerCase() == planLine.productId.toLowerCase()) {
                                                    line.fulllfillmentchannel = plan.fulfilmentChannel;
                                                }
                                            });
                                        });
                                    }
                                    if (isJSON(line.customInfo2)) {
                                        line.customInfo2 = JSON.parse(line.customInfo2);
                                        line.parentProductId = line.customInfo2.ParentProductId;
                                    }
                                    if (json.Attributes != null) {
                                        angular.forEach(json.Attributes, function (opt) {
                                            if (opt.FieldCode.toLowerCase() === "choose.size") {
                                                line.sizevalue = opt.FieldValue;
                                            }
                                        });
                                    }
                                    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);
                                            }
                                        });
                                    }
                                });

                                //Get max shipment date from deliveryPlans
                                var shipmentDates = [];
                                angular.forEach(gm.basketResponse.deliveryPlans, function (plan) {
                                    shipmentDates.push(Date.parse(plan.deliveryDateTarget));
                                });
                                gm.maxShipmentDate = new Date(Math.max.apply(null, shipmentDates));

                                gm.count = gm.basketResponse.lineItemCount;
                                extractSubscription();
                                // extractCustomInfo(gm.basketResponse);
                                updateBasketBadgeCount();
                            }
                            gm.basketResponse.sumofListPrice = sumofListPrice;
                            gm.basketResponse.sumofLinewiaseDiscount = sumofLineWiseDiscount;
                            gm.showSubTotalIncShipping();
                        })
                        .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);
                                }
                            });
                        }
                    });
                    initAddToBagQty();
                    gm.count = gm.basketResponse.lineItemCount;
                    gm.postCode = $.cookie(BULKORDER_CONSTANTS.POSTCODE);
                    gm.showSubTotalIncShipping();
                }
            }
        }
        //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);
                }
            }
        }

        function addLookbookToCart(data) {
            $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;
                            });
                            gm.count = gm.basketResponse.lineItemCount;
                            line.currentStock = json.CurrentStock;
                        }
                    }
                }).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 (data.product != null && data.product.productId != null && data.product.productId != undefined && 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, isShowItemAddedMsg, isLookbookRequest = false) {
            gm.itemQty = qty;
            gm.variantRecordId = gm.emptyGuid;
            if (document.getElementById("variantSizevalue") != null) {
                var variantSelected = document.getElementById("variantSizevalue").value;

                if (variantSelected != null && variantSelected != undefined && variantSelected != '') {
                    gm.variantRecordId = variantSelected;
                }
            }
            if (gm.variantRecordId != gm.emptyGuid && !gm.isMiniBagRequest) {
                recordId = gm.variantRecordId;
            }
            if (isSubscription == undefined || isSubscription == null)
                isSubscription = false;
            if ($scope.addToBagInProgress) { return; }
            $scope.addToBagInProgress = true;
            if (isShowItemAddedMsg == undefined)
                isShowItemAddedMsg = false;


            //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 == recordId) {
                            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 prod = { "basketId": basketId, "productId": recordId, "qty": qty, "displayOrder": gm.displayOrder, "itemType": itemType, "issubscription": isSubscription };
            //var eventData = { product: prodInBasket, basket: { id: null, lines: [], totalCost: null, totalItems: null, tax: null } };
            $http.post(globalConfig.addToBasket, prod)
                .success(function (data) {
                    gm.isMiniBagRequest = false;
                    if (!isLookbookRequest && qty > 0 && gm.variantRecordId.toLowerCase() == recordId.toLowerCase()) {
                        $('#addbag').addClass('btn-primary');
                        $('#addbag').removeClass('btn-success');
                        $('#addbag').text('ADDED');
                        $('#addbagPre').text('ADDED');
                        $('#addbagPre').addClass('btn-primary');
                        $('#addbagPre').removeClass('btn-success');
                        $timeout(function () {
                            $('#addbag').addClass('btn-success');
                            $('#addbag').removeClass('btn-primary');
                            $('#addbag').text('ADD TO BAG');
                            $('#addbagPre').addClass('btn-success');
                            $('#addbagPre').removeClass('btn-primary');
                            $('#addbagPre').text('PRE-ORDER NOW');
                        }, 3000);
                    }
                    if (qty >= 1) {
                        $('.cartopen').addClass('active');
                        $timeout(function () { $(".cartopen").removeClass("active"); }, 3000);
                    }
                    $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 
                            }
                        });
                        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);
                            return;
                        }
                    }
                    if (isLookbookRequest) {
                            $('#' + recordId).addClass('btn-primary');
                            $('#' + recordId).removeClass('btn-success');
                            $('#' + recordId).text('ADDED');
                            $timeout(function () {
                                $('#' + recordId).addClass('btn-success');
                                $('#' + recordId).removeClass('btn-primary');
                                $('#' + recordId).text('ADD TO BAG');
                            }, 3000);
                    }
                    if (isShowItemAddedMsg) {
                        gm.productId = recordId;
                        getProductAccessories(recordId);
                    }
                    updateBasket(data, isShowItemAddedMsg);
                    //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;
                                        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"
                                    ]);
                                }
                            }
                        }
                    }
                    //redirect to offer page                   
                    //if (qty > 0 && data.messageCode != BULKORDER_CONSTANTS.ITEM_STOCK_UNAVAILABLE)
                    //    alerts.success(data.message);                    
                    //else if(qty <= 0)
                    //    alerts.error("Item removed successfully.");
                    PubSub.publish("addToCart", prod);

                    if (gm.basketResponse.lineItemCount < 1)
                        window.location.reload();
                })
                .error(function (msg) {

                })
                .finally(function () {

                });
            window.setTimeout(function () {
                $(".alert-container").fadeOut(function () { $(this).remove(); });
            }, 10000);
        };

        function addbundleProductsInBasket(line) {

            $scope.bulkOrder = [];
            $scope.bulkOrder.push({ stockCode: line.stockCode, parentProductId: null, qty: 1, basketId: "" });

            angular.forEach(line.componentProducts, function (linetiem) {
                $scope.bulkOrder.push({ stockCode: linetiem.stockCode, parentProductId: line.recordId, qty: linetiem.qty, basketId: "" });
            });
            gm.bulkAddToBag();

        }
        function bulkAddToBag() {
            var eventData = { product: null, basket: { id: null, lines: [], totalCost: null, totalItems: null, tax: null } };
            $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) {
                        var sumofListPrice = 0;
                        var sumofLineWiseDiscount = 0;
                        if (gm.basketResponse.lineItems != null && gm.basketResponse.lineItems.length > 0) {
                            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;
                            var prodDetail = angular.copy(gm.basketResponse.lineItems[0]); // get the first product

                            prodDetail.qty = gm.basketResponse.lineItems[0].qty; /// set the actual qty that was requested to be aded instead of final  item qty
                            eventData.product = prodDetail;

                            angular.forEach(gm.basketResponse.lineItems, function (line) {
                                var json = eval('(' + line.attributesJson + ')');
                                line.slug = json.Slug;
                                if (line.price.raw.withTax > 0 && line.parentProductId == gm.emptyGuid) {
                                    sumofListPrice = sumofListPrice + + (line.listPrice.raw.withTax) * line.qty;
                                    sumofLineWiseDiscount = sumofLineWiseDiscount + line.lineDiscount;
                                }
                                //assign line fulfilmentChannel value from deliveryPlanLine
                                if (gm.basketResponse.deliveryPlans != null && gm.basketResponse.deliveryPlans.length > 0) {
                                    angular.forEach(gm.basketResponse.deliveryPlans, function (plan) {
                                        angular.forEach(plan.lineItems, function (planLine) {
                                            if (line.productId.toLowerCase() == planLine.productId.toLowerCase()) {
                                                line.fulllfillmentchannel = plan.fulfilmentChannel;
                                            }
                                        });
                                    });
                                }
                                if (line.price.raw.withTax > 0 && line.parentProductId == gm.emptyGuid) {
                                    sumofListPrice = sumofListPrice + + (line.listPrice.raw.withTax) * line.qty;
                                    sumofLineWiseDiscount = sumofLineWiseDiscount + line.lineDiscount;
                                }
                                if (gm.basketResponse.deliveryPlans != null && gm.basketResponse.deliveryPlans.length > 0) {
                                    line.fulllfillmentchannel = gm.basketResponse.deliveryPlans[0].fulfilmentChannel;
                                    var shipmentDates = [];
                                    angular.forEach(gm.basketResponse.deliveryPlans, function (plan) {
                                        shipmentDates.push(Date.parse(plan.deliveryDateTarget));
                                    });

                                    gm.maxShipmentDate = new Date(Math.max.apply(null, shipmentDates));
                                }

                                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.img };
                                eventData.basket.lines.push(li);

                                if (line.parentProductId == gm.emptyGuid) {
                                    count = count + line.qty;
                                }
                                var json = eval('(' + line.attributesJson + ')');
                                line.slug = json.Slug;
                            });
                            gm.basketResponse.sumofListPrice = sumofListPrice;
                            gm.basketResponse.sumofLinewiaseDiscount = sumofLineWiseDiscount;
                        }
                        gm.count = gm.basketResponse.lineItemCount;
                    }
                    $("#AddToBasketModel").modal("hide");
                    $("#bulkOrderMessage").modal();
                    gm.notFoundLength = data.message.split(",").length;
                    if (data.messageCode == BULKORDER_CONSTANTS.STOCK_UNAVAILABLE) {
                        gm.stockUnavailable = true; $('.stockUnavailable').show(0).delay(3000).hide(0);
                        gm.basketMessage = data.message;
                    }
                    if (data.message) {
                        if (data.messageCode == BULKORDER_CONSTANTS.STOCK_AVAILABLE) {
                            gm.basketMessage = data.message;// $('.basketMessage').show(0).delay(3000).hide(0);
                        }
                        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);
                                return;
                            }
                        }
                        if (data.message) {
                            $('#shopLook').addClass('btn-success');
                            $('#shopLook').removeClass('btn-primary');
                            $('#shopLook').text('ADDED');
                            $timeout(function () {
                                $('#shopLook').addClass('btn-primary');
                                $('#shopLook').removeClass('btn-success');
                                $('#shopLook').text('SHOP THE LOOK');
                            }, 3000);
                            //if (data.messageCode == BULKORDER_CONSTANTS.SUCCESS)
                            //    gm.basketMessage = data.message
                        }
                        else {
                            gm.basketMessage = data.message;
                            // $('.basketMessage').show(0).delay(3000).hide(0);
                        }
                        PubSub.publish("addToCart", eventData);
                        return;
                    }
                }).error(function () {
                    gm.wrongFormatMessage = true;
                    $('.wrongFormatError').show(0).delay(3000).hide(0);
                });
        }

        function bulkAddToBasket(productId, stockCode) {
            if (gm.addontobeaddedinbasket == null || gm.addontobeaddedinbasket == undefined) {
                return;
            }
            $scope.bulkOrder = [];
            $scope.bulkOrder.push({ stockCode: stockCode, parentProductId: null, qty: 1 });

            angular.forEach(gm.addontobeaddedinbasket, function (linetiem) {
                $scope.bulkOrder.push({ stockCode: linetiem.stockCode, parentProductId: productId, qty: linetiem.qty });
            });
            gm.bulkAddToBag();
        }

        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) {
            var countryCode = 'GB';
            if (gm.basketResponse.shippingAddress != null)
                countryCode = gm.basketResponse.shippingAddress.countryCode;
            $http.post(globalConfig.updateShipping, { id: gm.basketResponse.id, shippingId: id, nominatedDelivery: null, countryCode: countryCode })
                .success(function (data) {
                    if (data.shippingUpdateMessage != null) {
                        alerts.error(data.shippingUpdateMessage);
                    }
                    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;
                        }
                    });
                    gm.showSubTotalIncShipping();
                })
                .error(function (msg) {
                    // vm.errorMessage = msg.errorMessages;
                })
                .finally(function () {
                    // vm.saving = false;
                    //$("html, body").animate({ scrollTop: 0 }, "slow");
                });
        };

        function removePromoCode(id, promoCode) {
            $http.post(globalConfig.removePromoCode, { id: id, promoCode: promoCode })
                .success(function (data) {
                    var dataResult = gm.serializedData(data.result.basket);
                    gm.basketResponse = dataResult;
                    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

        function userLogin(model) {
            gm.saving = false;
            gm.errorMessage = null;
            gm.success = false;
            $(".alertBlock").fadeIn();
            $http.post(globalConfig.signIn, model)
                .success(function (data) {
                    if (data != null && !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: '/' });
                        var hasGuestBoard = $.cookie('hasguestboard');
                        if (hasGuestBoard == "yes") {
                            gm.assignGuestIdeaBoard();
                    }
                    if (gm.spopValue) {
                        var newsLetterCookie = $.cookie("_newsSub");
                        if (newsLetterCookie) {
                            alerts.success("Oops, it looks like you’ve already registered this email address with us! Please sign in to shop or alternatively check your inbox for exclusive offers from us.");
                            $timeout(function () {
                                $.removeCookie('_spop', { path: '/' });
                                $.cookie("_cpop", true, { path: '/', expires: 10 });
                            }, 2000);
                        }
                        else {
                            gm.updateNewsletterPref();
                        }
                    }                      
                    if ($scope.global_login || gm.forPaymentUpdate)
                        window.location.reload();
                    else
                        window.location.href = window.location.href;
                  
                })
                .error(function (msg) {
                    gm.errorMessage = msg.errorMessages;
                    $timeout(function () {
                        $(".alertBlock").fadeOut();
                    }, 10000);

                })
                .finally(function () {
                    gm.saving = false;
                    $timeout(function () { $(".alertBlock").fadeOut(); }, 3000);
                });
        }
        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;
                gm.passwordMatch = false;
            }
            else {
                form[cnfPwdId].$valid = true;
                gm.passwordMatch = true;
            }
            if (form[pwdId].$valid && form[cnfPwdId].$valid)
                return true;
            else
                return false;
        }
        function checkPassword(form, pwdId, cnfPwdId) {
            if (!gm.myPlugin) {
                gm.myPlugin = $("input[id='" + pwdId + "']").password_strength();
            }
            var resp = false;            
            $timeout(function () { resp = gm.myPlugin.metReq() }, 1500);
            $timeout(function () { gm.isPasswordPolicyMeet(resp, form, pwdId, cnfPwdId) }, 1500);
        }
        gm.passwordMatch = false;
        function registration(model, isRedeem) {
            $scope.global_login = false;
            $scope.signin = false;
            $scope.register = true;
            gm.saving = false;
            gm.errorMessage = null;
            gm.success = false;
            $(".alertBlock").fadeIn();

            if (!model.firstName || !model.lastName || !model.email || !model.password || !model.confirmPassword) {
                alerts.error('Please enter all mandatory fields!');
                return;
            }
            if (model.email != null && (model.email.includes("126.com") || model.email.includes("163.com"))) {
                alerts.error('Restricted email you can sign up using any other email address instead!');
                return;
            }
            if (!gm.passwordMatch) {
                alerts.error('The password and confirm password do not match!');
                return;
            }

            if (gm.model.registerViewModel.notifyByEmail == undefined || gm.model.registerViewModel.notifyByEmail == false) {
                gm.model.registerViewModel.sourceProcess = "OPTOUT"; //This is specially done for Ometria after seeing existing code where sourceProcess is being hardocoded in js.
            }
            gm.model.registerViewModel.NewsLetterSubscribed = gm.model.registerViewModel.notifyByEmail;
            $http.post(globalConfig.register, model)
                .success(function (data) {
                    if (data != null && !data.isValid != null && typeof data.errorMessages != 'undefined' && data.errorMessages.length > 0) {
                       gm.errorMessage = data.errorMessages;
                        return;
                    }
                    $.cookie('IsUserLoggedIn', true, { path: '/' });
                    var hasGuestBoard = $.cookie('hasguestboard');
                    if (hasGuestBoard == "yes") {
                        gm.assignGuestIdeaBoard();
                    }

                    if (isRedeem)
                        window.location.href = microCountry + "/redeem";
                    else {
                        if (gm.spopValue) {
                            alerts.success("Thank you for signing up to receive emails and exclusive offers. Please check your inbox for your welcome email. Happy shopping!");
                            $timeout(function () {
                                $.removeCookie('_spop', { path: '/' });
                                $.cookie("_cpop", true, { path: '/', expires: 10 });
                                window.location.href = microCountry + "/MyAccount";
                            }, 3000);
                        }
                        else
                            window.location.href = microCountry + "/MyAccount";
                    }

                })
                .error(function (msg) {
                    gm.errorMessage = msg.errorMessages;
                })
                .finally(function () {
                    $("html, body").animate({ scrollTop: 0 }, "slow");
                    $timeout(function () { $(".alertBlock").fadeOut(); }, 5000);
                });
            //The below part is commented because there is a newsletter subscribe call already present in the insert user call.
            //if (!gm.model.registerViewModel.notifyNone && (gm.model.registerViewModel.notifyByEmail || gm.model.registerViewModel.notifyByPost || gm.model.registerViewModel.notifyBySMS)) {
            //    if (gm.model.registerViewModel.notifyByEmail)
            //        var sourceProcess = "EXPLICITLY_OPTEDIN"; //This specially done for Ometria.... will be removed 
            //    var newsletterModel = { Email: gm.model.registerViewModel.email, notifyByEmail: gm.model.registerViewModel.notifyByEmail, notifyBySMS: gm.model.registerViewModel.notifyBySMS, notifyByPost: gm.model.registerViewModel.notifyByPost, sourceProcess: sourceProcess, sourceSection: gm.model.registerViewModel.sourceSection };
            //    $http.post(globalConfig.newsLetterSubscription, newsletterModel).then(function (success) { }, function (error) { });
            //}
        }

        function login(model) {
            $scope.signin = true;
            $scope.register = false;
            $scope.global_login = false;
            gm.userLogin(model);
        }

        function globalLogin(model) {
            $scope.signin = false;
            $scope.register = false;
            $scope.global_login = true;
            if (window.localStorage.hasOwnProperty("signIn")) {
                window.localStorage.removeItem("signIn");
            }
            gm.userLogin(model);
        }

        function forgotPassword(model) {
            $http.post(globalConfig.forgotPassword, model)
                .success(function (data) {
                    gm.errorMessage = null;
                    gm.isValid = data.isValid;
                    gm.isValiduser = !data.isValid;
                    //$timeout(function () {
                    //    gm.isValiduser = false;
                    //    gm.isValid = false;
                    //    window.location.href = gm.returnUrl;
                    //}, 10000);
                })
                .error(function (msg) {
                    gm.errorMessage = msg.errorMessages;
                    $timeout(function () {
                        gm.isValiduser = false;
                        $(".alertBlock").fadeOut();
                    }, 10000);
                })
                .finally(function () {
                });
        };

        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;
            gm.alreadySubscribed = 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();
                $('.newslettersuccess').hide();
                $('.newsletteralready').hide();
                $('#nwslttralertpopup').show();
                $('.nwsletteroverlaypopup').show();
                //setTimeout(function () { $('.newsletteralert').hide(); }, 2000);
            }
            if (email == "" || email == null) {
                gm.emailinvalid = true;
                $('.newsletteralert').show();
                $('.newslettersuccess').hide();
                $('.newsletteralready').hide();
                $('#nwslttralertpopup').show();
                $('.nwsletteroverlaypopup').show();
                //setTimeout(function () { $('.newsletteralert').hide(); }, 2000);
            } 
                var model = { email: email, notifyByEmail: true, newsLetterSubscribed: true, sourceProcess: "EXPLICITLY_OPTEDIN", sourceSection: gm.sourceSection }  //This specially done for Ometria.... will be removed 
                if (gm.emailinvalid == false) {
                    $http.post(globalConfig.newsLetterSubscription, { newsletter: model })
                        .success(function (data) {
                            gm.customerEmail = '';
                            if (data) {
                                gm.subssuccess = true;
                                $('.newslettersuccess').show();
                                $('.newsletteralert').hide();
                                $('.newsletteralready').hide();
                                $('#nwslttralertpopup').show();
                                $('.nwsletteroverlaypopup').show();
                                //setTimeout(function () { $('.newslettersuccess').hide(); }, 2000);
                            }
                            else {
                                gm.alreadySubscribed = true;
                                $('.newsletteralready').show();
                                $('.newsletteralert').hide();
                                $('.newslettersuccess').hide();
                                $('#nwslttralertpopup').show();
                                $('.nwsletteroverlaypopup').show();
                                //setTimeout(function () { $('.newsletteralready').hide(); }, 2000);
                            }
                        })
                        .error(function (msg) {
                            gm.alreadySubscribed = true;
                            $('.newsletteralert').show();
                            $('.newsletteralert').hide();
                            $('.newslettersuccess').hide();
                            $('#nwslttralertpopup').show();
                            $('.nwsletteroverlaypopup').show();
                            //setTimeout(function () { $('.newsletteralert').hide(); }, 2000);
                        })
                        .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 && 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;
        });
        PubSub.subscribe('earlyaccessemail', function (eventData) {
            //alert('PubSub Called')
            newsLetterSubscription(eventData);
            $timeout(function () { document.getElementById("earlyaccessemail").value = ''; }, 2000);
            
            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;
                        $('.submenu-mainmenu').addClass('active');
                        $('.cartopen').addClass('active'); $timeout(function () { $(".cartopen").removeClass("active"); }, 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);
            gm.groupedLookBooks = gm.groupLookBooks(gm.allLooks.dynamicLists, "displayGroupName");
            gm.groupedLookBookLoaded = true;
        }

        function groupLookBooks(arr, prop) {
            var lookbooks = arr;
            if (lookbooks != undefined) {
                var result = lookbooks.reduce(function (r, a) {
                    r[a[prop]] = r[a[prop]] || [];
                    r[a[prop]].push(a);
                    return r;
                }, Object.create(null));
                var lbks = Object.keys(result).map(function (key) {
                    var obj = {
                        displayGroupName: key,
                        lookbooks: result[key]
                    };
                    return obj;
                });
                return lbks;
            }
        }

        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);
                window.setTimeout(function () {
                    $(".alert-container").fadeOut(function () { $(this).remove(); });
                }, 10000);
            }
        }

        //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(isSelected) {
            if (isSelected)
                $("#giftChoose").modal();
        }

        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) {
            if (product != null && product != undefined) {
                //validate engraving message
                if (validatePersonalisation(gm.engravingMsg)) {

                    var basketId = '';
                    if (gm.basketResponse)
                        var 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);
                            //redirect to offer page


                        }

                    }, function (error) { });
                } else {
                    $timeout(function () { gm.engravingError = false }, 10000);
                    $timeout(function () { gm.regexError = false }, 10000);
                    $timeout(function () { gm.colourError = false }, 10000);
                    $timeout(function () { gm.termsError = false }, 10000);
                }
            }

        }
        function savePersonalisationInfo(data, model) {
            if (data) {
                $http.post("/TFSBasket/SavePersonalisationInfo", { basketResp: data.result, model: model }).then(function (success) {
                    $("#Engraving").modal('hide');
                    gm.engravingMsg = [];
                    gm.engravingColour = '';
                    gm.engravingTermsAndConditions = false;
                    $scope.hideEngraving = false;
                    //assign updated basket. 
                    updateBasket(success.data);



                }, function (error) { });
            }
        }
        function validatePersonalisation(engravings) {
            var isValid = true;
            if (engravings != null && engravings != '' && engravings.length > 0) {
                var regex = new RegExp(REGEX_CONSTANTS.LETTERS_AND_NUMBERS_ONLY);
                angular.forEach(engravings, function (item) {
                    if (item == '' || item == null || item == undefined) {
                        gm.engravingError = true;
                        isValid = false;
                    }
                    else if (!regex.test(item)) {
                        gm.regexError = true;
                        isValid = false;
                    }
                });
                if (gm.engravingColour == null || gm.engravingColour == undefined || gm.engravingColour == '') {
                    isValid = false;
                    gm.colourError = true;
                }
                if (!gm.engravingTermsAndConditions) {
                    isValid = false;
                    gm.termsError = true;
                }
            } else {
                gm.engravingError = true;
                isValid = false;
            }
            return isValid;
        }

        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, isShowItemAddedMsg = false) {

            if (data.messageCode == 'C002')
                gm.errorMessage = data.message;
            gm.basketResponse = data.result;
            //var count = 0;
            if (gm.basketResponse != null) {
                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;
                    var sumofListPriceBR = 0;
                    var sumofLineWiseDiscountBR = 0;
                    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.price.raw.withTax > 0 && line.parentProductId == gm.emptyGuid) {
                            sumofListPriceBR = sumofListPriceBR + (line.listPrice.raw.withTax) * line.qty;
                            sumofLineWiseDiscountBR = sumofLineWiseDiscountBR + line.lineDiscount;
                        }
                        var json = eval('(' + line.attributesJson + ')');
                        line.slug = json.Slug;

                        if (gm.basketResponse.deliveryPlans != null && gm.basketResponse.deliveryPlans.length > 0) {
                            line.fulllfillmentchannel = gm.basketResponse.deliveryPlans[0].fulfilmentChannel;
                        }
                        if (json.Attributes != null) {
                            angular.forEach(json.Attributes, function (opt) {
                                if (opt.FieldCode.toLowerCase() === "choose.size") {
                                    line.sizevalue = opt.FieldValue;
                                }
                            });
                        }
                        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 == line.giftWrapId.toUpperCase()) {
                                    line.giftWrappingInfo.push(opt);
                                }
                            });
                        }
                        line.updatedqty = line.qty;

                    });
                    gm.basketResponse.sumofListPrice = sumofListPriceBR;
                    gm.basketResponse.sumofLinewiaseDiscount = sumofLineWiseDiscountBR;
                    extractCustomInfo(gm.basketResponse);
                    extractSubscription();
                }
                gm.count = gm.basketResponse.lineItemCount;
                $(".basketItemCount").html(gm.count);
            }
            window.setTimeout(function () {
                gm.errorMessage = null;
            }, 10000);

            if (true && isShowItemAddedMsg) {
                $('.cartopen').addClass('active');
            }
        }

        function updateBasketBadgeCount() {
            if (gm.basketResponse != null && gm.basketResponse != undefined) {
                $(".basketItemCount").html(gm.basketResponse.lineItemCount);
            }

        }

        //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 (selectedGiftOption != null && Object.keys(selectedGiftOption) != 0) {
                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) {
                    $("#giftChoose").modal('hide');
                    gm.selectedGiftWrapOption = {}
                    //assign updated basket. 
                    updateBasket(success.data);
                }, function (error) { });
            } else {
                gm.giftWrapError = true;
                $timeout(function () { gm.giftWrapError = false; }, 10000);
            }
        }

        //Remove gift wrapping
        function removeGiftWrap(selectedGiftOption) {
            if (selectedGiftOption != null) {
                var model = {
                    basketId: gm.basketResponse.id, productId: selectedGiftOption.productId, stockCode: selectedGiftOption.stockCode, Qty: 0,
                    isGiftWrapApplied: false, parentProductId: gm.selectedLineItem.productId, itemType: selectedGiftOption.itemType
                }
                $http.post("/Basket/RemoveGiftWrap", { model: model }).then(function (success) {
                    $("#giftChoose").modal('hide');
                    gm.selectedGiftWrapOption = {}
                    //assign updated basket. 
                    updateBasket(success.data);
                }, function (error) { });
            } else {
                //give error msg.
            }
        }

        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 () {
                });
        };


        function extractOrderCustomInfo(order) {
            angular.forEach(order.items, function (line) {
                if (order.deliveryPlans != null && order.deliveryPlans.length > 0) {
                    line.fulllfillmentchannel = order.deliveryPlans[0].fulfilmentChannel;
                    var shipmentDates = [];
                    angular.forEach(order.deliveryPlans, function (plan) {
                        shipmentDates.push(Date.parse(plan.deliveryDateTarget));
                    });

                    gm.maxShipmentDate = new Date(Math.max.apply(null, shipmentDates));

                }
            })
        };
        function generateCoupons(order) {
            $http.post("/tfscheckout/GenerateGiftCoupon", { model: order }).success(function (resp) {
                gm.couponResponse = resp;

            });
        }

        function discountShow() {
            gm.isDiscounted = false;
        }

        function storeAddress() {
            $("#storeAddress").modal();
        }

        function openShare() {
            $("#registryShare").modal();
        }

        function openGiftPanel() {
            $("#openGiftModal").modal();
        }

        function getGrid() {
            $("#view").addClass('gridView');
            $("#view").removeClass('listView');
            gm.getView = true;
        }
        function getList() {
            $("#view").removeClass('gridView');
            $("#view").addClass('listView');
            gm.getView = false;
        }
        function openIdeaBoardModal() {
            $("#addToBoard").modal();
            $("body, html").addClass("no-overflow");
        }
        function closeBoardModal() {
            $("body, html").removeClass("no-overflow");
        }

        function getUserIdeaBoards(id) {
            //var model = { recordId: id, currentPage: 1, pageSize: 100 };
            //gm.globalIdeaBList = [];
            //if (globalConfig.getUserIdeaB != undefined) {
            //    $http.post(globalConfig.getUserIdeaB, model)
            //        .success(function (data) {
            //            if (data) {
            //                gm.globalIdeaBList = data;
            //                gm.isIdeaboardListLoaded = true;
            //            }
            //        })
            //        .error(function (msg) {
            //        })
            //        .finally(function () {
            //        });
            //}
        }

        function getProdMinimalForIB(model, fromIBDetail) {
            gm.prodMinForIB = {};
            if (fromIBDetail) {
                gm.prodMinForIB.productId = model.productId;
                gm.prodMinForIB.stockCode = model.stockCode;
                gm.prodMinForIB.productUrl = model.productUrl;
                gm.prodMinForIB.url = model.url;
                gm.prodMinForIB.image1 = model.image1;
                gm.prodMinForIB.image2 = model.image2;
                gm.prodMinForIB.name = model.productDetails.name;
            }
            else {
                gm.prodMinForIB.productId = model.RecordId;
                gm.prodMinForIB.stockCode = model.StockCode;
                gm.prodMinForIB.productUrl = (model.Slug != undefined) ? model.Slug : model.Link;
                gm.prodMinForIB.url = model.Image;
                gm.prodMinForIB.image1 = (model.Images[0] != null) ? model.Images[0].Image : null;
                gm.prodMinForIB.image2 = (model.Images[1] != null) ? model.Images[1].Image : null;
                gm.prodMinForIB.name = model.Name;
            }
        }

        function addItemToIBoard(boardId) {
            gm.prodMinForIB.ideaboardId = boardId;
            $http.post(globalConfig.addItemToIB, gm.prodMinForIB)
                .success(function (data) {
                    if (data.isValid) {
                        alerts.success(data.message);
                        $("#addToBoard").modal('hide');
                        gm.closeBoardModal();
                        window.location.href = window.location.href;
                    }
                    else {
                        alerts.error(data.message);
                    }
                })
                .error(function (msg) {
                })
                .finally(function () {
                });
        }

        function createItemBoard() {
            var model = { name: gm.ideaboardName };
            $http.post(globalConfig.createIB, model)
                .success(function (data) {
                    var mess = data.response.result.message;
                    if (data.response.result.isValid) {
                        if (gm.shopByInspToBoard) {
                            gm.addBulkItemsToBoard(data.response.result.recordId);
                        }
                        else {
                            gm.addItemToIBoard(data.response.result.recordId);
                        }
                    }
                    else {
                        alerts.error(mess);
                    }
                })
                .error(function (msg) {
                })
                .finally(function () {
                });
        }

        function showRegistration() {
            $("#loginModal").modal('hide');
            $("#registrationModal").modal();
        }

        function showLoginModal() {
            $("#registrationModal").modal('hide');
            $("#loginModal").modal();
        }

        function createProductDetailIB(model) {
            gm.prodMinForIB = {};
            gm.prodMinForIB.productId = model.productId;
            gm.prodMinForIB.stockCode = model.stockCode;
            gm.prodMinForIB.productUrl = model.slug;
            gm.prodMinForIB.url = model.image;
            gm.prodMinForIB.image1 = model.image;
            gm.prodMinForIB.image1 = model.image.substring(model.image.indexOf("/product")).trim();
            gm.prodMinForIB.name = model.name;
        }

        function showTradingForm() {
            setPCALookup(globalConfig.pcaAccessCode, globalConfig.countryCode, 'gm.model.company.address1', 'gm.model.company.address2', 'gm.model.company.city', 'gm.model.company.state', 'gm.model.company.postCode', "gm.model.company.companyName");
        }

        function addToWishlist(productId) {
            $http.post(globalConfig.addToWishlistUrl, { id: productId }).success(function (resp) {
                if (resp) {
                    gm.wishlistsaved = true;
                }
                else {
                    gm.wishlistexistserror = true;
                    gm.wishlisterror = false;
                }
                $timeout(function () {
                    $(".wishdiv").fadeOut();
                    gm.wishlistsaved = false;
                    gm.wishlistexistserror = false;
                }, 2000);
            }).error(function (msg) { })
                .finally(function () { });
        };

        function assignGuestIdeaBoard() {
            $http.get(globalConfig.assignGuestIB).success(function (resp) {
                if (resp.isValid) {
                    //alerts.success(resp.message);
                }
            })
        }

        function checkIfBoarded() {
            if (gm.globalIdeaBList.length > 0) {
                for (var i = 0; i < gm.globalIdeaBList.length; i++) {
                    gm.globalIdeaBList[i].isBoarded = false;
                    if (gm.globalIdeaBList[i].items.length > 0) {
                        for (var j = 0; j < gm.globalIdeaBList[i].items.length; j++) {
                            var boardItem = gm.globalIdeaBList[i].items[j];
                            if ((boardItem.productId == gm.prodMinForIB.productId.toLowerCase()) && (boardItem.stockCode == gm.prodMinForIB.stockCode)) {
                                gm.globalIdeaBList[i].isBoarded = true;
                                break;
                            }
                            else {
                                gm.globalIdeaBList[i].isBoarded = false;
                            }
                        }
                    }
                    else {
                        gm.globalIdeaBList[i].isBoarded = false;
                    }
                }
            }
        }

        function highlightBoardedProduct(recordid, ifPDP) {
            if (gm.globalIdeaBList.length > 0) {
                angular.forEach(gm.globalIdeaBList, function (value) {
                    if (value.items.length > 0) {
                        angular.forEach(value.items, function (item) {
                            if (item.productId == recordid.toLowerCase()) {
                                if (ifPDP) {
                                    gm.hoverUrlLink = true;
                                }
                                else {
                                    $("#product-" + recordid).addClass("active");
                                }
                            }
                        });
                    }
                });
            }
        };

        function getProductAccessories(id) {

            $http.post(globalConfig.getProductAcc, { id: id }).success(function (data) {
                gm.productModel = data;
            })
                .error(function (msg) {
                    // pm.errorMessage = msg.errorMessages;
                })
                .finally(function () {
                    //  pm.saving = false;
                });
        };

        function getLookbookProducts(lookbook, ifIndex) {
            var obj = angular.copy(lookbook);
            gm.prodMinForIB = {};
            gm.prodMinForIB.name = obj.name;
            gm.prodMinForIB.id = obj.id;
            if (ifIndex) {
                gm.prodMinForIB.products = obj.products.results;
                gm.prodMinForIB.url = obj.mainImage;
            }
            else {
                gm.prodMinForIB.products = obj.products;
                gm.prodMinForIB.url = obj.image;
            }
            gm.shopByInspToBoard = true;
        };

        function checkIfProductExistInBoard() {
            if (gm.globalIdeaBList.length > 0) {
                for (var i = 0; i < gm.globalIdeaBList.length; i++) {
                    gm.globalIdeaBList[i].isBoarded = false;
                    var count = 0;
                    if (gm.globalIdeaBList[i].items.length > 0) {
                        for (var j = 0; j < gm.globalIdeaBList[i].items.length; j++) {
                            var boardItem = gm.globalIdeaBList[i].items[j];
                            angular.forEach(gm.prodMinForIB.products, function (ibProd, index) {
                                if ((boardItem.productId == ibProd.recordId.toLowerCase()) && (boardItem.stockCode == ibProd.stockCode)) {
                                    count++;
                                }
                            })
                            if (count == gm.prodMinForIB.products.length) {
                                gm.globalIdeaBList[i].isBoarded = true;
                            }
                            else {
                                gm.globalIdeaBList[i].isBoarded = false;
                            }
                        }
                    }
                }
            }
        }

        function addBulkItemsToBoard(boardId) {
            var model = {};
            model.id = gm.prodMinForIB.id;
            model.ideaboardId = boardId;
            model.name = gm.prodMinForIB.name;
            model.products = [];
            if (gm.prodMinForIB.products.length > 0) {
                angular.forEach(gm.prodMinForIB.products, function (obj, index) {
                    var product = {
                        productId: obj.recordId,
                        stockCode: obj.stockCode,
                        productUrl: obj.slug,
                        image1: obj.image.substring(obj.image.indexOf("/product")).trim(),
                        image2: (obj.images != null && obj.images[1] != undefined) ? obj.images[1].image : null
                    }
                    model.products.push(product);
                });
            }
            $http.post(globalConfig.addBulkItemToIB, model)
                .success(function (data) {
                    if (data.isValid) {
                        alerts.success(data.message);
                        $("#addToBoard").modal('hide');
                        gm.closeBoardModal();
                        gm.shopByInspToBoard = false;
                        window.location.href = window.location.href;
                    }
                    else {
                        alerts.error(data.message);
                    }
                })
                .error(function (msg) {
                })
                .finally(function () {
                });
        }

        function highlightBoardedProducts() {
            var allLookBooks = angular.copy(gm.allLooks.dynamicLists);
            angular.forEach(allLookBooks, function (value, index) {
                var products = angular.copy(value.products.results);
                var itemCount = products.length;
                if (products.length > 0) {
                    var ideaboardList = angular.copy(gm.globalIdeaBList)
                    angular.forEach(ideaboardList, function (ideaboard, index) {
                        var items = angular.copy(ideaboard.items);
                        var count = 0;
                        angular.forEach(items, function (item, index) {
                            angular.forEach(products, function (product, index) {
                                if (item.productId.toLowerCase() == product.recordId.toLowerCase()) {
                                    count++;
                                }
                            })
                        });
                        if (count == itemCount) {
                            $("#shopbyinspirationindex-" + value.id).addClass("active");
                        }
                    });
                }

            });
        }

       
        gm.showCountryredirect = showCountryredirect;
        function showCountryredirect(isMobile, cookieName) {
            if (!$.cookie(cookieName)) {
                $http.get('/home/checkCountryRedirect').success(function (resp) {
                    if (resp.otherSites.length > 0) {
                        gm.otherSites = resp.otherSites;
                        gm.currentSite = resp.currentSite;
                        gm.openOtherSitesModel(isMobile);
                    } else {
                        var now = new Date();
                        var exp = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1);
                        $.cookie(cookieName, "1", { path: '/', expires: exp });
                    }

                });
            }
        }
        gm.openOtherSitesModel = openOtherSitesModel;
        function openOtherSitesModel(isMobile) {
            //if (isMobile === 1) {
            //    $("#othersite-modal").removeAttr("ng-init");
            //    var html = document.getElementById("othersite-modal").outerHTML;
            //    document.getElementById("othersite-modal").remove();
            //    document.getElementById("divOthersite").innerHTML = html;                             
            //} 
            $("#othersite-modal").modal('show');
            $("html").addClass('no-overflow');
            $(".other-backdrop-overlay").addClass('active');
        }
        gm.setCountryRedirect = setCountryRedirect;
        function setCountryRedirect(cookieName) {
            var now = new Date();
            var exp = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1);
            $.cookie(cookieName, "1", { path: '/', expires: exp });
            $("#othersite-modal").modal('hide');
            $("html").removeClass('no-overflow');
            $(".other-backdrop-overlay").removeClass('active');
        }
        gm.setLang = setLang;
        function setLang(cookieName,lang) {
            $.cookie(cookieName, lang);            
        }
        gm.setCookie = setCookie;
        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 });           
        }
        //gm.appendCountryCodeInUrl = appendCountryCodeInUrl;
        //function appendCountryCodeInUrl() {
        //    var countryCode = $.cookie('cookie_country');
        //    if (countryCode) {
        //        countryCode = countryCode.toLowerCase();
        //        if (countryCode === 'gb') return;
        //        var aTags = $("a");
        //        angular.forEach(aTags, function (aTag) {
        //            if ($(aTag).attr("href")) {
        //                var url = $(aTag).attr("href");
        //                if (!url.startsWith("//") && url.startsWith("/")) {
        //                    $(aTag).attr("href", '/' + countryCode + url);
        //                }
        //            }
        //        });
        //    }
            
        //}
        //gm.appendCountryCodeInUrl();

        function onFileSelected() {
            var files = gm.uploadFiles;
            if (!files.length || gm.uploadFiles.length >= 10) {
                return;
            } else {
                for (let i = 0; i < files.length; i++) {
                    let current = files[i];
                    gm.fileIdCounter++
                    let fileEntry = {
                        id: gm.fileIdCounter,
                        file: current,
                        previewUrl: window.URL.createObjectURL(files[i]),
                        data: null,
                        altText: "",
                        isDefault: "",
                        isActive: true,
                        isChecked: false,
                        name: current.name
                    };
                    var reader = new FileReader();
                    let f = current;
                    reader.onload = (function (theFile) {
                        return function (e) {
                            fileEntry.data = e.target.result;
                            var base64 = base64ArrayBuffer(fileEntry.data);
                            var model = {
                                "name": current.name,
                                "data": base64,
                                "displayOrder": fileEntry.id,
                                "isChecked": false
                            };
                            self.imageUploadInProgress = true;
                            var type = (fileEntry.file != null) ? fileEntry.file.type : null;
                            if (type != null) {
                                var extension = getSupportedExtensions(type);
                                if (extension != null) {
                                    $http.post(globalConfig.contactPageAttachment, model)
                                        .success(function (data) {
                                            self.imageUploadInProgress = false;
                                            if (data.name != null) {
                                                alerts.success(GLOBALATTRIBUES_CONSTANTS.ATTACH_ADD);
                                                gm.files.push(data);
                                            }
                                            else {
                                                alerts.error(data.url);
                                            }
                                        })
                                }
                                else {
                                    alerts.error(GLOBALATTRIBUES_CONSTANTS.UNSPTD_FILE);
                                }
                            }
                        };
                    })(f);
                    reader.readAsArrayBuffer(f);
                }
            }
        }

        function deleteAttachment(file) {
            if (file != null && file.image != "") {
                $http.post(globalConfig.removeAttachment, file)
                    .success(function (data) {
                        if (data) {
                            for (var i = 0; i < gm.files.length; i++)
                                if (gm.files[i].name === file.name) {
                                    gm.files.splice(i, 1);
                                    break;
                                }
                            alerts.success(" Attachment removed");
                        }
                    });
            }
        }
        function closeOnScreenModal(cookieName) {
            var now = new Date(),
                // this will set the expiration to 12 months
                exp = new Date(now.getFullYear() + 1, now.getMonth(), now.getDate());
            $.cookie("acceptCookiePopup", true, { path: '/', expires: exp });
                $(".cookiePrompt").hide(); 
        };
        function showSubTotalIncShipping() {
            if (gm.basketResponse) {
                gm.basketResponse.subTotal.formatted.withTax = gm.basketResponse.currencySymbol + (gm.basketResponse.subTotal.raw.withTax + gm.basketResponse.shippingCharge.raw.withTax).toFixed(2);
            }
        };

        function checkActiveTab() {
            var isSignin = window.localStorage.getItem("signIn");
            if (isSignin == "true") {
                $("#newToForever").addClass("active");
                $("#guest").addClass("active");
                $("#alreadyRegistered").removeClass("active");
                $("#registered").removeClass("active");
            }
            else {
                $("#alreadyRegistered").addClass("active");
                $("#registered").addClass("active");
                $("#newToForever").removeClass("active");
                $("#guest").removeClass("active");
            }
            gm.spopValue = $.cookie('_spop');
            if (gm.spopValue) {
                gm.model.registerViewModel = {};
                gm.model.registerViewModel.notifyNone = false;
                gm.model.registerViewModel.sourceProcess = 'EXPLICITLY_OPTEDIN';
                gm.model.registerViewModel.notifyByEmail = true;
            }
        };

        function authenticateSitePassword(pwd) {
            if (pwd != null && pwd.length > 0) {
                $http.post('/PasswordProtection/AuthenticateSitePassword', { password: pwd })
                    .success(function (resp) {
                        if (resp != null && resp.isValid) {
                            window.location.href = '/';
                        }
                        else {
                            gm.sitePwdError = true;
                            gm.sitePwdError = "Please provide valid password.";
                        }
                    })
                    .error(function (msg) {
                        gm.errorMessage = msg.errorMessages;
                    })
                    .finally(function () {
                        $timeout(function () { gm.sitePwdError = false; gm.sitePwdError = ""; }, 3000);
                    });
            }
        }

        function addlookbookBulkProducts(lines) {
            $scope.bulkOrder = [];
            if (lines != null && lines.length > 0) {
                angular.forEach(lines, function (line) {
                    $scope.bulkOrder.push({ stockCode: line.stockCode, parentProductId: null, qty: 1, basketId: "" });
                });
            }
            gm.bulkAddToBag();
        }

        function updateNewsletterPref() {
            var newsletterModel = { email: gm.model.loginViewModel.username, newsLetterSubscribed: true, notifyByEmail: true, sourceProcess: "EXPLICITLY_OPTEDIN" };
            $http.post(globalConfig.newsLetterSubscription, { newsletter: newsletterModel }).success(function (resp) {
                if (resp) {
                    alerts.success("Thank you for subscribing newsletter");
                    $timeout(function () {
                        $.removeCookie('_spop', { path: '/' });
                        $.cookie("_cpop", true, { path: '/', expires: 10 });
                        $.cookie("_newsSub", true, { path: '/', expires: 10 });
                    }, 2000);
                }
                else { alerts.error("There is some problem in updating preferences"); }
            });
        }
    };
})();
;
(function(n){"use strict";var t={item:3,autoWidth:!1,slideMove:1,slideMargin:10,addClass:"",mode:"slide",useCSS:!0,cssEasing:"ease",easing:"linear",speed:400,auto:!1,pauseOnHover:!1,loop:!1,slideEndAnimation:!0,pause:2e3,keyPress:!1,controls:!0,prevHtml:"",nextHtml:"",rtl:!1,adaptiveHeight:!1,vertical:!1,verticalHeight:500,vThumbWidth:100,thumbItem:10,pager:!0,gallery:!1,galleryMargin:5,thumbMargin:5,currentPagerPosition:"middle",enableTouch:!0,enableDrag:!0,freeMove:!0,swipeThreshold:40,responsive:[],onBeforeStart:function(){},onSliderLoad:function(){},onBeforeSlide:function(){},onAfterSlide:function(){},onBeforeNextSlide:function(){},onBeforePrevSlide:function(){}};n.fn.lightSlider=function(i){if(this.length===0)return this;if(this.length>1)return this.each(function(){n(this).lightSlider(i)}),this;var a={},r=n.extend(!0,{},t,i),p={},u=this;a.$el=this;r.mode==="fade"&&(r.vertical=!1);var s=u.children(),g=n(window).width(),ut=null,b=null,w=0,c=0,nt=!1,o=0,f="",e=0,tt=r.vertical===!0?"height":"width",it=r.vertical===!0?"margin-bottom":"margin-right",l=0,d=0,y=0,k=0,v=null,rt="ontouchstart"in document.documentElement,h={};h.chbreakpoint=function(){var f,i,t,u;if(g=n(window).width(),r.responsive.length){if(r.autoWidth===!1&&(f=r.item),g<r.responsive[0].breakpoint)for(i=0;i<r.responsive.length;i++)g<r.responsive[i].breakpoint&&(ut=r.responsive[i].breakpoint,b=r.responsive[i]);if(typeof b!="undefined"&&b!==null)for(t in b.settings)b.settings.hasOwnProperty(t)&&((typeof p[t]=="undefined"||p[t]===null)&&(p[t]=r[t]),r[t]=b.settings[t]);if(!n.isEmptyObject(p)&&g>r.responsive[0].breakpoint)for(u in p)p.hasOwnProperty(u)&&(r[u]=p[u]);r.autoWidth===!1&&l>0&&y>0&&f!==r.item&&(e=Math.round(l/((y+r.slideMargin)*r.slideMove)))}};h.calSW=function(){r.autoWidth===!1&&(y=(o-(r.item*r.slideMargin-r.slideMargin))/r.item)};h.calWidth=function(n){var i=n===!0?f.find(".lslide").length:s.length,t;if(r.autoWidth===!1)c=i*(y+r.slideMargin);else for(c=0,t=0;t<i;t++)c+=parseInt(s.eq(t).width())+r.slideMargin;return c};a={doCss:function(){var n=function(){for(var t=["transition","MozTransition","WebkitTransition","OTransition","msTransition","KhtmlTransition"],i=document.documentElement,n=0;n<t.length;n++)if(t[n]in i.style)return!0};return r.useCSS&&n()?!0:!1},keyPress:function(){if(r.keyPress)n(document).on("keyup.lightslider",function(t){n(":focus").is("input, textarea")||(t.preventDefault?t.preventDefault():t.returnValue=!1,t.keyCode===37?u.goToPrevSlide():t.keyCode===39&&u.goToNextSlide())})},controls:function(){if(r.controls){u.after('<div class="lSAction"><span class="lSPrev">'+r.prevHtml+'<\/span><span class="lSNext">'+r.nextHtml+"<\/span><\/div>");r.autoWidth?h.calWidth(!1)<o&&f.find(".lSAction").hide():w<=r.item&&f.find(".lSAction").hide();f.find(".lSAction a").on("click",function(t){return t.preventDefault?t.preventDefault():t.returnValue=!1,n(this).attr("class")==="lSPrev"?u.goToPrevSlide():u.goToNextSlide(),!1})}},initialStyle:function(){var n=this;r.mode==="fade"&&(r.autoWidth=!1,r.slideEndAnimation=!1);r.auto&&(r.slideEndAnimation=!1);r.autoWidth&&(r.slideMove=1,r.item=1);r.loop&&(r.slideMove=1,r.freeMove=!1);r.onBeforeStart.call(this,u);h.chbreakpoint();u.addClass("lightSlider").wrap('<div class="lSSlideOuter '+r.addClass+'"><div class="lSSlideWrapper"><\/div><\/div>');f=u.parent(".lSSlideWrapper");r.rtl===!0&&f.parent().addClass("lSrtl");r.vertical?(f.parent().addClass("vertical"),o=r.verticalHeight,f.css("height",o+"px")):o=u.outerWidth();s.addClass("lslide");r.loop===!0&&r.mode==="slide"&&(h.calSW(),h.clone=function(){var v,y,i,t,f,c,l,a;if(h.calWidth(!0)>o){for(v=0,y=0,i=0;i<s.length;i++)if(v+=parseInt(u.find(".lslide").eq(i).width())+r.slideMargin,y++,v>=o+r.slideMargin)break;if(t=r.autoWidth===!0?y:r.item,t<u.find(".clone.left").length)for(f=0;f<u.find(".clone.left").length-t;f++)s.eq(f).remove();if(t<u.find(".clone.right").length)for(c=s.length-1;c>s.length-1-u.find(".clone.right").length;c--)e--,s.eq(c).remove();for(l=u.find(".clone.right").length;l<t;l++)u.find(".lslide").eq(l).clone().removeClass("lslide").addClass("clone right").appendTo(u),e++;for(a=u.find(".lslide").length-u.find(".clone.left").length;a>u.find(".lslide").length-t;a--)u.find(".lslide").eq(a-1).clone().removeClass("lslide").addClass("clone left").prependTo(u);s=u.children()}else s.hasClass("clone")&&(u.find(".clone").remove(),n.move(u,0))},h.clone());h.sSW=function(){w=s.length;r.rtl===!0&&r.vertical===!1&&(it="margin-left");r.autoWidth===!1&&s.css(tt,y+"px");s.css(it,r.slideMargin+"px");c=h.calWidth(!1);u.css(tt,c+"px");r.loop===!0&&r.mode==="slide"&&nt===!1&&(e=u.find(".clone.left").length)};h.calL=function(){s=u.children();w=s.length};this.doCss()&&f.addClass("usingCss");h.calL();r.mode==="slide"?(h.calSW(),h.sSW(),r.loop===!0&&(l=n.slideValue(),this.move(u,l)),r.vertical===!1&&this.setHeight(u,!1)):(this.setHeight(u,!0),u.addClass("lSFade"),this.doCss()||(s.fadeOut(0),s.eq(e).fadeIn(0)));r.loop===!0&&r.mode==="slide"?s.eq(e).addClass("active"):s.first().addClass("active")},pager:function(){var i=this,n,t;h.createPager=function(){var p,a,t,s;k=(o-(r.thumbItem*r.thumbMargin-r.thumbMargin))/r.thumbItem;for(var v=f.find(".lslide"),w=f.find(".lslide").length,n=0,h="",l=0,n=0;n<w;n++)if(r.mode==="slide"&&(r.autoWidth?l+=(parseInt(v.eq(n).width())+r.slideMargin)*r.slideMove:l=n*(y+r.slideMargin)*r.slideMove),p=v.eq(n*r.slideMove).attr("data-thumb"),h+=r.gallery===!0?'<li style="width:100%;'+tt+":"+k+"px;"+it+":"+r.thumbMargin+'px"><a href="#"><img src="'+p+'" /><\/a><\/li>':'<li><a href="#">'+(n+1)+"<\/a><\/li>",r.mode==="slide"&&l>=c-o-r.slideMargin){n=n+1;a=2;r.autoWidth&&(h+='<li><a href="#">'+(n+1)+"<\/a><\/li>",a=1);n<a?(h=null,f.parent().addClass("noPager")):f.parent().removeClass("noPager");break}t=f.parent();t.find(".lSPager").html(h);r.gallery===!0&&(r.vertical===!0&&t.find(".lSPager").css("width",r.vThumbWidth+"px"),d=n*(r.thumbMargin+k)+.5,t.find(".lSPager").css({property:d+"px","transition-duration":r.speed+"ms"}),r.vertical===!0&&f.parent().css("padding-right",r.vThumbWidth+r.galleryMargin+"px"),t.find(".lSPager").css(tt,d+"px"));s=t.find(".lSPager").find("li");s.first().addClass("active");s.on("click",function(){return e=r.loop===!0&&r.mode==="slide"?e+(s.index(this)-t.find(".lSPager").find("li.active").index()):s.index(this),u.mode(!1),r.gallery===!0&&i.slideThumb(),!1})};r.pager&&(n="lSpg",r.gallery&&(n="lSGallery"),f.after('<ul class="lSPager '+n+'"><\/ul>'),t=r.vertical?"margin-left":"margin-top",f.parent().find(".lSPager").css(t,r.galleryMargin+"px"),h.createPager());setTimeout(function(){h.init()},0)},setHeight:function(n,t){var i=null,f=this,u;if(i=r.loop?n.children(".lslide ").first():n.children().first(),u=function(){var r=i.outerHeight(),u=0,f=r;t&&(r=0,u=f*100/o);n.css({height:r+"px","padding-bottom":u+"%"})},u(),i.find("img").length)if(i.find("img")[0].complete)u(),v||f.auto();else i.find("img").on("load",function(){setTimeout(function(){u();v||f.auto()},100)});else v||f.auto()},active:function(n,t){var i,o,s;this.doCss()&&r.mode==="fade"&&f.addClass("on");i=0;e*r.slideMove<w?(n.removeClass("active"),this.doCss()||r.mode!=="fade"||t!==!1||n.fadeOut(r.speed),i=t===!0?e:e*r.slideMove,t===!0&&(o=n.length,s=o-1,i+1>=o&&(i=s)),r.loop===!0&&r.mode==="slide"&&(i=t===!0?e-u.find(".clone.left").length:e*r.slideMove,t===!0&&(o=n.length,s=o-1,i+1===o?i=s:i+1>o&&(i=0))),this.doCss()||r.mode!=="fade"||t!==!1||n.eq(i).fadeIn(r.speed),n.eq(i).addClass("active")):(n.removeClass("active"),n.eq(n.length-1).addClass("active"),this.doCss()||r.mode!=="fade"||t!==!1||(n.fadeOut(r.speed),n.eq(i).fadeIn(r.speed)))},move:function(n,t){r.rtl===!0&&(t=-t);this.doCss()?r.vertical===!0?n.css({transform:"translate3d(0px, "+-t+"px, 0px)","-webkit-transform":"translate3d(0px, "+-t+"px, 0px)"}):n.css({transform:"translate3d("+-t+"px, 0px, 0px)","-webkit-transform":"translate3d("+-t+"px, 0px, 0px)"}):r.vertical===!0?n.css("position","relative").animate({top:-t+"px"},r.speed,r.easing):n.css("position","relative").animate({left:-t+"px"},r.speed,r.easing);var i=f.parent().find(".lSPager").find("li");this.active(i,!0)},fade:function(){this.active(s,!1);var n=f.parent().find(".lSPager").find("li");this.active(n,!0)},slide:function(){var n=this;h.calSlide=function(){c>o&&(l=n.slideValue(),n.active(s,!1),l>c-o-r.slideMargin?l=c-o-r.slideMargin:l<0&&(l=0),n.move(u,l),r.loop===!0&&r.mode==="slide"&&(e>=w-u.find(".clone.left").length/r.slideMove&&n.resetSlide(u.find(".clone.left").length),e===0&&n.resetSlide(f.find(".lslide").length)))};h.calSlide()},resetSlide:function(n){var t=this;f.find(".lSAction a").addClass("disabled");setTimeout(function(){e=n;f.css("transition-duration","0ms");l=t.slideValue();t.active(s,!1);a.move(u,l);setTimeout(function(){f.css("transition-duration",r.speed+"ms");f.find(".lSAction a").removeClass("disabled")},50)},r.speed+100)},slideValue:function(){var n=0,t;if(r.autoWidth===!1)n=e*(y+r.slideMargin)*r.slideMove;else for(n=0,t=0;t<e;t++)n+=parseInt(s.eq(t).width())+r.slideMargin;return n},slideThumb:function(){var i,n,s,t;switch(r.currentPagerPosition){case"left":i=0;break;case"middle":i=o/2-k/2;break;case"right":i=o-k}n=e-u.find(".clone.left").length;s=f.parent().find(".lSPager");r.mode==="slide"&&r.loop===!0&&(n>=s.children().length?n=0:n<0&&(n=s.children().length));t=n*(k+r.thumbMargin)-i;t+o>d&&(t=d-o-r.thumbMargin);t<0&&(t=0);this.move(s,t)},auto:function(){r.auto&&(clearInterval(v),v=setInterval(function(){u.goToNextSlide()},r.pause))},pauseOnHover:function(){var t=this;if(r.auto&&r.pauseOnHover){f.on("mouseenter",function(){n(this).addClass("ls-hover");u.pause();r.auto=!0});f.on("mouseleave",function(){n(this).removeClass("ls-hover");f.find(".lightSlider").hasClass("lsGrabbing")||t.auto()})}},touchMove:function(n,t){var s,i,e;f.css("transition-duration","0ms");r.mode==="slide"&&(s=n-t,i=l-s,i>=c-o-r.slideMargin?r.freeMove===!1?i=c-o-r.slideMargin:(e=c-o-r.slideMargin,i=e+(i-e)/5):i<0&&(i=r.freeMove===!1?0:i/5),this.move(u,i))},touchEnd:function(n){var i,t,h;f.css("transition-duration",r.speed+"ms");r.mode==="slide"?(i=!1,t=!0,l=l-n,l>c-o-r.slideMargin?(l=c-o-r.slideMargin,r.autoWidth===!1&&(i=!0)):l<0&&(l=0),h=function(n){var u=0,f,h,t;if(i||n&&(u=1),r.autoWidth){for(h=0,t=0;t<s.length;t++)if(h+=parseInt(s.eq(t).width())+r.slideMargin,e=t+u,h>=l)break}else f=l/((y+r.slideMargin)*r.slideMove),e=parseInt(f)+u,l>=c-o-r.slideMargin&&f%1!=0&&e++},n>=r.swipeThreshold?(h(!1),t=!1):n<=-r.swipeThreshold&&(h(!0),t=!1),u.mode(t),this.slideThumb()):n>=r.swipeThreshold?u.goToPrevSlide():n<=-r.swipeThreshold&&u.goToNextSlide()},enableDrag:function(){var e=this;if(!rt){var u=0,t=0,i=!1;f.find(".lightSlider").addClass("lsGrab");f.on("mousedown",function(t){if(c<o&&c!==0)return!1;n(t.target).attr("class")!=="lSPrev"&&n(t.target).attr("class")!=="lSNext"&&(u=r.vertical===!0?t.pageY:t.pageX,i=!0,t.preventDefault?t.preventDefault():t.returnValue=!1,f.scrollLeft+=1,f.scrollLeft-=1,f.find(".lightSlider").removeClass("lsGrab").addClass("lsGrabbing"),clearInterval(v))});n(window).on("mousemove",function(n){i&&(t=r.vertical===!0?n.pageY:n.pageX,e.touchMove(t,u))});n(window).on("mouseup",function(o){if(i){f.find(".lightSlider").removeClass("lsGrabbing").addClass("lsGrab");i=!1;t=r.vertical===!0?o.pageY:o.pageX;var s=t-u;if(Math.abs(s)>=r.swipeThreshold)n(window).on("click.ls",function(t){t.preventDefault?t.preventDefault():t.returnValue=!1;t.stopImmediatePropagation();t.stopPropagation();n(window).off("click.ls")});e.touchEnd(s)}})}},enableTouch:function(){var i=this,n,t;if(rt){n={};t={};f.on("touchstart",function(i){t=i.originalEvent.targetTouches[0];n.pageX=i.originalEvent.targetTouches[0].pageX;n.pageY=i.originalEvent.targetTouches[0].pageY;clearInterval(v)});f.on("touchmove",function(u){var s,f,e;if(c<o&&c!==0)return!1;s=u.originalEvent;t=s.targetTouches[0];f=Math.abs(t.pageX-n.pageX);e=Math.abs(t.pageY-n.pageY);r.vertical===!0?(e*3>f&&u.preventDefault(),i.touchMove(t.pageY,n.pageY)):(f*3>e&&u.preventDefault(),i.touchMove(t.pageX,n.pageX))});f.on("touchend",function(){if(c<o&&c!==0)return!1;var u;u=r.vertical===!0?t.pageY-n.pageY:t.pageX-n.pageX;i.touchEnd(u)})}},build:function(){var t=this;t.initialStyle();this.doCss()&&(r.enableTouch===!0&&t.enableTouch(),r.enableDrag===!0&&t.enableDrag());n(window).on("focus",function(){t.auto()});n(window).on("blur",function(){clearInterval(v)});t.pager();t.pauseOnHover();t.controls();t.keyPress()}};a.build();h.init=function(){h.chbreakpoint();r.vertical===!0?(o=r.item>1?r.verticalHeight:s.outerHeight(),f.css("height",o+"px")):o=f.outerWidth();r.loop===!0&&r.mode==="slide"&&h.clone();h.calL();r.mode==="slide"&&u.removeClass("lSSlide");r.mode==="slide"&&(h.calSW(),h.sSW());setTimeout(function(){r.mode==="slide"&&u.addClass("lSSlide")},1e3);r.pager&&h.createPager();r.adaptiveHeight===!0&&r.vertical===!1&&u.css("height",s.eq(e).outerHeight(!0));r.adaptiveHeight===!1&&(r.mode==="slide"?r.vertical===!1?a.setHeight(u,!1):a.auto():a.setHeight(u,!0));r.gallery===!0&&a.slideThumb();r.mode==="slide"&&a.slide();r.autoWidth===!1?s.length<=r.item?f.find(".lSAction").hide():f.find(".lSAction").show():h.calWidth(!1)<o&&c!==0?f.find(".lSAction").hide():f.find(".lSAction").show()};u.goToPrevSlide=function(){if(e>0)r.onBeforePrevSlide.call(this,u,e),e--,u.mode(!1),r.gallery===!0&&a.slideThumb();else if(r.loop===!0){if(r.onBeforePrevSlide.call(this,u,e),r.mode==="fade"){var n=w-1;e=parseInt(n/r.slideMove)}u.mode(!1);r.gallery===!0&&a.slideThumb()}else r.slideEndAnimation===!0&&(u.addClass("leftEnd"),setTimeout(function(){u.removeClass("leftEnd")},400))};u.goToNextSlide=function(){var n=!0,t;r.mode==="slide"&&(t=a.slideValue(),n=t<c-o-r.slideMargin);e*r.slideMove<w-r.slideMove&&n?(r.onBeforeNextSlide.call(this,u,e),e++,u.mode(!1),r.gallery===!0&&a.slideThumb()):r.loop===!0?(r.onBeforeNextSlide.call(this,u,e),e=0,u.mode(!1),r.gallery===!0&&a.slideThumb()):r.slideEndAnimation===!0&&(u.addClass("rightEnd"),setTimeout(function(){u.removeClass("rightEnd")},400))};u.mode=function(n){r.adaptiveHeight===!0&&r.vertical===!1&&u.css("height",s.eq(e).outerHeight(!0));nt===!1&&(r.mode==="slide"?a.doCss()&&(u.addClass("lSSlide"),r.speed!==""&&f.css("transition-duration",r.speed+"ms"),r.cssEasing!==""&&f.css("transition-timing-function",r.cssEasing)):a.doCss()&&(r.speed!==""&&u.css("transition-duration",r.speed+"ms"),r.cssEasing!==""&&u.css("transition-timing-function",r.cssEasing)));n||r.onBeforeSlide.call(this,u,e);r.mode==="slide"?a.slide():a.fade();f.hasClass("ls-hover")||a.auto();setTimeout(function(){n||r.onAfterSlide.call(this,u,e)},r.speed);nt=!0};u.play=function(){u.goToNextSlide();r.auto=!0;a.auto()};u.pause=function(){r.auto=!1;clearInterval(v)};u.refresh=function(){h.init()};u.getCurrentSlideCount=function(){var i=e,t,n;return r.loop&&(t=f.find(".lslide").length,n=u.find(".clone.left").length,i=e<=n-1?t+(e-n):e>=t+n?e-t-n:e-n),i+1};u.getTotalSlideCount=function(){return f.find(".lslide").length};u.goToSlide=function(n){e=r.loop?n+u.find(".clone.left").length-1:n;u.mode(!1);r.gallery===!0&&a.slideThumb()};u.destroy=function(){u.lightSlider&&(u.goToPrevSlide=function(){},u.goToNextSlide=function(){},u.mode=function(){},u.play=function(){},u.pause=function(){},u.refresh=function(){},u.getCurrentSlideCount=function(){},u.getTotalSlideCount=function(){},u.goToSlide=function(){},u.lightSlider=null,h={init:function(){}},u.parent().parent().find(".lSAction, .lSPager").remove(),u.removeClass("lightSlider lSFade lSSlide lsGrab lsGrabbing leftEnd right").removeAttr("style").unwrap().unwrap(),u.children().removeAttr("style"),s.removeClass("lslide active"),u.find(".clone").remove(),s=null,v=null,nt=!1,e=0)};setTimeout(function(){r.onSliderLoad.call(this,u)},10);n(window).on("resize orientationchange",function(n){setTimeout(function(){n.preventDefault?n.preventDefault():n.returnValue=!1;h.init()},200)});return this}})(jQuery);;
(function () {
    'use strict';

    window.app.constant("COMM_IMAGES", {
        'INVALID_IMAGECOUNT': "Please select atleast one image", 'INVALID_TANDCS': "Please select Terms Of Use",
        'INVALID_NICKNAME': "Please enter name", 'INVALID_MAIL': 'Please enter valid Email',
        'INVALID_CUSTOMEREMAIL' : "Please enter Email"
    });
    window.app.controller('communityImageCtrl', communityImageCtrl);
    communityImageCtrl.$inject = ['$scope', '$timeout', '$http', '$q', '$sce', 'loader', 'alerts', '$window', 'BASE_URL', 'COMM_IMAGES','communityImageConfig'];

    function communityImageCtrl($scope, $timeout, $http, $q, $sce, loader, alerts, $window, BASE_URL, COMM_IMAGES, communityImageConfig) {
        var ci = this;
        ci.model = { files: [], isTermsSelected: false};
        ci.uploadFiles = [];
        ci.uploadFinalFiles = [];
        ci.finalUploadStep = false;
        ci.uploadStep = 1;
        ci.currentRequest = null;
        ci.results = [];
        ci.fileIdCounter = 0;

        ci.onFileSelected = onFileSelected;
        ci.closeModal = closeModal;
        ci.uploadImages = uploadImages;
        ci.resetPhotoModel = resetPhotoModel;
        ci.saveCommunityImages = saveCommunityImages;

        function resetPhotoModel() {
            ci.uploadFiles = [];
            ci.model.files = [];
            ci.uploadStep = 1;
            ci.model.userNickName = '';
            ci.model.userEmail = '';
            ci.uploadFinalFiles = [];
            ci.fileIdCounter = 0;
            ci.finalUploadStep = false
            ci.uploadStep = 1
        }

        function onFileSelected() {
            var files = ci.uploadFiles;
            if (!files.length || ci.uploadFiles.length >= 10) {
                return;
            } else {
                for (let i = 0; i < files.length; i++) {
                    let current = files[i];
                    ci.fileIdCounter++
                    let fileEntry = {
                        id: ci.fileIdCounter,
                        file: current,
                        previewUrl: window.URL.createObjectURL(files[i]),
                        data: null,
                        altText: "",
                        isDefault: "",
                        isActive: true,
                        isChecked: false,
                        name: current.name  
                    };
                    ci.model.files.push(fileEntry);
                    ci.uploadStep = 2;
                    var reader = new FileReader();
                    let f = current;
                    reader.onload = (function (theFile) {
                        return function (e) {
                            fileEntry.data = e.target.result;
                            var base64 = base64ArrayBuffer(fileEntry.data);
                            var imageModel = {
                                "name": current.name,
                                "data": base64,
                                "displayOrder": fileEntry.id,
                                "isChecked": false
                            };
                            angular.forEach(ci.model.files, function (value) {
                                if (value.name == imageModel.name) {
                                    value.imageFiles = imageModel;
                                }
                            });
                        };
                    })(f);
                    reader.readAsArrayBuffer(f);
                }
            }
        }
        
        function uploadImages() {
            var count = 0;
            if (ci.model.files.length > 0) {
                angular.forEach(ci.model.files, function (value) {
                    if (value.isChecked) {
                        count++;
                    }
                });
                if (count == 0) {
                    alerts.error(COMM_IMAGES.INVALID_IMAGECOUNT)
                    return;
                }
            }
            if (!ci.model.isTermsSelected) {
                alerts.error(COMM_IMAGES.INVALID_TANDCS)
                return;
            }

            //Selected Checked Files
            if (ci.uploadFinalFiles.length == 0) {
                angular.forEach(ci.model.files, function (value) {
                    if (value.isChecked) {
                        value.productName = [];
                        value.selectedItem = null;
                        value.searchText = null;
                        ci.uploadFinalFiles.push(value);
                    }
                });
            }
            else {
                var count = 0;
                ci.uploadFinalFiles = [];
                angular.forEach(ci.model.files, function (value) {                   
                    if (value.isChecked) {
                        ci.uploadFinalFiles.push(value);
                        count++;
                    }
                    if (count == 0) {
                        value.productName = [];
                        value.selectedItem = null;
                        value.searchText = null;
                        ci.uploadFinalFiles.push(value);
                    }
                });
            }
            ci.uploadStep = 3;
        }

        function saveCommunityImages() {
            var imageModel = { imageFiles : [] };
            if ((ci.model.userNickName == "") || (ci.model.userNickName == undefined)) {
                alerts.error(COMM_IMAGES.INVALID_NICKNAME)
                return;
            }
            if ((ci.model.userEmail == "") || (ci.model.userEmail == undefined)) {
                alerts.error(COMM_IMAGES.INVALID_CUSTOMEREMAIL)
                return;
            }
            if ((ci.model.userEmail != "") || (ci.model.userEmail != undefined)) {
                var regex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
                var result = regex.test(String(ci.model.userEmail).toLowerCase())
                if (result == false) {
                    alerts.error(COMM_IMAGES.INVALID_MAIL)
                    return;
                }
            }
            if (ci.uploadFinalFiles != null) {
                imageModel.userPublicName = ci.model.userNickName;
                imageModel.userEmail = ci.model.userEmail;
                angular.forEach(ci.uploadFinalFiles, function (value) {
                    imageModel.imageFiles.push(value.imageFiles);
                });
            }

            //API Call
            $http.post(communityImageConfig.saveCommunityImage, imageModel)
                .success(function (response) {
                    if (response) {
                        if (response.isValid) {
                            ci.finalUploadStep = true;
                            alerts.success(response.message);
                            ci.closeModal();
                        }
                        else {
                            ci.finalUploadStep = false;
                            ci.uploadStep = 3;
                            alerts.error(response.message);
                        }
                    }
                })
                .error(function (msg) {
                })
                .finally(function () {
                });
        }

        function closeModal() {
            ci.resetPhotoModel();
            $("#uploadPhotoModal").modal('hide');
        }

        function base64ArrayBuffer(arrayBuffer) {
            var base64 = '';
            var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'

            var bytes = new Uint8Array(arrayBuffer);
            var byteLength = bytes.byteLength;
            var byteRemainder = byteLength % 3;
            var mainLength = byteLength - byteRemainder;

            var a, b, c, d;
            var chunk;

            // Main loop deals with bytes in chunks of 3
            for (var i = 0; i < mainLength; i = i + 3) {
                // Combine the three bytes into a single integer
                chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];

                // Use bitmasks to extract 6-bit segments from the triplet
                a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18
                b = (chunk & 258048) >> 12; // 258048   = (2^6 - 1) << 12
                c = (chunk & 4032) >> 6; // 4032     = (2^6 - 1) << 6
                d = chunk & 63;              // 63       = 2^6 - 1

                // Convert the raw binary segments to the appropriate ASCII encoding
                base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d];
            }

            // Deal with the remaining bytes and padding
            if (byteRemainder === 1) {
                chunk = bytes[mainLength];

                a = (chunk & 252) >> 2 // 252 = (2^6 - 1) << 2

                // Set the 4 least significant bits to zero
                b = (chunk & 3) << 4 // 3   = 2^2 - 1

                base64 += encodings[a] + encodings[b] + '==';
            } else if (byteRemainder === 2) {
                chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1]

                a = (chunk & 64512) >> 10; // 64512 = (2^6 - 1) << 10
                b = (chunk & 1008) >> 4; // 1008  = (2^6 - 1) << 4

                // Set the 2 least significant bits to zero
                c = (chunk & 15) << 2; // 15    = 2^4 - 1

                base64 += encodings[a] + encodings[b] + encodings[c] + '=';
            }

            return base64;
        }
    };
})();;
/*!
	dsCountDown v1.0
	jQuery count down plugin
	(c) 2013 I Wayan Wirka - http://iwayanwirka.duststone.com/dscountdown/
	license: http://www.opensource.org/licenses/mit-license.php
*/
(function(e){e.fn.dsCountDown=function(t){var n=this;var r=1e3,i=null,s=false,o=0,u=1,a=0,f=0,l=0,c=0,h=0,p=null,d=null,v=null,m=null;var g={startDate:new Date,endDate:null,elemSelDays:"",elemSelHours:"",elemSelMinutes:"",elemSelSeconds:"",theme:"white",titleDays:"Days",titleHours:"Hours",titleMinutes:"Minutes",titleSeconds:"Seconds",onBevoreStart:null,onClocking:null,onFinish:null};var y=e.extend({},g,t);if(this.length>1){this.each(function(){e(this).dsCountDown(t)});return this}var b=function(){if(!y.elemSelSeconds){n.prepend('<div class="ds-element ds-element-seconds">							<div class="ds-element-title">'+y.titleSeconds+'</div>							<div class="ds-element-value ds-seconds">00</div>						</div>');m=n.find(".ds-seconds")}else{m=n.find(y.elemSelSeconds)}if(!y.elemSelMinutes){n.prepend('<div class="ds-element ds-element-minutes">							<div class="ds-element-title">'+y.titleMinutes+'</div>							<div class="ds-element-value ds-minutes">00</div>						</div>');v=n.find(".ds-minutes")}else{v=n.find(y.elemSelMinutes)}if(!y.elemSelHours){n.prepend('<div class="ds-element ds-element-hours">							<div class="ds-element-title">'+y.titleHours+'</div>							<div class="ds-element-value ds-hours">00</div>						</div>');d=n.find(".ds-hours")}else{d=n.find(y.elemSelHours)}if(!y.elemSelDays){n.prepend('<div class="ds-element ds-element-days">							<div class="ds-element-title">'+y.titleDays+'</div>							<div class="ds-element-value ds-days">00</div>						</div>');p=n.find(".ds-days")}else{p=n.find(y.elemSelDays)}n.addClass("dsCountDown");n.addClass("ds-"+y.theme);if(y.startDate&&y.endDate){a=y.endDate.getTime()-y.startDate.getTime();if(a>0){var e=a/1e3;var t=e%86400;var r=t%3600;o=e;h=Math.floor(e/86400);c=Math.floor(t/3600);l=Math.floor(r/60);f=Math.floor(r%60)}}E()};var w=function(e){if(s){clearInterval(i);s=false}if(e){e(n)}};var E=function(){if(!s){if(o>0){if(y.onBevoreStart){y.onBevoreStart(n)}i=setInterval(function(){if(o>0){o-=u;f-=u;if(f<=0&&(l>0||c>0||h>0)){l--;f=60}if(l<=0&&(c>0||h>0)){c--;l=60}if(c<=0&&h>0){h--;c=24}if(p)p.html(h<10?"0"+h:h);if(d)d.html(c<10?"0"+c:c);if(v)v.html(l<10?"0"+l:l);if(m)m.html(f<10?"0"+f:f);if(y.onClocking){y.onClocking(n)}}else{w(y.onFinish)}},r);s=true}else{if(y.onFinish){y.onFinish(n)}}}};b()}})(jQuery)
;
