/* Minification failed. Returning unminified contents.
(4489,116-117): run-time error JS1195: Expected expression: >
(4491,18-19): run-time error JS1195: Expected expression: )
(4537,10-11): run-time error JS1004: Expected ';': )
(4541,5-6): run-time error JS1002: Syntax error: }
(4544,25-26): run-time error JS1002: Syntax error: }
(4547,48-49): run-time error JS1195: Expected expression: )
(4547,50-51): run-time error JS1004: Expected ';': {
(4603,3-4): run-time error JS1195: Expected expression: )
(6080,116-117): run-time error JS1195: Expected expression: >
(6082,18-19): run-time error JS1195: Expected expression: )
(6138,36-37): run-time error JS1195: Expected expression: >
(6142,34-35): run-time error JS1195: Expected expression: )
(6151,32-33): run-time error JS1195: Expected expression: >
(6155,30-31): run-time error JS1195: Expected expression: )
(6341,85-86): run-time error JS1195: Expected expression: >
(6341,132-133): run-time error JS1195: Expected expression: )
(6341,133-134): run-time error JS1004: Expected ';': )
(6349,29-30): run-time error JS1002: Syntax error: }
(6351,41-42): run-time error JS1195: Expected expression: )
(6351,43-44): run-time error JS1004: Expected ';': {
(6353,22-23): run-time error JS1195: Expected expression: )
(6356,69-70): run-time error JS1004: Expected ';': {
(6421,63-64): run-time error JS1195: Expected expression: >
(6421,88-89): run-time error JS1004: Expected ';': )
(6422,17-18): run-time error JS1002: Syntax error: }
(6424,50-58): run-time error JS1197: Too many errors. The file might not be a JavaScript file: function
(4599,5,4601,6): run-time error JS1018: 'return' statement outside of function: return {
        init: init
    }
 */
// venobox min
"use strict";

!(function (e) {
    "use strict";
    var o, t, a, n, i, s, c, r, l, d, v, u, b, p, m, f, g, h, k, x, y, w, C, _, B, M, P, E, O, Y, D, N, U, V, z, R, X, j, T, W;
    e.fn.extend({
        venobox: function venobox(q) {
            var F = this,
                $ = e.extend({
                    arrowsColor: "#B6B6B6",
                    contentMarginTop: null,
                    contentMarginBottom: null,
                    overFlowY: null,
                    autoplay: !1,
                    bgcolor: "#fff",
                    border: "0",
                    closeBackground: "#161617",
                    closeColor: "#d2d2d2",
                    framewidth: "",
                    frameheight: "",
                    infinigall: !1,
                    htmlClose: "&times;",
                    htmlNext: "<span>Next</span>",
                    htmlPrev: "<span>Prev</span>",
                    numeratio: !1,
                    numerationBackground: "#161617",
                    numerationColor: "#d2d2d2",
                    numerationPosition: "top",
                    overlayClose: !0,
                    overlayColor: "rgba(23,23,23,0.85)",
                    spinner: "double-bounce",
                    spinColor: "#d2d2d2",
                    titleattr: "title",
                    titleBackground: "#161617",
                    titleColor: "#d2d2d2",
                    titlePosition: "top",
                    cb_pre_open: function cb_pre_open() {
                        return !0;
                    },
                    cb_post_open: function cb_post_open() {},
                    cb_pre_close: function cb_pre_close() {
                        return !0;
                    },
                    cb_post_close: function cb_post_close() {},
                    cb_post_resize: function cb_post_resize() {},
                    cb_after_nav: function cb_after_nav() {},
                    cb_init: function cb_init() {}
                }, q);
            return $.cb_init(F), this.each(function () {
                if ((E = e(this)).data("venobox")) return !0;

                function q() {
                    y = E.data("gall"), g = E.data("numeratio"), b = E.data("infinigall"), p = e('.vbox-item[data-gall="' + y + '"]'), w = p.eq(p.index(E) + 1), C = p.eq(p.index(E) - 1), w.length || !0 !== b || (w = p.eq(0)), p.length > 1 ? (O = p.index(E) + 1, a.html(O + " / " + p.length)) : O = 1, !0 === g ? a.show() : a.hide(), "" !== x ? n.show() : n.hide(), w.length || !0 === b ? (e(".vbox-next").css("display", "block"), _ = !0) : (e(".vbox-next").css("display", "none"), _ = !1), p.index(E) > 0 || !0 === b ? (e(".vbox-prev").css("display", "block"), B = !0) : (e(".vbox-prev").css("display", "none"), B = !1), !0 !== B && !0 !== _ || (r.on(J.DOWN, S), r.on(J.MOVE, Z), r.on(J.UP, G));
                }

                function I(e) {
                    return !(e.length < 1) && !m && (m = !0, h = e.data("overlay") || e.data("overlaycolor"), v = e.data("framewidth"), u = e.data("frameheight"), i = e.data("border"), t = e.data("bgcolor"), l = e.data("href") || e.attr("href"), o = e.data("autoplay"), x = e.attr(e.data("titleattr")) || "", e === C && r.addClass("animated").addClass("swipe-right"), e === w && r.addClass("animated").addClass("swipe-left"), void r.animate({
                        opacity: 0
                    }, 500, function () {
                        k.css("background", h), r.removeClass("animated").removeClass("swipe-left").removeClass("swipe-right").css({
                            "margin-left": 0,
                            "margin-right": 0
                        }), "iframe" == e.data("vbtype") ? te() : "inline" == e.data("vbtype") ? ne() : "ajax" == e.data("vbtype") ? oe() : "video" == e.data("vbtype") || "vimeo" == e.data("vbtype") || "youtube" == e.data("vbtype") ? ae(o) : (r.html('<img src="' + l + '">'), ie()), E = e, q(), m = !1, $.cb_after_nav(E, O, w, C);
                    }));
                }

                function A(e) {
                    27 === e.keyCode && H(), 37 == e.keyCode && !0 === B && I(C), 39 == e.keyCode && !0 === _ && I(w);
                }

                function H() {
                    if (!1 === $.cb_pre_close(E, O, w, C)) return !1;
                    e("body").off("keydown", A).removeClass("vbox-open"), E.focus(), k.animate({
                        opacity: 0
                    }, 500, function () {
                        k.remove(), m = !1, $.cb_post_close();
                    });
                }
                F.VBclose = function () {
                    H();
                }, E.addClass("vbox-item"), E.data("framewidth", $.framewidth), E.data("frameheight", $.frameheight), E.data("border", $.border), E.data("bgcolor", $.bgcolor), E.data("numeratio", $.numeratio), E.data("infinigall", $.infinigall), E.data("overlaycolor", $.overlayColor), E.data("titleattr", $.titleattr), E.data("venobox", !0), E.on("click", function (b) {
                    if ((b.preventDefault(), E = e(this), !1 === $.cb_pre_open(E))) return !1;
                    switch ((F.VBnext = function () {
                        I(w);
                    }, F.VBprev = function () {
                        I(C);
                    }, h = E.data("overlay") || E.data("overlaycolor"), v = E.data("framewidth"), u = E.data("frameheight"), o = E.data("autoplay") || $.autoplay, i = E.data("border"), t = E.data("bgcolor"), _ = !1, B = !1, m = !1, l = E.data("href") || E.attr("href"), d = E.data("css") || "", x = E.attr(E.data("titleattr")) || "", M = '<div class="vbox-preloader">', $.spinner)) {
                        case "rotating-plane":
                            M += '<div class="sk-rotating-plane"></div>';
                            break;
                        case "double-bounce":
                            M += '<div class="sk-double-bounce"><div class="sk-child sk-double-bounce1"></div><div class="sk-child sk-double-bounce2"></div></div>';
                            break;
                        case "wave":
                            M += '<div class="sk-wave"><div class="sk-rect sk-rect1"></div><div class="sk-rect sk-rect2"></div><div class="sk-rect sk-rect3"></div><div class="sk-rect sk-rect4"></div><div class="sk-rect sk-rect5"></div></div>';
                            break;
                        case "wandering-cubes":
                            M += '<div class="sk-wandering-cubes"><div class="sk-cube sk-cube1"></div><div class="sk-cube sk-cube2"></div></div>';
                            break;
                        case "spinner-pulse":
                            M += '<div class="sk-spinner sk-spinner-pulse"></div>';
                            break;
                        case "three-bounce":
                            M += '<div class="sk-three-bounce"><div class="sk-child sk-bounce1"></div><div class="sk-child sk-bounce2"></div><div class="sk-child sk-bounce3"></div></div>';
                            break;
                        case "cube-grid":
                            M += '<div class="sk-cube-grid"><div class="sk-cube sk-cube1"></div><div class="sk-cube sk-cube2"></div><div class="sk-cube sk-cube3"></div><div class="sk-cube sk-cube4"></div><div class="sk-cube sk-cube5"></div><div class="sk-cube sk-cube6"></div><div class="sk-cube sk-cube7"></div><div class="sk-cube sk-cube8"></div><div class="sk-cube sk-cube9"></div></div>';
                    }
                    return M += "</div>", P = '<a class="vbox-next">' + $.htmlNext + '</a><a class="vbox-prev">' + $.htmlPrev + "</a>", D = '<div class="vbox-title"></div><div class="vbox-num">0/0</div><div class="vbox-close">' + $.htmlClose + "</div>", s = '<div class="vbox-overlay ' + d + '" style="background:' + h + '">' + M + '<div class="vbox-container"><div class="vbox-content"></div></div>' + D + P + "</div>", e("body").append(s).addClass("vbox-open"), e(".vbox-preloader .sk-child, .vbox-preloader .sk-rotating-plane, .vbox-preloader .sk-rect, .vbox-preloader .sk-cube, .vbox-preloader .sk-spinner-pulse").css("background-color", $.spinColor), k = e(".vbox-overlay"), c = e(".vbox-container"), r = e(".vbox-content"), a = e(".vbox-num"), (n = e(".vbox-title")).css($.titlePosition, "-1px"), n.css({
                        color: $.titleColor,
                        "background-color": $.titleBackground
                    }), e(".vbox-close").css({
                        color: $.closeColor,
                        "background-color": $.closeBackground
                    }), e(".vbox-num").css($.numerationPosition, "-1px"), e(".vbox-num").css({
                        color: $.numerationColor,
                        "background-color": $.numerationBackground
                    }), e(".vbox-next span, .vbox-prev span").css({
                        "border-top-color": $.arrowsColor,
                        "border-right-color": $.arrowsColor
                    }), r.html(""), r.css("opacity", "0"), k.css("opacity", "0"), q(), k.animate({
                        opacity: 1
                    }, 250, function () {
                        "iframe" == E.data("vbtype") ? te() : "inline" == E.data("vbtype") ? ne() : "ajax" == E.data("vbtype") ? oe() : "video" == E.data("vbtype") || "vimeo" == E.data("vbtype") || "youtube" == E.data("vbtype") ? ae(o) : (r.html('<img src="' + l + '">'), ie()), $.cb_post_open(E, O, w, C);
                    }), e("body").keydown(A), e(".vbox-prev").on("click", function () {
                        I(C);
                    }), e(".vbox-next").on("click", function () {
                        I(w);
                    }), !1;
                });
                var Q = ".vbox-overlay";

                function S(e) {
                    r.addClass("animated"), U = z = e.pageY, V = R = e.pageX, Y = !0;
                }

                function Z(e) {
                    if (!0 === Y) {
                        R = e.pageX, z = e.pageY, j = R - V, T = z - U;
                        var o = Math.abs(j);
                        o > Math.abs(T) && o <= 100 && (e.preventDefault(), r.css("margin-left", j));
                    }
                }

                function G(e) {
                    if (!0 === Y) {
                        Y = !1;
                        var o = E,
                            t = !1;
                        (X = R - V) < 0 && !0 === _ && (o = w, t = !0), X > 0 && !0 === B && (o = C, t = !0), Math.abs(X) >= W && !0 === t ? I(o) : r.css({
                            "margin-left": 0,
                            "margin-right": 0
                        });
                    }
                }
                $.overlayClose || (Q = ".vbox-close"), e(document).on("click", Q, function (o) {
                    (e(o.target).is(".vbox-overlay") || e(o.target).is(".vbox-content") || e(o.target).is(".vbox-close") || e(o.target).is(".vbox-preloader")) && H();
                }), V = 0, R = 0, X = 0, W = 50, Y = !1;
                var J = {
                        DOWN: "touchmousedown",
                        UP: "touchmouseup",
                        MOVE: "touchmousemove"
                    },
                    K = function K(o) {
                        var t;
                        switch (o.type) {
                            case "mousedown":
                                t = J.DOWN;
                                break;
                            case "mouseup":
                            case "mouseout":
                                t = J.UP;
                                break;
                            case "mousemove":
                                t = J.MOVE;
                                break;
                            default:
                                return;
                        }
                        var a = ee(t, o, o.pageX, o.pageY);
                        e(o.target).trigger(a);
                    },
                    L = function L(o) {
                        var t;
                        switch (o.type) {
                            case "touchstart":
                                t = J.DOWN;
                                break;
                            case "touchend":
                                t = J.UP;
                                break;
                            case "touchmove":
                                t = J.MOVE;
                                break;
                            default:
                                return;
                        }
                        var a,
                            n = o.originalEvent.touches[0];
                        a = t == J.UP ? ee(t, o, null, null) : ee(t, o, n.pageX, n.pageY), e(o.target).trigger(a);
                    },
                    ee = function ee(o, t, a, n) {
                        return e.Event(o, {
                            pageX: a,
                            pageY: n,
                            originalEvent: t
                        });
                    };

                function oe() {
                    e.ajax({
                        url: l,
                        cache: !1
                    }).done(function (e) {
                        r.html('<div class="vbox-inline">' + e + "</div>"), ie();
                    }).fail(function () {
                        r.html('<div class="vbox-inline"><p>Error retrieving contents, please retry</div>'), se();
                    });
                }

                function te() {
                    r.html('<iframe class="venoframe" src="' + l + '"></iframe>'), se();
                }

                function ae(e) {
                    var o,
                        t = (function (e) {
                            if ((e.match(/(http:|https:|)\/\/(player.|www.)?(vimeo\.com|youtu(be\.com|\.be|be\.googleapis\.com))\/(video\/|embed\/|watch\?v=|v\/)?([A-Za-z0-9._%-]*)(\&\S+)?/), RegExp.$3.indexOf("youtu") > -1)) var o = "youtube";
                            else if (RegExp.$3.indexOf("vimeo") > -1) var o = "vimeo";
                            return {
                                type: o,
                                id: RegExp.$6
                            };
                        })(l),
                        a = (e ? "?rel=0&autoplay=1" : "?rel=0") + (function (e) {
                            var o = "",
                                t = decodeURIComponent(e).split("?");
                            if (void 0 !== t[1]) {
                                var a,
                                    n,
                                    i = t[1].split("&");
                                for (n = 0; n < i.length; n++) a = i[n].split("="), o = o + "&" + a[0] + "=" + a[1];
                            }
                            return encodeURI(o);
                        })(l);
                    "vimeo" == t.type ? o = "https://player.vimeo.com/video/" : "youtube" == t.type && (o = "https://www.youtube.com/embed/"), r.html('<iframe class="venoframe vbvid" webkitallowfullscreen mozallowfullscreen allowfullscreen frameborder="0" src="' + o + t.id + a + '"></iframe>'), se();
                }

                function ne() {
                    r.html('<div class="vbox-inline">' + e(l).html() + "</div>"), se();
                }

                function ie() {
                    (N = r.find("img")).length ? N.each(function () {
                        e(this).one("load", function () {
                            se();
                        });
                    }) : se();
                }

                function se() {
                    n.html(x), r.find(">:first-child").addClass("figlio").css({
                        width: v,
                        height: u,
                        padding: i,
                        background: t
                    }), e("img.figlio").on("dragstart", function (e) {
                        e.preventDefault();
                    }), ce(), r.animate({
                        opacity: "1"
                    }, "slow", function () {});
                }

                function ce() {
                    var o = r.outerHeight(),
                        t = e(window).height();
                    f = o + 60 < t ? (t - o) / 2 : "30px", r.css("margin-top", null == $.contentMarginTop ? f : $.contentMarginTop + "px"), r.css("margin-bottom", null == $.contentMarginBottom ? f : $.contentMarginBottom + "px"), null != $.overFlowY && c.css("overflow-y", $.overFlowY), $.cb_post_resize();
                }
                "ontouchstart" in window ? (e(document).on("touchstart", L), e(document).on("touchmove", L), e(document).on("touchend", L)) : (e(document).on("mousedown", K), e(document).on("mouseup", K), e(document).on("mouseout", K), e(document).on("mousemove", K)), e(window).resize(function () {
                    e(".vbox-content").length && setTimeout(ce(), 800);
                });
            });
        }
    });
})(jQuery);

// stop hash link jump to on load
// to top right away
if (window.location.hash) scroll(0, 0);
// void some browsers issue
setTimeout(function () {
    scroll(0, 0);
}, 1);

var App = (function () {
    var _config = {
        'notifDisplayTimeout': 8000,
        'uidHash': ''
    };

    var init = function init(config) {
        if (config && typeof config == 'object') {
            $.extend(true, _config, config);
        }

        // *only* if we have anchor on the url
        if (window.location.hash && $('#' + window.location.hash.replace(/[^a-z0-9A-Z\-\_]*/gi, '')).length > 0) {
            // smooth scroll to the anchor id
            $('html, body').animate({
                scrollTop: $('#' + window.location.hash.replace(/[^a-z0-9A-Z\-\_]*/gi, '')).offset().top - 200 + 'px'
            }, 1000, 'swing');
        }

        $('.fname-round').each(function (i, o) {
            var color = nameColorPicker($(o).data('fname'));
            $(o).css({
                'background-color': color
            });
            $(o).colourBrightness();
        });

        // initialize regular image modal
        if ($('.venobox-image').length > 0) $('.venobox-image').venobox({
            spinColor: 'deeppink',
            cb_pre_open: function cb_pre_open(obj) {
                $('.vbox-preloader').hide();
                App.loader.showLoader();
            },
            cb_post_open: function cb_post_open(obj, gallIndex, thenext, theprev) {
                $('.vbox-preloader').hide();
                App.loader.hideLoader();
            }
        });

        // initialize image gallery (set data-gall="GalleryName")
        $('.venobox-gallery').venobox({
            infinigall: true,
            spinColor: 'deeppink',
            cb_pre_open: function cb_pre_open(obj) {
                $('.vbox-preloader').hide();
                App.loader.showLoader();
            },
            cb_post_open: function cb_post_open(obj, gallIndex, thenext, theprev) {
                $('.vbox-preloader').hide();
                App.loader.hideLoader();
            }
        });

        // for test reset button activation
        $('[data-answerResetId]').click(function () {
            var type = $(this).data('type');
            var id = $(this).data('answerresetid');
            var tid = $(this).data('tid');
            var market = $(this).data('market');
            var surveyTable = $(this).data('surveytable');
            App.loader.showLoader();

            window.location = '/' + market + '/survey/_resetanswer/' + id + '?type=' + type + '&marketuri=' + encodeURIComponent(market) + '&tid=' + tid + '&surveyTable=' + surveyTable;
        });

        // initialize full screen video (vimeo or youtube only)
        $('.venobox-video').venobox({
            framewidth: '100%', // default: ''
            frameheight: '100%', // default: ''
            titleattr: 'data-title', // default: 'title'
            numeratio: false, // default: false
            infinigall: false, // default: false
            spinner: 'cube-grid',
            contentMarginTop: 0,
            contentMarginBottom: 0,
            overFlowY: 'inherit',
            spinColor: 'deeppink',
            cb_pre_open: function cb_pre_open(obj) {
                $('.vbox-preloader').hide();
                App.loader.showLoader();
            },
            cb_post_open: function cb_post_open(obj, gallIndex, thenext, theprev) {
                $('.vbox-preloader').hide();
                App.loader.hideLoader();
            }
        });

        // enable bootstrap tooltip attributes
        $('[data-toggle="tooltip"]').tooltip();

        // general body/document click handler
        $(document).on('click', function (e) {
            var clickover = $(e.target);

            // close main menu when clicking the body
            var _closed = $("#btn-navbar").hasClass("collapsed");
            if (_closed !== true && !clickover.hasClass("navbar-toggle")) {
                $('.navbar-collapse').collapse('hide');
            }

            // close popover when click outside
            $('[data-toggle="popover"],[data-original-title]').each(function () {
                //the 'is' for buttons that trigger popups
                //the 'has' for icons within a button that triggers a popup
                if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
                    (($(this).popover('hide').data('bs.popover') || {}).inState || {}).click = false; // fix for BS 3.3.6
                }
            });
        });

        // Prevent 'Maximum call stack size exceeded' error when showing modal inside another modal
        $.fn.modal.Constructor.prototype.enforceFocus = function () {};

        /*
         Multipurpose confirm dialog using bootstrap modal
         Add these attributes to configure the dialog:        
          - data-click-continue: the function that will be called when clicking continue button. Will pass the element source of the click.
          - data-before-open: the function that will be called on dialog initialization. If this function return true, it will continue to load the dialog
          - data-title: title of the dialog
          - data-message: message of the dialog
          - data-text-continue: continue button text, default value is Continue.
          - data-text-cancel: cancel button text, default value is Cancel
         Bootstrap modal required attributes: data-toggle="modal" data-target="#waveConfirmDialog"
         Usage example:
            <span data-click-continue="App.Product._deleteMediaUpload" data-title="Sample title" data-text-continue="Continue"
                data-text-cancel="Cancel" data-message="Are you sure you want to continue?"
                data-toggle="modal" data-target="#waveConfirmDialog"></span>
        */
        $('#waveConfirmDialog').on('show.bs.modal', function (e) {
            var $this = $(this);
            var btnContinue = $this.find('button[name=btnContinue]');
            var btnCancel = $this.find('button[name=btnCancel]');
            var link = $(e.relatedTarget);

            // run this function before opening the modal from attribute: data-before-open
            var fnOpenStr = link.attr('data-before-open');
            if (typeof fnOpenStr != 'undefined' && fnOpenStr != '') {
                var fnOpen = App.getFunctionFromString(fnOpenStr);
                if (typeof fnOpen === 'function') {
                    // if function returns true, continue, otherwise dont show the modal
                    if (!fnOpen(link)) {
                        e.preventDefault(); // don't show the modal
                        return;
                    }
                }
            }

            // Set dialog title and message
            // Modal title from attribute: data-title
            $this.find('.modal-header-title').html(link.attr('data-title'));
            // Modal message from attribute: data-message
            $this.find('.modal-body-text').html(link.attr('data-message'));

            // Continue button text from attribute: data-text-continue
            var txtContinue = link.attr('data-text-continue');
            if (typeof txtContinue != 'undefined') btnContinue.html(txtContinue);

            // Cancel button text from attribute: data-text-cancel
            var txtCancel = link.attr('data-text-cancel');
            if (typeof txtCancel != 'undefined') btnCancel.html(txtCancel);

            // Set continue button callback function from attribute: data-click-continue
            btnContinue.off('click'); // remove previous callback if have 
            // Note: set 'data-click-continue' attribute with the full name of your function, e.g App.Product._deleteMediaUpload
            var fnClick = App.getFunctionFromString(link.attr('data-click-continue'));
            if (typeof fnClick === 'function') {
                // Pass the clicked element to the callback function
                btnContinue.on('click', function () {
                    fnClick(link);
                });
            }
        });

        // remove button callback on modal close
        $('#waveConfirmDialog').on('hidden.bs.modal', function (e) {
            var $this = $(this);
            var btnContinue = $this.find('button[name=btnContinue]');
            btnContinue.off('click');
        });

        /*
        Multipurpose info dialog using bootstrap modal
        Add these attributes to configure the dialog:        
          - data-title: title of the dialog
          - data-message: message of the dialog
          - data-text-close: close button text, default value is Close
        Bootstrap modal required attributes: data-toggle="modal" data-target="#waveInfoDialog"
        Usage example:        
            <a href="#" data-toggle="modal" data-target="#waveInfoDialog" data-title="Sample title" data-message="Sample message">
        */
        $('#waveInfoDialog').on('show.bs.modal', function (e) {
            var $this = $(this);
            var btnClose = $this.find('button[name=btnClose]');
            var link = $(e.relatedTarget);

            // Set dialog title and message
            // Modal title from 'data-title' attribute
            $this.find('.modal-header-title').html(link.attr('data-title'));
            // Modal message from 'data-message' attribute
            $this.find('.modal-body-text').html(link.attr('data-message'));

            // Continue button text
            var txtClose = link.attr('data-text-close');
            if (typeof txtClose != 'undefined') btnClose.html(txtClose);
        });

        // Owais custom droplist
        $(document).on('click', '.btn-select', function (e) {
            e.preventDefault();
            var ul = $(this).find("ul");
            if ($(this).hasClass("active")) {
                if (ul.find("li").is(e.target)) {
                    var target = $(e.target);
                    target.addClass("selected").siblings().removeClass("selected");
                    var value = target.html();
                    $(this).find(".btn-select-input").val(value);
                    $(this).find(".btn-select-value").html(value);
                }
                ul.hide();
                $(this).removeClass("active");
            } else {
                $('.btn-select').not(this).each(function () {
                    $(this).removeClass("active").find("ul").hide();
                });
                ul.slideDown(300);
                $(this).addClass("active");
            }
        });

        $(document).on('click', function (e) {
            var target = $(e.target).closest(".btn-select");
            if (!target.length) {
                $(".btn-select").removeClass("active").find("ul").hide();
            }
        });

        $(".btn-select").each(function (e) {
            var value = $(this).find("ul li.selected").html();
            if (value != undefined) {
                $(this).find(".btn-select-input").val(value);
                $(this).find(".btn-select-value").html(value);
            }
        });

        // form input interactive animation
        setTimeout(function () {
            $('.form-floating-label input, .form-floating-label textarea').focusin(function () {
                $(this).parent().addClass('has-value');
            });

            $('.form-floating-label input, .form-floating-label textarea').blur(function () {
                if (!$(this).val().length > 0) {
                    $(this).parent().removeClass('has-value');
                }
            });
        }, 300);

        //scroll to top assignment
        $('[data-toggle="scroll-to-top"]').click(function (e) {
            e.preventDefault();
            App.scrollToTop();
        });
    };

    var $loaderObj;
    var loader = {
        showLoader: function showLoader() {
            $loaderObj = $('<div class="vbox-overlay" style="background: rgba(255, 255, 255, 1); z-index: 1100"><div class="loaderD"></div></div>');
            $('body').append($loaderObj);
        },
        hideLoader: function hideLoader() {
            if (typeof $loaderObj != 'undefined') $loaderObj.remove();
            if ($('.loaderD').length > 0) $('.loaderD').parent().remove();
        },
        hasLoader: typeof $loaderObj != 'undefined'
    };

    var isNoNotice = function isNoNotice(url) {
        var isFound = false;
        for (var i = 0; i < _config.noReviewNoticeUrls.length; i++) {
            if (url.indexOf(_config.noReviewNoticeUrls[i]) > -1) {
                isFound = true;
                break;
            }
        }

        return isFound;
    };

    // Declare a proxy to reference the hub.
    var signalRHelper = $.connection.signalRHelper;
    // Create a function that the hub can call to broadcast messages.
    signalRHelper.client.broadcastNewReview = function (reviewerIdHash, userInfo, productName, productImg, url, timeString, countryId) {
        // Review notice shows only if clients on same market
        if (_config.countryId.toLowerCase() != countryId.toLowerCase()) return;

        // don't send notice to current user, it's called after review
        if (reviewerIdHash !== _config.uidHash && !isNoNotice(_config.controllerAction)) {
            showReviewNotice(reviewerIdHash, userInfo, productName, productImg, url, timeString);
        }
    };

    signalRHelper.client.broadcastUserFollow = function (followerIdHash, userInfo, userName, userImage, url, timeString, total, countryId) {
        showFollowedByNotice(userInfo, userName, userImage, url, timeString, total);
    };

    var showFollowedByNotice = function showFollowedByNotice(userInfo, userName, userImage, url, timeString, total) {
        var $reviewNotif = $('.followed-by-notification');
        if (userImage && userImage.length > 0)
            $reviewNotif.find('.notif-rect-left').html('<a href="' + url + '"><div class="dd-user_letter margin-t15" style="background-image:url(' + userImage + ')"></div></a>');
        else
            $reviewNotif.find('.notif-rect-left').html('<a href="' + url + '"><div class="dd-user_letter margin-t15 secondary-blue">' + userName[0].toUpperCase() + '</div></a>');

        $reviewNotif.find('.notif-product-name').html('<a class="href-link" href="' + url + '">' + userName + '</a><span class="notif-text-info italic-small-font">' + userInfo + '</span>');
        $reviewNotif.find('.notif-text-small-grey').html(timeString).show();

        $reviewNotif.removeClass('hidden').removeClass('bounceOutDown').addClass('bounceInUp');

        // use App.notifDisplayFollowedTimeoutId this var is set only on this event. This var is undefined on load.
        // This is used to clear this timeout when user click the notif close button
        App.notifDisplayFollowedTimeoutId = setTimeout(function () {
            $reviewNotif.removeClass('bounceInUp').addClass('bounceOutDown');
        }, _config.notifDisplayTimeout);
    };

    var showReviewNotice = function showReviewNotice(reviewerIdHash, userInfo, productName, productImg, url, timeString) {
        var $reviewNotif = $('.review-notification');
        $reviewNotif.find('.notif-rect-left').html('<a href="' + url + '"><div class="bg-img-contain margin-t15" style="background-image:url(' + productImg + ')"></div></a>');
        $reviewNotif.find('.notif-product-name').html('<a class="href-link" href="' + url + '">' + productName + '</a>');

        if (reviewerIdHash !== _config.uidHash) {
            $reviewNotif.find('.notif-text-info').html(userInfo).show();
            $reviewNotif.find('.notif-text-small-grey').html(timeString).show();
            $reviewNotif.find('.notif-text-info-user').hide();
        } else {
            // send a different message to current user who did the review
            $reviewNotif.find('.notif-text-info').hide();
            $reviewNotif.find('.notif-text-small-grey').hide();
            $reviewNotif.find('.notif-text-info-user').show();
        }

        $reviewNotif.removeClass('hidden').removeClass('bounceOutDown').addClass('bounceInUp');

        // use App.notifDisplayTimeoutId this var is set only on this event. This var is undefined on load.
        // This is used to clear this timeout when user click the notif close button
        App.notifDisplayTimeoutId = setTimeout(function () {
            $reviewNotif.removeClass('bounceInUp').addClass('bounceOutDown');
        }, _config.notifDisplayTimeout);
    };

    // Start signalr
    var hubReady = $.connection.hub.start({
        waitForPageLoad: false,
        transport: 'longPolling'
    });

    var avatarOnError = function avatarOnError(obj, userName) {
        if (typeof userName[0] === 'undefined') return;

        var parent = $(obj).parent();
        var clone = parent.clone();
        clone.empty();
        parent.html('<div class="vcenter text-center width-100pc"><span data-name="' + userName + '" class="user-fletter-circle">' + userName[0].toUpperCase() + '</span></div>');
        parent.addClass('round-user-image40 pos-neg-10');

        var color = nameColorPicker(userName);
        parent.css({
            'background-color': color
        });
        parent.colourBrightness();
    };

    var avatarOnError2 = function avatarOnError2(obj, userName) {
        if (typeof userName[0] === 'undefined') return;

        var parent = $(obj).parent();
        parent.html('<div class="vcenter width-100pc user-fname text-center" data-name="' + userName + '">' + userName[0].toUpperCase() + '</div>');

        var color = App.nameColorPicker(userName);
        parent.css({
            'background-color': color
        });
        parent.colourBrightness();
    };

    var nameColorPicker = function nameColorPicker(name) {
        name = name.toString();
        var n = 'abcdefghijklmnopqrstuvwxyz'.split('');
        var r = name.replace(/\s/ig, '').split('').map(function (e) {
            return n.indexOf(e);
        }).join('');
        var colorWheel = ['f6bf26', '7986cb', '9ccc65', '4fc3f7', '90a4ae', '57bb8a', 'f06292', 'b39ddb', 'ba68c8', '4dd0e1', 'FFCDD2', 'EF9A9A', 'E57373', 'E53935', 'FF8A80', 'FF5252', 'E91E63', 'F8BBD0', 'F48FB1', 'F06292', 'EC407A', 'D81B60', 'C2185B', 'AD1457', '880E4F', 'FF80AB', 'FF4081', 'C51162', 'AA00FF', 'D500F9', 'EA80FC', 'CE93D8', 'BA68C8', '8E24AA', 'B39DDB', '9575CD', '7E57C2', 'B388FF', '7C4DFF', '651FFF', '8C9EFF', '7986CB', '2196F3', 'BBDEFB', '90CAF9', '2196F3', '1976D2', '1565C0', '82B1FF', '448AFF', '03A9F4', 'B3E5FC', '81D4FA', '4FC3F7', '03A9F4', '039BE5', '0277BD', '01579B', 'B2EBF2', '80DEEA', '4DD0E1', '26C6DA', '00ACC1', '80D8FF', '40C4FF', '00B0FF', '0091EA', '00E5FF', '00B8D4', 'B2DFDB', '80CBC4', '009688', '64FFDA', '1DE9B6', '00BFA5', '4CAF50', 'A5D6A7', '388E3C', '69F0AE', '00E676', '00C853', '8BC34A', 'AED581', 'CCFF90', '64DD17', 'E6EE9C', 'F4FF81', 'C6FF00', 'AEEA00', 'FFEB3B', 'FFF59D', 'FFD54F', 'FFA726', 'FFC107', 'FDD835', 'FBC02D', 'FF8F00', 'FFEA00', 'FFD740', 'FFD180', 'FFD600', 'CFD8DC', 'FFB6C1', 'FFC0CB', 'FF69B4', 'CD5C5C', 'F08080', 'FA8072', 'FF6347', 'FFA07A', 'FF8C00', 'FFD700', '20B2AA', '66CDAA', '008B8B', '00CED1', '7B68EE', '6495ED', '1E90FF', '8A2BE2', '9400D3', 'BA55D3', 'DA70D6', '663399', 'DDA0DD', 'BC8F8F', 'F7CA18', 'F4D03F', '2980b9', 'f39c12', 'e67e22'];
        var colorIndex = (parseInt(r) < 0 ? parseInt(r) * -1 : parseInt(r)) % colorWheel.length;
        var color = '#' + colorWheel[colorIndex];

        return color;
    };

    var fixCommentsUserImage = function fixCommentsUserImage(parentElement) {
        var parent = typeof parentElement == 'undefined' ? '' : parentElement + ' ';
        // Fix user profile pic
        $(parent + '.user-profile-img').each(function (i, img) {
            if (!this.complete || typeof this.naturalWidth == "undefined" || this.naturalWidth == 0) {
                avatarOnError2(img, $(img).data('fname'));
            }
        });

        // Set background for users avatar not globally visible
        $(parent + '.user-fname-only').each(function () {
            var $this = $(this);
            var parent = $this.parent();
            var fname = $this.data('name');
            //var color = App.nameColorPicker(fname);
            parent.css({
                'background-color': '#8650d3'
            });
            parent.colourBrightness();
        });
    };

    // password strenth check
    var passwordNotice = function passwordNotice(input, selector, color) {
        var $input = $(input);
        var $notice = $(selector);
        $notice.find('span').css('color', '');

        $input.keyup(function () {
            var text = $.trim($(this).val());
            if (!color) color = {
                good: '#0edb73',
                bad: 'red'
            };

            if (text == null) return;

            $notice.find('span.pass-cap').css('color', text.match(/([A-Z])/g) ? color.good : color.bad); // capital letter
            $notice.find('span.pass-small').css('color', text.match(/([a-z])/g) ? color.good : color.bad); // small case letters
            $notice.find('span.pass-special').css('color', text.match(/([!@#$&*])/g) ? color.good : color.bad); // special char
            $notice.find('span.pass-num').css('color', text.match(/([\d])/g) ? color.good : color.bad); // a number
            $notice.find('span.pass-len').css('color', text.length > 7 ? color.good : color.bad); // at least 8 chars
        });
    };

    var resetFormError = function resetFormError(s) {
        // get the form inside we are working - change selector to your form as needed
        var $form = $(s);

        // get validator object
        var $validator = $form.validate();

        // get errors that were created using jQuery.validate.unobtrusive
        var $errors = $form.find(".field-validation-error span");

        // trick unobtrusive to think the elements were succesfully validated
        // this removes the validation messages
        $errors.each(function () {
            $validator.settings.success($(this));
        });

        // clear errors from validation
        $validator.resetForm();
    };

    var dataURItoBlob = function dataURItoBlob(dataURI) {
        var byteString = atob(dataURI.split(',')[1]);

        var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];

        var ab = new ArrayBuffer(byteString.length);
        var ia = new Uint8Array(ab);
        for (var i = 0; i < byteString.length; i++) {
            ia[i] = byteString.charCodeAt(i);
        }

        var bb = new Blob([ab], {
            "type": mimeString
        });
        return bb;
    };

    var getCurKbSize = function getCurKbSize(dataUrl) {
        return dataUrl.length * .75 / 1024;
    };

    var downScaleImage = function downScaleImage(dataUrl, newWidth, ext, imageArguments) {
        "use strict";
        var image, oldWidth, oldHeight, newHeight, canvas, ctx, newDataUrl, imageType;

        // Provide default values
        imageType = "image/" + (ext || 'jpeg');
        imageArguments = imageArguments || 0.7;

        // Create a temporary image so that we can compute the height of the downscaled image.
        image = new Image();
        image.src = dataUrl;
        oldWidth = image.width;
        oldHeight = image.height;
        newHeight = Math.floor(oldHeight * newWidth / oldWidth);

        // Create a temporary canvas to draw the downscaled image on.
        canvas = document.createElement("canvas");
        canvas.width = newWidth;
        canvas.height = newHeight;

        // Draw the downscaled image on the canvas and return the new data URL.
        ctx = canvas.getContext("2d");
        ctx.drawImage(image, 0, 0, newWidth, newHeight);
        newDataUrl = canvas.toDataURL(imageType, imageArguments);

        return newDataUrl;
    };

    var resizeImage = function resizeImage(dataUrl, ext, maxKb) {
        var image = new Image();
        image.src = dataUrl;
        var oldWidth = image.width;
        var curSize = getCurKbSize(dataUrl);
        var newDataUrl = dataUrl;
        var loop = 1;
        while (curSize > maxKb) {
            newDataUrl = downScaleImage(newDataUrl, oldWidth * 0.8, ext, 1);
            curSize = getCurKbSize(newDataUrl);

            var tmp = new Image();
            tmp.src = newDataUrl;
            oldWidth = tmp.width;
        }

        return newDataUrl;
    };

    var toScaledImage = function toScaledImage(obj) {
        // returns binary image data of scaled image
        var cropperData = $(obj).cropper('getCroppedCanvas', {
            aspectRatio: 1 / 1,
            width: 1024,
            height: 1024
        });

        if (!!!cropperData.toDataURL) return null;

        var cropperDataUrl = cropperData.toDataURL();
        var maxKbSize = 500;
        var isOrigFileSizeOk = true;

        if (cropperData.toDataURL().length * .75 / 1024 > maxKbSize) {
            isOrigFileSizeOk = false;
            var curKbSIze = cropperData.toDataURL().length * .75 / 1024;
            var maxRes = 100;
            var isStillLarge = true;
            while (isStillLarge) {
                if (maxRes == 0) break;
                maxRes -= 5;

                var dim = 750 * (maxRes / 100);
                var extension = $(obj).data('ext') == 'png' ? 'png' : 'jpeg';
                cropperDataUrl = cropperData.toDataURL("image/" + extension, maxRes / 100);
                curKbSIze = cropperDataUrl.length * .75 / 1024;
                isStillLarge = curKbSIze > maxKbSize;
            }
        }

        return cropperDataUrl;
    };

    var formValidateReset = function formValidateReset(s) {
        var form = $(s);
        form.removeData('validator');
        form.removeData('unobtrusiveValidation');
        $.validator.unobtrusive.parse(form);
    };

    var notify = {
        Success: function Success(message, title) {
            showBottomAlert('success', message, title);
        },
        Info: function Info(message, title, placementFrom) {
            showBottomAlert('info', message, title);
        },
        Warning: function Warning(message, title, placementFrom) {
            showBottomAlert('warning', message, title);
        },
        Danger: function Danger(message, title, placementFrom) {
            showBottomAlert('danger', message, title);
        },
        Debug: function Debug(message, title) {
            showBottomAlert('debug', message, title);
        }
    };

    function showBottomAlert(level, message, title) {
        level = !!level ? level : 'success';

        var alertDiv = $('.FlashAlert.alert').clone();
        var textDiv = alertDiv.find('span');
        var textTitle = alertDiv.find('h5');
        var delay = level == 'info' ? 10000 :
            level == 'debug' ? 0 :
                5000;

        alertDiv.addClass(level);
        textDiv.html(message);
        textTitle.html(title || '');
        $(document.body).append(alertDiv);
        alertDiv.fadeIn(400);
        if (delay > 0)
            setTimeout(function () {
                alertDiv.fadeOut(400, function () { alertDiv.remove(); });
            }, delay);
    }


    var isNullOrUndefined = function isNullOrUndefined(obj) {
        return typeof obj == 'undefined' || obj == null;
    };

    var fbInvite = function fbInvite(appId, content, url, data) {
        window.location = "https://www.facebook.com/dialog/apprequests?app_id=" + appId + "&message=" + content + "!&redirect_uri=" + encodeURIComponent(url) + "&data=" + data;
    };

    var getFunctionFromString = function getFunctionFromString(string) {
        var scope = window;
        var scopeSplit = string.split('.');
        for (var i = 0; i < scopeSplit.length - 1; i++) {
            scope = scope[scopeSplit[i]];

            if (scope == undefined) return;
        }

        return scope[scopeSplit[scopeSplit.length - 1]];
    };

    var scrollTo = function scrollTo(selector, speed) {
        $('html, body').animate({
            scrollTop: $(selector).offset().top
        }, speed);
    };

    // check if url is a valid youtube link and the video exist
    var youtubeVideoExists = function youtubeVideoExists(url, callback) {
        var v = null;
        if (url != undefined || url != '') {
            var regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=|\?v=)([^#\&\?]*).*/;
            var match = url.match(regExp);
            if (match && match[2].length == 11) {
                v = "https://img.youtube.com/vi/{0}/0.jpg".format(match[2]);
            }
        }

        if (v === null) {
            callback(false);
            return;
        }
        var image = new Image();
        image.onload = function () {
            callback(true);
        };
        image.onerror = function () {
            callback(false);
        };
        image.src = v;
    };

    var swipedetect = function swipedetect(el, callback) {
        /* Usage
            var el = document.getElementById('mybox');
            App.swipedetect(el, function (swipedir) {
                // swipedir contains either "none", "left", "right", "top", or "down"
                if (swipedir == 'left') // do something
                if (swipedir == 'right') // do something
                if (swipedir == 'top') // do something
                if (swipedir == 'down') // do something
            });
        */
        var touchsurface = el,
            swipedir,
            startX,
            startY,
            distX,
            distY,
            threshold = 120,
            //required min distance traveled to be considered swipe
            restraint = 100,
            // maximum distance allowed at the same time in perpendicular direction
            allowedTime = 250,
            // maximum time allowed to travel that distance
            elapsedTime,
            startTime,
            handleswipe = callback || function (swipedir) {};

        touchsurface.addEventListener('touchstart', function (e) {
            var touchobj = e.changedTouches[0];
            swipedir = 'none';
            startX = touchobj.pageX;
            startY = touchobj.pageY;
            startTime = new Date().getTime(); // record time when finger first makes contact with surface
            e.preventDefault();
        }, false);

        touchsurface.addEventListener('touchmove', function (e) {
            e.preventDefault(); // prevent scrolling when inside DIV
        }, false);

        touchsurface.addEventListener('touchend', function (e) {
            var touchobj = e.changedTouches[0];
            distX = touchobj.pageX - startX; // get horizontal dist traveled by finger while in contact with surface
            distY = touchobj.pageY - startY; // get vertical dist traveled by finger while in contact with surface
            elapsedTime = new Date().getTime() - startTime; // get time elapsed
            if (elapsedTime <= allowedTime) {
                // first condition for awipe met
                if (Math.abs(distX) >= threshold && Math.abs(distY) <= restraint) {
                    // 2nd condition for horizontal swipe met
                    swipedir = distX < 0 ? 'left' : 'right'; // if dist traveled is negative, it indicates left swipe
                } else if (Math.abs(distY) >= threshold && Math.abs(distX) <= restraint) {
                    // 2nd condition for vertical swipe met
                    swipedir = distY < 0 ? 'up' : 'down'; // if dist traveled is negative, it indicates up swipe
                }
            }
            handleswipe(swipedir);
            e.preventDefault();
        }, false);
    };

    var titleCase = function titleCase(str) {
        str = str.trim();
        if (str.length == 0) return str;

        var words = str.toLowerCase().split(' ');

        for (var i = 0; i < words.length; i++) {
            var letters = words[i].split('');
            letters[0] = letters[0].toUpperCase();
            words[i] = letters.join('');
        }
        return words.join(' ');
    };

    // Format date to: dd/MM/yyyy
    var formatDate = function formatDate(date) {
        var d = new Date(date),
            month = ("0" + d.getMonth()).slice(-2),
            day = ("0" + d.getDate()).slice(-2),
            year = d.getFullYear();

        return [day, month, year].join('/');
    };

    /* Cookie Handling */
    //#region Cookie handling
    function createCookie(name, value, days) {
        if (days) {
            var date = new Date();
            date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
            var expires = "; expires=" + date.toGMTString();
        } else var expires = "";
        document.cookie = name + "=" + value + expires + "; path=/";
    }

    function readCookie(name) {
        var nameEQ = name + "=";
        var ca = document.cookie.split(';');
        for (var i = 0; i < ca.length; i++) {
            var c = ca[i];
            while (c.charAt(0) == ' ') c = c.substring(1, c.length);
            if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
        }
        return null;
    }

    function eraseCookie(name) {
        createCookie(name, "", -1);
    }
    //#endregion
    /*
    function guid() {        
        return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
            (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
        )        
    }
    */

    // the above guid function cause issue on safari 6
    function guid() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
            var r = Math.random() * 16 | 0,
                v = c == 'x' ? r : r & 0x3 | 0x8;
            return v.toString(16);
        });
    }

    function inlineSuccessAlert(selector, message, placement) {
        var $obj = $(selector);
        var id = 'success_' + guid().replace(/\-/gi, '');
        var $messageBox = $('<div/>', {
            "class": 'alert alert-success',
            style: 'background-color: #fff; padding: 5px 8px; margin-left: auto; margin-right: auto; text-align:center; margin-top: 20px;clear: both',
            id: id,
            html: message
        });

        if (placement == App.placement.prepend) $obj.prepend($messageBox);
        if (placement == App.placement.before) $obj.before($messageBox);
        if (placement == App.placement.after) $obj.after($messageBox);
        else $obj.append($messageBox);

        setTimeout(function () {
            $messageBox.fadeOut(500, function () {
                $messageBox.remove();
            });
        }, 10 * 1000);
    }

    function loadSurveyQuestionTextClone() {
        $(document).on('scroll resize', function () {
            if (!$('.question-text-parent:not(.stop-float) > h6:visible').isInViewport()) {
                var $box = $('<div/>', {
                    "class": 'question-text-clone'
                });
                var $container = $('<div/>', {
                    "class": 'container'
                });
                var $clone = $('.question-text-parent:visible').clone();
                var maxCharToShow = 200;

                if ($clone.find('h6').text().length > maxCharToShow) {
                    // don't float header if it's too long, covers the whole mobile screen
                    $('.question-text-parent:visible').addClass('stop-float');
                    return;
                }

                $clone.removeClass('question-text-parent').removeClass('nopadding').addClass('padding-t10').addClass('padding-b10').addClass('text-size-14').addClass('floating-text').addClass('body-padding-l');
                $container.append($clone);
                if ($('tr.toptions.tstriped').is(':visible')) {
                    var $rowData = $('tr.toptions.tstriped:visible').eq(0).clone();
                    var $table = $('<table/>', {
                        "class": 'table margin-t20',
                        cellpadding: '0',
                        cellspacing: '0',
                        border: '0',
                        width: '100%'
                    });
                    var $tableBox = $('<div/>', {
                        "class": 'grid-float-title xs-hidden'
                    });
                    $table.append('<tbody></tbody>');
                    $table.find('tbody').append($rowData);
                    $tableBox.append($table);
                    $container.append($tableBox);
                }

                $box.append($container);
                $('body').append($box);
            } else if ($('.question-text-clone').length > 0) {
                $('.question-text-clone').remove();
            }
        });
    }

    function fbFeedDialog(link, callback) {
        if (typeof FB != 'undefined' && !!FB && !!FB.ui) {
            FB.ui({
                method: 'feed',
                link: link
            }, function (response) {
                if (!!callback) callback();
            });
        }
    }

    function scrollToTop() {
        $('html,body').animate({
            scrollTop: 0
        }, 700);
    }

    var fireDatalayerEvent = function fireDatalayerEvent(evt, uri, title) {
        window.dataLayer = window.dataLayer || [];
        window.dataLayer.push({
            'event': typeof evt != 'undefined' && !evt.isNullOrEmpty() ? evt.toLowerCase() : '',
            'pageUri': typeof uri != 'undefined' && !uri.isNullOrEmpty() ? uri.toLowerCase() : '',
            'pageTitle': typeof title != 'undefined' && !title.isNullOrEmpty() ? title.toLowerCase() : ''
        });
    };

    var fireDataLayerEventRoutes = function fireDataLayerEventRoutes(evt, uri, route) {
        if (!route || $.trim(route).length == 0) route = 'A';

        fireDatalayerEvent(evt + route.toLowerCase(), uri, document.title);
    };

    //copy text to clipboard
    var copyTextToClipboard = function copyTextToClipboard(str) {
        var id = 'txtCopyInput';
        var $input = $('<input/>', {
            id: id,
            style: 'position: absolute; top: -1000px; left: -1000px',
            val: str,
            type: 'text'
        });
        $('body').append($input);
        $input.select();
        setTimeout(function () {
            $input.remove();
        }, 1000);
        return document.execCommand('copy');
    };

    function editCreateFormDataAWS4(aws4Data) {
        var fd = new FormData();
        fd.append('key', aws4Data.Key);
        fd.append('acl', aws4Data.Acl);
        //fd.append('success_action_redirect', aws4Data.SuccessRedirectAction);
        fd.append('Content-Type', aws4Data.ContentType);
        fd.append('X-Amz-Credential', aws4Data.X_Amz_Credential);
        fd.append('X-Amz-Algorithm', aws4Data.X_Amz_Algorithm);
        fd.append('X-Amz-Date', aws4Data.X_Amz_Date);
        fd.append('x-amz-meta-tag', '');
        fd.append('Policy', aws4Data.Policy);
        fd.append('X-Amz-Signature', aws4Data.X_Amz_Signature);

        return fd;
    }

    function createFormDataAWS4(aws4Data) {
        var fd = new FormData();
        fd.append('key', aws4Data.Key);
        fd.append('acl', aws4Data.Acl);
        //fd.append('success_action_redirect', aws4Data.SuccessRedirectAction);
        fd.append('Content-Type', aws4Data.ContentType);
        fd.append('X-Amz-Credential', aws4Data.X_Amz_Credential);
        fd.append('X-Amz-Algorithm', aws4Data.X_Amz_Algorithm);
        fd.append('X-Amz-Date', aws4Data.X_Amz_Date);
        fd.append('x-amz-meta-tag', '');
        fd.append('Policy', aws4Data.Policy);
        fd.append('X-Amz-Signature', aws4Data.X_Amz_Signature);

        return fd;
    }

    var passwordRegex = function passwordRegex() {
        return new XRegExp('^(?=.*[!@#$&*])(?=.*[0-9].*)(?=.*[a-z])(?=.*[A-Z]).{8,}$');
    };

    // Credit David Walsh (https://davidwalsh.name/javascript-debounce-function)

    // Returns a function, that, as long as it continues to be invoked, will not
    // be triggered. The function will be called after it stops being called for
    // N milliseconds. If `immediate` is passed, trigger the function on the
    // leading edge, instead of the trailing.
    function debounce(func, wait, immediate) {
        var timeout;

        return function executedFunction() {
            var context = this;
            var args = arguments;

            var later = function () {
                timeout = null;
                if (!immediate) func.apply(context, args);
            };

            var callNow = immediate && !timeout;
            clearTimeout(timeout);

            timeout = setTimeout(later, wait);

            if (callNow) func.apply(context, args);
        };
    };

    var redirectToUrl = function redirectToUrl(url) {
        $window.location.href = url;
    };

    // https://stackoverflow.com/questions/20600800/js-client-side-exif-orientation-rotate-and-mirror-jpeg-images
    function getImageOrientation(file, callback) {
        var reader = new FileReader();

        reader.onload = function (event) {
            var view = new DataView(event.target.result);

            if (view.getUint16(0, false) != 0xFFD8) return callback(-2);

            var length = view.byteLength,
                offset = 2;

            while (offset < length) {
                var marker = view.getUint16(offset, false);
                offset += 2;

                if (marker == 0xFFE1) {
                    if (view.getUint32(offset += 2, false) != 0x45786966) {
                        return callback(-1);
                    }
                    var little = view.getUint16(offset += 6, false) == 0x4949;
                    offset += view.getUint32(offset + 4, little);
                    var tags = view.getUint16(offset, little);
                    offset += 2;

                    for (var i = 0; i < tags; i++)
                        if (view.getUint16(offset + (i * 12), little) == 0x0112)
                            return callback(view.getUint16(offset + (i * 12) + 8, little));
                }
                else if ((marker & 0xFF00) != 0xFF00) break;
                else offset += view.getUint16(offset, false);
            }
            return callback(-1);
        };

        reader.readAsArrayBuffer(file.slice(0, 64 * 1024));
    };

    function resetImageOrientation(srcBase64, srcOrientation, callback) {
        var img = new Image();

        img.onload = function () {
            var width = img.width,
                height = img.height,
                canvas = document.createElement('canvas'),
                ctx = canvas.getContext("2d"),
                drawX = 0, drawY = 0;

            // set proper canvas dimensions before transform & export
            if (4 < srcOrientation && srcOrientation < 9) {
                canvas.width = height;
                canvas.height = width;
            } else {
                canvas.width = width;
                canvas.height = height;
            }

            // transform context before drawing image
            switch (srcOrientation) {
                case 2: ctx.transform(-1, 0, 0, 1, width, 0); break;
                case 3: ctx.transform(-1, 0, 0, -1, width, height);
                    ctx.rotate(-180 * Math.PI / 180);
                    drawX = -width;
                    drawY = -height;
                    break;
                case 4: ctx.transform(1, 0, 0, -1, 0, height); break;
                case 5: ctx.transform(0, 1, 1, 0, 0, 0); break;
                case 6: ctx.transform(0, 1, -1, 0, height, 0);
                    canvas.width = width;
                    canvas.height = height;
                    ctx.rotate(0 * Math.PI / 180);
                    break;
                case 7: ctx.transform(0, -1, -1, 0, height, width); break;
                case 8: ctx.transform(0, -1, 1, 0, 0, width);
                    canvas.width = width;
                    canvas.height = height;
                    ctx.rotate(0 * Math.PI / 180);
                    break;
                default: break;
            }


            // draw image
            ctx.drawImage(img, drawX, drawY);

            // export base64
            callback(canvas.toDataURL());
        };

        img.src = srcBase64;
    };

    function rotateCropperImage($image, angle) {
        //get data
        var data = $image.cropper('getCropBoxData');
        var contData = $image.cropper('getContainerData');
        var imageData = $image.cropper('getImageData');
        //set data of cropbox to avoid unwanted behavior due to strict mode
        data.width = 2;
        data.height = 2;
        data.top = 0;
        var leftNew = (contData.width / 2) - 1;
        data.left = leftNew;
        $image.cropper('setCropBoxData', data);
        //rotate
        $image.cropper('rotate', angle);
        //get canvas data
        var canvData = $image.cropper('getCanvasData');
        //calculate new height and width based on the container dimensions
        var heightOld = canvData.height;
        var heightNew = contData.height;
        var koef = heightNew / heightOld;
        var widthNew = canvData.width * koef;
        canvData.height = heightNew;
        canvData.width = widthNew;
        canvData.top = 0;
        if (canvData.width >= contData.width) {
            canvData.left = 0;
        }
        else {
            canvData.left = (contData.width - canvData.width) / 2;
        }
        $image.cropper('setCanvasData', canvData);
        //and now set cropper "back" to full crop
        data.left = 0;
        data.top = 0;
        data.width = canvData.width;
        data.height = canvData.height;
        $image.cropper('setCropBoxData', data);
    } 

    function followUserFromMenu(userid, url, obj, successTxt) {
        //App.loader.showLoader()
        var previousHtml = $(obj).html();
        $(obj).html('<img src="//d2vtntcxpdw15n.cloudfront.net/img3/htc-loading.gif" style="height: 20px;">');
        $(obj).prop('disabled', true);
        $.post(url, $.param({ followedId: userid }), function (d) {
            
            if (!d.result) {
                App.notify.Danger(d.message, 'Error');
                return;
            }
            else {
                $(obj).parent().remove();
                App.notify.Success(successTxt);
            }
        });
    }

    function rotateElement(selector, hdnElem, deg) {
        var className = '';
        var $obj = $(selector);
        var $hdn = $(hdnElem);
        var current = parseInt($hdn.val());

        if (!current || current == null || isNaN(current)) current = 0;

        current += deg;
        if (current == 360 || current == -360) {
            current = 0; $hdn.val(0);
        }

        switch (current) {
            case -270: case 90:
                className = 'rotate-90'; break;
            case -180: case 180:
                className = 'rotate-180'; break;
            case -90: case 270:
                className = 'rotate-270'; break;
        }
        $hdn.val(current);
        $obj.removeClass('rotate-90').removeClass('rotate-180').removeClass('rotate-270').addClass(className);
    };

    return {
        init: init,
        loader: loader,
        signalRHelper: signalRHelper,
        hubReady: hubReady,
        resetFormError: resetFormError,
        dataURItoBlob: dataURItoBlob,
        resizeImage: resizeImage,
        avatarOnError: avatarOnError,
        nameColorPicker: nameColorPicker,
        formValidateReset: formValidateReset,
        isNullOrUndefined: isNullOrUndefined,
        fbInvite: fbInvite,
        angular: angular.module('ngWaveApp', ['customServices']),
        notify: notify,
        toScaledImage: toScaledImage,
        fixCommentsUserImage: fixCommentsUserImage,
        getFunctionFromString: getFunctionFromString,
        scrollTo: scrollTo,
        youtubeVideoExists: youtubeVideoExists,
        swipedetect: swipedetect,
        titleCase: titleCase,
        formatDate: formatDate,
        createCookie: createCookie,
        readCookie: readCookie,
        eraseCookie: eraseCookie,
        passwordNotice: passwordNotice,
        guid: guid,
        showReviewNotice: showReviewNotice,
        inlineSuccessAlert: inlineSuccessAlert,
        loadSurveyQuestionTextClone: loadSurveyQuestionTextClone,
        fbFeedDialog: fbFeedDialog,
        scrollToTop: scrollToTop,
        fireDatalayerEvent: fireDatalayerEvent,
        fireDataLayerEventRoutes: fireDataLayerEventRoutes,
        copyTextToClipboard: copyTextToClipboard,
        editCreateFormDataAWS4: editCreateFormDataAWS4,
        createFormDataAWS4: createFormDataAWS4,
        passwordRegex: passwordRegex,
        debounce: debounce,
        redirectToUrl: redirectToUrl,
        getImageOrientation: getImageOrientation,
        resetImageOrientation: resetImageOrientation,
        rotateCropperImage: rotateCropperImage,
        followUserFromMenu: followUserFromMenu,
        showFollowedByNotice: showFollowedByNotice,
        rotateElement: rotateElement
    };
})();

App.placement = {
    prepend: 0,
    append: 1,
    after: 2,
    before: 3
};


App.angular.directive('reviewmodal', ['$http', '$compile', '$q', '$sce', function ($http, $compile, $q, $sce) {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            /*
             * Requires: jquery.validator, jquery.unobtrusive, raty.js, cropper.js/.css
             * */
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            element
                .on('click', function (e) {
                    e.preventDefault();

                    scope.obj.insertHtml = function (s) {
                        return $sce.trustAsHtml(s);
                    }

                    var _uri = $(this).data('review_uri');
                    var _loginUri = $(this).data('login_uri');
                    var _isNew = parseInt($(this).data('is_new')) === 0;
                    var _useInlineLoader = $(this).data('inline_loader');
                    var _id = $(this).data('produc_id');
                    var _uid = $(this).data('user_id');
                    var _loadingTxt = $(this).data('loading_txt');
                    var _closeTxt = $(this).data('close_txt');
                    var _editTxt = $(this).data('edit_txt');
                    var _shareTxt = $(this).data('share_txt');
                    var _callbackString = $(this).data('review_callback');
                    var _modalId = 'modalReview';
                    var $template = '\
                                    <div class="modal fade in" id="' + _modalId + '" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">\
                                        <div class="modal-dialog" role="document">\
                                            <div id="reviewModalContent" class="modal-content">\
                                                <div id="reviewModalLoader" class="loaderD-overlay" style="display: none">\
                                                    <div class="loaderD-overlay-gif"></div>\
                                                </div>\
                                                <div class="modal-header">\
                                                    <button type="button" class=" close-modal-window" data-dismiss="modal" aria-label="Close">' + _closeTxt + ' <span class="PopupCloseBtn" aria-hidden="true"></span></button>\
                                                    <h4 class="modal-title-pp">' + (_isNew ? _shareTxt : _editTxt) + '</h4>\
                                                </div>\
                                                <div class="modal-body nopaddingtop" data-isloaded="false">\
                                                    <!-- Leave a Review form load via ajax-->\
                                                    '+ _loadingTxt + '\
                                                </div>\
                                            </div>\
                                        </div>\
                                    </div>';
                    $('body').append($template);

                    var $modal = $('#' + _modalId);
                    $modal.on('show.bs.modal', function () {
                        // go to login page if not logged in
                        if (_uid === 0) {
                            var ng = angular.element($('body')).scope(); // get angular scope
                            window.location = _loginUri + '?returnurl=';
                            return false;
                        }

                        var $modalBody = $modal.find('.modal-body');
                        if ($modalBody.data('isloaded') === false) {
                            $modalBody.load(_uri + '/' + _id, function (_, status) {
                                if (status === 'success') {
                                    // compile the html so the angular codes will work
                                    $compile($modal)(scope);
                                    scope.$digest();
                                    angular.element(function () {
                                        App.Product._Review && App.Product._Review.reviewCallback && App.Product._Review.reviewCallback(_callbackString);
                                        App.Product._EditReview && App.Product._EditReview.reviewCallback && App.Product._EditReview.reviewCallback(_callbackString);
                                        App.Product._Review && App.Product._Review.useInlineLoader && App.Product._Review.useInlineLoader(_useInlineLoader);
                                        App.Product._EditReview && App.Product._EditReview.useInlineLoader && App.Product._EditReview.useInlineLoader(_useInlineLoader);
                                    })
                                }
                            });
                        }
                    })

                    $modal.on('hidden.bs.modal', function () { $modal.remove(); })
                    $modal.modal('show');
                });
        }
    };
}])

App.angular.directive('askquestionmodal', ['$http', '$compile', '$q', '$sce', '$location', function ($http, $compile, $q, $sce, $location) {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            /*
             * Requires: jquery.validator, jquery.unobtrusive
             * */
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            element
                .on('click', function (e) {
                    e.preventDefault();

                    scope.obj.insertHtml = function (s) {
                        return $sce.trustAsHtml(s);
                    }
                    scope.obj.questionSubmitted = false;
                    scope.obj.askQuestionBox = '';
                    scope.obj.questionTitle = '';
                    scope.obj.postQuestion = function () {
                        var modalContent = $modal.find('.modal-content');
                        var textBox = modalContent.find('textarea[name=YourQuestion]');
                        var answerTxt = textBox.val();

                        if (answerTxt.isNullOrEmpty()) {
                            // show error
                            textBox.focus();
                            scope.obj.questionSubmitted = true;
                            return;
                        }

                        var questionTitle = modalContent.find('[name=QuestionTitle]').val();

                        // Remove act param from URL
                        if (!!_prodUri) {
                            $location.url(_prodUri + scope.getPageParam());
                        }

                        // Hide modal form
                        $('#modalAksQuestion').modal('hide');

                        App.loader.showLoader();
                        var jqxhr = $.post(_uri + '/' + _id, { ParentId: 0, Answer: scope.obj.askQuestionBox, Title: questionTitle }, function (data) {
                            if (data.result > 0) {
                                if (_callbackString) eval(_callbackString);
                            }
                        })
                            .fail(function () {
                                alert(_errorTxt);
                            })
                            .always(function () {
                                App.loader.hideLoader();
                            });
                    }
                    var _uri = $(this).data('ask_uri');
                    var _id = $(this).data('product_id');
                    var _uid = $(this).data('user_id');
                    var _closeTxt = $(this).data('close_txt');
                    var _askQuestionTxt = $(this).data('ask_question_txt');
                    var _noteTxt = $(this).data('note_txt');
                    var _titleTxt = $(this).data('title_txt');
                    var _submitTxt = $(this).data('submit_txt');
                    var _askToHtcTxt = $(this).data('ask_htc_txt');
                    var _errorTxt = $(this).data('error_txt');
                    var _callbackString = $(this).data('review_callback');
                    var _prodUri = $(this).data('prod_uri');
                    var _guid = 'modalAskQ' + App.guid().replace(/\-/gi, '');
                    var $template = '\
                                    <div class="modal fade" id="' + _guid + '" tabindex="-1" role="dialog" aria-labelledby="askquestion">\
                                        <style>.PopupCloseBtn{z-index:0;display:inline-block;margin-left:10px;margin-bottom:3px;width:25px;height:25px;line-height:34px;text-align:center;pointer-events:none;background-image:url(https://d2vtntcxpdw15n.cloudfront.net/img3/close-x-red.png);background-color:white;border-width:2px;border-style:solid;border-color:#f40650;border-image:initial;border-radius:50%;background-repeat:no-repeat;background-position:5px center;vertical-align:middle}.close-modal-window{font-family:\'MaisonNeue\',sans-serif;font-size:14px;font-weight:normal;font-style:normal;font-stretch:normal;line-height:normal;letter-spacing:normal;text-align:left;color:#000 !important}</style>\
                                        <div class="modal-dialog" role="document">\
                                            <div class="modal-content add-padding-15">\
                                                <div class="modal-header">\
                                                    <button type="button" class=" close-modal-window" data-dismiss="modal" aria-label="Close">' + _closeTxt + ' <span class="PopupCloseBtn" aria-hidden="true"></span></button>\
                                                    <h4 class="modal-title-pp" id="myModalLabel">'+_askQuestionTxt+'</h4>\
                                                    <p class="model-note">'+_noteTxt+'</p>\
                                                </div>\
                                                <div class="modal-body">\
                                                    <div class="row margin-b20">\
                                                        <div class="form-floating-label" ng-class="{\'has-value\': obj.questionTitle.length > 0}">\
                                                            <input type="text" class="form-control" id="QuestionTitle" name="QuestionTitle" ng-model="obj.questionTitle">\
                                                            <label for="QuestionTitle">'+_titleTxt+'</label>\
                                                        </div>\
                                                    </div>\
                                                    <div class="row">\
                                                        <div class="form-floating-label margin-b20" ng-class="{\'has-value\': obj.askQuestionBox.length > 0}">\
                                                            <textarea class="form-control" id="YourQuestion" name="YourQuestion" rows="5"\
                                                                      ng-model="obj.askQuestionBox"\
                                                                      ng-class="{\'input-validation-error\': obj.askQuestionBox == \'\' && obj.questionSubmitted }"></textarea>\
                                                            <label for="YourQuestion">'+_askToHtcTxt+'</label>\
                                                        </div>\
                                                        <div class="col-xs-12 text-center nopadding">\
                                                            <button name="btnQuestionSubmit" ng-click="obj.postQuestion()" class="btn btn-white margin-t10 margin-b10">' +_submitTxt+ '</button>\
                                                        </div>\
                                                    </div>\
                                                </div>\
                                            </div>\
                                        </div>\
                                    </div>';
                    $('body').append($template);
                    var $modal = $('#' + _guid);
                    $compile($modal)(scope);
                    scope.$digest();
                    $modal.on('hidden.bs.modal', function () { $modal.remove(); })
                    angular.element(function () { $modal.modal('show'); })
                });
        }
    };
}])

App.angular.directive('answerquestionmodal', ['$http', '$compile', '$q', '$sce', '$location', function ($http, $compile, $q, $sce, $location) {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            /*
             * Requires: jquery.validator, jquery.unobtrusive
             * */
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            element
                .on('click', function (e) {
                    e.preventDefault();

                    scope.obj.insertHtml = function (s) {
                        return $sce.trustAsHtml(s);
                    }
                    scope.obj.answerSubmitted = false;
                    scope.obj.answerQuestionBox = '';
                    scope.obj.postAnswer = function () {
                        var modalContent = $modal.find('.modal-content');
                        var textBox = modalContent.find('textarea[name=YourAnswer]');
                        var answerTxt = textBox.val();

                        if (answerTxt.isNullOrEmpty()) {
                            // show error
                            textBox.focus();
                            scope.obj.answerSubmitted = true;
                            return;
                        }

                        // Remove act param from URL
                        //if (!!_prodUri) {
                        //    $location.url(_prodUri + scope.getPageParam());
                        //}
                        _useInlineLoader ? $('#answerQuestionModalLoader').fadeIn(400) : App.loader.showLoader();

                        var jqxhr = $.post(_uri, { ParentId: _id, Answer: answerTxt }, function (data) {
                            if (data.result > 0) {
                                if (_callbackString) eval(_callbackString);
                            }
                        })
                            .fail(function () {
                                alert(_errorTxt);
                            })
                            .always(function () {
                                _useInlineLoader ? $('#answerQuestionModalLoader').fadeOut(400) : App.loader.hideLoader();
                            });
                    }

                    var _uri = $(this).data('answer_uri');
                    var _id = $(this).data('parent_id');
                    var _closeTxt = $(this).data('close_txt');
                    var _useInlineLoader = $(this).data('inline_loader');
                    var _postAnswerTxt = $(this).data('post_answer_txt');
                    var _noteTxt = $(this).data('note_txt');
                    var _yourAnswerTxt = $(this).data('your_answer_txt');
                    var _submitTxt = $(this).data('submit_txt');
                    var _errorTxt = $(this).data('error_txt');
                    var _callbackString = $(this).data('answer_callback');
                    var _guid = 'modalAnswerQ' + App.guid().replace(/\-/gi, '');
                    var $template = '\
                                    <div class="modal fade" id="' +_guid+ '" tabindex="-1" role="dialog" aria-labelledby="postanswer">\
                                        <style>.PopupCloseBtn{z-index:0;display:inline-block;margin-left:10px;margin-bottom:3px;width:25px;height:25px;line-height:34px;text-align:center;pointer-events:none;background-image:url(https://d2vtntcxpdw15n.cloudfront.net/img3/close-x-red.png);background-color:white;border-width:2px;border-style:solid;border-color:#f40650;border-image:initial;border-radius:50%;background-repeat:no-repeat;background-position:5px center;vertical-align:middle}.close-modal-window{font-family:\'MaisonNeue\',sans-serif;font-size:14px;font-weight:normal;font-style:normal;font-stretch:normal;line-height:normal;letter-spacing:normal;text-align:left;color:#000 !important}</style>\
                                        <div class="modal-dialog" role="document">\
                                            <div class="modal-content add-padding-15">\
                                                <div id="answerQuestionModalLoader" class="loaderD-overlay" style="display: none">\
                                                    <div class="loaderD-overlay-gif"></div>\
                                                </div>\
                                                <div class="modal-header">\
                                                    <button type="button" class=" close-modal-window" data-dismiss="modal" aria-label="Close">' +_closeTxt+ ' <span class="PopupCloseBtn" aria-hidden="true"></span></button>\
                                                    <h4 class="modal-title-pp" id="myModalLabel">' +_postAnswerTxt+ '</h4>\
                                                    <p class="model-note">' +_noteTxt+ '</p>\
                                                </div>\
                                                <div class="modal-body">\
                                                    <div class="row">\
                                                        <div class="form-floating-label" ng-class="{\'has-value\': obj.answerQuestionBox.length > 0}">\
                                                            <textarea data-qid="0" class="form-control" id="YourAnswer" name="YourAnswer" rows="5"\
                                                                      ng-model="obj.answerQuestionBox" ng-init="obj.answerQuestionBox=\'\'"\
                                                                      ng-class="{\'input-validation-error\': obj.answerQuestionBox == \'\' && obj.answerSubmitted }"></textarea>\
                                                            <label for="YourAnswer">' +_yourAnswerTxt+ '</label>\
                                                        </div>\
                                                        <div class="col-xs-12 text-center nopadding">\
                                                            <button ng-click="obj.postAnswer()" name="btnAnswerSubmit" class="btn btn-white margin-t10 margin-b10">' +_submitTxt+ '</button>\
                                                        </div>\
                                                    </div>\
                                                </div>\
                                            </div>\
                                        </div>\
                                    </div>';

                    $('body').append($template);
                    var $modal = $('#' + _guid);
                    $compile($modal)(scope);
                    scope.$digest();
                    $modal.on('hidden.bs.modal', function () { $modal.remove(); })
                    angular.element(function () { $modal.modal('show'); })
                });
        }
    };
}])

App.angular.filter('groupBy', ['$parse', function ($parse) {
    return _.memoize(function (items, field) {
        var getter = $parse(field);
        return _.groupBy(items, function (item) {
            return getter(item);
        });
    });
}]);

App.angular.directive('autosuggest', ['$http', '$compile', '$q', '$sce', function ($http, $compile, $q, $sce) {
    return {
        restrict: 'A',
        link: function link(scope, element, attrs) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            element.attr('autocomplete', 'off');
            element.on('keyup', function (e) {
                if (window.suggestCanceler) window.suggestCanceler.resolve();

                scope.obj.insertHtml = function (s) {
                    return $sce.trustAsHtml(s);
                };

                var eParent = element.parent();
                if (element.val().length <= 3) {
                    eParent.find('.fa-spin-replaced').removeClass('fa-spin-replaced fa-spin fa-spinner').addClass('fa-search');
                    scope.obj.searchedAlsoFound = null;
                    scope.obj.searchedList = null;
                    scope.obj.searchedTotal = null;
                    scope.$apply();
                    return;
                }

                var txt = element.val();
                var uri = element.attr("autosuggest-uri");
                window.suggestCanceler = $q.defer();

                eParent.find('.fa-search').removeClass('fa-search').addClass('fa-spin fa-spinner fa-spin-replaced');
                $http({
                    method: 'POST',
                    url: "/" + uri + "/widget/_productsuggestion",
                    params: {
                        find: txt
                    },
                    timeout: window.suggestCanceler.promise
                }).then(function (d) {
                    eParent.find('.fa-spin-replaced').removeClass('fa-spin-replaced fa-spin fa-spinner').addClass('fa-search');

                    if (d.status == 200 && d.data.status == 1) {
                        //success
                        scope.obj.searchedList = d.data.list;
                        scope.obj.searchedAlsoFound = d.data.alsoIn;
                        scope.obj.searchedTotal = d.data.total;
                        scope.obj.searchedUri = uri;
                        scope.obj.logSearch = function (c) {
                            $.get("/" + uri + "/widget/_searchlog/" + txt, function () {});
                        };

                        if (element.parent().find('.search-result-suggestion').length === 0) {
                            var template = "<div ng-if='obj.searchedList.length > 0' class='search-result-suggestion'>\n                                                        <ul>\n                                                            <li class='category'><a ng-href='/{{obj.searchedUri}}/reviews/search?product=" + txt + "'><span class='total'>{{obj.searchedTotal}} results found</span></a></li>\n                                                            <li ng-repeat='x in obj.searchedList' ng-class='{\"last\": $index === (obj.searchedList.length - 1)}'>\n                                                                <div class='display-table'><div class='display-cell search-prod-image'><a target='_blank' ng-href='/{{obj.searchedUri}}/reviews/{{x.product.UrlName}}'><img ng-src='{{x.product.Image}}' /></a></div>\n                                                                <div class='display-cell'><ul>\n                                                                    <li class='product'><a target='_blank' ng-click='obj.logSearch(x.product)' ng-href='/{{obj.searchedUri}}/reviews/{{x.product.UrlName}}' class='suggest-product' ng-bind-html='obj.insertHtml(x.product.Name)'></a></li>\n                                                                    <li class='category'><a target='_blank' ng-click='obj.logSearch(pc)' ng-href='/{{obj.searchedUri}}/reviews/{{pc.UrlName}}' ng-repeat='pc in x.category.Parents' class='suggest-cat-parent' style='font-size:14px;'>{{pc.Name}} / </a><a style='font-size:14px;' class='suggest-cat' ng-click='obj.logSearch(x.category)' ng-href='/{{obj.searchedUri}}/reviews/{{x.category.UrlName}}' target='_blank' ng-bind-html='obj.insertHtml(x.category.Name)'></a></li>\n                                                                </ul></div></div>\n                                                            </li>\n                                                            <li class='category also-found' ng-if='obj.searchedAlsoFound.length > 0'><span>Also found in</span></li>\n                                                            <li ng-if='obj.searchedAlsoFound.length > 0' class='category also-found-in' ng-repeat='c in obj.searchedAlsoFound'><a target='_blank' ng-click='obj.logSearch(pc)' ng-href='/{{obj.searchedUri}}/reviews/{{pc.UrlName}}' ng-repeat='pc in c.Parents' class='suggest-cat-parent'>{{pc.Name}} / </a><a class='suggest-cat' ng-click='obj.logSearch(c)' ng-href='/{{obj.searchedUri}}/reviews/{{c.UrlName}}' target='_blank' ng-bind-html='obj.insertHtml(c.Name)'></a></li>\n                                                        </ul>\n                                                    </div > ";
                            eParent.append(template);
                            $compile(eParent.contents())(scope);
                        }
                    }
                });
            });
        }
    };
}]);

App.angular.directive('imageonload', function () {
    return {
        restrict: 'A',
        link: function link(scope, element, attrs) {
            element.bind('load', function () {
                //call the function that was passed
                scope.$apply(attrs.imageonload);
            });
        }
    };
});

App.angular.directive('imageonerror', function () {
    return {
        restrict: 'A',
        link: function link(scope, element, attrs) {
            element.bind('error', function () {
                //call the function that was passed
                scope.$apply(attrs.imageonload);
            });
        }
    };
});

App.angular.directive('onEnter', function () {
    return function (scope, element, attrs) {
        element.bind("keydown keypress", function (event) {
            if (event.which === 13) {
                scope.$apply(function () {
                    scope.$eval(attrs.onEnter);
                });

                event.preventDefault();
            }
        });
    };
});

App.angular.factory('ScopeStorage', function () {
    var mem = {};
    return {
        store: function store(key, value) {
            mem[key] = value;
        },
        get: function get(key) {
            return mem[key];
        }
    };
});

App.angular.directive('numbersOnly', function () {
    // only allow number to be typed in textbox
    return {
        require: 'ngModel',
        link: function link(scope, element, attrs, modelCtrl) {
            modelCtrl.$parsers.push(function (inputValue) {
                // this next if is necessary for when using ng-required on your input.
                // In such cases, when a letter is typed first, this parser will be called
                // again, and the 2nd time, the value will be undefined
                if (inputValue == undefined) return '';
                var transformedInput = inputValue.replace(/[^0-9]/g, '');
                if (transformedInput != inputValue) {
                    modelCtrl.$setViewValue(transformedInput);
                    modelCtrl.$render();
                }

                return transformedInput;
            });
        }
    };
});

App.angular.directive('convertToNumber', function () {
    // apply to select whose model are int, use ngRepeat instead of ngOptions
    return {
        require: 'ngModel',
        link: function link(scope, element, attrs, ngModel) {
            ngModel.$parsers.push(function (val) {
                return val != null ? parseInt(val, 10) : null;
            });
            ngModel.$formatters.push(function (val) {
                return val != null ? '' + val : null;
            });
        }
    };
});

App.angular.filter('unsafe', ['$sce', function ($sce) {
    return $sce.trustAsHtml;
}]);

// place here any global angular accessible function
var customServices = angular.module('customServices', []).service('unitOfWork', function () {
    this.util = (function () {
        var resetFormError = function resetFormError(s) {
            // hides all form validation notice
            // get the form inside we are working - change selector to your form as needed
            var $form = $(s);

            // get validator object
            var $validator = $form.validate();

            // get errors that were created using jQuery.validate.unobtrusive
            var $errors = $form.find(".field-validation-error span");

            // trick unobtrusive to think the elements were succesfully validated
            // this removes the validation messages
            $errors.each(function () {
                $validator.settings.success($(this));
            });

            // clear errors from validation
            $validator.resetForm();
        };
        var formValidateReset = function formValidateReset(s) {
            var form = $(s);
            form.removeData('validator');
            form.removeData('unobtrusiveValidation');
            $.validator.unobtrusive.parse(form);
        };
        return {
            resetFormError: resetFormError,
            formValidateReset: formValidateReset
        };
    })();
});

$(function () {

    // Conditional include functions.
    // RequiredIf method will be included if jQuery validate plugin exist
    if (typeof $.fn.validate == "function") {
        // RequiredIf validation method
        jQuery.validator.addMethod('requiredif', function (value, element, params) {
            var $element = $(element);
            var dependentvalue = $element.attr("data-val-requiredif-dependentvalue");
            var control = $('#' + $element.attr("data-val-requiredif-dependentname"));
            var controlType = control.attr('type');
            var actualvalue = controlType === 'checkbox' ? control.is(':checked').toString() : control.val();

            if (dependentvalue.toLowerCase() === actualvalue.toLowerCase()) {
                return value.length > 0;
            }

            return true;
        }, '');
    }
});

// check if an element is viewable in viewport or not
$.fn.isInViewport = function (offset) {
    if (typeof $(this).offset() == 'undefined') return;

    offset = offset || 0; // e.g. floating menu offset

    var elementTop = $(this).offset().top;
    var elementBottom = elementTop + $(this).outerHeight() - offset;
    var viewportTop = $(window).scrollTop() + offset;
    var viewportBottom = viewportTop + $(window).height();
    return elementBottom > viewportTop && elementTop < viewportBottom;
};

$.fn.isInViewportPercent = function (offset) {
    if (typeof $(this).offset() == 'undefined') return 0;

    offset = offset || 0; // e.g. floating menu offset

    var viewportHeight = $(window).height();
    var elementTop = $(this).offset().top;
    var elementBottom = elementTop + $(this).outerHeight() - offset;
    var viewportTop = $(window).scrollTop() + offset;
    var viewportBottom = viewportTop + viewportHeight;

    var intersect = 0;
    if (elementBottom > viewportBottom && viewportBottom > elementTop) {
        intersect = viewportBottom - elementTop;
    } else if (viewportBottom > elementBottom && viewportTop > elementTop) {
        intersect = elementBottom - viewportTop;
    } else if (viewportBottom >= elementBottom && elementTop >= viewportTop) {
        intersect = elementBottom - elementTop;
    }

    if (intersect > viewportHeight) {
        intersect = viewportHeight;
    }

    return Math.round(intersect / viewportHeight * 100);
};

// truncate stringwith ellipses
String.prototype.trunc = String.prototype.trunc || function (n) {
    return this.length > n ? this.substr(0, n - 1) + ' ...' : this;
};

String.prototype.isNullOrEmpty = String.prototype.isNullOrEmpty || function (n) {
    return typeof this == 'undefined' || this == null || $.trim(this).length == 0;
};

// convert string to hash
String.prototype.hashCode = function () {
    var hash = 0,
        i,
        chr,
        len;
    if (this.length === 0) return hash;
    for (i = 0, len = this.length; i < len; i++) {
        chr = this.charCodeAt(i);
        hash = (hash << 5) - hash + chr;
        hash |= 0; // Convert to 32bit integer
    }
    return hash;
};

// endswith simulator
if (typeof String.prototype.endsWith !== 'function') {
    String.prototype.endsWith = function (suffix) {
        return this.indexOf(suffix, this.length - suffix.length) !== -1;
    };
}

// startswith simulator
if (typeof String.prototype.startsWith != 'function') {
    String.prototype.startsWith = function (str) {
        return this.slice(0, str.length) == str;
    };
}

// string.format simulator
if (!String.prototype.format) {
    String.prototype.format = function () {
        var args = arguments;
        return this.replace(/{(\d+)}/g, function (match, number) {
            return typeof args[number] != 'undefined' ? args[number] : match;
        });
    };
}

// Remove html on string
if (typeof String.prototype.stripHtml !== 'function') {
    String.prototype.stripHtml = function () {
        return this.replace(/<(?:.|\n)*?>/gm, '');
    };
}

if (typeof Number.prototype.isBetween !== 'function') {
    Number.prototype.isBetween = function (min, max, isInclusive) {
        if (typeof this == 'undefined' || this == null) false;
        if (!!!isInclusive) isInclusive = true;

        return isInclusive ? this > min && this < max || this == min || this == max : this > min && this < max;
    };
}

/* display rating in form of stars */
$.fn.makeStars = function () {
    $(this).each(function () {
        var rating = $(this).data('rating'),
            starNumber = $(this).children().length,
            fullStars = Math.floor(rating),
            halfStarPerc = (rating - fullStars) * 100;

        if (rating > 0) {
            $(this).children().each(function (index) {
                $(this).addClass('fa-star');
                $(this).removeClass('fa-star-open');
                return index + 1 < fullStars;
            });
        }

        if (halfStarPerc !== 0 && fullStars < starNumber) {
            var halfStar = $(this).children(":nth-child(" + parseInt(fullStars + 1, 10) + ")");

            $('<span class="fa fa-star fa-star-percentage"></span>').width(halfStarPerc + '%').appendTo(halfStar);
        }
    });
};

$.fn.colourBrightness = function () {
    var e,
        t,
        n,
        r,
        i = this.css("background-color");

    if (i.match(/^rgb/)) {
        i = i.match(/rgb\(([^)]+)\)/)[1];
        i = i.split(/ *, */).map(Number);
        e = i[0];
        t = i[1];
        n = i[2];
    } else if ("#" == i[0] && 7 == i.length) {
        e = parseInt(i.slice(1, 3), 16);
        t = parseInt(i.slice(3, 5), 16);
        n = parseInt(i.slice(5, 7), 16);
    } else if ("#" == i[0] && 4 == i.length) {
        e = parseInt(i[1] + i[1], 16);
        t = parseInt(i[2] + i[2], 16);
        n = parseInt(i[3] + i[3], 16);
    }
    r = (e * 299 + t * 587 + n * 114) / 1e3;

    r < 125 ? this.removeClass("avatar-light").addClass("avatar-dark") : this.removeClass("avatar-dark").addClass("avatar-light");
};

/*! Inline loader overlay  - v1.0.0
    Usage: $('#target').loadingOverlay(); // to show inline loader on the #target element
           $('#target').loadingOverlay('remove'); // to remove inline loader on the #target element
*/
(function ($) {
    'use strict';
    var methods = {
        init: function init(options) {
            var opts = $.extend({}, $.fn.loadingOverlay.defaults, options);
            var target = $(this).addClass(opts.loadingClass);
            var overlay = '<div class="' + opts.overlayClass + '">' + '<div class="' + opts.spinnerClass + '">' + '<span class="' + opts.textClass + '">' + opts.loadingText + '</span>' + '</div></div>';
            // Don't add duplicate loading-overlay
            if (!target.data('loading-overlay')) {
                target.prepend($(overlay)).data('loading-overlay', true);
            }
            return target;
        },

        remove: function remove(options) {
            var opts = $.extend({}, $.fn.loadingOverlay.defaults, options);
            var target = $(this).data('loading-overlay', false);
            target.find('.' + opts.overlayClass).detach();
            if (target.hasClass(opts.loadingClass)) {
                target.removeClass(opts.loadingClass);
            } else {
                target.find('.' + opts.loadingClass).removeClass(opts.loadingClass);
            }
            return target;
        },

        // Expose internal methods to allow stubbing in tests
        exposeMethods: function exposeMethods() {
            return methods;
        }
    };

    $.fn.loadingOverlay = function (method) {
        if (methods[method]) {
            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
        } else if (typeof method === 'object' || !method) {
            return methods.init.apply(this, arguments);
        } else {
            $.error('Method ' + method + ' does not exist on jQuery.loadingOverlay');
        }
    };

    /* Setup plugin defaults */
    $.fn.loadingOverlay.defaults = {
        loadingClass: 'loading', // Class added to target while loading
        overlayClass: 'loading-overlay', // Class added to overlay (style with CSS)
        spinnerClass: 'loaderD-inline', // Class added to loading overlay spinner
        iconClass: 'loading-icon', // Class added to loading overlay spinner
        textClass: 'loading-text', // Class added to loading overlay spinner
        loadingText: '' // Text within loading overlay
    };
})(jQuery);;
'use strict';

if (typeof App == 'undefined') var App = {};
App.Account = (function () {
    return {};
})();

App.Account.Index = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config == 'object') {
            $.extend(true, _config, config);
        }
        App.angular.controller('MainController', ['$scope', '$http', function ($scope, $http) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};
            $(function () { // add scripts here
            });
        }]);
    };
    return {
        init: init
    };
})();

App.Account.Unsubscribe = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config == 'object') {
            $.extend(true, _config, config);
        }
        App.angular.controller('MainController', ['$scope', '$http', function ($scope, $http) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};
            $(function () { // add scripts here
            });
        }]);
    };
    return {
        init: init
    };
})();

App.Account.Activate = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config == 'object') {
            $.extend(true, _config, config);
        }
        App.angular.controller('MainController', ['$scope', '$http', function ($scope, $http) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};
            var resendEmail = function resendEmail() {
                App.loader.showLoader();
                $.post(_config.resendUri, function (d) {
                    if (d.status == 1) {
                        App.notify.Success(_config.sucessTxt);
                    }
                    App.loader.hideLoader();
                });
            };
            $(function () {
                $('#btnResend').click(function () {
                    resendEmail();
                }); // add scripts here
                if (_config.isResend) resendEmail();
            });
        }]);
    };
    return {
        init: init
    };
})();

App.Account.ValidateCode = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config == 'object') {
            $.extend(true, _config, config);
        }
        App.angular.controller('MainController', ['$scope', '$http', function ($scope, $http) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};
            $(function () { // add scripts here
                $('#btnSubmitChangePhone').click(function () {
                    window.location = _config.joinUri;
                });
            });
        }]);
    };
    return {
        init: init
    };
})();

App.Account.Join = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config == 'object') {
            $.extend(true, _config, config);
        }
        App.angular.controller('MainController', ['$scope', '$http', function ($scope, $http) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.phone = _config.phone;
            $scope.obj = {
                email: _config.email,
                onEmailChange: function onEmailChange() {
                    $scope.obj.email = $.trim($scope.obj.email);
                    console.log($scope.obj.email);
                }
            };
            angular.element(function () {
                $.validator.addMethod('requiredutf8', function (value, element) {
                    var valid = false;
                    var $element = $(element);
                    if ($element.attr('id') == 'FirstName') {
                        var regUtf8 = new XRegExp('^(\\p{L}|[\\-0-9]){1,}(\\p{L}|[\\-0-9]|\\s){0,}$');
                        valid = regUtf8.test(value);
                    }
                    return valid && value != null;
                });
                var form = $("#frmJoin");
                form.removeData('validator');
                form.removeData('unobtrusiveValidation');
                $.validator.unobtrusive.adapters.addBool("requiredutf8", "requiredutf8");
                $.validator.unobtrusive.adapters.addBool("mandatory", "required");
                $.validator.unobtrusive.parse(form);
                $('#btnFacebook').click(function () {
                    App.fireDataLayerEventRoutes('account-join-facebook-', _config.controller + '/' + _config.action, _config.route);
                    window.location = _config.socialUri;
                });
                $('#btnEmail').click(function () {
                    App.fireDataLayerEventRoutes('account-join-email-', _config.controller + '/' + _config.action, _config.route);
                    $('#frmJoin').removeClass('hide');
                    $(this).remove();
                    $('html, body').animate({
                        scrollTop: $("#frmJoin").offset().top
                    }, 1000);
                });
                $('#frmJoin').submit(function (e) {
                    e.preventDefault();
                    if (!$(this).valid()) {
                        return false;
                    }
                    if (_config.route && _config.route.toLowerCase() == 'c') App.fireDatalayerEvent('account-submit-iamin-c', _config.controller + '/' + _config.action, document.title);
                    else if (_config.route) App.fireDataLayerEventRoutes('account-submit-email-', _config.controller + '/' + _config.action, _config.route);
                    $('#CountryCallCode').val($('#country-code-0').val());
                    $('#frmError').addClass('hide');
                    App.loader.showLoader();
                    $.post($(this).attr('action'), $(this).serialize(), function (d) {
                        App.fireDatalayerEvent('click-account-join-byemail', 'account/join', document.title);
                        if (d.status == 1) {
                            window.location = d.redirect;
                        } else {
                            if (typeof grecaptcha != 'undefined' && !_config.hasAuthy && !!grecaptcha) grecaptcha.reset();
                            if (typeof d.uri != 'undefined' && !d.uri.isNullOrEmpty()) {
                                window.location = d.uri;
                                return;
                            }
                            if (d.message && d.message.length > 0) {
                                var $error = $('<span/>', {
                                    text: d.message
                                });
                                $error.attr('id', 'Email-error');
                                $('[data-valmsg-for="Email"]').addClass('field-validation-error').html($error);
                                $('#Email').addClass('input-validation-error');
                            } else {
                                $('#FirstName,#Email').val(null);
                                $('#frmJoin').valid();
                            }
                            App.loader.hideLoader();
                        }
                    });
                    return false;
                });
                $('#lnkGoBack').on('click', function () {
                    window.history.back();
                });
                if ($(".pass-text-toggle").length > 0) {
                    $('.pass-text-toggle').click(function () {
                        var $icon = $(this).find('i');
                        var isHidden = $icon.hasClass('fa-eye-slash');
                        if (isHidden) { // unhide password
                            $icon.removeClass('fa-eye-slash');
                            $icon.addClass('fa-eye');
                            $('#Password').attr('type', 'text');
                            $('#ConfirmPassword').attr('type', 'text');
                            return;
                        }
                        $icon.removeClass('fa-eye');
                        $icon.addClass('fa-eye-slash');
                        $('#MPassword').attr('type', 'password');
                        $('#MConfirmPassword').attr('type', 'password');
                    });
                    App.passwordNotice('#Password', '#passNotice');
                }
                if ($('#FirstName').length > 0 && $('#FirstName').val().length > 0) // show details if name is populated
                    $('#btnEmail').click();
            });
        }]);
    };
    return {
        init: init
    };
})();

App.Account.Register = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config == 'object') {
            $.extend(true, _config, config);
        }
        App.angular.controller('MainController', ['$scope', '$http', '$timeout', function ($scope, $http, $timeout) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {
                submitClicked: false
            };
            $scope.obj.hasPhoto = false;
            $scope.obj.suburbList = _config.indoDistrictList;
            $scope.obj.address2List = _config.indoSubDistrictList;
            $scope.obj.hasFb = _config.hasFb;
            $scope.obj.hasIg = _config.hasIg;
            $scope.obj.uploadedPic = _config.uploadedPic;
            $scope.obj.hasPhoto = false;
            $scope.obj.shareMessage = _config.message;
            $scope.obj.showTab = function (selector) {
                var $tab = $(selector);
                $tab.tab('show');
                $('html, body').animate({
                    scrollTop: $tab.offset().top
                }, 500);
            };
            $scope.obj.addPhotoBox = function () {
                if ($scope.obj.hasPhoto) return;
                $scope.obj.currentAvatar = $('.photo-holder:eq(0)').data('img');
                $('#flePic').click();
            };
            $scope.obj.addPhoto = function () {
                $scope.obj.currentAvatar = $('.photo-holder:eq(0)').data('img');
                $('#flePic').click();
            };
            $scope.obj.deletePhoto = function () {
                $('.photo-holder:eq(0)').data("img", '');
                $('.photo-holder').css('background-image', 'none');
                $("#flePic").val('');
                $("#hdnFileName").val('');
                $scope.obj.uploadedPic = '';
                $scope.obj.hasPhoto = false;
            };
            var clearRotation = function clearRotation() {
                $('.photo-holder:eq(0)').removeClass('rotate-90').removeClass('rotate-180').removeClass('rotate-270'); // remove rotation
                $('#hdnRotate').val('');
            };
            $scope.obj.rotateElement = function (selector, deg) {
                var className = '';
                var $obj = $(selector);
                var $hdn = $('#hdnRotate');
                var current = parseInt($hdn.val());
                if (!current || current == null || isNaN(current)) current = 0;
                current += deg;
                if (current == 360 || current == -360) {
                    current = 0;
                    $hdn.val(0);
                }
                switch (current) {
                    case -270:
                    case 90:
                        className = 'rotate-90';
                        break;
                    case -180:
                    case 180:
                        className = 'rotate-180';
                        break;
                    case -90:
                    case 270:
                        className = 'rotate-270';
                        break;
                }
                $hdn.val(current);
                $obj.removeClass('rotate-90').removeClass('rotate-180').removeClass('rotate-270').addClass(className);
            };
            $scope.obj.goToTab = function (tab) {
                $timeout(function () {
                    $('[href="#' + tab + '"]').click();
                });
            };
            $scope.obj.skipToHome = function () {
                App.loader.showLoader();
                window.location = "/";
            };
            $scope.obj.goToNextDelivery = function () { //$scope.obj.setIdState();
                $('#divSuccessInfo').addClass('hide');
                $('[href="#delivery"]').click();
                $timeout(function () {
                    $('#frmInfo').show();
                }, 200);
            };
            $scope.obj.userState = _config.indoState;
            $scope.obj.userSuburb = _config.indoDistrict;
            $scope.obj.userAddress2 = _config.indoSubDistrict;
            $scope.obj.postcodeAreaListing = [];
            $scope.obj.marketSelected = _config.market;
            $scope.obj.stateList = _config.stateList;
            $scope.obj.dynamicPostCode = function () {
                if (!!!$scope.obj.userPostCode || $.trim($scope.obj.userPostCode).length < 4) return;
                App.loader.showLoader();
                $http.post(_config.getDynamicPcListUri, $.param({
                    code: $scope.obj.userPostCode,
                    market: $scope.obj.marketSelected
                })).then(function (d) {
                    if (d.status == 200) { //success
                        $scope.obj.postcodeAreaListing = d.data;
                    }
                    App.loader.hideLoader();
                }, function () {
                    App.loader.hideLoader();
                });
            };
            $scope.obj.setLocationByPostCode = function (_data) {
                App.loader.showLoader();
                $scope.obj.userState = _.find($scope.obj.stateList, function (x) {
                    return $.trim(x.Name).toLowerCase() == $.trim(_data.Province).toLowerCase();
                }).State; // assign state
                $scope.obj.setIdState(function () { // load district list
                    $scope.obj.userSuburb = _data.District; // assign district
                    $scope.obj.setIdSuburb(function () { // load subdistrict
                        $scope.obj.userAddress2 = _data.SubDistrict; // assign subdistrict
                        $scope.obj.userAddress3 = _data.Area; // assign area
                        $scope.obj.userPostCode = _data.PostCode; // assign postcode
                        $scope.obj.postcodeAreaListing = [];
                        App.loader.hideLoader();
                    });
                });
            };
            $scope.obj.setIdState = function (callback) {
                if (!!!$scope.obj.userState || $scope.obj.userState.length == 0) return;
                if (!callback) App.loader.showLoader();
                $http.post(_config.getSuburbListUri, $.param({
                    state: $scope.obj.userState
                })).then(function (d) {
                    if (d.status == 200 && d.data.status == 1) { //success
                        $scope.obj.suburbList = d.data.list;
                        if (callback) callback();
                    }
                    if (!callback) App.loader.hideLoader();
                }, function () {
                    App.loader.hideLoader();
                });
            };
            $scope.obj.setIdSuburb = function (callback) {
                if (!!!$scope.obj.userSuburb || $scope.obj.userSuburb.length == 0) return;
                if (!callback) App.loader.showLoader();
                $http.post(_config.getAddress2ListUri, $.param({
                    suburb: $scope.obj.userSuburb
                })).then(function (d) {
                    if (d.status == 200 && d.data.status == 1) { //success
                        $scope.obj.address2List = d.data.list;
                        if (callback) callback();
                    }
                    if (!callback) App.loader.hideLoader();
                }, function () {
                    App.loader.hideLoader();
                });
            };
            $scope.obj.setSocial = function (u) {
                App.loader.showLoader();
                window.location = u;
            }; //#region share section
            $scope.obj.getShareStatus = function (s) {
                if (s.Status == null) s.Status = 0;
                return _.find(_config.shareStatus, function (x) {
                    return x.key == s.Status;
                });
            };
            $scope.obj.shareFb = function () {
                var uri = _config.shareToFbUri + '&message=' + encodeURIComponent($scope.obj.shareMessage);
                App.loader.showLoader();
                App.fbFeedDialog(_config.linkToShare, function () {
                    $http.post(uri).then(function (res) {
                        if (res.status == 200) {
                            if (res.data.status == 1) {
                                App.notify.Success(_config.successTxt);
                                $scope.obj.shareMessage = null;
                                return;
                            } else App.notify.Warning(res.data.message);
                            App.loader.hideLoader();
                        }
                    });
                });
            };
            $scope.obj.removeFriend = function (s) {
                var uri = _config.unsubUri + '&id=' + s.Guid;
                App.loader.showLoader();
                $http.post(uri).then(function (res) {
                    if (res.status == 200) {
                        if (res.data.status == 1) {
                            App.notify.Success(_config.successTxt);
                            $scope.obj.sharedToFriends = _.reject($scope.obj.sharedToFriends, function (x) {
                                return x.Id == s.Id;
                            });
                        } else App.notify.Danger(res.data.message);
                        App.loader.hideLoader();
                    }
                });
            };
            $scope.obj.resendEmail = function (s) {
                var email = prompt('Please enter email');
                if (email == null || email.length == 0) return;
                if (!isStringEmail(email)) return;
                App.loader.showLoader();
                var uri = _config.resendEmailUri + "?id=" + s.Id + '&e=' + encodeURIComponent(email);
                $http.post(uri).then(function (res) {
                    if (res.status == 200) {
                        if (res.data.status == 1) App.notify.Success(_config.successTxt);
                        else App.notify.Danger(res.data.message);
                        App.loader.hideLoader();
                    }
                });
            };
            $scope.obj.showPreview = function () { // cleanup
                $('#contentDiv').remove();
                var iframe = document.getElementById('re_contentIframe');
                iframe.src = _config.frameUri + "/" + _config.boxId + "?body=" + encodeURIComponent($('#EmailBody').val());
                App.loader.showLoader();
                iframe.onload = function () {
                    App.loader.hideLoader(); // adjust iframe height
                    var frame = iframe.contentWindow ? iframe.contentWindow : iframe.contentDocument.document ? iframe.contentDocument.document : iframe.contentDocument;
                    var height = Math.max(frame.document.documentElement.clientHeight, frame.document.documentElement.scrollHeight, frame.document.documentElement.offsetHeight);
                    document.getElementById('re_contentIframe').style.height = /*height + */ '500px'; // show modal
                    $('#modalEmailBody').modal();
                };
            };

            function hideEmailErr() {
                $('#err_recipientsList').addClass('hide');
            }

            function isStringEmail(email) {
                var pattern = new RegExp(/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i);
                return pattern.test(email);
            } //#endregion
            var resendEmail = function resendEmail() {
                App.loader.showLoader();
                $.post(_config.resendEmailUri, function (d) {
                    if (d.status == 1) {
                        App.notify.Success(_config.uploadSuccessTxt);
                    }
                    App.loader.hideLoader();
                });
            };
            angular.element(function () { // add asterisk on required label fields
                $('[data-val-required]').parents('.form-group').find('label[for]:eq(0)').addClass('required');
                $('[href="#collapse-tab_new1"] .count').text($('#regTab li[role="presentation"]').length);
                $('[href="#collapse-tab_new1"] .count').removeClass('hide'); // set all email resend buttons
                $('.btn-resend-email-validation').click(function () {
                    resendEmail();
                });
                $('#lnkShareEmail').on('click', function (e) {
                    e.preventDefault();
                    $('#lnkShareEmail i,#lnkShareFb i').removeClass('active');
                    $('#divShareFb').addClass('hidden');
                    $('#divShareEmail').removeClass('hidden');
                    $('#lnkShareEmail i').addClass('active');
                    $('.circle_v2.circle-purple-hover').removeClass('active');
                    $(this).addClass('active');
                    App.scrollTo('#divShareEmail', 1000);
                });
                $('#lnkShareFb').on('click', function (e) {
                    e.preventDefault();
                    $('#lnkShareEmail i,#lnkShareFb i').removeClass('active');
                    $('#divShareEmail').addClass('hidden');
                    $('#divShareFb').removeClass('hidden');
                    $('#lnkShareFb i').addClass('active');
                    $('.circle_v2.circle-purple-hover').removeClass('active');
                    $(this).addClass('active');
                    App.scrollTo('#divShareFb', 1000);
                });
                $('#txtFbMessage').on("focus keyup", function (e) {
                    var keycode = e.keyCode ? e.keyCode : e.which ? e.which : e.charCode;
                    if (keycode === 9 || !keycode) { // select
                        var $this = $(this);
                        $this.select(); // For Chrome's bug
                        $this.on("mouseup", function () { // Unbindl mouseup
                            $this.off("mouseup");
                            return false;
                        });
                    }
                });
                $(document).on('shown.bs.tab', 'a[data-toggle="tab"]', function (e) { //$('html, body').animate({
                    //    scrollTop: $("#" + (e.target.hash.replace('#',''))).offset().top
                    //}, 1000);
                    $('#regTab li').removeClass('active');
                    $('.xs-tab-item a span').removeClass('tab-selected');
                    $('li[role="presentation"] [href="' + e.target.hash + '"]').parent().addClass('active');
                    $('.xs-tab-item a[href="' + e.target.hash + '"] span').addClass('tab-selected');
                    $('[href="#collapse-tab_new1"] .text').text($('.xs-tab-item a[href="' + e.target.hash + '"] span').text()); // hide xs tab list
                    $('#collapse-tab_new1').addClass('collapsing').removeClass('collapse in').attr('aria-expanded', 'false'); // scroll to tab nav on select
                    App.scrollTo('#regTab', 300);
                }); // add scripts here
                $.validator.addMethod('passwordpattern', function (value, element) {
                    var valid = false;
                    var $element = $(element);
                    if ($element.attr('id') == 'MemberInfo_Password') {
                        var regPass = App.passwordRegex();
                        valid = regPass.test(value);
                    }
                    return valid && value != null;
                });
                $.validator.addMethod('requiredutf8', function (value, element) {
                    var valid = false;
                    var $element = $(element);
                    if ($element.attr('id') == 'MemberInfo_FirstName' || $element.attr('id') == 'MemberInfo_LastName') {
                        var regUtf8 = new XRegExp('^(\\p{L}|[\\-0-9]){1,}(\\p{L}|[\\-0-9]|\\s){0,}$');
                        valid = regUtf8.test(value);
                    }
                    return valid && value != null;
                });
                $.validator.unobtrusive.adapters.add("mandatory", function (options) {
                    options.rules["required"] = true;
                    if (options.message) {
                        options.messages["required"] = options.message;
                    }
                });
                var form = $("#frmInfo");
                form.removeData('validator');
                form.removeData('unobtrusiveValidation');
                $.validator.unobtrusive.adapters.addBool("requiredutf8", "requiredutf8");
                $.validator.unobtrusive.adapters.addBool("mandatory", "required");
                $.validator.unobtrusive.adapters.addBool("passwordpattern", "passwordpattern");
                $.validator.unobtrusive.adapters.add("checkbox", function (options) {
                    if (options.element.tagName.toUpperCase() === "INPUT" && options.element.type.toUpperCase() === "CHECKBOX") {
                        options.rules["required"] = true;
                        if ($.trim(options.message).length == 0) {
                            options.messages["required"] = $(options.element).attr('id') == "MemberInfo_Agree" ? _config.agreementText : _config.plsSpecifyText; //options.message;
                        }
                    }
                });
                $.validator.unobtrusive.parse(form);
                App.formValidateReset('#frmDelivery');
                App.formValidateReset('#frmShare'); //#region Share section
                $('#frmShare').submit(function (e) {
                    e.preventDefault();
                    if (!$(this).valid()) return false;
                    var emailList = $("#txtEmails").tagsinput('items');
                    if (_.filter(emailList, function (x) {
                            return x.toLowerCase() == _config.myEmail.toLowerCase();
                        }).length > 0) {
                        App.notify.Warning(_config.notOwnEmailNoticeTxt);
                        return false;
                    }
                    if (_.filter(emailList, function (x) {
                            return !isStringEmail(x);
                        }).length > 0) {
                        App.notify.Warning(_config.onlyValidEmailNoticeTxt);
                        return false;
                    }
                    App.loader.showLoader();
                    $http.post($(this).attr('action'), $(this).serialize()).then(function (r) {
                        if (r.status == 200 && r.data.status == 1) {
                            $http.post(_config.getSharedFriendsUri).then(function (res) {
                                if (res.status == 200) {
                                    $scope.obj.sharedToFriends = res.data;
                                    $scope.obj.submitClicked = true;
                                    $('#txtEmails').val('');
                                    App.loader.hideLoader();
                                }
                            });
                        } else App.loader.hideLoader();
                    });
                });
                $('#frmFbShare').submit(function (e) {
                    e.preventDefault();
                });
                $('#txtEmails').on('beforeItemAdd', function (event) {
                    $('.bootstrap-tagsinput input:eq(0)').css('width', '100%');
                }).on('itemAdded', function (event) {
                    if (!isStringEmail(event.item)) return;
                    hideEmailErr();
                }).on('itemRemoved', function (event) {
                    if (!isStringEmail(event.item)) return;
                });
                $('#txtEmails').tagsinput({
                    tagClass: function tagClass(item) {
                        return isStringEmail(item) ? 'label-info' : 'label-danger';
                    },
                    trimValue: true,
                    confirmKeys: [13, 188, 44, 32]
                }); //#endregion
                $('#MemberInfo_State').change(function () {
                    var val = $(this).val();
                    $('#drpState').val(val);
                });
                $("#chkShowPass").change(function () {
                    var isChecked = $("#chkShowPass").prop('checked');
                    var selector = '#MemberInfo_Password,#MemberInfo_ConfirmPassword';
                    if (isChecked) $(selector).attr('type', 'text');
                    else $(selector).attr('type', 'password');
                });
                $('#frmInfo').submit(function () {
                    if (!$(this).valid()) return;
                    App.loader.showLoader();
                    App.fireDataLayerEventRoutes('account-submit-particulars-', _config.controller + '/' + _config.action, 'A');
                    var formData = new FormData(document.getElementById('frmInfo'));
                    $scope.obj.isUploading = true;
                    $.ajax({
                        url: $(this).attr('action'),
                        type: "POST",
                        data: formData,
                        processData: false,
                        contentType: false,
                        dataType: "json",
                        success: function success(d) {
                            App.fireDatalayerEvent('submit-account-register-registryinfo', 'account/register', document.title);
                            $timeout(function () {
                                $scope.obj.isUploading = false;
                                $('.upload-progress-box .upload-progress').css('width', '');
                                if (d.status == 1) {
                                    window.location = _config.registerUri;
                                } else {
                                    App.notify.Danger(d.message);
                                    App.loader.hideLoader();
                                }
                            });
                        },
                        error: function error() {
                            App.loader.hideLoader();
                        }
                    });
                    return false;
                });
                $('#frmDelivery').submit(function (e) {
                    if (!$(this).valid() || $(this).find('button:visible').length == 0) return false;
                    App.fireDataLayerEventRoutes('account-submit-delivery-', _config.controller + '/' + _config.action, 'A');
                    App.loader.showLoader();
                    $.post($(this).attr('action'), $(this).serialize(), function (d) {
                        App.fireDatalayerEvent('submit-account-register-deliveryinfo', 'account/register', document.title);
                        if (d.status == 1) window.location = _config.registerUri;
                        else {
                            App.notify.Danger(d.message);
                            App.loader.hideLoader();
                        }
                    });
                    return false;
                });
                $('#frmAvatar').submit(function (e) {
                    e.preventDefault();
                    App.loader.showLoader();
                    var formData = new FormData(document.getElementById('frmAvatar'));
                    if ($('#flePic').val().length > 0) formData.append('file', App.dataURItoBlob($('.photo-holder:eq(0)').data('img')));
                    formData.append('name', $('#hdnFileName').val());
                    formData.append('rotation', $('#hdnRotate').val());
                    $scope.obj.isUploading = true;
                    $.ajax({
                        xhr: function xhr() {
                            var xhr = new window.XMLHttpRequest();
                            xhr.upload.addEventListener("progress", function (evt) {
                                if (evt.lengthComputable) {
                                    var percentComplete = evt.loaded / evt.total;
                                    percentComplete = parseInt(percentComplete * 100);
                                    console.log(percentComplete);
                                    $('.upload-progress-box').show();
                                    $('.upload-progress-box .upload-progress').css('width', percentComplete + '%');
                                    if (percentComplete === 100) {
                                        $('.upload-progress-box').hide();
                                        $('.upload-progress-box .upload-progress').css('width', '0px');
                                    }
                                }
                            }, false);
                            return xhr;
                        },
                        url: $(this).attr('action'),
                        type: "POST",
                        data: formData,
                        processData: false,
                        contentType: false,
                        dataType: "json",
                        success: function success(d) {
                            $scope.obj.isUploading = false;
                            $('.upload-progress-box .upload-progress').css('width', '');
                            if (d.status == 1) {
                                if ($('#flePic').val().length > 0) $('#main_menu .username + img.round-user-image100').attr('src', $('.photo-holder:eq(0)').data('img'));
                                else $('#main_menu .username + img.round-user-image100').removeAttr('src');
                                $("#flePic").val('');
                                $("#hdnFileName").val('');
                                $scope.obj.uploadedPic = null;
                                $scope.obj.hasPhoto = false;
                                $('#btnAddPhoto').hide();
                                App.inlineSuccessAlert('#frmAvatar .circle_v2:eq(0)', _config.uploadSuccessTxt, App.placement.after);
                                $scope.$apply();
                                clearRotation();
                            } else {
                                App.notify.Danger(d.message);
                            }
                            App.loader.hideLoader();
                        },
                        error: function error() {
                            App.loader.hideLoader();
                        }
                    });
                });
                $("#flePic").change(function () {
                    if (this.files && this.files[0]) {
                        var reader = new FileReader();
                        var frag = this.files[0].name.split('.');
                        var ext = frag[frag.length - 1];
                        App.loader.showLoader();
                        reader.onload = function (e) {
                            var scaled = App.resizeImage(e.target.result, ext == 'jpg' ? 'jpeg' : ext, 200);
                            var image = scaled == 'data:,' ? e.target.result : scaled;
                            App.loader.hideLoader();
                            $scope.obj.hasPhoto = true;
                            $scope.$apply();
                            angular.element(function () {
                                clearRotation();
                                $('.photo-holder:eq(0)').data('img', image);
                                $('.photo-holder:eq(0)').css('background-image', 'url(' + image + ')');
                            });
                        };
                        reader.readAsDataURL(this.files[0]);
                        $("#hdnFileName").val(this.files[0].name);
                    }
                }); // password toggle
                $('.pass-text-toggle').click(function () {
                    var $icon = $(this).find('i');
                    var isHidden = $icon.hasClass('fa-eye-slash');
                    if (isHidden) { // unhide password
                        $icon.removeClass('fa-eye-slash');
                        $icon.addClass('fa-eye');
                        $('#MemberInfo_Password').attr('type', 'text');
                        $('#MemberInfo_ConfirmPassword').attr('type', 'text');
                        return;
                    }
                    $icon.removeClass('fa-eye');
                    $icon.addClass('fa-eye-slash');
                    $('#MemberInfo_Password').attr('type', 'password');
                    $('#MemberInfo_ConfirmPassword').attr('type', 'password');
                });
                App.passwordNotice('#MemberInfo_Password', '#passNotice'); // show error if exists
                if ($('#lnkWarning').length > 0) $('#lnkWarning').click(); // tab selection on load
                if (_config.isLoggedIn) {
                    if (_config.isFromFbShareFeed) {
                        $('[href="#socials"]').attr("data-toggle", "tab");
                        $scope.obj.goToTab('last');
                        $('#lnkShareFb').click();
                        App.inlineSuccessAlert('#divTextMessage', _config.successFbFeed, App.placement.after);
                        return;
                    }
                    if (!_config.userState || $.trim(_config.userState).length == 0) { // insert complete pixel
                        if ($.trim(_config.src).length > 0) {
                            var pxReg = App.readCookie(_config.pxRegister + _config.src);
                            if (pxReg == null || $.trim(pxReg).length == 0) {
                                var px = $('#complete_' + _config.src).val();
                                $('body').append(px);
                                App.createCookie(_config.pxRegister + _config.src, App.guid(), 1);
                            }
                        }
                        $scope.obj.goToTab('delivery');
                        return;
                    }
                    if (!_config.isProfileRequired || !!window._surveyObjects.answers && window._surveyObjects.answers.length > 0) $('[href="#socials"]').attr("data-toggle", "tab");
                    if (_config.fromSocialConnect && (_config.hasFb || _config.hasIg)) $scope.obj.goToTab('socials');
                    if (_config.isProfileRequired) {
                        if (!!window._surveyObjects.answers) {
                            $('[href="#about"]').attr("data-toggle", "tab");
                            $scope.obj.goToTab('about');
                        } else {
                            $('[href="#register"]').attr("data-toggle", "tab");
                            $scope.obj.goToTab('register');
                        }
                    } else if ($('[href="#register"]').length > 0) {
                        $('[href="#register"]').attr("data-toggle", "tab");
                        $scope.obj.goToTab('register');
                    }
                }
            });
        }]);
    };
    var submitPhoto = function submitPhoto() {
        $('#frmAvatar').submit();
    };
    return {
        init: init,
        submitPhoto: submitPhoto
    };
})();

App.Account.RegisterB = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config == 'object') {
            $.extend(true, _config, config);
        }
        App.angular.controller('MainController', ['$scope', '$http', '$sce', '$timeout', 'dateFilter', 'unitOfWork', function ($scope, $http, $sce, $timeout, dateFilter, unitOfWork) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {
                submitClicked: false,
                delvieryObj: {
                    hasGlobalLookup: _config.deliveryObj.hasGlobalLookup,
                    phone: _config.deliveryObj.phone,
                    userPin: _config.deliveryObj.userPin,
                    addressMain: _config.deliveryObj.userAddress,
                    userAddress4: _config.deliveryObj.userAddress4,
                    userAddress3: _config.deliveryObj.area
                },
                progressPerc: null
            };
            $scope.obj.hasPhoto = false;
            $scope.obj.suburbList = _config.indoDistrictList;
            $scope.obj.address2List = _config.indoSubDistrictList;
            $scope.obj.hasFb = _config.hasFb;
            $scope.obj.hasIg = _config.hasIg;
            $scope.obj.uploadedPic = _config.uploadedPic;
            $scope.obj.hasPhoto = false;
            $scope.obj.shareMessage = _config.message;
            $scope.obj.slideToInfo = function () {
                App.fireDataLayerEventRoutes('account-submit-iamin-', _config.controller + '/' + _config.action, 'b');
                $('#introSlide').addClass('hide');
                $('#infoSlide').removeClass('hide').slideDown();
                $scope.obj.progressPerc = 0.0;
                angular.element(function () {
                    App.scrollTo('#infoSlide', 300);
                });
            };
            $scope.obj.nextFinalSLide = function () {
                $('#socialSlide').addClass('hide');
                $('#finalSlide').removeClass('hide').slideDown();
                $scope.obj.progressPerc = 100;
                angular.element(function () {
                    App.scrollTo('#finalSlide', 300);
                    $('.survey_Qgraph_div').addClass('bar-full');
                });
            };
            $scope.obj.nextDeliverySLide = function () {
                var $currentSlide = $('.delivery-slide:visible');
                var isLastSlide = $currentSlide.next('.delivery-slide').length === 0;
                var $form = $('#frmDeliverySlide');
                App.resetFormError('#frmDeliverySlide');
                var isCurrentSlideValid = $currentSlide.find('input[name], select[name]').valid();
                if (isCurrentSlideValid && isLastSlide) { //submit info and save to DB
                    if (!$form.valid()) return;
                    $scope.obj.progressPerc += 10.0;
                    App.loader.showLoader();
                    $.post($form.attr('action'), $form.serialize(), function (d) {
                        App.fireDatalayerEvent('submit-account-register-deliveryinfo', 'account/register', document.title);
                        App.fireDatalayerEvent('account-submit-address-b', 'account/register', document.title);
                        if (d.status === 1) {
                            $('#deliverySlide').addClass('hide');
                            if (_config.isProfileRequired) $('#aboutSlide').removeClass('hide').slideDown();
                            else $('#socialSlide').removeClass('hide').slideDown();
                            $scope.$apply(function () {
                                $scope.obj.progressPerc = 60.0;
                                App.scrollTo('#aboutSlide:visible,#socialSlide:visible', 300);
                            });
                        } else console.log('Error');
                        App.loader.hideLoader();
                    });
                } else if (isCurrentSlideValid) { // go next
                    $scope.obj.progressPerc += 10.0;
                    if ($('.delivery-slide').is(':visible')) {
                        App.fireDatalayerEvent('account-submit-post-b', _config.controller + '/' + _config.action, document.title);
                        $scope.obj.delvieryObj.dynamicPostCode(function () {
                            $currentSlide.addClass('hide');
                            $currentSlide.next('.delivery-slide').removeClass('hide').slideDown(200);
                        });
                    } else {
                        $currentSlide.addClass('hide');
                        $currentSlide.next('.delivery-slide').removeClass('hide').slideDown(200);
                    }
                    App.scrollTo('.delivery-slide', 300);
                }
            };
            $scope.obj.nextLideInfoCounter = 0;
            $scope.obj.nextInfoSLide = function () {
                var $currentSlide = $('.info-slide:visible');
                var isLastSlide = $currentSlide.next('.info-slide.hide').length === 0;
                var $form = $('#frmInfoSlide');
                App.resetFormError('#frmInfoSlide');
                var isCurrentSlideValid = $currentSlide.find('input[name], select[name]').valid();
                if (isCurrentSlideValid && isLastSlide) { //submit info and save to DB
                    if (!$form.valid()) return;
                    App.fireDatalayerEvent('account-submit-agree-b', _config.controller + '/' + _config.action, document.title);
                    $scope.obj.progressPerc += 5.0;
                    App.loader.showLoader();
                    var formData = new FormData(document.getElementById('frmInfoSlide'));
                    $scope.obj.isUploading = true;
                    $.ajax({
                        url: $form.attr('action'),
                        type: "POST",
                        data: formData,
                        processData: false,
                        contentType: false,
                        dataType: "json",
                        success: function success(d) {
                            App.fireDatalayerEvent('submit-account-register-registryinfo', 'account/register', document.title);
                            $timeout(function () {
                                $scope.obj.isUploading = false;
                                if (d.status === 1) {
                                    $('#infoSlide').addClass('hide');
                                    $('#deliverySlide').removeClass('hide').slideDown();
                                    App.scrollTo('#deliverySlide', 300);
                                    App.loader.hideLoader();
                                } else {
                                    App.notify.Danger(d.message);
                                    App.loader.hideLoader();
                                }
                            });
                        },
                        error: function error() {
                            App.loader.hideLoader();
                        }
                    });
                } else if (isCurrentSlideValid) { // go next
                    var key = $scope.obj.nextLideInfoCounter == 1 ? 'account-submit-gender-b' : $scope.obj.nextLideInfoCounter == 2 ? 'account-submit-bday-b' : 'account-submit-name-b';
                    $scope.obj.nextLideInfoCounter++;
                    App.fireDatalayerEvent(key, _config.controller + '/' + _config.action, document.title);
                    $currentSlide.addClass('hide');
                    $currentSlide.next('.info-slide').removeClass('hide').slideDown(200);
                    $scope.obj.progressPerc += $scope.obj.progressPerc > 0 ? 5.0 : 15.0;
                    angular.element(function () {
                        App.scrollTo('.info-slide:visible', 300);
                    });
                }
            };
            $scope.obj.showTab = function (selector) {
                var $tab = $(selector);
                $tab.tab('show');
                $('html, body').animate({
                    scrollTop: $tab.offset().top
                }, 500);
            };
            $scope.obj.addPhotoBox = function () {
                if ($scope.obj.hasPhoto) return;
                $scope.obj.currentAvatar = $('.photo-holder:eq(0)').data('img');
                $('#flePic').click();
            };
            $scope.obj.addPhoto = function () {
                $scope.obj.currentAvatar = $('.photo-holder:eq(0)').data('img');
                $('#flePic').click();
            };
            $scope.obj.deletePhoto = function () {
                $('.photo-holder:eq(0)').data("img", '');
                $('.photo-holder').css('background-image', 'none');
                $("#flePic").val('');
                $("#hdnFileName").val('');
                $scope.obj.uploadedPic = '';
                $scope.obj.hasPhoto = false;
            };
            var clearRotation = function clearRotation() {
                $('.photo-holder:eq(0)').removeClass('rotate-90').removeClass('rotate-180').removeClass('rotate-270'); // remove rotation
                $('#hdnRotate').val('');
            };
            $scope.obj.rotateElement = function (selector, deg) {
                var className = '';
                var $obj = $(selector);
                var $hdn = $('#hdnRotate');
                var current = parseInt($hdn.val());
                if (!current || current == null || isNaN(current)) current = 0;
                current += deg;
                if (current == 360 || current == -360) {
                    current = 0;
                    $hdn.val(0);
                }
                switch (current) {
                    case -270:
                    case 90:
                        className = 'rotate-90';
                        break;
                    case -180:
                    case 180:
                        className = 'rotate-180';
                        break;
                    case -90:
                    case 270:
                        className = 'rotate-270';
                        break;
                }
                $hdn.val(current);
                $obj.removeClass('rotate-90').removeClass('rotate-180').removeClass('rotate-270').addClass(className);
            };
            $scope.obj.skipToHome = function () {
                App.loader.showLoader();
                window.location = "/";
            };
            $scope.obj.goToNextDelivery = function () { //$scope.obj.setIdState();
                $('#divSuccessInfo').addClass('hide');
                $('[href="#delivery"]').click();
                $timeout(function () {
                    $('#frmInfo').show();
                }, 200);
            };
            $scope.obj.setSocial = function (u) {
                App.loader.showLoader();
                window.location = u;
            }; //#region share section
            $scope.obj.getShareStatus = function (s) {
                if (s.Status == null) s.Status = 0;
                return _.find(_config.shareStatus, function (x) {
                    return x.key == s.Status;
                });
            };
            $scope.obj.shareFb = function () {
                var uri = _config.shareToFbUri + '&message=' + encodeURIComponent($scope.obj.shareMessage);
                App.loader.showLoader();
                App.fbFeedDialog(_config.linkToShare, function () {
                    $http.post(uri).then(function (res) {
                        if (res.status == 200) {
                            if (res.data.status == 1) {
                                App.notify.Success(_config.successTxt);
                                $scope.obj.shareMessage = null;
                                return;
                            } else App.notify.Warning(res.data.message);
                            App.loader.hideLoader();
                        }
                    });
                });
            };
            $scope.obj.removeFriend = function (s) {
                var uri = _config.unsubUri + '&id=' + s.Guid;
                App.loader.showLoader();
                $http.post(uri).then(function (res) {
                    if (res.status == 200) {
                        if (res.data.status == 1) {
                            App.notify.Success(_config.successTxt);
                            $scope.obj.sharedToFriends = _.reject($scope.obj.sharedToFriends, function (x) {
                                return x.Id == s.Id;
                            });
                        } else App.notify.Danger(res.data.message);
                        App.loader.hideLoader();
                    }
                });
            };
            $scope.obj.resendEmail = function (s) {
                var email = prompt('Please enter email');
                if (email == null || email.length == 0) return;
                if (!isStringEmail(email)) return;
                App.loader.showLoader();
                var uri = _config.resendEmailUri + "?id=" + s.Id + '&e=' + encodeURIComponent(email);
                $http.post(uri).then(function (res) {
                    if (res.status == 200) {
                        if (res.data.status == 1) App.notify.Success(_config.successTxt);
                        else App.notify.Danger(res.data.message);
                        App.loader.hideLoader();
                    }
                });
            };
            $scope.obj.showPreview = function () { // cleanup
                $('#contentDiv').remove();
                var iframe = document.getElementById('re_contentIframe');
                iframe.src = _config.frameUri + "/" + _config.boxId + "?body=" + encodeURIComponent($('#EmailBody').val());
                App.loader.showLoader();
                iframe.onload = function () {
                    App.loader.hideLoader(); // adjust iframe height
                    var frame = iframe.contentWindow ? iframe.contentWindow : iframe.contentDocument.document ? iframe.contentDocument.document : iframe.contentDocument;
                    var height = Math.max(frame.document.documentElement.clientHeight, frame.document.documentElement.scrollHeight, frame.document.documentElement.offsetHeight);
                    document.getElementById('re_contentIframe').style.height = /*height + */ '500px'; // show modal
                    $('#modalEmailBody').modal();
                };
            };

            function hideEmailErr() {
                $('#err_recipientsList').addClass('hide');
            }

            function isStringEmail(email) {
                var pattern = new RegExp(/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i);
                return pattern.test(email);
            } //#endregion
            var resendEmail = function resendEmail() {
                App.loader.showLoader();
                $.post(_config.resendEmailUri, function (d) {
                    if (d.status == 1) {
                        App.notify.Success(_config.uploadSuccessTxt);
                    }
                    App.loader.hideLoader();
                });
            }; //#region Post code lookup func
            $scope.obj.delvieryObj.dynamicFields = _config.deliveryObj.dynamicFields;
            $scope.obj.delvieryObj.marketSelected = _config.deliveryObj.market;
            $scope.obj.delvieryObj.nameSpace = _config.deliveryObj.nameSpace;
            $scope.obj.delvieryObj.showCountryOption = _config.deliveryObj.showCountryOption;
            $scope.obj.delvieryObj.hasPostcodeLookup = _config.deliveryObj.hasPostcodeLookup;
            $scope.obj.delvieryObj.userState = _config.deliveryObj.state;
            $scope.obj.delvieryObj.stateList = _config.deliveryObj.stateList;
            $scope.obj.delvieryObj.userSuburb = _config.deliveryObj.indoDistrict;
            $scope.obj.delvieryObj.userAddress2 = _config.deliveryObj.indoSubDistrict;
            $scope.obj.delvieryObj.hasDynamicSuburb = function () {
                return _.filter(_config.deliveryObj.dynamicSuburbCountries, function (x) {
                    return x == $scope.obj.delvieryObj.marketSelected;
                }).length > 0;
            };
            $scope.obj.delvieryObj.hasLookupData = function () {
                return !$.isEmptyObject($scope.obj.delvieryObj.lookupData);
            };
            $scope.obj.delvieryObj.hasReturnedLookup = false;
            $scope.obj.delvieryObj.postcodeAreaListing = [];
            $scope.obj.delvieryObj.suburbFiltered = function () {
                if (!$scope.obj.delvieryObj.dynamicFields.hasNoPost || $scope.obj.delvieryObj.userState == null) return $scope.obj.delvieryObj.suburbList;
                return _.filter($scope.obj.delvieryObj.suburbList, function (s) {
                    return $scope.obj.delvieryObj.userState == s.state;
                });
            };
            $scope.obj.delvieryObj.canShowInput = function () {
                return !$scope.obj.delvieryObj.hasGlobalLookup || $scope.obj.delvieryObj.hasGlobalLookup && $scope.obj.delvieryObj.hasReturnedLookup;
            };
            $scope.obj.delvieryObj.dynamicPostCode = function (callback) { //if (!$scope.obj.delvieryObj.hasGlobalLookup || !!!$scope.obj.delvieryObj.userPostCode || $.trim($scope.obj.delvieryObj.userPostCode).length < 2) return;
                App.loader.showLoader();
                $http.post(_config.deliveryObj.getDynamicPcListUri, $.param({
                    code: $scope.obj.delvieryObj.userPostCode,
                    country: $scope.obj.delvieryObj.marketSelected
                })).then(function (d) {
                    if (d.status === 200) { //success
                        $scope.obj.delvieryObj.hasReturnedLookup = true;
                        $('#btnRegisterDelivery').removeClass('hide');
                        var data = d.data;
                        if (data.status === 0) {
                            $scope.obj.delvieryObj.lookupData = {};
                            $scope.obj.delvieryObj.stateList = data.states;
                            $scope.obj.delvieryObj.suburbList = [];
                            $scope.obj.delvieryObj.address3List = [];
                            $scope.obj.delvieryObj.address4List = [];
                            clearLookup();
                            App.loader.hideLoader();
                            angular.element(function () {
                                unitOfWork.util.resetFormError("#frmDeliverySlide");
                                unitOfWork.util.formValidateReset("#frmDeliverySlide");
                                if (callback) callback();
                            });
                            return;
                        }
                        $scope.obj.delvieryObj.lookupData = data;
                        $scope.obj.delvieryObj.setLookupData(data);
                        angular.element(function () {
                            if (callback) callback();
                        });
                    }
                    App.loader.hideLoader();
                }, function () {
                    App.loader.hideLoader();
                });
            };

            function clearLookup() {
                $scope.obj.delvieryObj.userSuburb = null;
                $scope.obj.delvieryObj.userState = null;
                $scope.obj.delvieryObj.userAddress3 = null;
                $scope.obj.delvieryObj.userAddress4 = null;
                $scope.obj.delvieryObj.userStateName = null;
            }
            var returnLocation = function returnLocation(x) {
                return {
                    state: x.State,
                    text: (x.Eng || '') + ($.trim(x.Local || '').length > 0 && $.trim(x.Eng || '').length > 0 ? '-' : '') + (x.Local || ''),
                    val: $.trim(x.Eng || '').length > 0 ? x.Eng : x.Local
                };
            };
            var firstOrDefault = function firstOrDefault(x, k) {
                if (!!!x || x == null || x.length == 0) return null;
                return x[0][k];
            };
            $scope.obj.delvieryObj.setLookupData = function (data) {
                clearLookup();
                $scope.obj.delvieryObj.stateList = data.States;
                $scope.obj.delvieryObj.suburbList = _.map(data.Suburbs, returnLocation); //_.pluck(data.Suburbs, 'Eng');
                $scope.obj.delvieryObj.address3List = _.map(data.Address3s, returnLocation); //_.pluck(data.Address3s, 'Eng');
                $scope.obj.delvieryObj.address4List = _.map(data.Address4s, returnLocation); //_.pluck(data.Address4s, 'Eng');
                if ($scope.obj.delvieryObj.stateList.length === 1) {
                    $scope.obj.delvieryObj.userState = $scope.obj.delvieryObj.stateList[0].State;
                    $scope.obj.delvieryObj.userStateName = $scope.obj.delvieryObj.stateList[0].Name;
                }
                if ($scope.obj.delvieryObj.suburbList.length <= 1) $scope.obj.delvieryObj.userSuburb = firstOrDefault($scope.obj.delvieryObj.suburbList, 'text');
                if ($scope.obj.delvieryObj.address3List.length <= 1) $scope.obj.delvieryObj.userAddress3 = firstOrDefault($scope.obj.delvieryObj.address3List, 'text');
                if ($scope.obj.delvieryObj.address4List.length <= 1) $scope.obj.delvieryObj.userAddress4 = firstOrDefault($scope.obj.delvieryObj.address4List, 'text');
                angular.element(function () {
                    unitOfWork.util.resetFormError("#frmDeliverySlide");
                    unitOfWork.util.formValidateReset("#frmDeliverySlide");
                });
            }; //#endregion
            angular.element(function () { //#region Post Lookup
                $scope.obj.delvieryObj.userPostCode = _config.deliveryObj.userPostCode;
                $scope.obj.delvieryObj.userSuburb = _config.deliveryObj.userSuburb; // assign district
                $scope.obj.delvieryObj.userAddress2 = _config.deliveryObj.subDistrict; // assign subdistrict
                $scope.obj.delvieryObj.userAddress3 = _config.deliveryObj.area; // assign area
                if ($scope.obj.delvieryObj.dynamicFields.hasNoPost) // immediately load details for no postcode with global address
                    $scope.obj.delvieryObj.dynamicPostCode(); //#endregion
                // add asterisk on required label fields
                $('[data-val-required]').parents('.form-group').find('label[for]:eq(0)').addClass('required');
                $('[href="#collapse-tab_new1"] .count').text($('#regTab li[role="presentation"]').length);
                $('[href="#collapse-tab_new1"] .count').removeClass('hide'); // set all email resend buttons
                $('.btn-resend-email-validation').click(function () {
                    resendEmail();
                });
                $('#cmn-toggle-fb, #cmn-toggle-ig').click(function (e) {
                    e.preventDefault();
                    App.fireDatalayerEvent('account-submit-socials-b', _config.controller + '/' + _config.action, document.title);
                    var lnk = $(this).attr('href');
                    window.location = lnk;
                });
                $('#lnkShareEmail').on('click', function (e) {
                    e.preventDefault();
                    $('#lnkShareEmail i,#lnkShareFb i').removeClass('active');
                    $('#divShareFb').addClass('hidden');
                    $('#divShareEmail').removeClass('hidden');
                    $('#lnkShareEmail i').addClass('active');
                    $('.circle_v2.circle-purple-hover').removeClass('active');
                    $(this).addClass('active');
                    App.scrollTo('#divShareEmail', 1000);
                });
                $('#lnkShareFb').on('click', function (e) {
                    e.preventDefault();
                    $('#lnkShareEmail i,#lnkShareFb i').removeClass('active');
                    $('#divShareEmail').addClass('hidden');
                    $('#divShareFb').removeClass('hidden');
                    $('#lnkShareFb i').addClass('active');
                    $('.circle_v2.circle-purple-hover').removeClass('active');
                    $(this).addClass('active');
                    App.scrollTo('#divShareFb', 1000);
                });
                $('#txtFbMessage').on("focus keyup", function (e) {
                    var keycode = e.keyCode ? e.keyCode : e.which ? e.which : e.charCode;
                    if (keycode === 9 || !keycode) { // select
                        var $this = $(this);
                        $this.select(); // For Chrome's bug
                        $this.on("mouseup", function () { // Unbindl mouseup
                            $this.off("mouseup");
                            return false;
                        });
                    }
                }); // add scripts here
                $.validator.addMethod('passwordpattern', function (value, element) {
                    var valid = false;
                    var $element = $(element);
                    if ($element.attr('id') == 'MemberInfo_Password') {
                        var regPass = App.passwordRegex();
                        valid = regPass.test(value);
                    }
                    return valid && value != null;
                });
                $.validator.addMethod('requiredutf8', function (value, element) {
                    var valid = false;
                    var $element = $(element);
                    if ($element.attr('id') == 'MemberInfo_FirstName' || $element.attr('id') == 'MemberInfo_LastName') {
                        var regUtf8 = new XRegExp('^(\\p{L}|[\\-0-9]){1,}(\\p{L}|[\\-0-9]|\\s){0,}$');
                        valid = regUtf8.test(value);
                    }
                    return valid && value != null;
                });
                $.validator.unobtrusive.adapters.add("mandatory", function (options) {
                    options.rules["required"] = true;
                    if (options.message) {
                        options.messages["required"] = options.message;
                    }
                });
                $.validator.unobtrusive.adapters.addBool("requiredutf8", "requiredutf8");
                $.validator.unobtrusive.adapters.addBool("mandatory", "required");
                $.validator.unobtrusive.adapters.add("checkbox", function (options) {
                    if (options.element.tagName.toUpperCase() === "INPUT" && options.element.type.toUpperCase() === "CHECKBOX") {
                        options.rules["required"] = true;
                        if ($.trim(options.message).length == 0) {
                            options.messages["required"] = $(options.element).attr('id') == "MemberInfo_Agree" ? _config.agreementText : _config.plsSpecifyText; //options.message;
                        }
                    }
                });
                App.formValidateReset('#frmInfoSlide');
                App.formValidateReset('#frmDeliverySlide');
                App.formValidateReset('#frmShare'); //#region Share section
                $('#frmShare').submit(function (e) {
                    e.preventDefault();
                    if (!$(this).valid()) return false;
                    var emailList = $("#txtEmails").tagsinput('items');
                    if (_.filter(emailList, function (x) {
                            return x.toLowerCase() == _config.myEmail.toLowerCase();
                        }).length > 0) {
                        App.notify.Warning(_config.notOwnEmailNoticeTxt);
                        return false;
                    }
                    if (_.filter(emailList, function (x) {
                            return !isStringEmail(x);
                        }).length > 0) {
                        App.notify.Warning(_config.onlyValidEmailNoticeTxt);
                        return false;
                    }
                    App.loader.showLoader();
                    $http.post($(this).attr('action'), $(this).serialize()).then(function (r) {
                        if (r.status == 200 && r.data.status == 1) {
                            $http.post(_config.getSharedFriendsUri).then(function (res) {
                                if (res.status == 200) {
                                    $scope.obj.sharedToFriends = res.data;
                                    $scope.obj.submitClicked = true;
                                    $('#txtEmails').val('');
                                    App.loader.hideLoader();
                                }
                            });
                        } else App.loader.hideLoader();
                    });
                });
                $('#frmFbShare').submit(function (e) {
                    e.preventDefault();
                });
                $('#txtEmails').on('beforeItemAdd', function (event) {
                    $('.bootstrap-tagsinput input:eq(0)').css('width', '100%');
                }).on('itemAdded', function (event) {
                    if (!isStringEmail(event.item)) return;
                    hideEmailErr();
                }).on('itemRemoved', function (event) {
                    if (!isStringEmail(event.item)) return;
                });
                $('#txtEmails').tagsinput({
                    tagClass: function tagClass(item) {
                        return isStringEmail(item) ? 'label-info' : 'label-danger';
                    },
                    trimValue: true,
                    confirmKeys: [13, 188, 44, 32]
                }); //#endregion
                $('#MemberInfo_State').change(function () {
                    var val = $(this).val();
                    $('#drpState').val(val);
                });
                $('#frmAvatar').submit(function (e) {
                    e.preventDefault();
                    App.loader.showLoader();
                    var formData = new FormData(document.getElementById('frmAvatar'));
                    if ($('#flePic').val().length > 0) formData.append('file', App.dataURItoBlob($('.photo-holder:eq(0)').data('img')));
                    formData.append('name', $('#hdnFileName').val());
                    formData.append('rotation', $('#hdnRotate').val());
                    $scope.obj.isUploading = true;
                    $.ajax({
                        xhr: function xhr() {
                            var xhr = new window.XMLHttpRequest();
                            xhr.upload.addEventListener("progress", function (evt) {
                                if (evt.lengthComputable) {
                                    var percentComplete = evt.loaded / evt.total;
                                    percentComplete = parseInt(percentComplete * 100);
                                    console.log(percentComplete);
                                    $('.upload-progress-box').show();
                                    $('.upload-progress-box .upload-progress').css('width', percentComplete + '%');
                                    if (percentComplete === 100) {
                                        $('.upload-progress-box').hide();
                                        $('.upload-progress-box .upload-progress').css('width', '0px');
                                    }
                                }
                            }, false);
                            return xhr;
                        },
                        url: $(this).attr('action'),
                        type: "POST",
                        data: formData,
                        processData: false,
                        contentType: false,
                        dataType: "json",
                        success: function success(d) {
                            $scope.obj.isUploading = false;
                            $('.upload-progress-box .upload-progress').css('width', '');
                            if (d.status == 1) {
                                if ($('#flePic').val().length > 0) $('#main_menu .username + img.round-user-image100').attr('src', $('.photo-holder:eq(0)').data('img'));
                                else $('#main_menu .username + img.round-user-image100').removeAttr('src');
                                $("#flePic").val('');
                                $("#hdnFileName").val('');
                                $scope.obj.uploadedPic = null;
                                $scope.obj.hasPhoto = false;
                                $('#btnAddPhoto').hide();
                                App.inlineSuccessAlert('#frmAvatar .circle_v2:eq(0)', _config.uploadSuccessTxt, App.placement.after);
                                $scope.$apply();
                                clearRotation();
                            } else {
                                App.notify.Danger(d.message);
                            }
                            App.loader.hideLoader();
                        },
                        error: function error() {
                            App.loader.hideLoader();
                        }
                    });
                });
                $("#flePic").change(function () {
                    if (this.files && this.files[0]) {
                        var reader = new FileReader();
                        var frag = this.files[0].name.split('.');
                        var ext = frag[frag.length - 1];
                        App.loader.showLoader();
                        reader.onload = function (e) {
                            var scaled = App.resizeImage(e.target.result, ext == 'jpg' ? 'jpeg' : ext, 200);
                            var image = scaled == 'data:,' ? e.target.result : scaled;
                            App.loader.hideLoader();
                            $scope.obj.hasPhoto = true;
                            $scope.$apply();
                            angular.element(function () {
                                clearRotation();
                                $('.photo-holder:eq(0)').data('img', image);
                                $('.photo-holder:eq(0)').css('background-image', 'url(' + image + ')'); //immediately open modal to upload
                                $('[data-click-continue="App.Account.Register.submitPhoto"]').click();
                            });
                        };
                        reader.readAsDataURL(this.files[0]);
                        $("#hdnFileName").val(this.files[0].name);
                    }
                }); // password toggle
                $('.pass-text-toggle').click(function () {
                    var $icon = $(this).find('i');
                    var isHidden = $icon.hasClass('fa-eye-slash');
                    if (isHidden) { // unhide password
                        $icon.removeClass('fa-eye-slash');
                        $icon.addClass('fa-eye');
                        $('#MemberInfo_Password').attr('type', 'text');
                        $('#MemberInfo_ConfirmPassword').attr('type', 'text');
                        return;
                    }
                    $icon.removeClass('fa-eye');
                    $icon.addClass('fa-eye-slash');
                    $('#MemberInfo_Password').attr('type', 'password');
                    $('#MemberInfo_ConfirmPassword').attr('type', 'password');
                });
                App.passwordNotice('#MemberInfo_Password', '#passNotice'); // show error if exists
                if ($('#lnkWarning').length > 0) $('#lnkWarning').click(); // tab selection on load
                if (_config.isLoggedIn) {
                    if (!_config.userState || $.trim(_config.userState).length == 0) { // insert complete pixel
                        if ($.trim(_config.src).length > 0) {
                            var pxReg = App.readCookie(_config.pxRegister + _config.src);
                            if (pxReg == null || $.trim(pxReg).length == 0) {
                                var px = $('#complete_' + _config.src).val();
                                $('body').append(px);
                                App.createCookie(_config.pxRegister + _config.src, App.guid(), 1);
                            }
                        }
                        return;
                    }
                } // clear style from survey
                if ($('.text-center-xs-right-md').length > 0) {
                    $('#aboutSlide p.body-font.txt-left').addClass('text-center').removeClass('txt-left');
                    $('#aboutSlide .heading-font-h6').addClass('margin-b30');
                    $('.text-center-xs-right-md').addClass('text-center').removeClass('text-center-xs-right');
                    $('.question-container').removeClass('layout-wrapper');
                    $('#aboutSlide>div.cp-elements-wrapper>div').removeClass('margin-t40');
                }
                if (_config.fromSocialConnect) {
                    $('#introSlide').addClass('hide');
                    $('#socialSlide').removeClass('hide');
                    $scope.$apply(function () {
                        $scope.obj.progressPerc = 90.0;
                    });
                }
            });
        }]);
    };
    var submitPhoto = function submitPhoto() {
        $('#frmAvatar').submit();
    };
    return {
        init: init,
        submitPhoto: submitPhoto
    };
})();

App.Account.RegisterC = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config == 'object') {
            $.extend(true, _config, config);
        }
        App.angular.controller('MainController', ['$scope', '$http', '$timeout', 'unitOfWork', function ($scope, $http, $timeout, unitOfWork) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {
                submitClicked: false,
                delvieryObj: {
                    hasGlobalLookup: _config.deliveryObj.hasGlobalLookup,
                    phone: _config.deliveryObj.phone,
                    userPin: _config.deliveryObj.userPin,
                    addressMain: _config.deliveryObj.userAddress,
                    userAddress4: _config.deliveryObj.userAddress4,
                    userAddress3: _config.deliveryObj.area
                },
                progressPerc: null
            };
            $scope.obj.hasPhoto = false;
            $scope.obj.suburbList = _config.indoDistrictList;
            $scope.obj.address2List = _config.indoSubDistrictList;
            $scope.obj.hasFb = _config.hasFb;
            $scope.obj.hasIg = _config.hasIg;
            $scope.obj.uploadedPic = _config.uploadedPic;
            $scope.obj.hasPhoto = false;
            $scope.obj.shareMessage = _config.message;
            $scope.obj.nextFinalSLide = function () {
                $('#socialSlide').addClass('hide');
                $('#finalSlide').removeClass('hide').slideDown();
                $scope.obj.progressPerc = 100;
                angular.element(function () {
                    App.scrollTo('#finalSlide', 300);
                    $('.survey_Qgraph_div').addClass('bar-full');
                });
            };
            $scope.obj.nextDeliverySLide = function () {
                var $currentSlide = $('.delivery-slide:visible');
                var isLastSlide = $currentSlide.next('.delivery-slide').length === 0;
                var $form = $('#frmDeliverySlide');
                App.resetFormError('#frmDeliverySlide');
                var isCurrentSlideValid = $currentSlide.find('input[name], select[name]').valid();
                if (isCurrentSlideValid && isLastSlide) { //submit info and save to DB
                    if (!$form.valid()) return;
                    App.fireDatalayerEvent('account-submit-address-c', _config.controller + '/' + _config.action, document.title);
                    $scope.obj.progressPerc += 10.0;
                    App.loader.showLoader();
                    $.post($form.attr('action'), $form.serialize(), function (d) {
                        App.fireDatalayerEvent('submit-account-register-deliveryinfo', 'account/register', document.title);
                        if (d.status === 1) {
                            $('#deliverySlide').addClass('hide');
                            if (_config.isProfileRequired) $('#aboutSlide').removeClass('hide').slideDown();
                            else $('#socialSlide').removeClass('hide').slideDown();
                            $scope.$apply(function () {
                                $scope.obj.progressPerc = 60.0;
                                App.scrollTo('#aboutSlide:visible,#socialSlide:visible', 300);
                            });
                        } else console.log('Error');
                        App.loader.hideLoader();
                    });
                } else if (isCurrentSlideValid) { // go next
                    $scope.obj.progressPerc += 10.0;
                    if ($('.delivery-slide').is(':visible')) {
                        App.fireDatalayerEvent('account-submit-post-c', _config.controller + '/' + _config.action, document.title);
                        $scope.obj.delvieryObj.dynamicPostCode(function () {
                            $currentSlide.addClass('hide');
                            $currentSlide.next('.delivery-slide').removeClass('hide').slideDown(200);
                        });
                    } else {
                        $currentSlide.addClass('hide');
                        $currentSlide.next('.delivery-slide').removeClass('hide').slideDown(200);
                    }
                    App.scrollTo('.delivery-slide', 300);
                }
            };
            $scope.obj.nextInfoSLideCounter = 0;
            $scope.obj.nextInfoSLide = function () {
                var $currentSlide = $('.info-slide:visible');
                var isLastSlide = $currentSlide.next('.info-slide.hide').length === 0;
                var $form = $('#frmInfoSlide');
                App.resetFormError('#frmInfoSlide');
                var isCurrentSlideValid = $currentSlide.find('input[name], select[name]').valid();
                if (isCurrentSlideValid && isLastSlide) { //submit info and save to DB
                    if (!$form.valid()) return;
                    App.fireDatalayerEvent('account-submit-agree-c', 'account/register', document.title);
                    $scope.obj.progressPerc += 5.0;
                    App.loader.showLoader();
                    var formData = new FormData(document.getElementById('frmInfoSlide'));
                    $scope.obj.isUploading = true;
                    $.ajax({
                        url: $form.attr('action'),
                        type: "POST",
                        data: formData,
                        processData: false,
                        contentType: false,
                        dataType: "json",
                        success: function success(d) {
                            App.fireDatalayerEvent('submit-account-register-registryinfo', 'account/register', document.title);
                            $timeout(function () {
                                $scope.obj.isUploading = false;
                                if (d.status === 1) {
                                    $('#MVCProductID').val(d.id);
                                    $('#infoSlide').addClass('hide');
                                    $('#deliverySlide').removeClass('hide').slideDown();
                                    App.scrollTo('#deliverySlide', 300);
                                    App.loader.hideLoader();
                                } else {
                                    if (d.message.toLowerCase().indexOf('already exists') > -1) {
                                        var errTpl = _config.emailAccountErr;
                                        App.notify.Danger(errTpl);
                                        $('.lnk-use-other-email').click(function (e) {
                                            e.preventDefault();
                                            $('#frmInfoSlide .info-slide:visible').addClass('hide');
                                            $('#frmInfoSlide .info-slide:eq(1)').removeClass('hide');
                                            $('[data-notify]').remove();
                                            $('#MemberInfo_Email').focus().select();
                                        });
                                    } else App.notify.Danger(d.message);
                                    App.loader.hideLoader();
                                }
                            });
                        },
                        error: function error() {
                            App.loader.hideLoader();
                        }
                    });
                } else if (isCurrentSlideValid) { // go next
                    var dataLayerKey = $scope.obj.nextInfoSLideCounter == 1 ? 'account-submit-secureacc-c' : $scope.obj.nextInfoSLideCounter == 2 ? 'account-submit-gender-c' : $scope.obj.nextInfoSLideCounter == 3 ? 'account-submit-bday-c' : $scope.obj.nextInfoSLideCounter == 4 ? 'account-submit-agree-c)' : 'account-submit-name-c';
                    $scope.obj.nextInfoSLideCounter++;
                    App.fireDatalayerEvent(dataLayerKey, _config.controller + '/' + _config.action, document.title);
                    $currentSlide.addClass('hide');
                    $currentSlide.next('.info-slide').removeClass('hide').slideDown(200);
                    $scope.obj.progressPerc += $scope.obj.progressPerc > 0 ? 5.0 : 15.0;
                    angular.element(function () {
                        App.scrollTo('.info-slide:visible', 300);
                    });
                }
            };
            $scope.obj.showTab = function (selector) {
                var $tab = $(selector);
                $tab.tab('show');
                $('html, body').animate({
                    scrollTop: $tab.offset().top
                }, 500);
            };
            $scope.obj.addPhotoBox = function () {
                if ($scope.obj.hasPhoto) return;
                $scope.obj.currentAvatar = $('.photo-holder:eq(0)').data('img');
                $('#flePic').click();
            };
            $scope.obj.addPhoto = function () {
                $scope.obj.currentAvatar = $('.photo-holder:eq(0)').data('img');
                $('#flePic').click();
            };
            $scope.obj.deletePhoto = function () {
                $('.photo-holder:eq(0)').data("img", '');
                $('.photo-holder').css('background-image', 'none');
                $("#flePic").val('');
                $("#hdnFileName").val('');
                $scope.obj.uploadedPic = '';
                $scope.obj.hasPhoto = false;
            };
            var clearRotation = function clearRotation() {
                $('.photo-holder:eq(0)').removeClass('rotate-90').removeClass('rotate-180').removeClass('rotate-270'); // remove rotation
                $('#hdnRotate').val('');
            };
            $scope.obj.rotateElement = function (selector, deg) {
                var className = '';
                var $obj = $(selector);
                var $hdn = $('#hdnRotate');
                var current = parseInt($hdn.val());
                if (!current || current == null || isNaN(current)) current = 0;
                current += deg;
                if (current == 360 || current == -360) {
                    current = 0;
                    $hdn.val(0);
                }
                switch (current) {
                    case -270:
                    case 90:
                        className = 'rotate-90';
                        break;
                    case -180:
                    case 180:
                        className = 'rotate-180';
                        break;
                    case -90:
                    case 270:
                        className = 'rotate-270';
                        break;
                }
                $hdn.val(current);
                $obj.removeClass('rotate-90').removeClass('rotate-180').removeClass('rotate-270').addClass(className);
            };
            $scope.obj.skipToHome = function () {
                App.loader.showLoader();
                window.location = "/";
            };
            $scope.obj.goToNextDelivery = function () { //$scope.obj.setIdState();
                $('#divSuccessInfo').addClass('hide');
                $('[href="#delivery"]').click();
                $timeout(function () {
                    $('#frmInfo').show();
                }, 200);
            };
            $scope.obj.setSocial = function (u) {
                App.loader.showLoader();
                window.location = u;
            }; //#region share section
            $scope.obj.getShareStatus = function (s) {
                if (s.Status == null) s.Status = 0;
                return _.find(_config.shareStatus, function (x) {
                    return x.key == s.Status;
                });
            };
            $scope.obj.shareFb = function () {
                var uri = _config.shareToFbUri + '&message=' + encodeURIComponent($scope.obj.shareMessage);
                App.loader.showLoader();
                App.fbFeedDialog(_config.linkToShare, function () {
                    $http.post(uri).then(function (res) {
                        if (res.status == 200) {
                            if (res.data.status == 1) {
                                App.notify.Success(_config.successTxt);
                                $scope.obj.shareMessage = null;
                                return;
                            } else App.notify.Warning(res.data.message);
                            App.loader.hideLoader();
                        }
                    });
                });
            };
            $scope.obj.removeFriend = function (s) {
                var uri = _config.unsubUri + '&id=' + s.Guid;
                App.loader.showLoader();
                $http.post(uri).then(function (res) {
                    if (res.status == 200) {
                        if (res.data.status == 1) {
                            App.notify.Success(_config.successTxt);
                            $scope.obj.sharedToFriends = _.reject($scope.obj.sharedToFriends, function (x) {
                                return x.Id == s.Id;
                            });
                        } else App.notify.Danger(res.data.message);
                        App.loader.hideLoader();
                    }
                });
            };
            $scope.obj.resendEmail = function (s) {
                var email = prompt('Please enter email');
                if (email == null || email.length == 0) return;
                if (!isStringEmail(email)) return;
                App.loader.showLoader();
                var uri = _config.resendEmailUri + "?id=" + s.Id + '&e=' + encodeURIComponent(email);
                $http.post(uri).then(function (res) {
                    if (res.status == 200) {
                        if (res.data.status == 1) App.notify.Success(_config.successTxt);
                        else App.notify.Danger(res.data.message);
                        App.loader.hideLoader();
                    }
                });
            };
            $scope.obj.showPreview = function () { // cleanup
                $('#contentDiv').remove();
                var iframe = document.getElementById('re_contentIframe');
                iframe.src = _config.frameUri + "/" + _config.boxId + "?body=" + encodeURIComponent($('#EmailBody').val());
                App.loader.showLoader();
                iframe.onload = function () {
                    App.loader.hideLoader(); // adjust iframe height
                    var frame = iframe.contentWindow ? iframe.contentWindow : iframe.contentDocument.document ? iframe.contentDocument.document : iframe.contentDocument;
                    var height = Math.max(frame.document.documentElement.clientHeight, frame.document.documentElement.scrollHeight, frame.document.documentElement.offsetHeight);
                    document.getElementById('re_contentIframe').style.height = /*height + */ '500px'; // show modal
                    $('#modalEmailBody').modal();
                };
            };

            function hideEmailErr() {
                $('#err_recipientsList').addClass('hide');
            }

            function isStringEmail(email) {
                var pattern = new RegExp(/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i);
                return pattern.test(email);
            } //#endregion
            var resendEmail = function resendEmail() {
                App.loader.showLoader();
                $.post(_config.resendEmailUri, function (d) {
                    if (d.status == 1) {
                        App.notify.Success(_config.uploadSuccessTxt);
                    }
                    App.loader.hideLoader();
                });
            }; //#region Post code lookup func
            $scope.obj.delvieryObj.dynamicFields = _config.deliveryObj.dynamicFields;
            $scope.obj.delvieryObj.marketSelected = _config.deliveryObj.market;
            $scope.obj.delvieryObj.nameSpace = _config.deliveryObj.nameSpace;
            $scope.obj.delvieryObj.showCountryOption = _config.deliveryObj.showCountryOption;
            $scope.obj.delvieryObj.hasPostcodeLookup = _config.deliveryObj.hasPostcodeLookup;
            $scope.obj.delvieryObj.userState = _config.deliveryObj.state;
            $scope.obj.delvieryObj.stateList = _config.deliveryObj.stateList;
            $scope.obj.delvieryObj.userSuburb = _config.deliveryObj.indoDistrict;
            $scope.obj.delvieryObj.userAddress2 = _config.deliveryObj.indoSubDistrict;
            $scope.obj.delvieryObj.hasDynamicSuburb = function () {
                return _.filter(_config.deliveryObj.dynamicSuburbCountries, function (x) {
                    return x == $scope.obj.delvieryObj.marketSelected;
                }).length > 0;
            };
            $scope.obj.delvieryObj.hasLookupData = function () {
                return !$.isEmptyObject($scope.obj.delvieryObj.lookupData);
            };
            $scope.obj.delvieryObj.hasReturnedLookup = false;
            $scope.obj.delvieryObj.postcodeAreaListing = [];
            $scope.obj.delvieryObj.suburbFiltered = function () {
                if (!$scope.obj.delvieryObj.dynamicFields.hasNoPost || $scope.obj.delvieryObj.userState == null) return $scope.obj.delvieryObj.suburbList;
                return _.filter($scope.obj.delvieryObj.suburbList, function (s) {
                    return $scope.obj.delvieryObj.userState == s.state;
                });
            };
            $scope.obj.delvieryObj.canShowInput = function () {
                return !$scope.obj.delvieryObj.hasGlobalLookup || $scope.obj.delvieryObj.hasGlobalLookup && $scope.obj.delvieryObj.hasReturnedLookup;
            };
            $scope.obj.delvieryObj.dynamicPostCode = function (callback) { //if (!$scope.obj.delvieryObj.hasGlobalLookup || !!!$scope.obj.delvieryObj.userPostCode || $.trim($scope.obj.delvieryObj.userPostCode).length < 2) return;
                App.loader.showLoader();
                $http.post(_config.deliveryObj.getDynamicPcListUri, $.param({
                    code: $scope.obj.delvieryObj.userPostCode,
                    country: $scope.obj.delvieryObj.marketSelected
                })).then(function (d) {
                    if (d.status === 200) { //success
                        $scope.obj.delvieryObj.hasReturnedLookup = true;
                        $('#btnRegisterDelivery').removeClass('hide');
                        var data = d.data;
                        if (data.status === 0) {
                            $scope.obj.delvieryObj.lookupData = {};
                            $scope.obj.delvieryObj.stateList = data.states;
                            $scope.obj.delvieryObj.suburbList = [];
                            $scope.obj.delvieryObj.address3List = [];
                            $scope.obj.delvieryObj.address4List = [];
                            clearLookup();
                            App.loader.hideLoader();
                            angular.element(function () {
                                unitOfWork.util.resetFormError("#frmDeliverySlide");
                                unitOfWork.util.formValidateReset("#frmDeliverySlide");
                                if (callback) callback();
                            });
                            return;
                        }
                        $scope.obj.delvieryObj.lookupData = data;
                        $scope.obj.delvieryObj.setLookupData(data);
                        angular.element(function () {
                            if (callback) callback();
                        });
                    }
                    App.loader.hideLoader();
                }, function () {
                    App.loader.hideLoader();
                });
            };

            function clearLookup() {
                $scope.obj.delvieryObj.userSuburb = null;
                $scope.obj.delvieryObj.userState = null;
                $scope.obj.delvieryObj.userAddress3 = null;
                $scope.obj.delvieryObj.userAddress4 = null;
                $scope.obj.delvieryObj.userStateName = null;
            }
            var returnLocation = function returnLocation(x) {
                return {
                    state: x.State,
                    text: (x.Eng || '') + ($.trim(x.Local || '').length > 0 && $.trim(x.Eng || '').length > 0 ? '-' : '') + (x.Local || ''),
                    val: $.trim(x.Eng || '').length > 0 ? x.Eng : x.Local
                };
            };
            var firstOrDefault = function firstOrDefault(x, k) {
                if (!!!x || x == null || x.length == 0) return null;
                return x[0][k];
            };
            $scope.obj.delvieryObj.setLookupData = function (data) {
                clearLookup();
                $scope.obj.delvieryObj.stateList = data.States;
                $scope.obj.delvieryObj.suburbList = _.map(data.Suburbs, returnLocation); //_.pluck(data.Suburbs, 'Eng');
                $scope.obj.delvieryObj.address3List = _.map(data.Address3s, returnLocation); //_.pluck(data.Address3s, 'Eng');
                $scope.obj.delvieryObj.address4List = _.map(data.Address4s, returnLocation); //_.pluck(data.Address4s, 'Eng');
                if ($scope.obj.delvieryObj.stateList.length === 1) {
                    $scope.obj.delvieryObj.userState = $scope.obj.delvieryObj.stateList[0].State;
                    $scope.obj.delvieryObj.userStateName = $scope.obj.delvieryObj.stateList[0].Name;
                }
                if ($scope.obj.delvieryObj.suburbList.length <= 1) $scope.obj.delvieryObj.userSuburb = firstOrDefault($scope.obj.delvieryObj.suburbList, 'text');
                if ($scope.obj.delvieryObj.address3List.length <= 1) $scope.obj.delvieryObj.userAddress3 = firstOrDefault($scope.obj.delvieryObj.address3List, 'text');
                if ($scope.obj.delvieryObj.address4List.length <= 1) $scope.obj.delvieryObj.userAddress4 = firstOrDefault($scope.obj.delvieryObj.address4List, 'text');
                angular.element(function () {
                    unitOfWork.util.resetFormError("#frmDeliverySlide");
                    unitOfWork.util.formValidateReset("#frmDeliverySlide");
                });
            }; //#endregion
            angular.element(function () { //#region Post Lookup
                $scope.obj.delvieryObj.userPostCode = _config.deliveryObj.userPostCode;
                $scope.obj.delvieryObj.userSuburb = _config.deliveryObj.userSuburb; // assign district
                $scope.obj.delvieryObj.userAddress2 = _config.deliveryObj.subDistrict; // assign subdistrict
                $scope.obj.delvieryObj.userAddress3 = _config.deliveryObj.area; // assign area
                if ($scope.obj.delvieryObj.dynamicFields.hasNoPost) // immediately load details for no postcode with global address
                    $scope.obj.delvieryObj.dynamicPostCode(); //#endregion
                // add asterisk on required label fields
                $('[data-val-required]').parents('.form-group').find('label[for]:eq(0)').addClass('required');
                $('[href="#collapse-tab_new1"] .count').text($('#regTab li[role="presentation"]').length);
                $('[href="#collapse-tab_new1"] .count').removeClass('hide'); // set all email resend buttons
                $('.btn-resend-email-validation').click(function () {
                    resendEmail();
                });
                $('#cmn-toggle-fb, #cmn-toggle-ig').click(function (e) {
                    e.preventDefault();
                    App.fireDatalayerEvent('account-submit-socials-c', _config.controller + '/' + _config.action, document.title);
                    var lnk = $(this).attr('href');
                    window.location = lnk;
                });
                $('#lnkShareEmail').on('click', function (e) {
                    e.preventDefault();
                    $('#lnkShareEmail i,#lnkShareFb i').removeClass('active');
                    $('#divShareFb').addClass('hidden');
                    $('#divShareEmail').removeClass('hidden');
                    $('#lnkShareEmail i').addClass('active');
                    $('.circle_v2.circle-purple-hover').removeClass('active');
                    $(this).addClass('active');
                    App.scrollTo('#divShareEmail', 1000);
                });
                $('#lnkShareFb').on('click', function (e) {
                    e.preventDefault();
                    $('#lnkShareEmail i,#lnkShareFb i').removeClass('active');
                    $('#divShareEmail').addClass('hidden');
                    $('#divShareFb').removeClass('hidden');
                    $('#lnkShareFb i').addClass('active');
                    $('.circle_v2.circle-purple-hover').removeClass('active');
                    $(this).addClass('active');
                    App.scrollTo('#divShareFb', 1000);
                });
                $('#txtFbMessage').on("focus keyup", function (e) {
                    var keycode = e.keyCode ? e.keyCode : e.which ? e.which : e.charCode;
                    if (keycode === 9 || !keycode) { // select
                        var $this = $(this);
                        $this.select(); // For Chrome's bug
                        $this.on("mouseup", function () { // Unbindl mouseup
                            $this.off("mouseup");
                            return false;
                        });
                    }
                }); //#region Validator Reset
                $.validator.addMethod('passwordpattern', function (value, element) {
                    var valid = false;
                    var $element = $(element);
                    if ($element.attr('id') == 'MemberInfo_Password') {
                        var regPass = App.passwordRegex();
                        valid = regPass.test(value);
                    }
                    return valid && value != null;
                });
                $.validator.addMethod('requiredutf8', function (value, element) {
                    var valid = false;
                    var $element = $(element);
                    if ($element.attr('id') == 'MemberInfo_FirstName' || $element.attr('id') == 'MemberInfo_LastName') {
                        var regUtf8 = new XRegExp('^(\\p{L}|[\\-0-9]){1,}(\\p{L}|[\\-0-9]|\\s){0,}$');
                        valid = regUtf8.test(value);
                    }
                    return valid && value != null;
                });
                $.validator.unobtrusive.adapters.add("mandatory", function (options) {
                    options.rules["required"] = true;
                    if (options.message) {
                        options.messages["required"] = options.message;
                    }
                });
                $.validator.unobtrusive.adapters.addBool("requiredutf8", "requiredutf8");
                $.validator.unobtrusive.adapters.addBool("mandatory", "required");
                $.validator.unobtrusive.adapters.add("checkbox", function (options) {
                    if (options.element.tagName.toUpperCase() === "INPUT" && options.element.type.toUpperCase() === "CHECKBOX") {
                        options.rules["required"] = true;
                        if ($.trim(options.message).length == 0) {
                            options.messages["required"] = $(options.element).attr('id') == "MemberInfo_Agree" ? _config.agreementText : _config.plsSpecifyText; //options.message;
                        }
                    }
                });
                App.formValidateReset('#frmInfoSlide');
                App.formValidateReset('#frmDeliverySlide');
                App.formValidateReset('#frmShare'); //#endregion
                $('#MemberInfo_State').change(function () {
                    var val = $(this).val();
                    $('#drpState').val(val);
                });
                $('#frmAvatar').submit(function (e) {
                    e.preventDefault();
                    App.loader.showLoader();
                    var formData = new FormData(document.getElementById('frmAvatar'));
                    if ($('#flePic').val().length > 0) formData.append('file', App.dataURItoBlob($('.photo-holder:eq(0)').data('img')));
                    formData.append('name', $('#hdnFileName').val());
                    formData.append('rotation', $('#hdnRotate').val());
                    $scope.obj.isUploading = true;
                    $.ajax({
                        xhr: function xhr() {
                            var xhr = new window.XMLHttpRequest();
                            xhr.upload.addEventListener("progress", function (evt) {
                                if (evt.lengthComputable) {
                                    var percentComplete = evt.loaded / evt.total;
                                    percentComplete = parseInt(percentComplete * 100);
                                    console.log(percentComplete);
                                    $('.upload-progress-box').show();
                                    $('.upload-progress-box .upload-progress').css('width', percentComplete + '%');
                                    if (percentComplete === 100) {
                                        $('.upload-progress-box').hide();
                                        $('.upload-progress-box .upload-progress').css('width', '0px');
                                    }
                                }
                            }, false);
                            return xhr;
                        },
                        url: $(this).attr('action'),
                        type: "POST",
                        data: formData,
                        processData: false,
                        contentType: false,
                        dataType: "json",
                        success: function success(d) {
                            $scope.obj.isUploading = false;
                            $('.upload-progress-box .upload-progress').css('width', '');
                            if (d.status == 1) {
                                if ($('#flePic').val().length > 0) $('#main_menu .username + img.round-user-image100').attr('src', $('.photo-holder:eq(0)').data('img'));
                                else $('#main_menu .username + img.round-user-image100').removeAttr('src');
                                $("#flePic").val('');
                                $("#hdnFileName").val('');
                                $scope.obj.uploadedPic = null;
                                $scope.obj.hasPhoto = false;
                                $('#btnAddPhoto').hide();
                                App.inlineSuccessAlert('#frmAvatar .circle_v2:eq(0)', _config.uploadSuccessTxt, App.placement.after);
                                $scope.$apply();
                                clearRotation();
                            } else {
                                App.notify.Danger(d.message);
                            }
                            App.loader.hideLoader();
                        },
                        error: function error() {
                            App.loader.hideLoader();
                        }
                    });
                });
                $("#flePic").change(function () {
                    if (this.files && this.files[0]) {
                        var reader = new FileReader();
                        var frag = this.files[0].name.split('.');
                        var ext = frag[frag.length - 1];
                        App.loader.showLoader();
                        reader.onload = function (e) {
                            var scaled = App.resizeImage(e.target.result, ext == 'jpg' ? 'jpeg' : ext, 200);
                            var image = scaled == 'data:,' ? e.target.result : scaled;
                            App.loader.hideLoader();
                            $scope.obj.hasPhoto = true;
                            $scope.$apply();
                            angular.element(function () {
                                clearRotation();
                                $('.photo-holder:eq(0)').data('img', image);
                                $('.photo-holder:eq(0)').css('background-image', 'url(' + image + ')'); //immediately open modal to upload
                                $('[data-click-continue="App.Account.Register.submitPhoto"]').click();
                            });
                        };
                        reader.readAsDataURL(this.files[0]);
                        $("#hdnFileName").val(this.files[0].name);
                    }
                }); // password toggle
                $('.pass-text-toggle').click(function () {
                    var $icon = $(this).find('i');
                    var isHidden = $icon.hasClass('fa-eye-slash');
                    if (isHidden) { // unhide password
                        $icon.removeClass('fa-eye-slash');
                        $icon.addClass('fa-eye');
                        $('#MemberInfo_Password').attr('type', 'text');
                        $('#MemberInfo_ConfirmPassword').attr('type', 'text');
                        return;
                    }
                    $icon.removeClass('fa-eye');
                    $icon.addClass('fa-eye-slash');
                    $('#MemberInfo_Password').attr('type', 'password');
                    $('#MemberInfo_ConfirmPassword').attr('type', 'password');
                });
                App.passwordNotice('#MemberInfo_Password', '#passNotice'); // show error if exists
                if ($('#lnkWarning').length > 0) $('#lnkWarning').click(); // tab selection on load
                if (_config.isLoggedIn) {
                    if (!_config.userState || $.trim(_config.userState).length == 0) { // insert complete pixel
                        if ($.trim(_config.src).length > 0) {
                            var pxReg = App.readCookie(_config.pxRegister + _config.src);
                            if (pxReg == null || $.trim(pxReg).length == 0) {
                                var px = $('#complete_' + _config.src).val();
                                $('body').append(px);
                                App.createCookie(_config.pxRegister + _config.src, App.guid(), 1);
                            }
                        }
                        return;
                    }
                } // clear style from survey
                if ($('.text-center-xs-right-md').length > 0) {
                    $('#aboutSlide p.body-font.txt-left').addClass('text-center').removeClass('txt-left');
                    $('#aboutSlide .heading-font-h6').addClass('margin-b30');
                    $('.text-center-xs-right-md').addClass('text-center').removeClass('text-center-xs-right');
                    $('.question-container').removeClass('layout-wrapper');
                    $('#aboutSlide>div.cp-elements-wrapper>div').removeClass('margin-t40');
                }
                if (_config.fromSocialConnect) {
                    $('#introSlide').addClass('hide');
                    $('#socialSlide').removeClass('hide');
                    $scope.$apply(function () {
                        $scope.obj.progressPerc = 90.0;
                    });
                }
            });
        }]);
    };
    var submitPhoto = function submitPhoto() {
        $('#frmAvatar').submit();
    };
    return {
        init: init,
        submitPhoto: submitPhoto
    };
})();

App.Account.Login = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);
        }
        App.angular.controller('MainController', ['$scope', '$http', function ($scope, $http) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};
            $scope.email = _config.email;
            angular.element(function () {
                $('.pass-text-toggle').click(function () {
                    var $icon = $(this).find('i');
                    var isHidden = $icon.hasClass('fa-eye-slash');
                    if (isHidden) { // unhide password
                        $icon.removeClass('fa-eye-slash');
                        $icon.addClass('fa-eye');
                        $('#Password').attr('type', 'text');
                        return;
                    }
                    $icon.removeClass('fa-eye');
                    $icon.addClass('fa-eye-slash');
                    $('#Password').attr('type', 'password');
                });
                $("#frmLogin :input").each(function () {
                    if ($(this).attr("name")) {
                        if ($(this).val().length > 0) {
                            $(this).parent().addClass('has-value');
                        } else {
                            $(this).parent().removeClass('has-value');
                        }
                    }
                });
                $('#lnkGoBack').on('click', function () {
                    window.history.back();
                });
                $('#IsPersist').on('click', function () {
                    $(this).val($(this).is(':checked'));
                });
                $('#btnEmail').click(function () {
                    $('.login-inputs').hide().removeClass('hide');
                    $('.login-inputs').slideDown();
                    $(this).parent().remove();
                    $([document.documentElement, document.body]).animate({
                        scrollTop: $("#welcomeHome").offset().top
                    }, 1000);
                });
                if (!_config.email.isNullOrEmpty()) {
                    $('.login-inputs').hide().removeClass('hide');
                    $('.login-inputs').slideDown();
                    $('#btnEmail').parent().remove();
                }
            });
        }]);
        (function (l) {
            var i, s = {
                touchend: function touchend() {}
            };
            for (i in s) l.addEventListener(i, s);
        })(document); // sticky hover fix in iOS
    };
    return {
        init: init
    };
})();

App.Account.DeleteAccount = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config == 'object') {
            $.extend(true, _config, config);
        }

        App.angular.controller('MainController', ['$scope', '$http', function ($scope, $http) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};
            angular.element(function () {
                $('#frmDelete').submit(function (e) {
                    e.preventDefault();
                    var $form = $(this);
                    if (!$form.valid()) {
                        return;
                    }
                    App.loader.showLoader();
                    $.post($form.attr('action'), $form.serialize(), function (d) {
                        if (d.status == 1) {
                            window.location = './../';
                        } else App.loader.hideLoader();
                    });
                });
            });
        }]);
    };
    return {
        init: init
    };
})();

App.Account.ForgotPassword = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config == 'object') {
            $.extend(true, _config, config);
        }
        App.angular.controller('MainController', ['$scope', '$http', function ($scope, $http) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};
            $(function () {
                $('#lnkGoBack').on('click', function () {
                    window.history.back();
                });
                setTimeout(function () {
                    $('#Email').val('');
                }, 300);
            });
        }]);
    };
    return {
        init: init
    };
})();

App.Account.ResetPassword = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config == 'object') {
            $.extend(true, _config, config);
        }
        App.angular.controller('MainController', ['$scope', '$http', function ($scope, $http) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};
            angular.element(function () {
                var form = $("#frmReset");
                form.removeData('validator');
                form.removeData('unobtrusiveValidation');
                $.validator.unobtrusive.adapters.addBool("mandatory", "required");
                $.validator.unobtrusive.adapters.addBool("passwordpattern", "passwordpattern");
                $.validator.addMethod('passwordpattern', function (value, element) {
                    var valid = false;
                    var $element = $(element);
                    if ($element.attr('id') == 'Password') {
                        var regPass = App.passwordRegex();
                        valid = regPass.test(value);
                    }
                    return valid && value != null;
                });
                $.validator.unobtrusive.parse(form);
                App.passwordNotice('#Password', '#passNotice', {
                    good: '#0edb73',
                    bad: 'white'
                });
                $('.pass-text-toggle').click(function () {
                    var $icon = $(this).find('i');
                    var isHidden = $icon.hasClass('fa-eye-slash');
                    if (isHidden) { // unhide password
                        $icon.removeClass('fa-eye-slash');
                        $icon.addClass('fa-eye');
                        $('#Password,#ConfirmPassword').attr('type', 'text');
                        return;
                    }
                    $icon.removeClass('fa-eye');
                    $icon.addClass('fa-eye-slash');
                    $('#Password,#ConfirmPassword').attr('type', 'password');
                });

                if (!_config.error.isNullOrEmpty()) App.notify.Danger(_config.error);
            });
        }]);
    };
    return {
        init: init
    };
})();;
if (typeof App === 'undefined') var App = {};

App.ActivityFeed = function () { return {} }();
App.ActivityFeed.Index = function () {
    var _config = {};
    var init = function (config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);
        }

        App.angular.controller('MainController', function ($scope, $http, $compile) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};

            angular.element(function () {
                function appendToTabletSection(id) {
                    var c = $('#' + id).clone();
                    c.attr('id', c.attr('id') + '_t');
                    $('#tabletSection').append(c);
                }

                ['recentlyAdded', 'categoryProds', 'trendingProds', 'recommendedProds', 'htProds'].forEach((o, i) => {
                    appendToTabletSection(o);
                })

                $('#recentlyAdded,#categoryProds,#trendingProds,#recommendedProds,#htProds,#recentlyAdded_t,#categoryProds_t,#trendingProds_t,#recommendedProds_t,#htProds_t')
                    .find('.js-star-rating').makeStars();

                // add scripts here
                //custom carousel
                $('.responsive-slider').slick({
                    dots: false,
                    infinite: false,
                    speed: 300,
                    slidesToShow: 2,
                    slidesToScroll: 2,
                    responsive: [
                        //{
                        //    breakpoint: 1080,
                        //    settings: {
                        //        slidesToShow: 3,
                        //        slidesToScroll: 3,
                        //        infinite: true,
                        //        dots: true
                        //    }
                        //},
                        {
                            breakpoint: 920,
                            settings: {
                                slidesToShow: 2,
                                slidesToScroll: 2
                            }
                        },
                        {
                            breakpoint: 700,
                            settings: {
                                slidesToShow: 1,
                                slidesToScroll: 1
                            }
                        }
                        // You can unslick at a given breakpoint now by adding:
                        // settings: "unslick"
                        // instead of a settings object
                    ]
                });


            });

        });



    };


    return { init: init };
}();

App.ActivityFeed._UserActivityFeed = function () {
    var _config = { 'markets': '', 'mobileSize': 400 };

    var init = function (config) {
        if (config && typeof (config) === 'object') {
            $.extend(true, _config, config);
        }

        $(function () {
            //custom carousel
            $('.responsive-slider-feed').slick({
                dots: false,
                infinite: false,
                speed: 300,
                slidesToShow: 3,
                slidesToScroll: 3,
                responsive: [
                    //{
                    //    breakpoint: 1080,
                    //    settings: {
                    //        slidesToShow: 3,
                    //        slidesToScroll: 3,
                    //        infinite: true,
                    //        dots: true
                    //    }
                    //},
                    {
                        breakpoint: 920,
                        settings: {
                            slidesToShow: 2,
                            slidesToScroll: 2
                        }
                    },
                    {
                        breakpoint: 700,
                        settings: {
                            slidesToShow: 1,
                            slidesToScroll: 1
                        }
                    }
                    // You can unslick at a given breakpoint now by adding:
                    // settings: "unslick"
                    // instead of a settings object
                ]
            });
        });

        // colorize stars based on product ratings
        $('.js-star-rating').makeStars();

    };

    return {
        init: init
    };

}();

;
'use strict';

if (typeof App === 'undefined') var App = {};

App.Common = (function () {
    return {};
})();

App.Common._Footer = (function () {
    var _config = {
        'markets': ''
    };

    var init = function init(config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);
        }

        // Note: Don't enclose init function in $()
        App.angular.controller('ngFooterController', ['$scope', function ($scope) {
            $scope.markets = _config.markets;

            $scope.firstLang = function (market) {
                return _.first(market.Languages);
            };

            $scope.getUrl = function (language) {
                return ('/' + language.CountryId + '/' + language.Language.substring(0, 2)).toLowerCase();
            };

            $scope.popUpPostToSocial = function (type, message) {
                if (message.length === 0) message = document.title;

                var socialUri = type === 'fb' ? 'http://www.facebook.com/sharer.php?s=100&p[url]=THE_URI' : type === 'tw' ? 'https://twitter.com/intent/tweet?url=THE_URI&text=THE_TEXT' : '';
                var uri = location.href;

                socialUri = socialUri.replace("THE_TEXT", message.trunc(260));
                socialUri = socialUri.replace("THE_URI", encodeURIComponent(uri));
                window.open(socialUri, '', 'menubar=no,toolbar=no,resizable=yes,scrollbars=yes,height=300,width=600');
            };

            // init FB sdk
            angular.element(function () {
                //$.getScript(_config.fbSdkUri, function () {
                //    FB.init({
                //        appId: _config.appId,
                //        version: _config.fbVersion
                //    });
                //});
            });
        }]);

        // footer change country popover
        $("#change-country-link").popover({
            html: true,
            content: function content() {
                return $("#country-popover-content").html();
            },
            title: _config.T_ChangeCountry,
            placement: 'top',
            trigger: 'click' // when using 'focus', clicking links inside the popover doesn't work
        });

        $('#scrollTopBtn').on('click', function () {
            $("html, body").animate({
                "scrollTop": "0px"
            }, 300);
        });

        $('.review-notification .close').on('click', function () {
            $(this).closest('.review-notification').removeClass('bounceInUp').addClass('bounceOutDown');
            if (typeof App.notifDisplayTimeoutId !== 'undefined') {
                clearTimeout(App.notifDisplayTimeoutId);
            }
            // to show back notification: $('.review-notification').removeClass('bounceOutDown').addClass('bounceInUp');
        });
    };

    return {
        init: init
    };
})();

App.Common._Menu = (function () {
    var _config = {
        'userMenuName': 'My Dashboard',
        'dashboardUrl': '#',
        'notificationUpdateReadUrl': ''
    };

    var init = function init(config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);
        }
        var notifCount = $('#user-menu-popover-content').find('li[data-notified="0"]').length;
        if (notifCount > 0) {
            $('.user-menu-link').find('span.badge').text(notifCount);
        } else {
            $('.user-menu-link').find('span.badge').hide();
        }

        var $popover = $("nav .user-menu-link").popover({
            html: true,
            content: function content() {
                return $("#tplNotice").clone().html();
            },
            title: '<a class="link-white" href="' + _config.dashboardUrl + '">' + _config.userMenuName + '</a>',
            placement: 'bottom',
            trigger: 'click' // when using 'focus', clicking links inside the popover doesn't work
        });

        $popover.on('shown.bs.popover', function () {
            //$('#myTabNotice [data-toggle="tab"]').click(function () {
            //    $('#tabNoticeContent [role="tabpanel"]').removeClass('active');
            //    console.log($(this).attr('href'))
            //    var $target = $($(this).attr('href'));
            //    $target.addClass('active');
            //})
        });

        $("nav .user-menu-link").on('click', function () {
            // update notifications to read
            $.get(_config.notificationUpdateReadUrl, function () {});
            // count down notification count
            var $notifBadge = $('.user-menu-link').find('span.badge');
            var interval = setInterval(function () {
                var notifCount = $notifBadge.html();
                var counter = parseInt(notifCount);
                var decrement = counter > 100 ? 50 : counter > 20 ? 10 : counter > 10 ? 3 : counter > 4 ? 2 : 1;

                counter -= decrement;
                if (counter <= 0) {
                    $notifBadge.hide();
                    return clearInterval(interval);
                }
                $notifBadge.html(counter);
            }, 150);
        });

        // Check error on user image
        $('img.round-user-image40').each(function () {
            if (!this.complete || typeof this.naturalWidth === "undefined" || this.naturalWidth === 0) {
                // image was broken, replace with your new image
                App.avatarOnError(this, $(this).data('fname'));
            }
        });

        $('#divCloseEmailRibbon').click(function () {
            $(this).parent().parent().parent().remove();
            App.createCookie(resendCookie, 'sent', 0.041666); // don't show ribbon again for the next hour
        });

        var resendCookie = 'resendEmailCookie';
        var validateDelayCookie = 'ValidateDelay';
        $('#btnResendValidate').click(function () {
            App.loader.showLoader();
            $.post(_config.resendUrl, function (d) {
                if (d.status === 1) {
                    $('#resendEmailValidationMessageIcon').removeClass('hide');
                    $('#resendEmailValidationMessage').text(_config.T_ResendActivationMessage);
                    $('#btnResendValidate').addClass('hide');
                    // create a 1 week cookie to hide the notice
                    App.createCookie(resendCookie, 'sent', 7);
                    setTimeout(function () {
                        $('#nagRibbonEmail').fadeOut();
                    }, 3 * 1000);
                }

                App.loader.hideLoader();
            });
        });

        var confirmEmailCookie = 'confirmEmailCookie';
        $('#btnConfirmEMailYes').click(function () {
            App.loader.showLoader();
            $.post(_config.confirmEmailUrl, function (d) {
                if (d.status === 1) {
                    $('#icoConfirmEMailYes').removeClass('hide');
                    $('#btnConfirmEMailYes,#btnConfirmEMailNo').addClass('hide');
                    // create a 1 week cookie to hide the notice
                    App.createCookie(confirmEmailCookie, 'sent', 7);
                    setTimeout(function () {
                        $('#nagConfirmEmail').fadeOut();
                    }, 3 * 1000);
                }

                App.loader.hideLoader();
            });
        });

        $('#divCloseConfirmRibbon').click(function () {
            $(this).parent().parent().parent().remove();
            App.createCookie(confirmEmailCookie, 'sent', 0.041666); // don't show ribbon again for the next hour
        });

        $('#open-nav').click(function (e) {
            e.preventDefault();
            document.getElementById("mySidenav").style.width = "100%";
        });

        $('#close-nav').click(function (e) {
            e.preventDefault();
            document.getElementById("mySidenav").style.width = "0";
        });

        $('.review-link:not(.external-link)').click(function () {
            window.location = $(this).attr('href');
        });

        $('#btnClosePrivacy').on('click', function () {
            App.createCookie(_config.pvcyCookie, App.guid(), 9999);
            $('#nagRibbonPrivacy').remove();
        });

        var showPrivacyNag = !App.readCookie(_config.pvcyCookie);
        if (showPrivacyNag) $('#nagRibbonPrivacy').removeClass('hide');

        var showBounceEmailConfirmation = !App.readCookie(confirmEmailCookie) && $('#nagConfirmEmail').length > 0;
        var showEmailValidationRibbon = !showBounceEmailConfirmation && !App.readCookie(validateDelayCookie) && !App.readCookie(resendCookie) && $('#nagRibbonEmail').length > 0;

        // cookie expired and ribbon nag is available
        if (showEmailValidationRibbon) $('#nagRibbonEmail').removeClass('hide');

        // cookie expired and confirm email nag is available
        if (showBounceEmailConfirmation) $('#nagConfirmEmail').removeClass('hide');

        // header search function
        // if search text have value, expand it
        var searchInput = $("#custom-search .search-query");
        if (searchInput.val() !== '') searchInput.focus();

        $("#custom-search").click(function () {
            $("#custom-search .search-query").focus();
        });

        $("#custom-search button").click(function (e) {
            e.preventDefault();
            var inp = $("#custom-search .search-query");
            if (inp.val() !== '') {
                window.location = _config.searchUrl + '?product=' + inp.val();
                return;
            }

            setTimeout(function () {
                inp.addClass('focus');
            }, 100);
        });

        var $navSearchBox = $('#custom-search input');
        $navSearchBox.on('focus', function (e) {
            $(this).addClass('focus');
        });

        $navSearchBox.on('blur', function () {
            if ($.trim($(this).val()).length > 0) {
                $('.search-result-suggestion').show();
                return;
            }

            $navSearchBox.removeClass('focus');
        });

        $(document).on('click', function (e) {
            var target = $(e.target);
            if ($navSearchBox.length > 0) {
                if ($.trim($navSearchBox.val()).length > 0) {
                    $('.search-result-suggestion').show();
                    return;
                }

                if (!target.hasClass('search-query')) $navSearchBox.removeClass('focus');
            }
        });

        $(window).scroll(function () {
            if (!_config.disableSticky) {
                // sticky header
                var $bar = $('.navbar-wrapper:eq(0)');
                var height = $bar.height();
                if ($(this).scrollTop() > height) {
                    $bar.addClass('scroll-header pos-f');
                } else {
                    $bar.removeClass('scroll-header pos-f');
                }
            }
        });

        $(document).keypress(function (e) {
            var inp = $("#custom-search .search-query");
            if (e.which === 13 && inp.is(":focus") && inp.val() !== '') {
                window.location = _config.searchUrl + '?product=' + inp.val();
            }
        });
        // end header section search

        $('#divCloseTncRibbon').click(function (e) {
            var tag = $(this).data('tag');
            var q = $(this).data('q');
            var cookie = App.readCookie(tag);
            if ($.trim(cookie).length == 0) //new cookie
                cookie = q;
            else {
                App.eraseCookie(tag);
                cookie += "," + q;
            }

            App.createCookie(tag, cookie, 999);

            // clear ribbon
            $('#nagNewTnc').fadeOut('fast', function () { $('#nagNewTnc').remove() });
        });
    };

    return {
        init: init
    };
})();

;
'use strict';

if (typeof App == 'undefined') var App = {};

App.Competitions = (function () {
   return {};
})();

App.Competitions.Index = (function () {
   var _config = {};
   var init = function init(config) {
      if (config && typeof config == 'object') {
         $.extend(true, _config, config);
      }

      App.angular.controller('MainController', ['$scope', '$http', function ($scope, $http) {
         $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
         $scope.obj = {};
      }]);

      App.angular.controller('competitionsController', function () {

         // private fields
         var competitions = this;
         var _competitions = _config.competitions;

         $(function () {});

         // public properties
         competitions.competitions = function (newCompetitions) {
            return arguments.length > 0 ? competitions._competitions = newCompetitions : _competitions;
         };
      });
   };

   return {
      init: init
   };
})();;
'use strict';

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } }

if (typeof App == 'undefined') var App = {};

App.Dashboard = (function () {
    return {};
})();
App.Dashboard.Index = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config == 'object') {
            $.extend(true, _config, config);
        }

        App.angular.controller('MainController', ['$scope', '$http', '$sce', '$compile', 'unitOfWork', 'activityService', function ($scope, $http, $sce, $compile, unitOfWork, activityService) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};
            $scope.obj.hasFb = _config.hasFb;
            $scope.obj.hasIg = _config.hasIg;
            $scope.obj.hasTw = _config.hasTw;
            $scope.obj.jsonCompletedSurveyList = _config.jsonCompletedSurveyList;
            $scope.obj.commentList = _config.commentList;
            $scope.obj.questionList = _config.questionList;
            $scope.obj.totalComments = _config.totalComments;
            $scope.obj.commentOffset = 1;
            $scope.obj.uploadedPic = _config.uploadedPic;
            $scope.obj.hasPhoto = false;
            $scope.obj.rotateElement = function (selector, hdnRotate, deg) {
                App.rotateElement(selector, hdnRotate, deg);
            }
            $scope.obj.cleanUpDate = function (d) {
                return d.indexOf('/Date(') > -1 ? new Date(parseFloat(d.replace('/Date(', '').replace(')/', ''))) : new Date(d);
            };
            $scope.obj.hasMoreCompletedSurveys = function () {
                return $scope.obj.jsonCompletedSurveyList.length < _config.totalCompletedSurvey;
            };

            $scope.obj.followPageSize = 6;
            $scope.obj.setFollowPageDisplay = function (dataset) {
                if (dataset && dataset.data) {
                    dataset.maxPage = Math.ceil(dataset.data.length / $scope.obj.followPageSize);

                    dataset.pageNumberDisplay = [];
                    if (dataset.maxPage <= 7 || dataset.pageNumber <= 3) {
                        for (var i = 0; i < dataset.maxPage; i++) {
                            dataset.pageNumberDisplay.push(i);
                        }
                    } else {
                        if (dataset.maxPage - dataset.pageNumber <= 3) {
                            for (var i = dataset.maxPage - 6; i < dataset.maxPage; i++) {
                                dataset.pageNumberDisplay.push(i);
                            }
                        } else {
                            for (var i = dataset.pageNumber - 3; i < dataset.pageNumber + 3; i++) {
                                dataset.pageNumberDisplay.push(i);
                            }
                        }
                    }
                }
            };
            $scope.obj.followersTab = {
                data: _config.followers || [],
                pageNumberDisplay: [],
                pageItems: _config.followers != null ? _config.followers.slice(0, $scope.obj.followPageSize) : 0,
                pageNumber: 1,
                maxPage: _config.followers != null ? Math.ceil(_config.followers.length / $scope.obj.followPageSize) : 0,
                firstPage: true,
                lastPage: _config.followers != null ? Math.ceil(_config.followers.length / $scope.obj.followPageSize) == 1 : false
            };
            $scope.obj.following = _config.following || [];
            $scope.obj.followingTab = {
                data: $scope.obj.following,
                pageNumberDisplay: [],
                pageItems: _config.following != null ? _config.following.slice(0, $scope.obj.followPageSize) : 0,
                maxPage: _config.following != null ? Math.ceil(_config.following.length / $scope.obj.followPageSize) : 0,
                pageNumber: 1,
                firstPage: true,
                lastPage: _config.following != null ? Math.ceil(_config.following.length / $scope.obj.followPageSize) == 1 : false
            };
            $scope.obj.setFollowPageDisplay($scope.obj.followersTab);
            $scope.obj.setFollowPageDisplay($scope.obj.followingTab);

            $scope.obj.setFollowPage = function (dataset, page) {
                if (dataset) {
                    dataset.firstPage = false;
                    dataset.lastPage = false;
                    if (page <= 1) {
                        dataset.firstPage = true;
                    }
                    if (page >= dataset.maxPage) {
                        page = dataset.maxPage;
                        dataset.lastPage = true;
                    }
                    dataset.pageNumber = page;
                    var start = (page - 1) * $scope.obj.followPageSize;
                    var end = start + $scope.obj.followPageSize;
                    dataset.pageItems = dataset.data.slice(start, end);
                }
            };

            $scope.obj.showMoreFollowing = function () {
                if ($scope.obj.followingTab.pageItems.length < $scope.obj.followingTab.data.length) {
                    var _$scope$obj$followingTab$pageItems;

                    (_$scope$obj$followingTab$pageItems = $scope.obj.followingTab.pageItems).push.apply(_$scope$obj$followingTab$pageItems, _toConsumableArray($scope.obj.followingTab.data.slice($scope.obj.followingTab.pageItems.length, $scope.obj.followingTab.pageItems.length + $scope.obj.followPageSize)));
                }
            };

            $scope.obj.showMoreFollowers = function () {
                if ($scope.obj.followersTab.pageItems.length < $scope.obj.followersTab.data.length) {
                    var _$scope$obj$followersTab$pageItems;

                    (_$scope$obj$followersTab$pageItems = $scope.obj.followersTab.pageItems).push.apply(_$scope$obj$followersTab$pageItems, _toConsumableArray($scope.obj.followersTab.data.slice($scope.obj.followersTab.pageItems.length, $scope.obj.followersTab.pageItems.length + $scope.obj.followPageSize)));
                }
            };

            $scope.obj.isFollowing = function (id) {
                return $scope.obj.following.filter(function (f) {
                    return f.FId == id;
                }).length > 0;
            };

            $scope.obj.isBlockedFollower = function (id) {
                return $scope.obj.followersTab.data.filter(function (f) {
                    return f.UId == id && f.UBlocked;
                }).length > 0;
            };

            $scope.obj.blockFollower = function (followed) {
                activityService.blockUser(followed.UId, _config.blockUserUri).then(function (data) {
                    if (data.result) {
                        // find the right obj and change blocked prop
                        var index = $scope.obj.followersTab.data.findIndex(function (f) {
                            return f.UId == followed.UId;
                        });
                        $scope.obj.followersTab.data[index].UBlocked = true;
                    }
                })['catch'](function (error) {
                    App.notify.Danger(error.message);
                });
            };

            $scope.obj.unblockFollower = function (followed) {
                activityService.unBlockUser(followed.UId, _config.unblockUserUri).then(function (data) {
                    if (data.result) {
                        var index = $scope.obj.followersTab.data.findIndex(function (f) {
                            return f.UId == followed.UId;
                        });
                        $scope.obj.followersTab.data[index].UBlocked = false;
                    }
                })['catch'](function (error) {
                    App.notify.Danger(error.message);
                });
            };

            $scope.obj.followFollower = function (followed) {
                activityService.followUser(followed.UId, _config.followUserUri).then(function (data) {
                    if (data.result) {
                        var follower = {
                            UId: followed.FId,
                            UName: followed.FName,
                            UPic: followed.FPic,
                            UVisible: followed.FVIsible,
                            UState: followed.Fstate,
                            USuburb: followed.FSuburb,
                            UDate: followed.FDate,
                            FId: followed.UId,
                            FName: followed.UName,
                            FPic: followed.UPic,
                            FVIsible: followed.UVisible,
                            Fstate: followed.UState,
                            FSuburb: followed.USuburb,
                            FDate: followed.UDate
                        };
                        $scope.obj.following.push(follower);
                        if (!$scope.obj.followingTab.data.includes(follower)) {
                            $scope.obj.followingTab.data.push(follower);
                            $scope.obj.followingTab.maxPage = Math.ceil(_config.followers.length / $scope.obj.followPageSize);
                        }
                    }
                })['catch'](function (error) {
                    App.notify.Danger(error.message);
                });
            };

            $scope.obj.unfollowFollower = function (followed) {
                activityService.unFollowUser(followed.UId, _config.unfollowUserUri).then(function (data) {
                    if (data.result) {
                        $scope.obj.following = $scope.obj.following.filter(function (f) {
                            return f.FId !== followed.UId;
                        });
                    }
                })['catch'](function (error) {
                    App.notify.Danger(error.message);
                });
            };

            $scope.obj.followUser = function (followed) {
                activityService.followUser(followed.FId, _config.followUserUri).then(function (data) {
                    if (data.result) {
                        $scope.obj.following.push(followed);
                        if (!$scope.obj.followingTab.data.includes(followed)) {
                            $scope.obj.followingTab.data.push(followed);
                            $scope.obj.followingTab.maxPage = Math.ceil(_config.followers.length / $scope.obj.followPageSize);
                        }
                    }
                })['catch'](function (error) {
                    App.notify.Danger(error.message);
                });
            };

            $scope.obj.unfollowUser = function (followed) {
                activityService.unFollowUser(followed.FId, _config.unfollowUserUri).then(function (data) {
                    if (data.result) {
                        $scope.obj.following = $scope.obj.following.filter(function (f) {
                            return f.FId !== followed.FId;
                        });
                    }
                })['catch'](function (error) {
                    App.notify.Danger(error.message);
                });
            };

            $scope.obj.loadMoreCompletedSurvey = function () {
                App.loader.showLoader();
                var items = 10;
                var page = Math.ceil($scope.obj.jsonCompletedSurveyList.length / items) + 1;
                $http.post(_config.completedSurveysUri, $.param({ page: page, items: items })).then(function (d) {
                    if (d.status == 200) {
                        //success
                        for (var s in d.data) {
                            $scope.obj.jsonCompletedSurveyList.push(d.data[s]);
                        }
                    }
                    App.loader.hideLoader();
                }, function () {
                    App.loader.hideLoader();
                });
            };

            $scope.obj.showMobileTab = function () {
                var isHidden = $('#myTab').is(':hidden');
                var $caret = $('p.tab-selected-box .tab-caret .fa');

                $caret.removeClass('fa-angle-up').removeClass('fa-angle-down');
                var caret = isHidden ? 'fa-angle-up' : 'fa-angle-down';
                $caret.addClass(caret);

                if (isHidden) $('#myTab').slideDown(); else $('#myTab').slideUp('fast');
            };

            $scope.obj.addPhoto = function () {
                $scope.obj.currentAvatar = $('.photo-holder:eq(0)').data('img');
                $('#flePic').click();
            };

            $scope.obj.deletePhoto = function () {
                $('.photo-holder:eq(0)').data("img", $scope.obj.currentAvatar);
                $('.photo-holder:eq(0)').css('background-image', 'url(' + $scope.obj.currentAvatar + ')');
                $("#flePic").val('');
                $("#hdnFileName").val('');
                $scope.obj.hasPhoto = false;
                clearRotation();
            };

            $scope.obj.showTab = function (selector) {
                var $tab = $(selector);
                if ($tab.length > 0) $tab.tab('show');
            };

            $scope.obj.showProfile = function () {
                $scope.obj.showTab('.nav-tabs a[href="#profile"]');
            };

            $scope.obj.showAchievement = function () {
                $scope.obj.showTab('.nav-tabs a[href="#mybadges"]');
            };

            $scope.obj.inserRawHtml = function (s) {
                return $sce.trustAsHtml(s);
            };

            $scope.obj.showMoreComments = function () {
                App.loader.showLoader();
                $http.post(_config.moreCommentUri, $.param({ o: $scope.obj.commentOffset, i: 3 })).then(function (d) {
                    if (d.status == 200) {
                        //success
                        for (var i in d.data) {
                            $scope.obj.commentList.push(d.data[i]);
                        }
                        $scope.obj.commentOffset++;
                    }
                    App.loader.hideLoader();
                }, function () {
                    App.loader.hideLoader();
                });
            };

            $scope.obj.setSocial = function (u, p) {

                var hasSocialLinked = p == 'instagram' ? $scope.obj.hasIg : p == 'twitter' ? $scope.obj.hasTw : $scope.obj.hasFb;
                if (!hasSocialLinked) {
                    // detach social account from HTC
                    if (!confirm('Are you sure you want to detach #provider# from your HTC account?'.replace('#provider#', p))) {
                        $scope.obj[p == 'instagram' ? 'hasIg' : p == 'twitter' ? 'hasTw' : 'hasFb'] = true;
                        return;
                    }

                    App.loader.showLoader();
                    $http.post(_config.releaseSocialUri, $.param({ provider: p })).then(function (d) {
                        if (d.status == 200 && d.data.status == 1) {
                            //success
                            App.notify.Success(_config.sucessTxt);
                        }
                        App.loader.hideLoader();
                    }, function () {
                        App.loader.hideLoader();
                    });
                } else {
                    // link social account
                    App.loader.showLoader();
                    window.location = u;
                }
            };

            $scope.obj.iframSource = function (x) {
                return $sce.trustAsResourceUrl(x);
            };

            //#region User Uploads
            var rebuildModalVideo = function rebuildModalVideo() {
                // re-bind modal pop-up
                $('.upload-video-popup').magnificPopup({
                    fixedContentPos: false, // prevent scroll top on img click                   
                    mainClass: 'mfp-with-zoom mfp-img-mobile',
                    zoom: {
                        enabled: true
                    },
                    closeMarkup: '<button title="%title%" class="btn-nobg btn-close-media-popup" style="z-index:9999;position: absolute; top: 44px; right: 2px; opacity:.7; font-size:24px;"><i class="fa fa-minus-circle dark-grey-color" aria-hidden="true"></i></button>'
                });
            };

            $scope.obj.uploadItem = 4;
            $scope.obj.uploadPage = 1;
            $scope.obj.userUploadList = _config.userUploadList;
            $scope.obj.totalUserUploads = _config.totalUserUploads;
            $scope.obj.showMoreUserUploads = function () {
                App.loader.showLoader();
                $http.post(_config.userUploadsUri, $.param({ items: $scope.obj.uploadItem, page: $scope.obj.uploadPage, filter: $scope.obj.uploadFilter })).then(function (d) {
                    if (d.status == 200) {
                        //success
                        for (var i in d.data.data) {
                            var uu = d.data.data[i];
                            $scope.obj.userUploadList.push(uu);
                        }
                        $scope.obj.uploadPage++;
                        $scope.obj.totalUserUploads = d.data.count;
                        angular.element(function () {
                            rebuildModalVideo();
                        });
                    }
                    App.loader.hideLoader();
                }, function () {
                    App.loader.hideLoader();
                });
            };

            $scope.obj.setOffline = function (e, u) {
                var $obj = $(e.target);
                App.loader.showLoader();
                $http.post(_config.setOfflineUri, $.param({ id: u.Id })).then(function (d) {
                    if (d.status == 200) {
                        //success
                        $obj.parents('.dropdown:eq(0)').remove();
                        App.notify.Success(_config.sucessTxt);
                    }
                    App.loader.hideLoader();
                }, function () {
                    App.loader.hideLoader();
                });
            };

            $scope.obj.filterUploadList = function () {

                if (!$scope.obj.uploadFilter || $scope.obj.uploadFilter == 0) return $scope.obj.userUploadList;

                var result = $scope.obj.userUploadList;
                return _.filter(result, function (x) {
                    if ($scope.obj.uploadFilter == 2) return _.filter(["vbupload", "vbrecord", "vbio", "you", "youopen", "vim", "video"], function (y) {
                        return x.FileType.toLowerCase() == y;
                    }).length > 0; else return x.FileType.toLowerCase() == 'img';
                });
            };

            $scope.obj.uploadListFilter = function (t) {
                $scope.obj.uploadFilter = t;
            };
            //#endregion

            //#region Badge/Achievements
            $scope.obj.productListTemplate = (function () {
                return $('#tmplPlist').clone().html();
            })();
            $scope.obj._selectedItem = {};
            $scope.obj.badgeGroupSelect = 0;
            $scope.obj.showAchievedOnly = false;
            $scope.obj.badgeList = _config.badgeList;
            $scope.obj.achievements = _config.achievements;
            $scope.obj.newBadges = _config.newBadges;
            $scope.obj.categories = _config.categories;
            $scope.obj._products = [];
            $scope.obj.productCategory = [{ type: 'Reviews_Beauty', cid: [10] }, { type: 'Reviews_Food', cid: [1, 2, 3, 5, 16] }, { type: 'Reviews_House', cid: [4, 6, 7, 8, 9, 12] }, { type: 'Reviews_Kids', cid: [15] }, { type: 'Reviews_Pet', cid: [14] }];

            $scope.obj.divToggle2 = function (pin, cin, item, x, parent, prefix) {
                $('.more-info-holder').remove();

                if ($scope.obj._selectedItem.item && $scope.obj._selectedItem.item.BadgeCode == item.BadgeCode) {
                    $scope.obj._selectedItem = {};
                    return;
                }

                var mappedList = [];

                $('#' + parent + ' .item-acquired').each(function (index, value) {
                    mappedList.push({ id: $(this).attr('id'), top: $(this).position().top });
                });

                var currentId = prefix + '_' + pin + '_' + cin;
                var currentObject = $('#' + currentId);
                var nextObject = null;
                var currentIndex = _.findIndex(mappedList, function (x) {
                    return x.id == currentId;
                });
                if (currentIndex == mappedList.length - 1) nextObject = currentObject; else {
                    var hasFound = false,
                        cout = 0,
                        currentTop = mappedList[currentIndex].top;
                    while (!hasFound) {
                        cout++;
                        var nextTop = mappedList[currentIndex + cout].top;
                        if (nextTop > currentTop) {
                            cout--;
                            hasFound = true;
                        } else if (currentIndex + cout == mappedList.length - 1) hasFound = true;
                    }

                    nextObject = $('#' + mappedList[currentIndex + cout].id);
                }

                $scope.obj._selectedItem.item = item;
                $scope.obj._selectedItem.x = x;

                var template = angular.element('#tmplMoreInfo').clone().html();
                var result = $compile(template)($scope);
                var divToInsert = $('<div class="col-md-12 col-xs-12 col-sm-12 more-info-holder" style="display:none"></div>');
                divToInsert.html(result);

                nextObject.after(divToInsert);
                divToInsert.slideDown({
                    done: function done() {
                        $('.btn-what:eq(0)').click();
                    }
                });
            };

            $scope.obj.isNotAchieved = function (b) {
                if ($scope.obj.achievements.length == 0 || typeof b == 'undefined') return true;

                return typeof b.ReceivedDate === 'undefined' || b.ReceivedDate === null;
            };

            $scope.obj.getAlreadyAcquiredBadges = function (blist) {
                var b = _.chain(blist).filter(function (x) {
                    return !$scope.obj.isNotAchieved(x);
                }).sortBy(function (x) {
                    return x.Ord;
                }).value();

                if (b.length == 0) return null;

                return b;
            };

            $scope.obj.getLatestAchievement = function (blist) {
                var b = $scope.obj.getAlreadyAcquiredBadges(blist);

                if (b == null) return null;

                return b[0];
            };

            $scope.obj.getNextLevelBadge = function (blist) {
                var b = _.chain(blist).filter(function (x) {
                    return $scope.obj.isNotAchieved(x);
                }).first().value();

                if (b == null) return null;
                return [b]; // put in array to use ng-repeat
            };

            $scope.obj.myBadgeListAll = function (list) {
                var result = _.flatten(list);

                if ($scope.obj.showAchievedOnly) {
                    result = _.reject(result, function (x) {
                        return $scope.obj.isNotAchieved(x);
                    });
                }

                return result;
            };

            $scope.obj.futureList = function (list) {
                var result = _.chain(list).filter(function (x) {
                    var item = $scope.obj.getLatestAchievement(x);
                    return $scope.obj.isNullOrUndefined(item);
                })
                    //.filter(function (x) {
                    //    var items = _.filter(x, function (y) {
                    //        return y.BadgeGroup == $scope.obj.badgeGroupSelect
                    //    });
                    //    return items.length > 0;
                    //})
                    .value();

                return result;
            };

            $scope.obj.myBadgeListGrouped = function (list) {
                var result = _.chain(list).reject(function (x) {
                    //var items = _.filter(x, function (y) {
                    //    return y.BadgeGroup == $scope.obj.badgeGroupSelect
                    //});
                    var items = x;
                    var item = $scope.obj.getLatestAchievement(items);
                    return $scope.obj.isNullOrUndefined(item);
                }).value();

                return result;
            };

            $scope.obj.myBadgeList = function (list, limit) {
                if (!limit) limit = null;
                var result = _.chain(list).reject(function (x) {
                    var item = $scope.obj.getLatestAchievement(x);

                    return $scope.obj.isNullOrUndefined(item);
                }).value();

                if (limit != null && limit > 0) result = _.first(result, limit);

                return result;
            };

            $scope.obj.isNew = function (b) {
                if ($scope.obj.isNotAchieved(b) || typeof b == 'undefined') return false;

                var act = _.find($scope.obj.achievements, function (x) {
                    return x.BadgeId == b.Id;
                });

                if (act == null) return false;

                var id = _.find($scope.obj.newBadges, function (x) {
                    return x == act.Id;
                });

                return id != null;
            };

            $scope.obj.isNullOrUndefined = function (x) {
                return typeof x == 'undefined' || x == null;
            };

            $scope.obj.getBadgeImage = function (item) {
                if (item == null) return "";

                var arr = item.BadgeCode.split('_');
                var mkt = arr[0];
                arr.shift();
                return '/Content/Img/badges/' + mkt + '/' + arr.join('_') + '.png';
            };

            $scope.obj.getBadgeProgress = function (item) {
                return (item.UserHas / item.PointsAchievedAt * 100).toFixed(1);
            };

            $scope.obj.getCategoryByBadgeType = function (type) {
                return _.find($scope.obj.productCategory, function (x) {
                    return x.type == type;
                });
            };

            $scope.obj.countBadgeGroup = function () {
                var blist = $scope.obj.myBadgeList($scope.obj.badgeList);
                var arr = [];
                blist.forEach(function (x) {
                    arr = _.union(arr, $scope.obj.getAlreadyAcquiredBadges(x));
                });

                //var result = _.filter(arr, function (x) {
                //    return x.BadgeGroup == $scope.obj.badgeGroupSelect;
                //});
                return arr.length;
            };

            $scope.obj.countFutureBadgeGroup = function () {
                var blist = $scope.obj.futureList($scope.obj.badgeList);
                var arr = [];
                blist.forEach(function (x) {
                    arr.push(x[0]);
                });

                //var result = _.filter(arr, function (x) {
                //    return x.BadgeGroup == $scope.obj.badgeGroupSelect;
                //});

                return arr.length;
            };

            $scope.obj.showInfo = function (item) {
                var $div = $('#div' + item.BadgeCode);
                $div.slideToggle();
                if ($div.data('isloaded')) return;

                var category = $scope.obj.getCategoryByBadgeType(item.BadgeType);
                var cidString = category.cid.toString();
                var cidIndex = cidString.hashCode();
                $scope.obj._products[cidIndex] = {
                    badgeName: item.BadgeName,
                    badgeAlias: item.BadgeAlias,
                    badgeDescription: item.Description,
                    badgeImage: $scope.obj.getBadgeImage(item),
                    products: [],
                    page: 1
                };

                if (_.filter($scope.obj.productCategory, function (x) {
                    return x.type == item.BadgeType;
                }).length > 0) {
                    $scope.obj.loadDashboardProducts(item);
                }
            };

            $scope.obj.loadDashboardProducts = function (item) {
                var category = $scope.obj.getCategoryByBadgeType(item.BadgeType);
                var cidString = category.cid.toString();
                var cidIndex = cidString.hashCode();
                $scope.obj._products[cidIndex].categoryImage = _.find($scope.obj.categories, function (x) {
                    return x.Id == category.cid[0];
                }).Logo;
                // _GetDashboardProducts does the randomization of data '@Url.Action("_GetDashboardProducts", "Dashboard", new { rows = 4 })&q=' + cidString + "&page=" + $scope._products[cidIndex].page
                $http.post(_config.getProductUri, $.param({ q: cidString, page: $scope.obj._products[cidIndex].page, rows: 4 })).then(function (data) {
                    if (data.status == 200 && data.data.length > 0) {
                        $scope.obj._products[cidIndex].products = data.data.concat($scope.obj._products[cidIndex].products);
                        $scope.obj._products[cidIndex].products = _.uniq($scope.obj._products[cidIndex].products, function (item, key, a) {
                            return item.id;
                        });
                    }
                    var template = $scope.obj.productListTemplate.replace('obj._products.products', 'obj._products[' + cidIndex + '].products');
                    var result = $compile(template)($scope);
                    var $divInner = $('#inner' + item.BadgeCode);
                    var $div = $('#div' + item.BadgeCode);

                    $divInner.html(result);
                    $divInner.parent().show();
                    $div.data('isloaded', true);
                });
            };
            //#endregion

            $scope.obj.stripHtml = function (html) {
                var tmp = document.createElement("DIV");
                tmp.innerHTML = html;
                return tmp.textContent || tmp.innerText || "";
            };

            var clearRotation = function clearRotation() {
                $('.photo-holder:eq(0)').removeClass('rotate-90').removeClass('rotate-180').removeClass('rotate-270'); // remove rotation
                $('#hdnRotate').val('');
            };

            var onWindowResize = function onWindowResize() {
                var isMobile = $(window).width() <= 768;

                var $caret = $('p.tab-selected-box .tab-caret .fa');
                $caret.removeClass('fa-angle-up').removeClass('fa-angle-down');
                if (!isMobile) {
                    $('#myTab').show(); $caret.addClass('fa-angle-up');
                } else {
                    $('#myTab').hide(); $caret.addClass('fa-angle-down');
                }
            };

            $(window).resize(function () {
                onWindowResize();
            });

            function toggleFloatTab() {
                var $float = $('.float-panel-dashboard');
                !$('#myTab').isInViewport() ? $float.show() : $float.hide();

                resetFloatTabs();
            }

            function resetFloatTabs() {
                var $fTabs = $('.float-panel-dashboard .float-nav-table');
                $fTabs.removeClass('activebox');
                $fTabs.each(function (i, o) {
                    var obj = $(o);
                    if ($('#' + obj.data('tab')).is(':visible')) obj.addClass('activebox');
                });
            }

            function assignFLoatTabs() {
                var $fTabs = $('.float-panel-dashboard .float-nav-table');
                $fTabs.each(function (i, o) {
                    var obj = $(o);
                    obj.click(function () {
                        $scope.obj.showTab('ul.nav a[href="#' + obj.data('tab') + '"]');
                        $('html, body').animate({
                            scrollTop: 300
                        }, 500);
                    });
                });
            }

            function testUserPic() {
                // catch failed loaded image and show name text instead for userpic
                if (!$scope.obj.uploadedPic) return;

                var img = new Image();
                img.onerror = function () {
                    console.log('error called');
                    $scope.$apply(function () {
                        $scope.obj.uploadedPic = '';
                        $scope.obj.hasPhoto = false;
                    });
                };
                img.src = $scope.obj.uploadedPic;
            }

            angular.element(function () {
                onWindowResize();

                $(window).on('scroll resize', function () {
                    toggleFloatTab();
                });
                toggleFloatTab();
                assignFLoatTabs();
                testUserPic();

                if (_config.hasFbCallbackWarning) {
                    $('#lnkFbWarning').click();
                }
                $('.collapse-link-invite').click('on', function (e) {
                    e.preventDefault();
                });
                $('.progress-pink .progress-bar-pink').css("width", function () {
                    return $(this).attr("aria-valuenow") + "%";
                });
                // add scripts here
                $.validator.addMethod('passwordpattern', function (value, element) {
                    if (value == null || $.trim(value).length == 0) return true;

                    var valid = false;
                    var $element = $(element);
                    if ($element.attr('id') == 'SecurityModel_Password') {
                        var regPass = App.passwordRegex();
                        valid = regPass.test(value);
                    }
                    return valid;
                });
                $.validator.unobtrusive.adapters.add("mandatory", function (options) {
                    options.rules["required"] = true;
                    if (options.message) {
                        options.messages["required"] = options.message;
                    }
                });
                $.validator.unobtrusive.adapters.addBool("passwordpattern", "passwordpattern");

                unitOfWork.util.formValidateReset("#frmSecurity");
                //unitOfWork.util.formValidateReset("#frmUserInfo");

                // add scripts here
                $("#chkShowPass").change(function () {
                    var isChecked = $("#chkShowPass").prop('checked');
                    var selector = '#SecurityModel_Password,#SecurityModel_ConfirmPassword';
                    if (isChecked) $(selector).attr('type', 'text'); else $(selector).attr('type', 'password');
                });

                $('#frmUserInfo').submit(function (e) {
                    e.preventDefault(); //return false;
                    if (!$(this).valid()) return false;

                    App.loader.showLoader();
                    $.post($(this).attr('action'), $(this).serialize(), function (d) {
                        if (d.status == 1) {
                            App.notify.Success(_config.sucessTxt, _config.sucessTxt);
                            if (d.reset == 1) window.location.reload();
                            if (d.reloadtUri && d.reloadtUri.length > 0) window.location = d.reloadtUri;

                            App.loader.hideLoader();
                        } else {
                            App.notify.Danger(d.message);
                            App.loader.hideLoader();
                        }
                    });
                });

                $('#frmSecurity').submit(function (e) {
                    e.preventDefault();

                    if (!$(this).valid()) return false;

                    App.loader.showLoader();
                    $.post($(this).attr('action'), $(this).serialize(), function (d) {
                        if (d.status == 1) {
                            App.notify.Success(_config.sucessTxt, _config.sucessTxt);
                            $('#SecurityModel_Password,#SecurityModel_ConfirmPassword').val('');
                            App.loader.hideLoader();
                        } else {
                            App.notify.Danger(d.message);
                            App.loader.hideLoader();
                        }
                    });
                });

                // add callbacks for tab click events (before shown)
                //$('a[data-toggle="tab"]').on('show.bs.tab', function (e) { })
                $(document).on('show.bs.tab', '.nav-tabs-responsive [data-toggle="tab"]', function (e) {
                    console.log(e);
                });

                //fakewaffle.responsiveTabs(['xs', 'sm']);

                $('#frmAvatar').submit(function (e) {
                    e.preventDefault();
                    App.loader.showLoader();

                    var formData = new FormData(document.getElementById('frmAvatar'));
                    if ($('#flePic').val().length > 0 || $('.photo-holder:eq(0)').data('img').length > 0) formData.append('file', App.dataURItoBlob($('.photo-holder:eq(0)').data('img')));
                    formData.append('name', $('#hdnFileName').val());
                    formData.append('rotation', $('#hdnRotate').val());

                    $scope.obj.isUploading = true;
                    //$scope.$apply();
                    $.ajax({
                        xhr: function xhr() {
                            var xhr = new window.XMLHttpRequest();
                            xhr.upload.addEventListener("progress", function (evt) {
                                if (evt.lengthComputable) {
                                    var percentComplete = evt.loaded / evt.total;
                                    percentComplete = parseInt(percentComplete * 100);
                                    console.log(percentComplete);
                                    $('.upload-progress-box').show();
                                    $('.upload-progress-box .upload-progress').css('width', percentComplete + '%');
                                    if (percentComplete === 100) {
                                        $('.upload-progress-box').hide();
                                        $('.upload-progress-box .upload-progress').css('width', '0px');
                                    }
                                }
                            }, false);

                            return xhr;
                        },
                        url: $(this).attr('action'),
                        type: "POST",
                        data: formData,
                        processData: false,
                        contentType: false,
                        dataType: "json",
                        success: function success(d) {
                            $scope.obj.isUploading = false;
                            $('.upload-progress-box .upload-progress').css('width', '');
                            if (d.status == 1) {
                                var imagePath = d.path.replace('/thumb_', '/'); // get big image
                                clearRotation();
                                if ($('#flePic').val().length > 0) $('#main_menu .username + img.round-user-image100').attr('src', imagePath); else $('#main_menu .username + img.round-user-image100').removeAttr('src');

                                $("#flePic").val('');
                                $("#hdnFileName").val('');
                                $('.photo-holder:eq(0)').data('img', imagePath);
                                $('.photo-holder:eq(0)').css('background-image', 'url(' + imagePath + ')');
                                $scope.obj.uploadedPic = $('.photo-holder:eq(0)').data('img');
                                $scope.obj.hasPhoto = false;
                                $scope.$apply();
                                App.inlineSuccessAlert('#frmAvatar', _config.uploadSuccessTxt, App.placement.after);
                            } else {
                                App.notify.Danger(d.message);
                            }
                            App.loader.hideLoader();
                        },
                        error: function error() {
                            App.loader.hideLoader();
                        }
                    });
                });

                $("#flePic").change(function () {
                    if (this.files && this.files[0]) {
                        var reader = new FileReader();
                        var frag = this.files[0].name.split('.');
                        var ext = frag[frag.length - 1];

                        App.loader.showLoader();
                        reader.onload = function (e) {
                            var scaled = App.resizeImage(e.target.result, ext == 'jpg' ? 'jpeg' : ext, 200);
                            var image = scaled == 'data:,' ? e.target.result : scaled;
                            App.loader.hideLoader();
                            $scope.obj.hasPhoto = true;
                            $scope.$apply();
                            angular.element(function () {
                                $('.photo-holder:eq(0)').data('img', image);
                                $('.photo-holder:eq(0)').css('background-image', 'url(' + image + ')');
                            });
                        };
                        reader.readAsDataURL(this.files[0]);
                        $("#hdnFileName").val(this.files[0].name);
                    }
                });

                // re-bind modal pop-up
                rebuildModalVideo();

                App.passwordNotice('#SecurityModel_Password', '#passNotice');

                // password toggle
                $('.pass-text-toggle').click(function () {
                    var $icon = $(this).find('i');
                    var isHidden = $icon.hasClass('fa-eye-slash');
                    if (isHidden) {
                        // unhide password
                        $icon.removeClass('fa-eye-slash');
                        $icon.addClass('fa-eye');
                        $('#SecurityModel_Password').attr('type', 'text');
                        $('#SecurityModel_ConfirmPassword').attr('type', 'text');
                        return;
                    }
                    $icon.removeClass('fa-eye');
                    $icon.addClass('fa-eye-slash');
                    $('#SecurityModel_Password').attr('type', 'password');
                    $('#SecurityModel_ConfirmPassword').attr('type', 'password');
                });

                // scroll to tab on mobile
                $('#myTab a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
                    //e.target // newly activated tab
                    //e.relatedTarget // previous active tab 
                    var href = $(this).attr('href');
                    toggleLeftPanel(href);

                    // assign text to mobile only tab header
                    $('.tab-selected:first').text($(this).find('.text').text());

                    var windowWidth = $(window).width();
                    if (windowWidth <= 768) {
                        // only for mobile/small screen

                        // select activity if setting is chosen and sub tab is clear
                        if ($('#myTab2 li[role="presentation"].active').length === 0) $('#aboutme-tab').click();;

                        // hide tabs for mobile
                        $('#myTab').slideUp();
                        $('p.tab-selected-box .tab-caret .fa').removeClass('fa-angle-up').addClass('fa-angle-down');

                        $('html, body').animate({
                            scrollTop: $(href).offset().top - 200
                        }, 100);
                    }

                    toggleForcedWidth(href);
                });

                function toggleForcedWidth(hash) {
                    if (hash !== '#mysettings' && hash !== '#myfollowers' && $('.your-product-test-cshtml').length === 0 && $('.box-test-listing').length === 0) {
                        $('.right-panel, .top-tab').addClass("forced-full-width");
                    } else $('.right-panel, .top-tab').removeClass("forced-full-width");
                }

                function toggleLeftPanel(href) {
                    $('.dashboard-tabs [data-left-toggle]').hide();
                    if (href === '#mysettings') $('.dashboard-tabs [data-left-toggle="togglable-tabs"]').show(); else if (href === '#activity') $('.dashboard-tabs [data-left-toggle="togglable-activities"]').show(); else if (href === '#myfollowers') $('.dashboard-tabs [data-left-toggle="togglable-followers"]').show(); else $('.dashboard-tabs [data-left-toggle="togglable-tasks"]').show();
                }

                // hot link bootstrap tabs from URL
                var setTabOnLoad = function setTabOnLoad(h, id, id2) {
                    var list = $('#' + id + ' a[role="tab"]').map(function (x, i) {
                        return $(i).attr('href').substr(1);
                    }).toArray();
                    h && list.filter(function (x) {
                        return x === hash;
                    }).length > 0 && $scope.obj.showTab('ul.nav a[href="#' + id2 + '"]');
                };
                var hash = window.location.hash ? window.location.hash.replace(/[^a-z0-9A-Z\-\_]*/gi, '') : null;
                toggleForcedWidth('#' + hash);
                hash && $scope.obj.showTab('ul.nav a[href="#' + hash + '"]');
                setTabOnLoad(hash, 'myTab2', 'mysettings');
                setTabOnLoad(hash, 'myTab3', 'myfollowers');
                setTabOnLoad(hash, 'myTab4', 'activity');
                toggleLeftPanel('#' + hash);
            });
        }]);
    };

    var submitPhoto = function submitPhoto() {
        $('#frmAvatar').submit();
    };

    var deleteComment = function deleteComment(el) {

        var id = el.data('cid');
        if (id === 0) return;

        App.loader.showLoader();
        $.post(_config.deleteCommentUri + '/' + id, function (d) {
            if (d.status === 1) {
                //success

                var $scope = angular.element($('body')).scope(); // get angular scope
                $scope.$apply(function () {
                    $scope.obj.commentList = _.reject($scope.obj.commentList, function (x) {
                        return x.Id === id;
                    });
                });
            }
        }).fail(function () {
            App.notify.Warning(_config.T_ErrorProcessingRequest);
        }).always(function () {
            App.loader.hideLoader();
        });
    };

    var deleteUserUpload = function deleteUserUpload(el) {

        var id = el.data('cid');
        if (id === 0) return;

        App.loader.showLoader();
        $.post(_config.deleteUserUploadUri + '/' + id, function (d) {
            if (d.status === 1) {
                //success

                var $scope = angular.element($('body')).scope(); // get angular scope
                $scope.$apply(function () {
                    $scope.obj.userUploadList = _.reject($scope.obj.userUploadList, function (x) {
                        return x.Id === id;
                    });

                    // update total count
                    $scope.obj.totalUserUploads -= 1;
                });
            }
        }).fail(function () {
            App.notify.Warning(_config.T_ErrorProcessingRequest);
        }).always(function () {
            App.loader.hideLoader();
        });
    };

    var deleteUserQuestion = function deleteUserQuestion(el) {
        var id = el.data('cid');
        if (id === 0) return;

        App.loader.showLoader();
        $.post(_config.deleteUserQuestionUri + '/' + id, function (d) {
            if (d.status === 1) {
                //success

                var $scope = angular.element($('body')).scope(); // get angular scope
                $scope.$apply(function () {
                    $scope.obj.questionList = _.reject($scope.obj.questionList, function (x) {
                        return x.Id === id;
                    });
                });
            }
        }).fail(function () {
            App.notify.Warning(_config.T_ErrorProcessingRequest);
        }).always(function () {
            App.loader.hideLoader();
        });
    };

    return { init: init, submitPhoto: submitPhoto, deleteComment: deleteComment, deleteUserUpload: deleteUserUpload, deleteUserQuestion: deleteUserQuestion };
})();;
if (typeof App === 'undefined') var App = {};

App.Feed = function () { return {} }();
App.Feed.Index = function () {
    var _config = {};

    var init = function (config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);
        }

        App.angular.controller('MainController', function ($scope, $http, $compile, unitOfWork, activityService, $sce) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {
                showReloadPage: false,
                rotateElement: function (selector, hdnRotate, deg) {
                    App.rotateElement(selector, hdnRotate, deg);
                },
                hasPhoto: _config.hasPhoto || false
            };

            angular.element(function () {
                if (_config.isFromFBSuccess) App.notify.Success(_config.T_ConnectToFb, _config.successTxt)
                function appendToTabletSection(id) {
                    var c = $('#' + id).clone();
                    c.attr('id', c.attr('id') + '_t');
                    $('#tabletSection').append(c);
                }

                ['recentlyAdded', 'categoryProds', 'trendingProds', 'recommendedProds', 'htProds'].forEach((o, i) => {
                    appendToTabletSection(o);
                })

                // add scripts here
                //custom carousel
                var $slick = $('.responsive-slider').slick({
                    dots: false,
                    infinite: false,
                    speed: 300,
                    slidesToShow: 2,
                    slidesToScroll: 2,
                    responsive: [
                        {
                            breakpoint: 920,
                            settings: {
                                slidesToShow: 2,
                                slidesToScroll: 2
                            }
                        },
                        {
                            breakpoint: 700,
                            settings: {
                                slidesToShow: 1,
                                slidesToScroll: 1
                            }
                        }
                        // You can unslick at a given breakpoint now by adding:
                        // settings: "unslick"
                        // instead of a settings object
                    ]
                });

                function checkIsMobile() {
                    var newWindowWidth = $(window).width();
                    if (newWindowWidth < 767) {
    	                return true;
                    }

    	            return false;
                }

                $scope.obj.currentMobileView = "#feedHome";
                $scope.obj.isMobile = false;
                adjustDisplay(checkIsMobile());

                $(window).on("resize", function (e) {
                    adjustDisplay(checkIsMobile());
                });

                function adjustDisplay(isMobile) {
                    if (isMobile) {
                        if (!$scope.obj.isMobile) {
                            mobileViewSwitcher($scope.obj.currentMobileView);
                        }
                    } else {
                        ['#recentlyAdded', '#feedHome', '#userProfile']
                            .forEach(
                                x => {
                                    var section = $(x);
                                    section.show();
                                    section.removeClass('visible-xs');
                                });
                    }
                    $scope.obj.isMobile = isMobile;
                }

                function mobileViewSwitcher(id) {

                    ['#recentlyAdded', '#feedHome', '#userProfile']
                        .forEach(
                            x => {
                                var section = $(x);
                                section.hide();
                                section.removeClass('visible-xs');
                            });

                    var section = $(id);
                    section.addClass('visible-xs');
                    section.fadeIn();

                }

                $('#frmRotateAvatar').submit(function (e) {
                    e.preventDefault();
                    App.loader.showLoader();

                    var formData = new FormData(document.getElementById('frmRotateAvatar'));
                    if ($('.photo-holder-feed:eq(0)').data('img').length > 0) formData.append('file', App.dataURItoBlob($('.photo-holder-feed:eq(0)').data('img')));
                    formData.append('name', $('#hdnFileName').val());
                    formData.append('rotation', $('#hdnRotate').val());

                    $scope.obj.isUploading = true;
                    $.ajax({
                        xhr: function xhr() {
                            var xhr = new window.XMLHttpRequest();
                            xhr.upload.addEventListener("progress", function (evt) {
                                if (evt.lengthComputable) {
                                    var percentComplete = evt.loaded / evt.total;
                                    percentComplete = parseInt(percentComplete * 100);
                                    console.log(percentComplete);
                                    $('.upload-progress-box').show();
                                    $('.upload-progress-box .upload-progress').css('width', percentComplete + '%');
                                    if (percentComplete === 100) {
                                        $('.upload-progress-box').hide();
                                        $('.upload-progress-box .upload-progress').css('width', '0px');
                                    }
                                }
                            }, false);

                            return xhr;
                        },
                        url: $(this).attr('action'),
                        type: "POST",
                        data: formData,
                        processData: false,
                        contentType: false,
                        dataType: "json",
                        success: function success(d) {
                            $scope.obj.isUploading = false;
                            $('.upload-progress-box .upload-progress').css('width', '');
                            if (d.status == 1) {
                                var imagePath = d.path.replace('/thumb_', '/'); // get big image
                                if ($('.photo-holder-feed:eq(0)').data('img').length > 0) $('[data-fname].round-circle.round-user-image40').attr('src', imagePath); else $('#main_menu .username + img.round-user-image100').removeAttr('src');

                                $("#flePic").val('');
                                $("#hdnFileName").val('');
                                $scope.$apply();
                                App.notify.Success(_config.successTxt);
                            } else {
                                App.notify.Danger(d.message);
                            }
                            App.loader.hideLoader();
                        },
                        error: function error() {
                            App.loader.hideLoader();
                        }
                    });
                });

                $('#lnkUser').on('click', function (e) {
                    e.preventDefault();
                    $scope.obj.currentMobileView = '#userProfile';
                    mobileViewSwitcher('#userProfile');
                    window.scrollTo(0, 0);
                });

                $('#lnkHome').on('click', function (e) {
                    e.preventDefault();
                    $scope.obj.currentMobileView = '#feedHome';
                    mobileViewSwitcher('#feedHome');
                    window.scrollTo(0, 0);
                });

                $('#lnkRecent').on('click', function (e) {
                    e.preventDefault();
                    $scope.obj.currentMobileView = '#recentlyAdded';
                    mobileViewSwitcher('#recentlyAdded');
                    window.scrollTo(0, 0);
                });

                $scope.obj.resxStrings = _config.resxStrings;

                $scope.obj.checkAuthRedirect = function () {
                    if (_config.uId === "0") {
                        return window.location = _config.loginUrl + '?returnurl=' + _config.feedUrl;
                    }
                }

                $scope.obj.makeStars = function () {
                    $('#feed-list,#recentlyAdded,#categoryProds,#trendingProds,#recommendedProds,#htProds,#recentlyAdded_t,#categoryProds_t,#trendingProds_t,#recommendedProds_t,#htProds_t')
                        .find('.js-star-rating').makeStars();
                }
                $scope.obj.makeStars();

                $scope.obj.initFeedLoaded = false;
                $scope.obj.hasMoreFeedItems = true;
                $scope.obj.isLoadingMoreFeedItems = false;
                if ($scope.obj.followedCategoryNames === undefined) {
                    $scope.obj.followedCategoryNames = {};
                }
                $scope.obj.feedPageSize = _config.feedPageSize;
                $scope.obj.feedPage = 0;
                $scope.obj.numFollowedCategories = function () {
                    return Object.keys($scope.obj.followedCategoryNames).length;
                }

                $scope.obj.handleFeedScrolling = App.debounce(function () {
                    if ($('#end-of-feed').isInViewport() && $scope.obj.hasMoreFeedItems && !$scope.obj.isLoadingMoreFeedItems) {
                        $scope.obj.isFromReloadPage = false;
                        $scope.obj.loadMoreFeedItems();
                    }

                    $('.mark-activity-is-seen').each(function (i, obj) {
                        if ($(obj).isInViewport() && !$scope.obj.FeedActivities[obj.id].marked) {
                            $scope.obj.markActivity(
                                obj.id,
                                $scope.obj.FeedActivities[obj.id].group,
                                $scope.obj.FeedActivities[obj.id].identifier,
                                $scope.obj.FeedActivities[obj.id].provider,
                                $scope.obj.FeedActivities[obj.id].type,
                                '',
                                false,
                                true,
                                false,
                                function (groupId) {
                                    $scope.obj.FeedActivities[groupId].marked = true;
                                });
                        }
                    });
                }, 250, false);

                $(document).on('scroll', $scope.obj.handleFeedScrolling);

                $scope.obj.reloadFeed = function () {
                    $('#feed-list .activity-card:not(.reminder-card)').remove();
                    $scope.obj.feedPage = 0;
                    $scope.obj.showReloadPage = false;
                    $scope.obj.isFromReloadPage = true;
                    $scope.obj.loadMoreFeedItems();
                }

                $scope.obj.loadMoreFeedItems = function () {
                    $scope.obj.checkAuthRedirect();
                    $scope.obj.isLoadingMoreFeedItems = true;
                    $scope.obj.initFeedLoaded = true;
                    $scope.obj.hasEmptyActivity = false;
                    if (!$scope.obj.isFromReloadPage) { $scope.$apply(); }

                    App.fireDatalayerEvent('FEED_LOADMORE_' + ($scope.obj.feedPage + 1), window.Location.href, document.title);
                    $.get(_config.feedUri + '?page=' + ($scope.obj.feedPage + 1) + '&pagesize=' + $scope.obj.feedPageSize, function (data) {
                        if (data) {
                            var match = data.toString().match(/<div\sclass=([',"])feed-card/g);
                            $scope.obj.hasMoreFeedItems = match && match.length === $scope.obj.feedPageSize;
                            var feedList = $('#feed-list');
                            angular.element(feedList).append($compile(data)($scope));
                            angular.element(function () {
                                $scope.obj.makeStars();
                                $scope.obj.feedPage++;
                                $scope.obj.isLoadingMoreFeedItems = false;
                                if (!!$scope.obj.hasEmptyActivity) { // async load prod suggestion
                                    $http.post(_config.userSetupUri).then(function (d) {
                                        if (d.status == 200) {
                                            if (d.data.status == 1) {
                                                $scope.obj.showReloadPage = true;
                                                return;
                                            }

                                            $scope.obj.showError(d.data.message);
                                        }
                                    })
                                    .catch(function (error) {
                                        $scope.obj.showError(error.data.message);
                                    });
                                }

                                $scope.$apply();

                                // update isSeen action
                                var unSeenObj = $('[data-seen="0"]');
                                if (unSeenObj.length > 0) {
                                    var idString = Array.from(unSeenObj.map((i, o) => { return parseInt($(o).data('activityid')); })).join();
                                    $.post(_config.actionInsertUri, $.param({ 'q': idString }),
                                        function (data) {
                                            if (data.status == 1) {
                                                $('[data-seen="0"]').removeAttr('data-seen');
                                            }
                                        })
                                }
                            });
                        }
                    }).always(function () {
                        $scope.obj.isLoadingMoreFeedItems = false;
                    });
                }

                $scope.obj.hideFeedItem = function (group, message) {
                    $scope.obj.showFeedItemMessage(message);
                    var feedCardDiv = $('#' + group);
                    setTimeout(function () {
                        feedCardDiv.fadeOut(400);
                    }, 400 * 2);
                    setTimeout(function () {
                        feedCardDiv.hide();
                    }, 400 * 3);
                }

                $scope.obj.showFeedItemMessage = function (message, title) {
                    var alertDiv = $('.Feed-FlashAlert').clone();
                    var textDiv = alertDiv.find('span');
                    var textTitle = alertDiv.find('h5');
                    textDiv.html(message);
                    textTitle.html(title || '');
                    $(document.body).append(alertDiv);
                    alertDiv.fadeIn(400);
                    setTimeout(function () {
                        alertDiv.fadeOut(400, function () { alertDiv.remove(); });
                    }, 1000 * 2);
                }

                $scope.obj.copyTextToClipboard = function (value, message) {
                    App.copyTextToClipboard(value);
                    $scope.obj.showFeedItemMessage(message);
                }

                $scope.obj.markActivity = function (groupid, group, id, provider, type, message, hideItem, isSeen, isRead, callback) {
                    $scope.obj.checkAuthRedirect();
                    if (groupid && id && type && provider) {
                        var params = {
                            groupId: groupid,
                            id: id,
                            type: type,
                            provider: provider,
                        };
                        if (isSeen) {
                            params.isSeen = true;
                        }
                        if (isRead) {
                            params.isRead = true;
                        }
                        $http.post(_config.markActivityUri, $.param(params)).then(function (data) {
                            if (data) {
                                if (hideItem) {
                                    $scope.obj.hideFeedItem(group, message ? message : _config.resxStrings['T_FeedPreferencesNoted']);
                                }
                                if (callback) {
                                    callback(groupid);
                                }
                            }
                        })
                        .catch(function (error) {
                            $scope.obj.showError(error.data.message);
                        });
                    }
                }

                $scope.obj.showCategory = {};
                $scope.obj.categorySearchTerm = '';
                $scope.obj.categorySearchResults = [];

                $scope.obj.getCategories = function(parentId) {
                    return $scope.obj.allCategories.filter(c => c.parentId === parentId);
                }

                $scope.obj.getLevel3Categories = function() {
                    return $scope.obj.allCategories.filter(c => c.level === 3);
                }
                $scope.obj.clearCategorySearch = function () {
                    $scope.obj.categorySearchTerm = '';
                    $scope.obj.updateCategorySearch();
                }
                $scope.obj.updateCategorySearch = function () {
                    if ($scope.obj.categorySearchTerm.length < 2) {
                        $scope.obj.categorySearchResults = [];
                    } else {
                        var results =
                            $scope.obj.allCategories
                                .filter(
                                    c => c.level === 3 && (c.name.toLowerCase().indexOf($scope.obj.categorySearchTerm.toLowerCase()) !== -1))
                                .sort((a, b) => (a.name > b.name) ? 1 : -1)
                                .slice(0, 11);

                        results.forEach(
                                    cat => cat.hightlightedName = $sce.trustAsHtml(cat.name.replace(new RegExp($scope.obj.categorySearchTerm, 'gi'), '<span class="category-search-highlight">$&</span>'))
                                );
                        $scope.obj.categorySearchResults = results;
                    }
                }

                $scope.obj.followUser = function (userId, group) {
                    $scope.obj.checkAuthRedirect();
                    activityService.followUser(userId, _config.followUserUri)
                    .then(function (data) {
                        if (data) {
                            $scope.obj.followedUserIds.push(userId);
                            $scope.obj.showFeedItemMessage(_config.resxStrings['T_YouAreNowFollowingThisUser']);
                        }
                    })
                    .catch(function (error) {
                        $scope.obj.showError(error.message);
                    });
                }

                $scope.obj.followProduct = function (productId, group) {
                    $scope.obj.checkAuthRedirect();
                    $http.post(_config.followProductUri, $.param({
                        productId: productId,
                    })).then(function (data) {
                        if (data) {
                            $scope.obj.followedProductIds.push(productId);
                            $scope.obj.showFeedItemMessage(_config.resxStrings['T_YouAreNowFollowingThisProduct']);
                        }
                    })
                    .catch(function (error) {
                        $scope.obj.showError(error.message);
                    });
                }

                $scope.obj.followProductCategory = function (prodCatId, group, name) {
                    $scope.obj.checkAuthRedirect();
                    $http.post(_config.followProductCategoryUri, $.param({
                        prodCatId: prodCatId,
                    })).then(function (data) {
                        if (data) {
                            $scope.obj.followedProductCategoryIds.push(prodCatId);
                            if (group) {
                                //used in the feed
                                $scope.obj.showFeedItemMessage(_config.resxStrings['T_YouAreNowFollowingThisCategory']);
                            }
                            if (name) {
                                $scope.obj.followedCategoryNames[prodCatId.toString()] = name;
                            }
                        }
                    })
                    .catch(function (error) {
                        $scope.obj.showError(error.data.message);
                    });
                }

                $scope.obj.unFollowProduct = function (productId, group) {
                    $scope.obj.checkAuthRedirect();
                    $http.post(_config.unFollowProductUri, $.param({
                        productId: productId,
                    })).then(function (data) {
                        if (data) {
                            $scope.obj.followedProductIds = $scope.obj.followedProductIds.filter(item => item !== Number(productId));
                            $scope.obj.hideFeedItem(group, _config.resxStrings['T_YouAreNoLongerFollowingThisProduct']);
                        }
                    })
                    .catch(function (error) {
                        $scope.obj.showError(error.data.message);
                    });
                }

                $scope.obj.unFollowUser = function (followedId, group) {
                    $scope.obj.checkAuthRedirect();
                    activityService.unFollowUser(followedId, _config.unFollowUserUri)
                    .then(function (data) {
                        if (data) {
                            $scope.obj.followedUserIds = $scope.obj.followedUserIds.filter(item => item !== Number(followedId));
                            //TODO: shuld we hide this?
                            //$scope.obj.hideFeedItem(group, _config.resxStrings['T_YouAreNoLongerFollowingThisUser']);
                            $scope.obj.showFeedItemMessage(_config.resxStrings['T_YouAreNoLongerFollowingThisUser']);
                        }
                    })
                    .catch(function (error) {
                        $scope.obj.showError(error.data.message);
                    });
                }

                $scope.obj.unFollowProductCategory = function (prodCatId, group, name) {
                    $scope.obj.checkAuthRedirect();
                    $http.post(_config.unFollowProductCategoryUri, $.param({
                        prodCatId: prodCatId,
                    })).then(function (data) {
                        if (data) {
                            //TODO: should we mark this as seen?
                            $scope.obj.followedProductCategoryIds = $scope.obj.followedProductCategoryIds.filter(item => item !== Number(prodCatId));
                            if (group) {
                                $scope.obj.hideFeedItem(group, _config.resxStrings['T_YouAreNoLongerFollowingThisCategory']);
                            }
                            if (name) {
                                delete $scope.obj.followedCategoryNames[prodCatId.toString()];
                            }
                        }
                    })
                    .catch(function (error) {
                        $scope.obj.showError(error.data.message);
                    });
                }

                $scope.obj.toggleProductCategory = function (prodCatId, name){
                    if ($scope.obj.followedProductCategoryIds.includes(prodCatId)) {
                        $scope.obj.unFollowProductCategory(prodCatId, '', name);
                    } else {
                        $scope.obj.followProductCategory(prodCatId, '', name);
                    }
                }

                $scope.obj.loadCategorySelectionCard = function (id, activityGroupId, activityGroup, activityIdentifier, activityProvider, activityType, parentId) {
                    $scope.obj.checkAuthRedirect();
                    $http.post(_config.categorySelectionActivityUri, $.param({
                        parentId: parentId,
                        followedCategoryIds: $scope.obj.followedProductCategoryIds,
                        activityGroupId: activityGroupId,
                        activityGroup: activityGroup,
                        activityIdentifier: activityIdentifier,
                        activityProvider: activityProvider,
                        activityType: activityType,
                    })).then(function (data) {
                        if (data) {
                            angular.element($('#' + id)).html($compile(data.data)($scope));
                        }
                    })
                    .catch(function (error) {
                        $scope.obj.showError(error.data.message);
                    });
                }

                $scope.obj.showError = function (message) {
                    if (!message) {
                        message = _config.resxStrings['T_ErrorProcessingRequest'];
                    }
                    App.notify.Danger(message);
                }

                $scope.obj.answerQuestionCallback = function () {
                    var obj = arguments[0];
                    $scope.obj.showFeedItemMessage(_config.resxStrings['T_AnswerPosted']);
                    obj.modal.modal('hide');
                }

                $scope.obj.isItemLiked = function (type, id) {
                    var listing = type == 'comments' ? $scope.obj.likedReviewIds : $scope.obj.likedUploadIds;
                    if (!listing || listing.length == 0) return false;

                    return listing.indexOf(id) > -1;
                }

                $scope.obj.chooseAvatarImage = function () {
                    $('#hdnFeedAvatarFile').click();
                }

                $scope.obj.rotateFeedElement = function (selector, deg) {
                    var className = '';
                    var $obj = $(selector);
                    var $hdn = $('#hdnFeedRotate');
                    var current = parseInt($hdn.val());

                    if (!current || current == null || isNaN(current)) current = 0;

                    current += deg;
                    if (current == 360 || current == -360) {
                        current = 0; $hdn.val(0);
                    }

                    switch (current) {
                        case -270: case 90:
                            className = 'rotate-90'; break;
                        case -180: case 180:
                            className = 'rotate-180'; break;
                        case -90: case 270:
                            className = 'rotate-270'; break;
                    }
                    $hdn.val(current);
                    $obj.removeClass('rotate-90').removeClass('rotate-180').removeClass('rotate-270').addClass(className);
                };

                $scope.obj.clearAvatarSelect = function () {
                    $scope.obj.hasFeedPhoto = false;
                    $('#hdnFeedAvatarFile').val('');
                    $('#avatar_feed_card .photo-holder:eq(0)').data('img', null);
                }

                $scope.obj.askMeLater = function (type) {
                    $http.post(_config.askLaterUri).then(function (d) {
                        if (d.status == 200) {
                            if (d.data.status == 1) {
                                $('.category-selection').fadeOut(500, function () { $('.category-selection').remove() });
                                return;
                            }

                            $scope.obj.showError(d.data.message);
                        }
                    })
                    .catch(function (error) {
                        $scope.obj.showError(error.data.message);
                    });
                };

                // change avatar on error
                if (_config.isAvatarVisible) {
                    var img = new Image();
                    img.src = _config.avatar;
                    img.onerror = function () {
                        var $avatar = $('.feed-user-profile');
                        $avatar.after($('<div>', { class: 'avatar-letter' }).html($avatar.data('fname')));
                        $avatar.remove();
                    }
                }

                if (_config.customMessage && _config.customTitle)
                    $scope.obj.showFeedItemMessage(_config.customMessage, _config.customTitle)

                App.Feed.Index.addGtag();

                $scope.obj.isFromReloadPage = false;
                $scope.obj.loadMoreFeedItems();
            });

        });

    };

    function addGtag() {
        angular.element(function () {
            // applpy gtag events
            $('[data-gtag]:not(.gtag-enabled), [data-gtag] a:not(.gtag-enabled)').each(function (i, o) {
                $(o).addClass('gtag-enabled');
                $(o).click(function () {
                    var key = $(this).data('gtag');
                    if (typeof key == 'undefined' || key == null)
                        key = $(this).parents('[data-gtag]').eq(0).data('gtag');
                    App.fireDatalayerEvent(key, window.location.href, 'FEED ' + key);
                })
            });
        })
    }

    var reviewCallback = function (groupid, group, id, provider, type, productId, userId) {
        // TODO: should we mark the activity as seen so it won't show up in the feed again
        //scope.obj.markActivity(groupid, group, id, provider, type, '', false, true, true);

        var modalId = 'modalReview';
        var $modal = $(`#${modalId}`);
        $modal.modal('hide');

        var ng = angular.element($('body')).scope(); // get angular scope
        ng.obj.reviewedProductIds.push(productId.toString());

        ng.obj.showFeedItemMessage(_config.resxStrings['T_ThanksReviewReceived']);
        ng.$apply();

        return true;
    }

    var reportComment = function (el) {
        // report upload
        var commentId = el.data('cid');
        var groupid = el.data('groupid');
        var group = el.data('group');
        var id = el.data('id');
        var provider = el.data('provider');
        var type = el.data('type');
        var table = el.data('table');
        if (id === 0) return;

        var ng = angular.element($('body')).scope(); // get angular scope
        ng.obj.checkAuthRedirect();
        App.loader.showLoader();
        var jqxhr = $.post((!table || table == 'Comments' ? _config.reportCommentUrl : _config.reportUploadUrl) + '/' + commentId, function (data) {
            // success, remove response box          
            if (data.result > 0) {
                ng.obj.markActivity(groupid, group, id, provider, type, _config.resxStrings['T_InAppropriateCommentReported'], true, true, false);
            }
            else if (data.message !== '') {
                App.notify.Warning(data.message);
            }
        })
        .fail(function () {
            App.notify.Warning(_config.T_ErrorProcessingRequest);
        })
        .always(function () {
            App.loader.hideLoader();
        });
    };

    function likeItem(table, type, id, obj) {
        var $elem = $(obj);
        var ng = angular.element($('body')).scope(); // get angular scope
        $elem.find('img').attr('src', '//d2vtntcxpdw15n.cloudfront.net/img3/heart-outline-purple.gif');
        $.post(_config.likeUrl, $.param({ id, theTable: table, type }), function (data) {
            // success, change heart to solid          
            //ng.obj.showFeedItemMessage(data);
            $elem.find('img').attr('src', '//d2vtntcxpdw15n.cloudfront.net/img3/heart-solid-purple.png');
        })
        .fail(function () {
            App.notify.Warning(_config.T_ErrorProcessingRequest);
            $elem.find('img').attr('src', '//d2vtntcxpdw15n.cloudfront.net/img3/heart-outline-purple.png');
        })
        .always(function () {
        });
    }

    function submitFeedPhoto() {
        $('#frmFeedAvatar').submit();
    }

    function resizePostCard(frameId, containerId) {
        resizeIntervalObj[frameId] = setInterval(function () {
            if (document.getElementById(frameId).contentWindow.document.getElementsByClassName('fb-post')[0].firstChild != null && document.getElementById(frameId).contentWindow.document.getElementsByClassName('fb-post')[0].firstChild.offsetHeight > 0) {
                var height = document.getElementById(frameId).contentWindow.document.getElementsByClassName('fb-post')[0].firstChild.offsetHeight + 'px';
                document.getElementById(containerId).style.height = height;
                document.getElementById(frameId).style.height = height;
                $('#' + containerId).parents('.feed-card').find('.mini-loader-bg').remove();

                clearInterval(resizeIntervalObj[frameId]);
            }
        }, 2000);
    }
    
    function submitRotatedPhoto() {
        $('#frmRotateAvatar').submit();
    }

    var resizeIntervalObj = {};

    return {
        init: init,
        reportComment: reportComment,
        reviewCallback: reviewCallback,
        likeItem: likeItem,
        submitFeedPhoto: submitFeedPhoto,
        addGtag: addGtag,
        resizePostCard: resizePostCard,
        submitRotatedPhoto: submitRotatedPhoto
    };
}();

;
if (typeof App === 'undefined') var App = {};

App.Gamification = function () {
    return {};
}();

App.Gamification.Index = function () {
    var _config = {};
    var init = function (config) {
        if (config && typeof (config) === 'object') {
            $.extend(true, _config, config);

            App.angular.controller('MainController', function ($scope, $http, $sce, dateFilter, unitOfWork) {
                $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
                $scope.obj = {};

                $(function () {
                    // add scripts here
                })
            });
        }
    };

    return { init: init };
}();
;
'use strict';

if (typeof App === 'undefined') var App = {};

App.Home = (function () {
    return {};
})();

App.Home.Index = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);
        }

        App.angular.controller('MainController', ['$scope', '$http', function ($scope, $http) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};

            $(function () {
                // add scripts here

                var sliderItems = $('.home-main-slider .bxslider li').length;
                var homeMainSlider = $('.home-main-slider .bxslider').bxSlider({
                    auto: sliderItems > 1 ? true : false,
                    speed: 1000,
                    pause: 10000,
                    touchEnabled: false,
                    onSlideBefore: function onSlideBefore() {
                        $('.home-main-slider .bx-default-pager').hide();
                    },
                    onSlideAfter: function onSlideAfter() {
                        $('.home-main-slider .bx-default-pager').show();
                    },
                    onSliderLoad: function onSliderLoad() {
                        $('.home-main-slider .bx-prev').hide();
                        $('.home-main-slider .bx-next').hide();
                        var defaultPager = $('.home-main-slider .bx-default-pager');
                        if (this.getSlideCount() > 1) {
                            defaultPager.show();
                        } else {
                            defaultPager.hide();
                        }
                        $('.home-main-slider .slider-link').removeClass('hidden');
                    }
                });

                // stop auto play on slider when clicking the pager
                $('.home-main-slider .bx-pager-link').on('click', function () {
                    homeMainSlider.stopAuto(false);
                });
                homeMainSlider.swipe({
                    swipeRight: function swipeRight(event, direction, distance, duration, fingerCount) {
                        homeMainSlider.goToPrevSlide();
                    },
                    swipeLeft: function swipeLeft(event, direction, distance, duration, fingerCount) {
                        homeMainSlider.goToNextSlide();
                    },
                    threshold: 100
                });

                $('.Herocounter').css('visibility', 'visible');
                $('.Herocounter').counterUp({
                    delay: 10,
                    time: 2000,
                    formatter: function formatter(n) {
                        return n.replace(/,/g, _config.thousandSepator);
                    }
                });

                $(".boxCellPic-container .boxCellPic-overlay").each(function (i, o) {
                    if ($(o).find('a.href-link2').length == 0) {
                        $(o).css('cursor', 'initial');
                        $(o).find('.href-link2').css('cursor', 'initial');
                    }
                });

                $(".boxCellPic-container .boxCellPic-overlay").click(function () {
                    if ($(this).find("a").length == 0) return false;

                    window.location = $(this).find("a").attr("href");
                    return false;
                });
            });
        }]);
    };

    return {
        init: init
    };
})();

App.Home.ChooseCountry = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);
        }

        App.angular.controller('MainController', ['$scope', '$http', function ($scope, $http) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {
                selectCountry: function selectCountry(uri, name) {
                    $scope.obj.selectedCountry = name;
                    window.location.replace(uri);
                    $scope.obj.isShow = false;
                }
            };

            angular.element(function () {
                $('body').click(function (evt) {
                    if (evt.target.id === "countrySelectList") return;
                    //For descendants of menu_content being clicked, remove this check if you do not want to put constraint on descendants.
                    if ($(evt.target).closest('#countrySelectList').length) return;

                    $scope.obj.isShow = false;
                    $scope.$apply();
                });
            });
        }]);
    };

    return {
        init: init
    };
})();

App.Home.Privacy = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);
        }

        App.angular.controller('MainController', ['$scope', '$http', function ($scope, $http) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};

            $(function () {
                // add scripts here

            });
        }]);
    };

    return {
        init: init
    };
})();

App.Home.Disclosure = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);
        }

        App.angular.controller('MainController', ['$scope', '$http', function ($scope, $http) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};

            $(function () {
                // add scripts here

            });
        }]);
    };

    return {
        init: init
    };
})();

App.Home.DMCA = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);
        }

        App.angular.controller('MainController', ['$scope', '$http', function ($scope, $http) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};

            $(function () {
                // add scripts here

            });
        }]);
    };

    return {
        init: init
    };
})();

App.Home.Terms = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config == 'object') {
            $.extend(true, _config, config);
        }

        App.angular.controller('MainController', ['$scope', '$http', function ($scope, $http) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};

            $(function () {
                // add scripts here

            });
        }]);
    };

    return {
        init: init
    };
})();

App.Home.Page = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config == 'object') {
            $.extend(true, _config, config);
        }

        App.angular.controller('MainController', ['$scope', '$http', function ($scope, $http) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};

            $(function () {
                // add scripts here

            });
        }]);
    };

    return {
        init: init
    };
})();;
'use strict';

if (typeof App == 'undefined') var App = {};

App.MemberArea = (function () {
    return {};
})();

App.MemberArea.MemberDetail = (function () {
    var _config = {};
    var commentPage = 1;
    var init = function init(config) {
        if (config && typeof config == 'object') {
            $.extend(true, _config, config);
        }

        App.angular.controller('MainController', ['$scope', '$http', '$sce', 'activityService', function ($scope, $http, $sce, activityService) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};
            $scope.obj.commentPagesize = _config.commentsPerPage;
            $scope.obj.Comments = [];
            $scope.obj.following = _config.following;

            $scope.trustHtml = function (html) {
                return $sce.trustAsHtml(html);
            };

            $scope.formatDate = function (dateStr) {
                var date = new Date(parseInt(dateStr.substr(6)));
                return App.formatDate(date);
            };

            $scope.getComments = function (url, $target, callback) {
                if (typeof $target != 'undefined' && $target.length > 0) {
                    $target.loadingOverlay();
                } else {
                    App.loader.showLoader();
                }

                $http.get(url).then(function (response) {
                    // success                       
                    $scope.obj.Comments.push.apply($scope.obj.Comments, response.data.UserComments);

                    if (response.data.UserComments.length < $scope.obj.commentPagesize) {
                        $scope.obj.showMoreComments = false;
                    } else {
                        $scope.obj.showMoreComments = true;
                    }

                    setTimeout(function () {
                        // post processing
                        //App.fixCommentsUserImage();

                    }, 100);

                    if (typeof callback != 'undefined') callback();
                }, function (response) {
                    // error                                               
                })['finally'](function () {
                    if (typeof $target != 'undefined' && $target.length > 0) {
                        $target.loadingOverlay('remove');
                    } else {
                        App.loader.hideLoader();
                    }
                });
            };

            $scope.followUser = function (followedId) {
                activityService.followUser(followedId, _config.followUserUrl)
                .then(function (data) {
                    if (data.result) {
                        $scope.obj.following = true;
                    }
                })
                .catch(function (error) {
                    App.notify.Danger(error.message);
                });
            };

            $scope.unfollowUser= function (followedId) {
                activityService.unFollowUser(followedId, _config.unfollowUserUrl)
                .then(function (data) {
                    if (data.result) {
                        $scope.obj.following = false;
                    }
                })
                .catch(function (error) {
                    App.notify.Danger(error.message);
                });
            };


            $scope.getMoreComments = function () {
                commentPage += 1;
                var url = _config.commentsUrl + '?page=' + commentPage;
                $scope.getComments(url);
            };

            $(function () {
                var $commentsSection = $('#commentsSection');
                if ($commentsSection.length > 0) {
                    $scope.getComments(_config.commentsUrl + '?page=1', $commentsSection);
                }
            });
        }]);
    };

    return {
        init: init
    };
})();;
'use strict';

if (typeof App == 'undefined') var App = {};

App.Notifications = (function () {
    return {};
})();
App.Notifications._NotificationHeader = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config == 'object') {
            $.extend(true, _config, config);
        }

        var notifCount = $('#user-menu-popover-content').find('li[data-notified="0"]').length;
        if (notifCount > 0) {
            $('.user-menu-link').find('span.badge').text(notifCount);
        } else {
            $('.user-menu-link').find('span.badge').hide();
        }
        $('.notif-image').on('error', function () {
            $(this).replaceWith('<div class="icon vcenter round-circle secondary-orange" style="height:40px;">&nbsp;</div>');
        });
    };

    return {
        init: init
    };
})();

App.Notifications.Index = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config == 'object') {
            $.extend(true, _config, config);
        }

        App.angular.controller('MainController', ['$scope', '$http', function ($scope, $http) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};

            $(function () {

                // add event handler here

            });
        }]);
    };

    return {
        init: init
    };
})();;
'use strict';
if (typeof App === 'undefined') var App = {};
App.Product = (function () {
    return {};
})();

App.Product.Index = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);
        }
    };
    return {
        init: init
    };
})();

App.Product.ProductSuggestion = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);
        }

        App.angular.controller('MainController', ['$scope', '$http', function ($scope, $http) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};
            angular.element(document).ready(function () { // add scripts here
            });
        }]);

        App.angular.controller('productSuggestionController', ['$scope', '$location', '$anchorScroll', '$window', function ($scope, $location, $anchorScroll, $window) {
            var productSupport = this;
            productSupport.productName = '';
            productSupport.brandName = '';
            productSupport.suggestion = '';
            productSupport.displayFailedMessage = false;
            productSupport.messageTimer = null;
            productSupport.hasProductNameError = false;
            productSupport.hasProductBrandError = false;
            productSupport.hasProductSuggestionError = false;
            angular.element(document).ready(function () {});
            productSupport.submitSuggestion = function () { // validate
                var hasError = false;
                if (productSupport.productName.trim() === '') {
                    productSupport.hasProductNameError = true;
                    hasError = true;
                }
                if (productSupport.brandName.trim() === '') {
                    productSupport.hasProductBrandError = true;
                    hasError = true;
                }
                if (productSupport.suggestion.trim() === '') {
                    productSupport.hasProductSuggestionError = true;
                    hasError = true;
                }
                if (hasError) return; // put up the loader
                App.loader.showLoader();
                var data = {
                    productName: productSupport.productName,
                    brandName: productSupport.brandName,
                    suggestion: productSupport.suggestion
                };
                $.post(_config.submitFeedbackUri, data).done(function (result) {
                    if (result.result === false) {
                        productSupport.displayFailedMessage = true;
                        $location.hash('failed-message');
                        productSupport.startMessageTimer();
                        $scope.$apply();
                        $anchorScroll(); // hide the loader
                        App.loader.hideLoader();
                    } else {
                        productSupport.productName = '';
                        productSupport.brandName = '';
                        productSupport.suggestion = '';
                        $scope.$apply();
                        $window.location.href = result.result.toString();
                    }
                }).fail(function () {
                    productSupport.displayFailedMessage = true;
                    $location.hash('failed-message');
                    productSupport.startMessageTimer();
                    $scope.$apply();
                    $anchorScroll(); // hide the loader
                    App.loader.hideLoader();
                });
            };
            productSupport.startMessageTimer = function () { // Set a timer to hide the message panel
                productSupport.messageTimer = setTimeout(function () {
                    productSupport.messageTimer = null;
                    productSupport.displayFailedMessage = false;
                    $scope.$apply();
                }, 5000);
            };
        }]);
    };
    return {
        init: init
    };
})();

App.Product.Details = (function () {
    var _config = {
        'commentsPageSize': 15,
        'commentsUrl': '',
        'reviewResponseUrl': '',
        'loginUrl': '',
        'deleteCommentUrl': '',
        'T_ErrorProcessingRequest': ''
    };
    var init = function init(config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);
        }
        App.angular.config(['$locationProvider', function ($locationProvider) { // use the HTML5 History API            
            $locationProvider.html5Mode({
                enabled: true,
                rewriteLinks: false // make link on same base clickable or work normally
            });
        }]);

        App.angular.controller('MainController', ['$compile', '$location', '$scope', '$http', '$sce', 'activityService', function ($compile, $location, $scope, $http, $sce, activityService) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $http.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
            $scope.obj = {};
            $scope.obj.isDebug = $location.absUrl().indexOf('debug=1') > -1 ? true : false;
            $scope.obj.uId = _config.uId;
            $scope.obj.canReview = _config.canReview > 0;
            $scope.obj.isMobile = _config.isMobile;
            $scope.commentsSearch = '';
            $scope.commentsRdoRating = '';
            $scope.commentType = '';
            $scope.commentsStarFilter = [];
            $scope.commentsTotalRows = 0; // initialized in /product/_comments
            $scope.commentsTempData = [];
            $scope.pagination = {
                current: _config.currentPage
            };
            $scope.commentsOrderBy = _config.defaultOrderBy; // display radio model
            $scope.currentOrderBy = _config.defaultOrderBy; //
            $scope.commentsOrderByLocal = _config.defaultOrderBy; // actual order value pass as parameter
            $scope.obj.following = _config.following;
            $scope.T_Reply = _config.T_Reply;
            $scope.T_Cancel = _config.T_Cancel;
            $scope.T_Submit = _config.T_Submit;
            $scope.T_WriteYourReponsePlaceholder = _config.T_WriteYourReponsePlaceholder;
            $scope.T_DeleteComment = _config.T_DeleteComment;
            $scope.T_ConfirmDeleteComment = _config.T_ConfirmDeleteComment;
            $scope.T_Delete = _config.T_Delete; // initialize interface from url params

            $scope.obj.askQuestionCallback = function () {
                var obj = arguments[0];
                var answerTxt = obj.answer;
                var data = obj.data;
                var questionTitle = obj.title;
                var modal = obj.modal;

                // prepend new question
                if ($('#questionTemplate').length > 0) {
                    var tmpHtml = $('#questionTemplate').clone().html().replace(/%qt_id%/g, data.result)
                        .replace(/%qt_title%/g, questionTitle)
                        .replace(/%qt_description%/g, answerTxt)
                        .replace(/%qt_datecreated%/g, $scope.getCurrDate());

                    $('#divUserQuestions div:first').prepend(tmpHtml);
                }

                var $addedDiv = $('#divUserQuestions div:first-child');

                // add tooltips
                $addedDiv.find(".tooltips").tooltip({ trigger: "hover" });

                // Scroll to Q and A
                $('html, body').animate({
                    scrollTop: $("#questionanswer").offset().top
                }, 500);

                if (modal) modal.modal('hide');
            }

            var searchObject = $location.search();
            // initialize pagesize
            $scope.commentsPageSize = _config.commentsPerPage; // default
            if (typeof searchObject.pagesize !== 'undefined') {
                $scope.commentsPageSize = searchObject.pagesize;
            } // initialize comtype            
            if (typeof searchObject.comtype !== 'undefined') {
                $scope.commentType = searchObject.comtype;
            } // initialize sort by
            if (typeof searchObject.orderby !== 'undefined') {
                $scope.commentsOrderBy = searchObject.orderby;
                $scope.commentsOrderByLocal = searchObject.orderby;
                var comTypeAr = $scope.commentType.split(',');
                if (comTypeAr.indexOf('1') > -1) { // homeTested
                    $scope.commentsOrderBy = 'haveTried';
                } else if (comTypeAr.indexOf('2') > -1) { // homeTested
                    $scope.commentsOrderBy = 'homeTested';
                }
                $scope.currentOrderBy = $scope.commentsOrderBy;
            } else { // check auto reorder 'TESTED' to 'NEWEST' due to no data
                var autoOrder = $('#reviewOrder').data('defaultorderby');
                if (_config.defaultOrderBy !== autoOrder) {
                    $scope.commentsOrderBy = autoOrder;
                    $scope.currentOrderBy = autoOrder;
                }
            } // initialize star rating filter based on startrating URL param
            if (typeof searchObject.starfilter !== 'undefined') {
                $scope.commentsStarFilter.push(searchObject.starfilter.split(','));
                $scope.commentsRdoRating = '' + searchObject.starfilter; // check the rating radio                
            }
            $scope.getCommentsRatingsFilter = function () {
                $scope.commentsStarFilter = []; // reset star filter
                var rating = $('[name=radioRating]:checked').val();
                if (rating !== '') $scope.commentsStarFilter.push(rating);
            };
            $scope.getCommentTypeFilter = function (sortBy) {
                $scope.commentsOrderByLocal = sortBy;
                $scope.commentType = '';
                if (sortBy === 'homeTested') {
                    $scope.commentsOrderByLocal = 'id desc';
                    $scope.commentType = '2';
                } else if (sortBy === 'haveTried') {
                    $scope.commentsOrderByLocal = 'id desc';
                    $scope.commentType = '1';
                }
            };
            $scope.getUrlParam = function () {
                var starFilters = $scope.commentsStarFilter.join(',');
                var filterParam = '?page=' + $scope.pagination.current + '&pagesize=' + $scope.commentsPageSize;
                filterParam += $scope.commentsOrderByLocal !== '' && typeof $scope.commentsOrderByLocal !== 'undefined' ? '&orderby=' + $scope.commentsOrderByLocal : '';
                filterParam += $scope.commentType !== '' ? '&comtype=' + $scope.commentType : '';
                filterParam += starFilters !== '' ? '&starfilter=' + starFilters : '';
                filterParam += $scope.commentsSearch !== '' ? '&search=' + $scope.commentsSearch : '';
                return filterParam;
            };
            $scope.getPageParam = function () {
                var starFilters = $scope.commentsStarFilter.join(',');
                var strFilter = '';
                var filterParam = [];
                if ($scope.commentsOrderByLocal !== '' && typeof $scope.commentsOrderByLocal !== 'undefined') filterParam.push('orderby=' + $scope.commentsOrderByLocal);
                if ($scope.commentType !== '') filterParam.push('comtype=' + $scope.commentType);
                if (starFilters !== '') filterParam.push('starfilter=' + starFilters);
                if ($scope.commentsSearch !== '') filterParam.push('search=' + $scope.commentsSearch);
                if (filterParam.length > 0) {
                    strFilter = '&' + filterParam.join('&');
                }
                if (_config.defaultPerPage !== $scope.commentsPageSize) {
                    return '?review-page=' + $scope.pagination.current + ',' + $scope.commentsPageSize + strFilter;
                } else {
                    return '?review-page=' + $scope.pagination.current + strFilter;
                }
            };
            $scope.fixUserImage = function () {
                $('.user-profile-img').each(function (i, div) {
                    var img = $(div)[0],
                        style = img.currentStyle || window.getComputedStyle(img, false),
                        bi = style.backgroundImage.slice(4, -1).replace(/"/g, "");
                    $('<img/>').attr('src', bi).on('load', function () {
                        $(this).remove(); // prevent memory leaks
                    }).on('error', function () {
                        var $this = $(div);
                        var fname = $this.data('fname');
                        $this.parent().html('<div class="review-user_letter">' + fname[0].toUpperCase() + '</div>');
                    });
                });
            };
            $scope.getCurrDate = function () {
                var today = new Date();
                var dd = today.getDate();
                var mm = today.getMonth() + 1; //January is 0! 
                var yyyy = today.getFullYear();
                if (dd < 10) {
                    dd = '0' + dd;
                }
                if (mm < 10) {
                    mm = '0' + mm;
                }
                var currDate = dd + '/' + mm + '/' + yyyy;
                return currDate;
            };
            $scope.getChildComments = function (parentIds, callback) {
                $http.post(_config.childCommentsUrl, $.param({
                    parentIds: parentIds
                })).then(function (response) { // success                                             
                    $scope.obj.ChildComments = response.data.ChildComments;
                    $scope.obj.ChildCommentsReplies = response.data.ChildCommentsReplies; // set tooltips
                    $(".tooltips").tooltip({
                        trigger: "hover"
                    }); // fix avatar image
                    //$scope.fixUserImage();                        
                    if (typeof callback !== 'undefined') callback();
                }, function (response) { // error                                                
                })['finally'](function () {
                    App.loader.hideLoader();
                });
            };
            $scope.obj.hideMoreComments = false;
            $scope.getComments = function (url, callback, appendonly) {
                App.loader.showLoader();
                $http.get(url).then(function (response) { // success                        
                    if (typeof appendonly !== 'undefined' && appendonly === true) {
                        $('#divReviewSection').append(response.data); // rebind angularjs scope on appended comments
                        $compile($('.div-more-comments').last().contents())($scope);
                    } else {
                        $('#divReviewSection').parent().replaceWith(response.data); // rebind angularjs scope on divReviewSection
                        $compile($('#divReviewSection').parent().contents())($scope);
                    } // colorize stars based on product ratings
                    $('.js-star-rating').makeStars(); // set tooltips
                    $(".tooltips").tooltip({
                        trigger: "hover"
                    }); // floating label event
                    $('.form-floating-label input, .form-floating-label textarea').focusin(function () {
                        $(this).parent().addClass('has-value');
                    });
                    $('.form-floating-label input, .form-floating-label textarea').blur(function () {
                        if (!$(this).val().length > 0) {
                            $(this).parent().removeClass('has-value');
                        }
                    });
                    setTimeout(function () { // fix avatar image
                        $scope.fixUserImage();
                        $.each($('.forthumbnail'), function () {
                            genVideoThumbnail($(this));
                        });
                    }, 300);
                    if (typeof callback !== 'undefined') callback();
                }, function (response) { // error                                                
                })['finally'](function () {
                    App.loader.hideLoader();
                });
            };
            $scope.FindUserMessageStamp = function (comment) {
                return _.find($scope.obj.MessagesStamps, function (item) {
                    return item.ItemId === comment.Id;
                });
            };
            $scope.obj.UsersUploads = [];
            $scope.obj.userUploadPage = 1;
            $scope.obj.showMoreUploads = true;
            $scope.getUsersUploads = function (page, pageSize, orderBy, $targetContainer, successCallback, errorCallback) {
                if (typeof $targetContainer !== 'undefined') { //$targetContainer.loadingOverlay();
                }
                var url = _config.testersGalleryUrl + '?page=' + page + '&pageSize=' + pageSize + '&sortBy=' + orderBy;
                url += $scope.obj.isDebug ? '&debug=1' : '';
                $http.get(url).then(function (response) {
                    $scope.obj.Queries = response.data.Queries;
                    if (response.data.UsersUploads.length < $scope.obj.userUploadPagesize) {
                        $scope.obj.showMoreUploads = false;
                    } else {
                        $scope.obj.showMoreUploads = true;
                    } // call callback if provided
                    if (typeof successCallback !== 'undefined') successCallback(response.data);
                }, function (response) { // error 
                    if (typeof errorCallback !== 'undefined') errorCallback(response);
                    console.log(response.statusText);
                })['finally'](function () { // 
                    if (typeof $targetContainer !== 'undefined') {
                        $targetContainer.loadingOverlay('remove');
                    }
                });
            };
            $scope.getUsersReview = function (uId, callback) {
                var url = _config.getUserReviewUrl + '&uId=' + uId;
                $http.get(url).then(function (response) { // call callback if provided
                    if (typeof callback !== 'undefined') callback(response.data);
                }, function (response) { // error 
                    console.log(response.statusText);
                })['finally'](function () { //                         
                });
            };
            $scope.fullGalleryData = [];
            $scope.obj.ngUserUploadPage = 0;
            $scope.obj.showMoreUploadsFG = false;
            $scope.obj.showTextLoading = true;
            $scope.obj.galleryFullPerPage = _config.galleryFullPerPage;
            $scope.getMoreUsersUploadsNg = function ($event) {
                if ($scope.obj.showMoreUploadsFG || $scope.obj.ngUserUploadPage === 0) {
                    $scope.obj.ngUserUploadPage += 1;
                    var btn;
                    if (typeof $event !== 'undefined') { // add loading to btn and disable
                        btn = $($event.currentTarget);
                        btn.prepend('<i class="fa fa-spinner fa-spin"></i> ');
                        btn.addClass('disabled');
                    }
                    $scope.getUsersUploads($scope.obj.ngUserUploadPage, $scope.obj.galleryFullPerPage, 'quality desc,dateCreated desc', undefined, function (data) { // on success
                        $scope.obj.showTextLoading = false; // Merges response comments to fullGalleryData                            
                        Array.prototype.push.apply($scope.fullGalleryData, data.UsersUploads);
                        if (data.UsersUploads.length < $scope.obj.galleryFullPerPage) {
                            $scope.obj.showMoreUploadsFG = false;
                        } else {
                            $scope.obj.showMoreUploadsFG = true;
                        } // Add items to modal thumbnails if not exist
                        var $carousel = $('#userGalleryModal .modalgallery-carousel');
                        for (var i = 0; i < data.UsersUploads.length; i++) {
                            var up = data.UsersUploads[i];
                            var item = $('.modalgallery-carousel').find('a[data-uploadid="' + up.Id + '"]');
                            if (item.length > 0) continue;
                            var slHtmlthumb = '<div><a href="" name="lnkModalThumbnail" data-uploadid="' + up.Id + '">';
                            if (up.IsYouTube) {
                                slHtmlthumb += '<div class="tester-gallery-nav-vid-icon">' + '<i class="fa fa-play fa-4x"></i>' + '<div class="tester-gallery-thumb" style="background-image: url(' + up.Thumbnail + ')"></div>' + '</div>';
                            } else if (up.IsVideo) {
                                slHtmlthumb += '<div class="tester-gallery-nav-vid-icon">' + '<i class="fa fa-play fa-4x"></i>' + '<div class="tester-gallery-thumb" style="background-image: url(https://tools.buchanangroup.com/videothumbnail/Thumbnail.ashx?vid=' + up.FileName + ')"></div>' + '</div>';
                            } else if (up.IsImage || up.PType === 'IG') {
                                slHtmlthumb += '<div class="tester-gallery-thumb" style="background-image: url(' + up.Thumbnail + ')"></div>';
                            }
                            slHtmlthumb += '</a></div>'; // add to carousel                             
                            $carousel.slick('slickAdd', slHtmlthumb);
                        } // check image for error
                        for (var ii = 0; ii < data.UsersUploads.length; ii++) {
                            var up2 = data.UsersUploads[ii];
                            if (up2.IsImage || up2.PType === 'IG') {
                                $('<img/>').attr('src', up2.Thumbnail).data('uploadid', up2.Id).data('ptype', up2.PType).on('load', function () {
                                    $(this).remove(); // prevent memory leaks
                                }).on('error', function () { // on error 
                                    var $this = $(this);
                                    var upId = $this.data('uploadid');
                                    var pType = $this.data('ptype');
                                    for (var j = 0; j < $scope.fullGalleryData.length; j++) {
                                        if ($scope.fullGalleryData[j].Id === upId) {
                                            $scope.$apply(function () {
                                                $scope.fullGalleryData.splice(j, 1);
                                            });
                                            break;
                                        }
                                    } // remove item from carousel
                                    var thumb = $('.modalgallery-carousel a[data-uploadid="' + upId + '"]').parent();
                                    $carousel.slick('slickRemove', $('.modalgallery-carousel .slick-slide').index(thumb)); // report broken image to server
                                    $scope.takeOfflineUpload(upId, pType);
                                });
                            }
                        }
                        if (typeof btn !== 'undefined') {
                            btn.removeClass('disabled');
                            btn.find('i').remove();
                        }
                    }, function (res) { // on fail
                        if (typeof btn !== 'undefined') {
                            btn.removeClass('disabled');
                            btn.find('i').remove();
                        }
                    });
                }
            };
            $scope.takeOfflineUpload = function (uploadId, pType) {
                var jqxhr = $.post(_config.takeOfflineUploadUrl, {
                    id: uploadId,
                    pType: pType
                }, function (data) {}).fail(function () {
                    console.log(_config.T_ErrorProcessingRequest);
                }).always(function () {});
            };
            $scope.removeGalleryImageWithError = function (imgDiv, onErrorCallback) {
                var $carousel = $('#userGalleryModal .modalgallery-carousel');
                $(imgDiv).each(function (i, div) {
                    var img = $(div)[0],
                        style = img.currentStyle || window.getComputedStyle(img, false),
                        bi = style.backgroundImage.slice(4, -1).replace(/"/g, "");
                    $('<img/>').attr('src', bi).on('load', function () {
                        $(this).remove(); // prevent memory leaks
                    }).on('error', function () {
                        var $link = $(div).parent().parent();
                        var uploadId = $link.data('uploadid');
                        var pType = $link.data('ptype'); // call on error function
                        onErrorCallback($link); // remove item from carousel
                        var thumb = $('.modalgallery-carousel a[data-uploadid="' + uploadId + '"]').parent();
                        $carousel.slick('slickRemove', $('.modalgallery-carousel .slick-slide').index(thumb)); // report broken image to server
                        $scope.takeOfflineUpload(uploadId, pType);
                    });
                });
            };
            $scope.getMoreUsersUploads = function ($event, elementId, pageSize, callback) {
                if ($scope.obj.showMoreUploads) {
                    $scope.obj.userUploadPage += 1;
                    var btn;
                    if (typeof $event !== 'undefined') { // add loading to btn and disable
                        btn = $($event.currentTarget);
                        btn.prepend('<i class="fa fa-spinner fa-spin"></i> ');
                        btn.addClass('disabled');
                    }
                    $scope.getUsersUploads($scope.obj.userUploadPage, pageSize, 'quality desc,dateCreated desc', undefined, function (data) { // on sucess
                        var slHtml = '';
                        var $carousel = $('#userGalleryModal .modalgallery-carousel');
                        if (data.UsersUploads.length < pageSize) {
                            $scope.obj.showMoreUploads = false;
                        } else {
                            $scope.obj.showMoreUploads = true;
                        }
                        for (var i = 0; i < data.UsersUploads.length; i++) {
                            var up = data.UsersUploads[i];
                            slHtml += '<div data-uid="' + up.Id + '" class="col-xs-4" style="display: inline-block;">' + '<a href="#userGalleryModal" alt="' + up.AltLabel + '" data-dismiss="modal" data-toggle="modal" data-ptype="' + up.PType + '" ' + 'data-uploadid="' + up.Id + '" data-file="' + up.UploadUrl + '" data-type="' + up.DataType + '" ' + 'data-username="' + up.UserName + '" data-suburb="' + up.SubUrb + '" data-reviewtitle="' + up.ReviewTitle + '" ' + 'data-reviewtext="' + up.ReviewText + '" data-reviewtextshort="' + up.ReviewTextShort + '" ' + 'data-rating="' + up.ReviewStarRating + '" data-liked="' + up.Liked + '" data-description="' + up.Description + '" ' + 'data-isinstagram="' + up.IsInstagram + '" data-isuserupload="' + up.IsUsersUpload + '" data-usermessagestamp="' + up.UserMessageStamp + '" ' + '">';
                            if (up.PType === 'IG') {
                                slHtml += '<div class="tester-galler-insta">' + '<i class="fa fa-instagram" aria-hidden="true"></i><div aria-label="' + up.AltLabel + '" style="background-image: url(' + up.Thumbnail + ')" class="tester-gallery-height"></div>' + '</div>';
                            } else if (up.IsImage) {
                                slHtml += '<div aria-label="' + up.AltLabel + '" style="background-image: url(' + up.Thumbnail + ')" class="tester-gallery-height"></div>';
                            } else if (up.IsYouTube) {
                                slHtml += '<div class="tester-galler-vid"><i class="fa fa-play fa-4x"></i><div style="background-image: url(' + up.Thumbnail + ')" class="tester-gallery-height"></div></div>';
                            } else if (up.IsVideo) {
                                slHtml += '<div class="tester-galler-vid">' + '<i class="fa fa-play fa-4x"></i><div style="background-image: url(https://tools.buchanangroup.com/videothumbnail/Thumbnail.ashx?vid=' + up.FileName + ')" class="tester-gallery-height"></div>' + '</div>';
                            }
                            slHtml += '<div class="margin-t15 margin-b15 hidden-xs">' + '<p class="body-font-p text-size-18 text-center color-252525">' + up.UserName + '</p></div>' + '</a ></div >'; // find upload in carousel, add if not found
                            var item = $carousel.find('a[data-uploadid="' + up.Id + '"]');
                            if (item.length === 0) {
                                var slHtmlthumb = '<div><a href="" name="lnkModalThumbnail" data-uploadid="' + up.Id + '">';
                                if (up.IsYouTube) {
                                    slHtmlthumb += '<div class="tester-gallery-nav-vid-icon">' + '<i class="fa fa-play fa-4x"></i>' + '<div class="tester-gallery-thumb" style="background-image: url(' + up.Thumbnail + ')"></div>' + '</div>';
                                } else if (up.IsVideo) {
                                    slHtmlthumb += '<div class="tester-gallery-nav-vid-icon">' + '<i class="fa fa-play fa-4x"></i>' + '<div class="tester-gallery-thumb" style="background-image: url(https://tools.buchanangroup.com/videothumbnail/Thumbnail.ashx?vid=' + up.FileName + ')"></div>' + '</div>';
                                } else if (up.IsImage || up.PType === 'IG') {
                                    slHtmlthumb += '<div class="tester-gallery-thumb" style="background-image: url(' + up.Thumbnail + ')"></div>';
                                }
                                slHtmlthumb += '</a></div>'; // add to carousel                                 
                                $carousel.slick('slickAdd', slHtmlthumb);
                            }
                        }
                        $('#' + elementId).append(slHtml); // remove image with errors from gallery
                        $scope.removeGalleryImageWithError('#userUploadsGallery .tester-galler-insta div', function ($link) { // remove the item from gallery
                            $link.parent().remove();
                        });
                        if (typeof btn !== 'undefined') {
                            btn.removeClass('disabled');
                            btn.find('i').remove();
                        }
                        if (typeof callback !== 'undefined') {
                            callback(data);
                        }
                    }, function (res) { // on fail 
                        if (typeof btn !== 'undefined') {
                            btn.removeClass('disabled');
                            btn.find('i').remove();
                        }
                    });
                }
            };
            $scope.obj.SimilarProducts = [];
            $scope.obj.similarProductsPage = 1;
            $scope.obj.similarProductsPagesize = 21;
            $scope.getSimilarProducts = function (page, $targetContainer, callback) {
                if (_config.productCategoryId === '') return;
                if (typeof $targetContainer !== 'undefined') {
                    $targetContainer.loadingOverlay();
                }
                var url = _config.similarProductsUrl + '?page=' + page + '&category=' + _config.productCategoryId + '&pageSize=' + $scope.obj.similarProductsPagesize;
                url += $scope.obj.isDebug ? '&debug=1' : ''; //console.log(url);
                $http.get(url).then(function (response) {
                    $scope.obj.Queries = response.data.Queries; // append new data to SimilarProducts
                    $scope.obj.SimilarProducts.push.apply($scope.obj.SimilarProducts, response.data.SimilarProducts);
                    if (response.data.SimilarProducts.length < $scope.obj.similarProductsPagesize) {
                        $scope.obj.showMoreSimilarProducts = false;
                    } else {
                        $scope.obj.showMoreSimilarProducts = true;
                    }
                    setTimeout(function () { // colorize stars based on product ratings
                        $('.js-star-rating').makeStars();
                    }, 100); // call callback if provided
                    if (typeof callback !== 'undefined') callback();
                }, function (response) { // error 
                    console.log(response.statusText);
                })['finally'](function () { // 
                    if (typeof $targetContainer !== 'undefined') {
                        $targetContainer.loadingOverlay('remove');
                    }
                });
            };
            $scope.commentsPageChangeHandler = function (pageSize) {
                $scope.commentsPageSize = pageSize;
                var url = _config.commentsUrl + $scope.getUrlParam();
                $scope.getComments(url, function () { // go to review section
                    $('html, body').animate({
                        scrollTop: $("#reviews").offset().top
                    }, 500);
                });
                $location.url(_config.productUrl + $scope.getPageParam());
            };
            $scope.commentsSortChange = function ($event, sortBy) { // prevent fetch if user click same order as previous
                if ($scope.currentOrderBy === sortBy) return;
                $scope.currentOrderBy = sortBy;
                $scope.getCommentTypeFilter(sortBy);
                $scope.pagination.current = 1;
                var url = _config.commentsUrl + $scope.getUrlParam();
                $scope.getComments(url, function () { // go to review section
                    $('html, body').animate({
                        scrollTop: $("#reviews").offset().top
                    }, 500);
                });
                $location.url(_config.productUrl + $scope.getPageParam());
            };
            $scope.commentsRatingChange = function () {
                $scope.commentsStarFilter = [];
                $scope.pagination.current = 1;
                var rating = $('[name=radioRating]:checked').val();
                if (rating !== '') $scope.commentsStarFilter.push(rating);
                var url = _config.commentsUrl + $scope.getUrlParam();
                $scope.getComments(url, function () { // go to review section
                    $('html, body').animate({
                        scrollTop: $("#reviews").offset().top
                    }, 500);
                });
                $location.url(_config.productUrl + $scope.getPageParam());
            };
            $scope.commentsRatingChangeXs = function () {
                $scope.commentsStarFilter = [];
                $scope.pagination.current = 1;
                var rating = $('[name=radioRatingXs]:checked').val();
                if (rating !== '') $scope.commentsStarFilter.push(rating);
                var url = _config.commentsUrl + $scope.getUrlParam();
                $scope.getComments(url, function () { // go to review section
                    $('html, body').animate({
                        scrollTop: $("#reviews").offset().top
                    }, 500);
                });
                $location.url(_config.productUrl + $scope.getPageParam());
            }; /* new functions */
            $scope.getProductComments = function () {
                var url = _config.commentsUrl + $scope.getUrlParam();
                $scope.getComments(url);
            };
            var totalCommentPages = $('#divReviewSection').data('totalpages');
            if (totalCommentPages === 1) $scope.obj.hideMoreComment = true;
            $scope.getMoreComments = function () {
                var currPage = parseInt($scope.pagination.current) + 1;
                $scope.pagination.current = currPage;
                var url = _config.commentsUrl + $scope.getUrlParam() + '&isMoreComments=true';
                $scope.getComments(url, undefined, true);
                if (currPage >= totalCommentPages) {
                    $scope.obj.hideMoreComments = true;
                }
            };
            $scope.formatSuburb = function (userString) {
                if (typeof userString === 'undefined') return '';
                return App.titleCase(userString.split('|')[0]);
            };
            $scope.formatDate = function (dateStr) {
                var date = new Date(parseInt(dateStr.substr(6)));
                return App.formatDate(date);
            };
            $scope.trustSrc = function (src) {
                return $sce.trustAsResourceUrl(src);
            };
            $scope.escapeQuote = function (str) {
                if (str === null || str.isNullOrEmpty()) return '';
                return str.replace(/'/g, "\\'");
            };
            angular.element(document).ready(function () { // preload images
                if (document.images) {
                    var img1 = new Image();
                    img1.src = "/images/heart-outline-purple.gif";
                }
                var slickOptions3 = {
                    dots: false,
                    infinite: false,
                    speed: 300,
                    slidesToShow: 3,
                    slidesToScroll: 3,
                    responsive: [{
                        breakpoint: 920,
                        settings: {
                            slidesToShow: 2,
                            slidesToScroll: 2
                        }
                    }, {
                        breakpoint: 700,
                        settings: {
                            slidesToShow: 1,
                            slidesToScroll: 1
                        }
                    }]
                }; // Get first page comments
                $scope.getCommentTypeFilter($scope.commentsOrderBy); // set the actual parameter based on default order by
                //$scope.getProductComments();
                // Get child comments
                var commentsIds = [];
                $('.tab-reviews-comments-wrapper > div').each(function () {
                    var id = $(this).attr('id');
                    if (!isNaN(id)) {
                        commentsIds.push($(this).attr('id'));
                    }
                });
                $('#productsCarousel .custom-carousel').on('afterChange', function (event, slick, currentSlide) { //var itemLength = $scope.obj.SimilarProducts.length - 1;
                    if (slick.$slides.length - 1 === currentSlide) { //console.log('end');
                        if ($scope.obj.showMoreSimilarProducts) {
                            $scope.obj.similarProductsPage += 1;
                        }
                    }
                }); // Show float panel on scrollTop > 300
                $(window).scroll(function () {
                    if ($(this).scrollTop() > 300) {
                        $('.float-panel').css('display', 'block').addClass('fixed');
                    } else {
                        $('.float-panel').css('display', 'none').removeClass('fixed');
                    }
                });
                var updateScrollToActive = function updateScrollToActive(link) {
                    var $link = $(link);
                    $link.parent().parent().find('li.active').removeClass('active'); //$link.parent().addClass('active');
                };
                var floatMenuOffsetScroll = $(window).width() < 768 ? 135 : 90;
                $(document).on('click', 'a[name=scrollToReviews]', function () {
                    $('html, body').animate({
                        scrollTop: $("#reviews").offset().top - (60 + floatMenuOffsetScroll)
                    }, 500);
                    updateScrollToActive(this);
                });
                $(document).on('click', 'a[name=scrollToTestersGallery]', function () {
                    $('html, body').animate({
                        scrollTop: $("#testersgallery").offset().top - (40 + floatMenuOffsetScroll)
                    }, 500);
                    updateScrollToActive(this);
                });
                $(document).on('click', 'a[name=scrollToSimilarProducts]', function () {
                    $('html, body').animate({
                        scrollTop: $("#similarproducts").offset().top - (90 + floatMenuOffsetScroll)
                    }, 500);
                    updateScrollToActive(this);
                });
                $(document).on('click', 'a[name=scrollToExtendedContent]', function () {
                    $('html, body').animate({
                        scrollTop: $("#extendedcontent").offset().top - (90 + floatMenuOffsetScroll)
                    }, 500);
                    updateScrollToActive(this);
                });
                $(document).on('click', 'a[name=scrollToBuyNow]', function () {
                    $('html, body').animate({
                        scrollTop: $("#buynow").offset().top - (60 + floatMenuOffsetScroll)
                    }, 500);
                    updateScrollToActive(this);
                });
                $(document).on('click', 'a[name=scrollToQuestionAnswer]', function () {
                    $('html, body').animate({
                        scrollTop: $("#questionanswer").offset().top - (45 + floatMenuOffsetScroll)
                    }, 500);
                    updateScrollToActive(this);
                });
                $scope.updateCommentLikes = function updateCommentLikes($event, commentId, likedCount) {
                    if ($scope.obj.uId === 0) {
                        return window.location = _config.loginUrl + '?returnurl=' + encodeURIComponent(_config.productUrl + $scope.getPageParam() + '#' + commentId);
                    } // use animate heart loading
                    var currTarget = $($event.currentTarget);
                    currTarget.find('img').attr('src', '/images/heart-outline-purple.gif'); // change to animated heart                    
                    angular.element($event.currentTarget).unbind('click'); // remove ng-click
                    var postData = {
                        id: commentId,
                        theTable: _config.tableToVote,
                        type: 1
                    };
                    var jqxhr = $.post(_config.addEmojiCommentUrl, postData, function (data) { // post success       
                        if (!data.hasError) { // increment likes
                            likedCount += 1; // add tooltip                            
                            currTarget.find('img').attr('src', '//d2vtntcxpdw15n.cloudfront.net/img3/heart-solid-purple.png'); // change to filled heart
                            currTarget.attr('data-original-title', data).addClass('tooltips');
                            currTarget.next().find('.like-count').removeClass('hide').text(likedCount); // update count
                            $(".tooltips").tooltip({
                                trigger: "hover"
                            });
                        } else {
                            App.notify.Warning(data.message);
                            currTarget.find('img').attr('src', '//d2vtntcxpdw15n.cloudfront.net/img3/heart-outline-purple.png');
                            angular.element($event.currentTarget).bind('click');
                        }
                    }).fail(function () {
                        App.notify.Danger(_config.T_ErrorProcessingRequest);
                        currTarget.find('img').attr('src', '//d2vtntcxpdw15n.cloudfront.net/img3/heart-outline-purple.png');
                        angular.element($event.currentTarget).bind('click');
                    }).always(function () {});
                };


                $scope.followUser = function followUser(followedId) {
                    activityService.followUser(followedId, _config.followUserUrl)
                        .then(function (data) {
                            if (data.result) {
                                $scope.obj.following.push(followedId);
                            }
                        })
                        .catch(function (error) {
                            App.notify.Danger(error.message);
                        });
                };

                $scope.unfollowUser = function unfollowUser(followedId) {
                    activityService.unFollowUser(followedId, _config.unfollowUserUrl)
                        .then(function (data) {
                            if (data.result) {
                                $scope.obj.following = $scope.obj.following.filter(f => f !== followedId);
                            }
                        })
                        .catch(function (error) {
                            App.notify.Danger(error.message);
                        });
                };
                var shareMenuPopper = null;
                var shareMenuContent = $('#share-popover')[0];

                function createShareMenu(refBtn) {
                    shareMenuPopper = Popper.createPopper(refBtn, shareMenuContent, {
                        modifiers: [{
                            name: 'offset',
                            options: {
                                offset: [0, 8]
                            }
                        }]
                    });
                }

                function destroyShareMenu() {
                    if (shareMenuPopper) {
                        shareMenuPopper.destroy();
                        shareMenuPopper = null;
                    }
                }

                function showShareMenu(refBtn) {
                    shareMenuContent.setAttribute('data-show', '');
                    createShareMenu(refBtn);
                }

                function hideShareMenu() {
                    shareMenuContent.removeAttribute('data-show');
                    destroyShareMenu();
                } // hide share menu on click outside
                $(document).on('click', function (e) {
                    var target = $(e.target);
                    if (target.is(shareMenuContent)) return;
                    hideShareMenu();
                });
                $scope.shareReview = function ($event) {
                    $event.stopPropagation();
                    var currTarget = $($event.currentTarget);
                    var pg = _config.currentPage;
                    var cid = currTarget.data('cid');
                    var url = 'https://' + _config.domain + _config.productUrl + (pg > 1 ? '?review-page=' + pg : '') + '#' + cid;
                    var stbtn = $(shareMenuContent).find('.st-custom-button');
                    stbtn.attr('data-url', url); // below top float menu
                    $(shareMenuContent).css('zIndex', 100);
                    showShareMenu(currTarget[0]);
                };
                $scope.shareReviewImage = function ($event) {
                    $event.stopPropagation();
                    var currTarget = $($event.currentTarget);
                    var upid = currTarget.data('uploadid');
                    var pg = _config.currentPage;
                    var url = 'https://' + _config.domain + _config.productUrl + (pg > 1 ? '?review-page=' + pg + '&' : '?') + 'act=show-ugc&upid=' + upid;
                    var stbtn = $(shareMenuContent).find('.st-custom-button');
                    stbtn.attr('data-url', url); // just above modal
                    $(shareMenuContent).css('zIndex', 1060);
                    showShareMenu(currTarget[0]);
                };
                $scope.updateUserUploadsLikes = function ($event) {
                    if ($scope.obj.uId === 0) {
                        return window.location = _config.loginUrl + '?returnurl=' + encodeURIComponent(_config.productUrl + $scope.getPageParam());
                    }
                    var currTarget = $($event.currentTarget); // prevent click if user has already liked
                    if (currTarget.data('hasliked')) return;
                    var likedCount = currTarget.data('liked');
                    var uploadId = currTarget.data('uploadid');
                    currTarget.data('hasliked', true);
                    currTarget.find('img').attr('src', '/images/heart-outline-purple.gif'); // change to animated heart                                        
                    var postData = {
                        id: uploadId,
                        theTable: _config.tableToVoteUserUploads,
                        type: 1
                    };
                    var jqxhr = $.post(_config.addEmojiCommentUrl, postData, function (data) { // post success       
                        if (!data.hasError) { // increment likes
                            likedCount += 1; // upload like count of gallery thumbnail
                            var thumbLink = $('#userUploadsGallery [data-uid=' + uploadId + ']').find('a');
                            thumbLink.data('liked', likedCount);
                            thumbLink.data('usermessagestamp', data); // change to filled heart but be sure to reset to empty on gallery modal init
                            currTarget.find('img').attr('src', '//d2vtntcxpdw15n.cloudfront.net/img3/heart-solid-purple.png'); // add tooltips
                            currTarget.attr('data-original-title', data).addClass('tooltips');
                            currTarget.parent().find('.like-count').removeClass('hide').text(likedCount); // update count
                            currTarget.tooltip('enable');
                            $(".tooltips").tooltip({
                                trigger: "hover"
                            });
                        } else {
                            App.notify.Warning(data.message);
                            currTarget.find('img').attr('src', '//d2vtntcxpdw15n.cloudfront.net/img3/heart-outline-purple.png');
                            currTarget.data('hasliked', false);
                        }
                    }).fail(function () {
                        App.notify.Danger(_config.T_ErrorProcessingRequest);
                        currTarget.find('img').attr('src', '//d2vtntcxpdw15n.cloudfront.net/img3/heart-outline-purple.png');
                        currTarget.data('hasliked', false);
                    }).always(function () {});
                };
                $scope.modalPrev = function ($event) {
                    var $this = $($event.currentTarget);
                    var uploadId = $this.data('uploadid');
                    var thumbLink = $('#userUploadsGallery [data-uid=' + uploadId + ']');
                    var $link = thumbLink.prev().find('a[href="#userGalleryModal"]');
                    if ($link.length === 0) { // find it in full gallery
                        $link = $('#divFullGallery [data-uid=' + uploadId + ']').prev().find('a[href="#userGalleryModal"]');
                    }
                    if ($link.length > 0) {
                        initGalleryModal($link);
                    } else { // if from comments section and item not on gallery
                        // just go to the first item in gallery if not already the first
                        var first = $('#userUploadsGallery a[href="#userGalleryModal"]:first');
                        if (first.length > 0 && first.data('uploadid') !== uploadId) {
                            initGalleryModal(first);
                        }
                    }
                };
                $scope.modalNext = function ($event) {
                    var $this = $($event.currentTarget);
                    var uploadId = $this.data('uploadid');
                    var thumbLink = $('#userUploadsGallery [data-uid=' + uploadId + ']');
                    var $link = thumbLink.next().find('a[href="#userGalleryModal"]');
                    if ($link.length === 0) { // find it in full gallery
                        $link = $('#divFullGallery [data-uid=' + uploadId + ']').next().find('a[href="#userGalleryModal"]');
                    }
                    if ($link.length > 0) {
                        initGalleryModal($link);
                    } else {
                        var first = $('#userUploadsGallery a[href="#userGalleryModal"]:first'); // if not found and is from comments section: data-isfromcomment = true
                        // just go to the first item in gallery
                        var isFromComment = $this.data('isfromcomment');
                        if (isFromComment) {
                            if (first.length > 0) {
                                initGalleryModal(first);
                            }
                        } else if ($scope.obj.showMoreUploads) { // reach the end of gallery, load more
                            // show loading on button
                            $this.attr('disabled', 'disabled');
                            $this.html('<i class="fa fa-circle-o-notch fa-spin" style="font-size: 24px;color: white;"></i>');
                            $this.addClass('modal-btn-loading');
                            $scope.getMoreUsersUploads(undefined, 'userUploadsGallery', _config.galleryPerPage, function (data) {
                                $link = thumbLink.next().find('a[href="#userGalleryModal"]');
                                if ($link.length > 0) {
                                    initGalleryModal($link);
                                } // remove loading
                                $this.html('');
                                $this.removeClass('modal-btn-loading');
                                $this.removeAttr('disabled');
                            });
                        } else { // or reach end of gallery, show first item                            
                            if (first.length > 0) {
                                initGalleryModal(first);
                            }
                        }
                    }
                };
                $(document).on('click', 'a[name=lnkModalThumbnail]', function (e) {
                    e.preventDefault();
                    var $this = $(this);
                    var uploadId = $this.data('uploadid');
                    var thumbLink = $('#userUploadsGallery [data-uid=' + uploadId + ']');
                    var $link = thumbLink.find('a[href="#userGalleryModal"]');
                    if ($link.length === 0) { // find it in full gallery
                        $link = $('#divFullGallery [data-uid=' + uploadId + ']').find('a[href="#userGalleryModal"]');
                    }
                    if ($link.length > 0) {
                        initGalleryModal($link);
                    }
                }); // modal gallery slick carousel
                $('#userGalleryModal .modalgallery-carousel').slick({
                    infinite: false,
                    dots: false,
                    slidesToShow: 4,
                    slidesToScroll: 4,
                    variableWidth: true
                });
                $scope.moreDescription = function ($event) {
                    var $this = $($event.currentTarget);
                    var $parent = $this.parent();
                    $parent.find('span').toggle();
                    $parent.parent().find('.moreellipses').toggle();
                    $this.toggleClass('less');
                    if ($this.hasClass('less')) {
                        $this.html(_config.T_ShowLess);
                    } else {
                        $this.html(_config.T_ShowMore);
                    }
                };

                $('#modalAnswerQuestion').on('hidden.bs.modal', function () {
                    $scope.$apply(function () {
                        $scope.obj.answerReplySubmitted = false;
                    });
                });
                
                $(document).on('scroll resize', function () {
                    if ($('.pp-img img').isInViewport() || $('#back-to-top').isInViewport()) $('[data-toggle="scroll-to-top"]:not([id="back-to-top"])').hide();
                    else $('[data-toggle="scroll-to-top"]:not([id="back-to-top"])').show();
                    var floatMenuOffset = 140; // highlight float nav if section is in viewport
                    var navReviews = $('.float-navigation-md [name=scrollToReviews]');
                    var mobReviews = $('.float-navigation-xs [name=scrollToReviews]').parent().parent();
                    var tabReviews = $('.cp-tab-wrapper [name=scrollToReviews]').parent();
                    var navGallery = $('.float-navigation-md [name=scrollToTestersGallery]');
                    var mobGallery = $('.float-navigation-xs [name=scrollToTestersGallery]').parent().parent();
                    var tabGallery = $('.cp-tab-wrapper [name=scrollToTestersGallery]').parent();
                    var navExtended = $('.float-navigation-md [name=scrollToExtendedContent]');
                    var tabExtended = $('.cp-tab-wrapper [name=scrollToExtendedContent]').parent();
                    var navBuyNow = $('.float-navigation-md [name=scrollToBuyNow]');
                    var mobBuyNow = $('.float-navigation-xs [name=scrollToBuyNow]').parent().parent();
                    var tabBuyNow = $('.cp-tab-wrapper [name=scrollToBuyNow]').parent();
                    var navQA = $('.float-navigation-md [name=scrollToQuestionAnswer]');
                    var mobQA = $('.float-navigation-xs [name=scrollToQuestionAnswer]').parent().parent();
                    var tabQA = $('.cp-tab-wrapper [name=scrollToQuestionAnswer]').parent();
                    $('.float-navigation-md a').removeClass('active');
                    $('.float-navigation-xs .float-nav-table').removeClass('activebox');
                    $('.cp-tab-wrapper li').removeClass('active');
                    if ($("#reviews").isInViewport(floatMenuOffset)) {
                        navReviews.addClass('active');
                        mobReviews.addClass('activebox');
                        tabReviews.addClass('active');
                    } else if ($("#testersgallery").isInViewport(floatMenuOffset)) {
                        navGallery.addClass('active');
                        mobGallery.addClass('activebox');
                        tabGallery.addClass('active');
                    } else if ($("#questionanswer").isInViewport(floatMenuOffset)) {
                        navQA.addClass('active');
                        mobQA.addClass('activebox');
                        tabQA.addClass('active');
                    } else if ($("#testersgallery").isInViewport(floatMenuOffset)) {
                        navGallery.addClass('active');
                        mobGallery.addClass('activebox');
                        tabGallery.addClass('active');
                    } else if ($("#buynow").isInViewport()) {
                        navBuyNow.addClass('active');
                        mobBuyNow.addClass('activebox');
                        tabBuyNow.addClass('active');
                    } else if ($("#extendedcontent").isInViewport(floatMenuOffset)) {
                        navExtended.addClass('active');
                        tabExtended.addClass('active');
                    } // load ask question section on-demand
                    var $aq = $('#questionanswer');
                    var $divAq = $('#divUserQuestions');
                    if ($aq.isInViewport() && $divAq.data('loaded') === false) {
                        $divAq.data('loaded', true);
                        $divAq.load(_config.askQuestionUrl + '&page=1', function (_, status) {
                            if (status === 'success') { // compile the html so the angular codes will work
                                var scope = angular.element($divAq).scope();
                                $compile($divAq)(scope);
                                scope.$digest(); // init form jquery events
                                App.Product._UserQuestions.init(_config);
                            }
                        });
                    }
                }); // colorize stars based on product ratings
                $('.js-star-rating').makeStars(); // set tooltips
                $(".tooltips").tooltip({
                    trigger: "hover"
                }); // floating label event
                $('.form-floating-label input, .form-floating-label textarea').focusin(function () {
                    $(this).parent().addClass('has-value');
                });
                $('.form-floating-label input, .form-floating-label textarea').blur(function () {
                    if (!$(this).val().length > 0) {
                        $(this).parent().removeClass('has-value');
                    }
                }); // Similar product carousel
                $('#productsCarousel .custom-carousel').slick(slickOptions3);
                $('.ext-files-gallery').on('click', function () {
                    var $li = $(this).parent().parent(); // get click item index and show it by default
                    var index = $("#extendedFilesGallery li.ext-files-gallery-li").index($li[0]); // generate dynamic content
                    var extEl = [];
                    for (var x = 0; x < _config.extendedFiles.length; x++) {
                        if (_config.extendedFiles[x].FileType.toLowerCase() === 'video') {
                            extEl.push({
                                'html': '#video-ext-' + _config.extendedFiles[x].Id,
                                'thumb': _config.extendedFiles[x].Thumbnail,
                                'subHtml': _config.extendedFiles[x].Description
                            });
                        } else {
                            extEl.push({
                                'src': _config.extendedFiles[x].Url,
                                'thumb': _config.extendedFiles[x].Thumbnail,
                                'subHtml': _config.extendedFiles[x].Description
                            });
                        }
                    }
                    var $lg = $li.parent();
                    $lg.lightGallery({
                        index: index,
                        dynamic: true,
                        dynamicEl: extEl,
                        zoom: false,
                        share: false,
                        fullScreen: false,
                        autoplayControls: false,
                        loadYoutubeThumbnail: true,
                        youtubeThumbSize: 'default',
                        loadVimeoThumbnail: true,
                        vimeoThumbSize: 'thumbnail_medium'
                    });
                });
                var $extFilesGallery = $("#extendedFilesGallery"); // Change extended files gallery background on open
                $extFilesGallery.on('onBeforeSlide.lg', function (event, prevIndex, index) {
                    $('.lg-outer').css('background-color', 'rgba(51, 51, 51, 0.95)');
                }); // destroy gallery on close
                $extFilesGallery.on('onCloseAfter.lg', function (event, index, fromTouch, fromThumb) {
                    $(this).data('lightGallery').destroy(true);
                });
                $("#modalLeaveReview").on("show.bs.modal", function (e) { // go to login page if not logged in
                    if (_config.uId === 0) {
                        var ng = angular.element($('body')).scope(); // get angular scope
                        window.location = _config.loginUrl + '?returnurl=' + encodeURIComponent(_config.productUrl + ng.getPageParam());
                        return false;
                    }
                    var link = $(e.relatedTarget);
                    var $modalBody = $(this).find(".modal-body");
                    if ($modalBody.data('isloaded') === false) {
                        $modalBody.load(link.data("link"), function (_, status) {
                            if (status === 'success') {
                                $modalBody.data('isloaded', true); // avoid reloading the form, double loading will cause the $compile error
                                // compile the html so the angular codes will work
                                var scope = angular.element($modalBody).scope();
                                $compile($modalBody)(scope);
                                scope.$digest();
                            }
                        });
                    }
                }); // user gallery modal, update image/video on modal show
                function initGalleryModal($link) {
                    var user = $link.data('username');
                    var rating = $link.data('rating');
                    var likeCount = parseInt($link.data('liked'));
                    var uploadId = $link.data('uploadid');
                    var reviewText = $link.data('reviewtext');
                    var $modalBody = $('#userGalleryModal').find(".modal-body");
                    $modalBody.find('.review-user_letter').html(user[0].toUpperCase());
                    $modalBody.find('.modal-gallery-username').html(user);
                    $modalBody.find('.modal-review-txt').html(reviewText);
                    $modalBody.find('.modal-review-title').html($link.data('reviewtitle'));
                    $modalBody.find('.js-star-rating').data('rating', rating);
                    var $likeCount = $modalBody.find('.like-count');
                    $likeCount.html(''); // reset like count
                    if (likeCount > 0) {
                        $likeCount.html(likeCount);
                    }
                    $modalBody.find('.modal-btn-prev').data('uploadid', uploadId);
                    $modalBody.find('.modal-btn-next').data('uploadid', uploadId); // set all like buttons (mobile/desktop) attributes and reset
                    $modalBody.find('.review-user-like a').each(function (i) { // add uploadid, and reset like link to all hidden                        
                        $(this).data('uploadid', uploadId).data('liked', likeCount).addClass('hidden');
                    }); // set all share button
                    $modalBody.find('.share-btn-wrapper a').each(function (i) { // add uploadid, and reset like link to all hidden                        
                        $(this).data('uploadid', uploadId);
                    }); // reset lnkLikedAllowed img to outline
                    var lnkAllowed = $modalBody.find('.review-user-like a[name="lnkLikeAllowed"]');
                    lnkAllowed.find('img').attr('src', '//d2vtntcxpdw15n.cloudfront.net/img3/heart-outline-purple.png');
                    lnkAllowed.attr('data-original-title', '');
                    lnkAllowed.tooltip('disable');
                    lnkAllowed.removeClass('tooltips');
                    lnkAllowed.data('hasliked', false); // show like link
                    var messageStamp = $link.data('usermessagestamp');
                    var isUserUpload = $link.data('isuserupload');
                    var isInstagram = $link.data('isinstagram');
                    var type = $link.data('type');
                    var file = $link.data('file');
                    var lnkAL = $modalBody.find('[name=lnkAlreadyLiked]');
                    lnkAL.attr('data-original-title', ''); // reset like tooltip
                    if (messageStamp === '') {
                        lnkAL.attr('data-original-title', '');
                        lnkAL.tooltip('disable');
                    }
                    if (messageStamp !== '') {
                        lnkAL.removeClass('hidden');
                        lnkAL.attr('data-original-title', messageStamp);
                        lnkAL.tooltip('enable');
                        lnkAL.tooltip({
                            trigger: "hover"
                        });
                    } else if (isUserUpload === 'True' || isUserUpload === true) {
                        $modalBody.find('[name=lnkUserOwned]').removeClass('hidden');
                    } else if (isInstagram === 'True' || isInstagram === true) {
                        $modalBody.find('[name=lnkInstagramLiked]').removeClass('hidden');
                    } else {
                        $modalBody.find('[name=lnkLikeAllowed]').removeClass('hidden');
                    }
                    if (rating === 0) {
                        $modalBody.find('.review-user_starrating').addClass('hide');
                    } else {
                        $modalBody.find('.review-user_starrating').removeClass('hide');
                    }
                    var caption = $link.data('description');
                    if (caption !== '' && caption !== null) {
                        var quote = isInstagram === 'True' || isInstagram === true ? "" : "\"";
                        $modalBody.find('.modal-caption-title').html(quote + caption + quote);
                    } // setup overlay text
                    var pType = $link.data('ptype');
                    var reviewTextShort = $link.data('reviewtextshort');
                    var overlayTextDiv = $modalBody.find('.overlay-text-div');
                    overlayTextDiv.data('reviewtextshort', reviewTextShort);
                    overlayTextDiv.html(reviewTextShort);
                    if (pType === 'IG') {
                        overlayTextDiv.data('reviewtext', caption);
                    } else {
                        overlayTextDiv.data('reviewtext', reviewText);
                    }
                    overlayTextDiv.parent().show(); // close overlay text if open
                    overlayTextDiv.parent().addClass('overlay-min-div').removeClass('overlay-full-div');
                    overlayTextDiv.parent().parent().find('.overlay-text-close').addClass('hidden');
                    var imgDiv = $modalBody.find('#divImgGalleryModal');
                    if (type === 'image' || type === 'instagram') {
                        imgDiv.html('<div class="tester-galler-insta"><img src="' + file + '" width="650" class="img-responsive center-block"></div>');
                    } else if (type === 'video') {
                        var vidFile = file.indexOf('http') === 0 ? file : 'https://d13isgnnvtd7yz.cloudfront.net/' + file;
                        imgDiv.html('<div align="center" class="embed-responsive embed-responsive-16by9 tester-galler-vid">' + '<i id="btnPlayModalVideo" class="btn-play-vid fa fa-play fa-4x"></i>' + '<video id="modalVideoPlayer" poster="https://tools.buchanangroup.com/videothumbnail/Thumbnail.ashx?vid=' + file + '" ' + 'onpause="App.Product.Details.onPauseModalVideo()" class="embed-responsive-item" preload="none">' + '<source src= "' + vidFile + '" type = "video/mp4" >' + 'Your browser does not support HTML5 video.' + '</video></div>');
                    } else if (type === 'youtube') {
                        imgDiv.html('<iframe width="420" height="310" class="youtube-vid" src="' + file + '"></iframe>');
                    } // reset rating
                    $modalBody.find('.js-star-rating .fa-star').each(function (index) {
                        $(this).addClass('fa-star-open');
                    });
                    $modalBody.find('.js-star-rating').makeStars(); // report button hide on instagram
                    var rptBtns = $modalBody.find('.report-btn');
                    rptBtns.parent().removeClass('hidden'); // reset
                    rptBtns.attr('data-cid', uploadId);
                    if (isInstagram === 'True' || isInstagram === true) {
                        rptBtns.parent().addClass('hidden');
                    } // slide to that modal thumbnail                    
                    var thumb = $('.modalgallery-carousel a[data-uploadid="' + uploadId + '"]').closest('.slick-slide');
                    var index = $('.modalgallery-carousel .slick-slide').index(thumb);
                    $('#userGalleryModal .modalgallery-carousel').slick('slickGoTo', index);
                }
                $(document).on('click', '#btnPlayModalVideo', function (e) {
                    $(this).hide();
                    $('#userGalleryModal .overlay-text-div').parent().hide();
                    var player = $('#modalVideoPlayer')[0];
                    player.controls = true;
                    player.play();
                });
                $('.overlay-text-div').on('click', function () {
                    var textDiv = $(this);
                    textDiv.parent().removeClass('overlay-min-div').addClass('overlay-full-div');
                    textDiv.html(textDiv.data('reviewtext'));
                    textDiv.parent().parent().find('.overlay-text-close').removeClass('hidden');
                });
                $('.overlay-text-close').on('click', function () {
                    var $this = $(this);
                    $this.addClass('hidden');
                    $this.parent().find('.overlay-full-div').addClass('overlay-min-div').removeClass('overlay-full-div');
                    var textDiv = $this.parent().find('.overlay-text-div');
                    textDiv.html(textDiv.data('reviewtextshort'));
                });
                $('#userGalleryModal').on('show.bs.modal', function (e) {
                    var $link = $(e.relatedTarget);
                    initGalleryModal($link);
                });
                $('#userGalleryModal').on('hide.bs.modal', function (e) {
                    var $if = $(e.delegateTarget).find('iframe');
                    if ($if.length > 0) {
                        $if.remove();
                    } else {
                        var $vid = $(e.delegateTarget).find('video');
                        if ($vid.length > 0) {
                            $vid.remove();
                        }
                    }
                });
                $("#fullGalleryModal").on("show.bs.modal", function (e) {
                    var $modalBody = $('#fullGalleryModal').find(".modal-gallery-wrapper");
                    if ($modalBody.data('loaded') === false) {
                        $scope.getMoreUsersUploadsNg(_config.galleryFullPerPage);
                        $modalBody.data('loaded', true);
                    }
                });

                function loadAskQuestionSection(successCallback) {
                    var $divAq = $('#divUserQuestions'); // load ask question section if not loaded yet to be able to add question
                    if ($divAq.data('loaded') === false) {
                        $divAq.data('loaded', true);
                        $divAq.load(_config.askQuestionUrl + '&page=1', function (_, status) {
                            if (status === 'success') { // compile the html so the angular codes will work                                    
                                var scope = angular.element($divAq).scope();
                                $compile($divAq)(scope);
                                scope.$digest(); // init form jquery events
                                App.Product._UserQuestions.init(_config);
                                if (typeof successCallback !== 'undefined') {
                                    successCallback();
                                }
                            }
                        });
                    } else {
                        if (typeof successCallback !== 'undefined') {
                            successCallback();
                        }
                    }
                }
                var searchObj = $location.search();
                var hash = $location.hash(); // open respond box if it was click before login
                if (typeof searchObj.act !== 'undefined') {
                    if (searchObj.act === 'ask-question') { // open ask question modal
                        $('#modalAksQuestion').modal('show');
                        loadAskQuestionSection();
                    } else if (searchObj.act === 'answer-question') { // open answer question modal
                        $('#modalAnswerQuestion').modal('show');
                        var txtAnswer = $('#modalAnswerQuestion').find('textarea[name=YourAnswer]');
                        txtAnswer.data('qid', searchObj.qid);
                        loadAskQuestionSection();
                    } else if (searchObj.act === 'answer' || searchObj.act === 'ans-reply') {
                        $('html, body').animate({
                            scrollTop: $("#questionanswer").offset().top + 140
                        }, 300);
                    } else if (searchObj.act === 'show-ugc') {
                        var upid = searchObj.upid;
                        setTimeout(function () {
                            var ugc = $('a[data-uploadid=' + upid + ']').first();
                            ugc.trigger('click');
                            $('html, body').animate({
                                scrollTop: ugc.offset().top + 140
                            }, 300);
                        }, 500);
                    } // remove act param                 
                    $scope.$apply(function () {
                        $location.search('act', null);
                        $location.search('upid', null);
                    });
                } // remove gallery image with errors
                $scope.removeGalleryImageWithError('#userUploadsGallery .tester-galler-insta div', function ($link) { // remove the item from gallery
                    $link.parent().remove();
                });
                setTimeout(function () { // fix avatar image of comments
                    $scope.fixUserImage();
                    if (hash && $('#' + hash.replace(/[^a-z0-9A-Z\-\_]*/gi, '')).length > 0) { // smooth scroll to the anchor id, override app.js scroll by setting higher duration
                        $('html, body').animate({
                            scrollTop: $('#' + hash.replace(/[^a-z0-9A-Z\-\_]*/gi, '')).offset().top - 150
                        }, 1200, 'swing', function () { // animation complete, remove hash
                            history.replaceState("", document.title, window.location.pathname + window.location.search);
                        });
                    }
                }, 300);
            });
        }]);
    };
    var beforeReportComment = function beforeReportComment(el) {
        var id = el.data('cid');
        if (_config.uId === 0) {
            var ng = angular.element($('body')).scope(); // get angular scope
            window.location = _config.loginUrl + '?returnurl=' + encodeURIComponent(_config.productUrl + ng.getPageParam() + '#' + id);
            return false;
        }
        return true;
    };
    var reportComment = function reportComment(el) { // report upload
        var id = el.data('cid');
        if (id === 0) return;
        if (_config.uId === 0) {
            var ng = angular.element($('body')).scope(); // get angular scope
            return window.location = _config.loginUrl + '?returnurl=' + encodeURIComponent(_config.productUrl + ng.getPageParam() + '#' + id);
        }
        App.loader.showLoader();
        var jqxhr = $.post(_config.reportCommentUrl + '/' + id, function (data) { // success, remove response box          
            if (data.result > 0) { //App.notify.Success(_config.T_InAppropriateCommentReported);
                // removed the comment
                $('#' + id).remove();
            } else if (data.message !== '') {
                App.notify.Warning(data.message);
            }
        }).fail(function () {
            App.notify.Warning(_config.T_ErrorProcessingRequest);
        }).always(function () {
            App.loader.hideLoader();
        });
    };
    var beforeReportUpload = function beforeReportUpload(el) {
        var id = el.data('cid');
        if (_config.uId === 0) {
            var ng = angular.element($('body')).scope(); // get angular scope
            window.location = _config.loginUrl + '?returnurl=' + encodeURIComponent(_config.productUrl + ng.getPageParam());
            return false;
        }
        return true;
    };
    var reportUpload = function reportUpload(el) { // report upload
        var id = el.data('cid');
        if (id === 0) return;
        if (_config.uId === 0) {
            var ng = angular.element($('body')).scope(); // get angular scope
            return window.location = _config.loginUrl + '?returnurl=' + encodeURIComponent(_config.productUrl + ng.getPageParam());
        }
        App.loader.showLoader();
        var jqxhr = $.post(_config.reportUserUploadUrl + '/' + id, function (data) { // success, remove response box          
            if (data.result > 0) { //App.notify.Success(_config.T_InAppropriateUploadReported);
            } else if (data.message !== '') {
                App.notify.Warning(data.message);
            }
        }).fail(function () {
            App.notify.Warning(_config.T_ErrorProcessingRequest);
        }).always(function () {
            App.loader.hideLoader();
        });
    };
    var deleteResponse = function deleteResponse(el) { // delete comment        
        var cid = el.data('cid');
        if (cid === 0) return;
        App.loader.showLoader();
        var jqxhr = $.post(_config.deleteCommentUrl + '/' + cid, function (data) { // success, remove response box                  
            if (data.result > 0) {
                var closeBtn = $('button[data-closecid=' + cid + ']');
                var commentBox = closeBtn.closest('.child-comment-box');
                commentBox.animate({
                    height: 0
                }, 1000, function () {
                    commentBox.parent().parent().empty();
                });
            }
        }).fail(function () {
            alert(_config.T_ErrorProcessingRequest);
        }).always(function () {
            App.loader.hideLoader();
        });
    };
    var onPauseModalVideo = function onPauseModalVideo() {
        var player = $('#modalVideoPlayer')[0];
        player.controls = false;
        $('#btnPlayModalVideo').show();
        $('#userGalleryModal .overlay-text-div').parent().show();
    };
    return {
        init: init,
        beforeReportComment: beforeReportComment,
        reportComment: reportComment,
        deleteResponse: deleteResponse,
        beforeReportUpload: beforeReportUpload,
        reportUpload: reportUpload,
        onPauseModalVideo: onPauseModalVideo
    };
})();

// Modal review form functions
App.Product._Review = (function () {
    var _config = {
        'ratingHints': [],
        'months': [],
        'years': [],
        'purchasedMonth': 1,
        'purchasedYear': 2017,
        'initialScore': ''
    };
    var init = function init(config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);
        }
        var $scope = angular.element($('body')).scope(); // get angular scope
        $scope.months = _config.months;
        $scope.years = _config.years;
        $scope.purchasedMonth = _config.purchasedMonth;
        $scope.purchasedYear = _config.purchasedYear;
        $scope.obj.isMobile = _config.isMobile;
        $scope.obj.reviewMinLength = _config.reviewMinLength;
        $scope.obj.reviewMaxLength = _config.reviewMaxLength;
        $scope.obj.formSubmitted = false;
        $scope.obj.showSpecifyTerms = false;
        $scope.obj.ReviewTextPercent = '0%';
        $scope.obj.HaveTried = false;
        var _reviewCallback = null;
        var _useInlineLoader = false;
        var isNaNorEmpty = function (itm) {
            return isNaN(itm) || $.trim(itm).length == 0;
        }

        this.useInlineLoader = function (value) {
            _useInlineLoader = value;
        }

        this.reviewCallback = function (newCallBack) {
            return arguments.length > 0 ? (_reviewCallback = newCallBack) : _reviewCallback;
        }

        $scope.obj.isPurchaseDatePast = function () {
            if (isNaN($scope.purchasedMonth) || isNaN($scope.purchasedYear)) return true; // don't show if user has not selected any yet
            var now = new Date();
            var nowMonth = now.getMonth() + 1;
            var nowYear = now.getFullYear();
            if ($scope.purchasedYear === nowYear && $scope.purchasedMonth > nowMonth) return false;
            return true;
        };
        $scope.obj.isPurchaseDateValid = function () {
            if (!$scope.obj.submitReviewClicked) return true;
            if (isNaN($scope.purchasedMonth) || isNaN($scope.purchasedYear)) return false; // don't show if user has not selected any yet
            return true;
        };
        $scope.obj.thumbClicked = function (value) {
            $scope.obj.thumbValue = value;
            $('[data-valmsg-for="Recommended"]').parent().remove();
        };
        $scope.obj.ReviewTextCount = '(0/1000)';
        $scope.obj.ReviewHintText = _config.T_OverallOpinionOfProduct;
        $scope.obj.reviewHints = function () {
            $scope.obj.ReviewTextCount = '(' + $scope.obj.ReviewText.length + '/1000)';
            if ($scope.obj.ReviewText.length < $scope.obj.reviewMinLength) {
                $scope.obj.ReviewTextPercent = '0%';
            } else {
                $scope.obj.ReviewTextPercent = Math.round($scope.obj.ReviewText.length / 176 * 100) + '%';
            }
            if ($scope.obj.ReviewText.length <= 49) {
                $scope.obj.ReviewHintText = _config.T_OverallOpinionOfProduct;
            } else if ($scope.obj.ReviewText.length >= 50 && $scope.obj.ReviewText.length <= 70) {
                $scope.obj.ReviewHintText = _config.T_WhyDidYouFeelThatWay;
            } else if ($scope.obj.ReviewText.length >= 71 && $scope.obj.ReviewText.length <= 105) {
                $scope.obj.ReviewHintText = _config.T_WhatDidYouLikeTheProduct;
            } else if ($scope.obj.ReviewText.length >= 106 && $scope.obj.ReviewText.length <= 140) {
                $scope.obj.ReviewHintText = _config.T_AnyImprovementsYouThink;
            } else if ($scope.obj.ReviewText.length >= 141 && $scope.obj.ReviewText.length <= 175) {
                $scope.obj.ReviewHintText = _config.T_WouldYouRecommendThis;
            } else if ($scope.obj.ReviewText.length >= 176) {
                $scope.obj.ReviewHintText = _config.T_AwesomeReviewThanks; // hide progress bar
                $scope.obj.ReviewTextPercent = '0%';
            }
        };
        $scope.obj.ReviewTextCountNT = '(0/1000)';
        $scope.obj.ReviewHintTextNT = _config.T_FocusOnFactualAndObjective;
        $scope.obj.reviewHintsNT = function () {
            $scope.obj.ReviewTextCountNT = '(' + $scope.obj.YourReviewNotTried.length + '/1000)';
            if ($scope.obj.YourReviewNotTried.length < $scope.obj.reviewMinLength) {
                $scope.obj.ReviewTextPercentNT = '0%';
            } else {
                $scope.obj.ReviewTextPercentNT = Math.round($scope.obj.YourReviewNotTried.length / 176 * 100) + '%';
            }
            if ($scope.obj.YourReviewNotTried.length >= 176) {
                $scope.obj.ReviewHintTextNT = _config.T_AwesomeReviewThanks; // hide progress bar
                $scope.obj.ReviewTextPercentNT = '0%';
            } else {
                $scope.obj.ReviewHintTextNT = _config.T_FocusOnFactualAndObjective;
            }
        };

        function showInlineLoader(id) {
            $('#' + id).fadeIn(400);
        }

        function hideInlineLoader(id) {
            $('#' + id).fadeOut(400);
        }

        function scrollToReviewModal(elementId) {
            $('#modalLeaveReview').animate({
                scrollTop: $(elementId).offset().top - 10
            }, 500);
        }

        function videoUploadProgress() {
            var xhr = new window.XMLHttpRequest();
            var form = $('#frmProductReview');
            xhr.upload.addEventListener("progress", function (evt) {
                if (evt.lengthComputable) {
                    var percentComplete = evt.loaded / evt.total;
                    percentComplete = parseInt(percentComplete * 100);
                    form.find('.upload-progress-box .upload-progress').css('width', percentComplete + '%');
                    if (percentComplete === 100) {
                        form.find('.upload-progress-box').hide();
                        form.find('.upload-progress-box .upload-progress').css('width', '0px');
                        _useInlineLoader ? showInlineLoader('reviewModalLoader') : App.loader.showLoader();
                    }
                }
            }, false);
            return xhr;
        }

        function generateFormData() { // create a new FormData from frmProductReviewEdit to avoid using FormData.delete
            // FormData.delete not support on older android chrome browser
            var form = $('#frmProductReview');
            var fd = new FormData();
            fd.append('__RequestVerificationToken', form.find('[name=__RequestVerificationToken]').val());
            fd.append('CommentId', $('#CommentId').val());
            fd.append('IsBazaarVoice', $('#IsBazaarVoice').val());
            fd.append('ForumId', $('#ForumId').val());
            fd.append('ForumType', $('#ForumType').val());
            fd.append('BvFingerprint', $('#BvFingerprint').val());
            fd.append('HaveTried', $('#HaveTried').val());
            fd.append('StarRating', $('#StarRating').val());
            fd.append('ReviewTitle', $('#ReviewTitle').val());
            fd.append('Nickname', $('#Nickname').val());
            fd.append('YourReview', $('#YourReview').val());
            fd.append('YourReviewNotTried', $('#YourReviewNotTried').val());
            fd.append('PurchasedYear', $('#PurchasedYear').val());
            fd.append('PurchasedMonth', $('#PurchasedMonth').val());
            fd.append('Recommended', $('#Recommended').val());
            fd.append('ImageDescription', $('#ImageDescription').val());
            fd.append('VideoDescription', $('#VideoDescription').val()); // don't add image/video file input here
            return fd;
        }

        $(function () { // allow validation for hidden fields, e.g. Recommended hidden field as its value is set by js
            $.validator.setDefaults({
                ignore: null
            });
            App.formValidateReset('#frmProductReview');
            $(document).off('click.productController', 'button[name=btnReviewTriedSubmit], button[name=btnReviewNotTriedSubmit]').on('click.productController', 'button[name=btnReviewTriedSubmit], button[name=btnReviewNotTriedSubmit]', function (e) {
                e.preventDefault();
                var form = $(this).parents('form');
                var $chkTerms = $('#chkTerms');
                var isChecked = $chkTerms.is(':checked');
                $scope.$apply(function () {
                    $scope.obj.formSubmitted = true;
                    if ($chkTerms.length > 0 && !isChecked) {
                        $scope.obj.showSpecifyTerms = true;
                    }
                });
                var reviewTextNotValid = $scope.obj.ReviewText.length < $scope.obj.reviewMinLength || $scope.obj.ReviewText.length > $scope.obj.reviewMaxLength;
                var reviewNotTriedNotValid = $scope.obj.YourReviewNotTried.length < $scope.obj.reviewMinLength || $scope.obj.YourReviewNotTried.length > $scope.obj.reviewMaxLength;
                var haveTried = $('#HaveTried').val();
                var msgYR = $('#YourReview').data('val-required'); // focus on the first invalid item
                if (form.valid() === false && haveTried === 'True') { // scroll to the first error                          
                    if ($('#StarRating').valid() === false) {
                        scrollToReviewModal('#StarRating');
                    } else if ($('#ReviewTitle').valid() === false) {
                        scrollToReviewModal('#ReviewTitle');
                        $('#ReviewTitle').focus();
                    } else if ($('#Nickname').length === 1 && $('#Nickname').valid() === false) {
                        scrollToReviewModal('#Nickname');
                        $('#Nickname').focus();
                    } else if (reviewTextNotValid) {
                        scrollToReviewModal('#YourReview');
                        $('#YourReview').focus();
                        $('[data-valmsg-for="YourReview"]').addClass('field-validation-error').text(msgYR).show();
                    } else if ($('#Recommended').valid() === false) {
                        scrollToReviewModal('#divRecommended');
                    }
                    return false;
                } else if (reviewTextNotValid && haveTried === 'True') {
                    scrollToReviewModal('#YourReview');
                    $('#YourReview').focus();
                    $('[data-valmsg-for="YourReview"]').addClass('field-validation-error').text(msgYR).show();
                    return false;
                } else if (reviewNotTriedNotValid && haveTried === 'False') {
                    scrollToReviewModal('#YourReviewNotTried');
                    $('#YourReviewNotTried').focus();
                    var msgYRNT = $('#YourReviewNotTried').data('val-required');
                    $('[data-valmsg-for="YourReviewNotTried"]').addClass('field-validation-error').text(msgYRNT).show();
                    return false;
                } else if ($chkTerms.length > 0 && !isChecked && haveTried === 'True') {
                    scrollToReviewModal('#divChkTerms');
                    return false;
                }
                if (!$scope.obj.isPurchaseDateValid() || !$scope.obj.isPurchaseDatePast()) return false; //if (!form.valid() && haveTried === 'True') return false;
                var enableUpload = true; // set to true to enable upload                
                var imageInput = form.find('#imageInputFile').get(0);
                var videoInput = form.find('#UploadVideo').get(0);
                if (enableUpload) { // remove any previous error for video and photo if have
                    $('[data-valmsg-for=ImageDescription]').html('').removeClass('field-validation-error');
                    $('[data-valmsg-for=VideoDescription]').html('').removeClass('field-validation-error');
                    var isUploadValid = true; // Photo is not required, but if photo is inputted, user must also add its description and accept terms.                    
                    var photoDesc = $.trim($('#ImageDescription').val());
                    if (imageInput.files && imageInput.files.length > 0 && photoDesc === '') {
                        var msgImgDesc = $('#ImageDescription').data('val-required');
                        $('span[data-valmsg-for="ImageDescription"]').addClass('field-validation-error').text(msgImgDesc).show();
                        isUploadValid = false;
                        $('#ImageDescription').focus();
                    } // Video is not required, but if video is inputted, user must also add its description and accept terms.                                      
                    var videoDesc = $.trim($('#VideoDescription').val());
                    if (videoInput.files && videoInput.files.length > 0 && videoDesc === '') {
                        var msgVD = $('#VideoDescription').data('val-required');
                        $('span[data-valmsg-for="VideoDescription"]').addClass('field-validation-error').text(msgVD).show();
                        isUploadValid = false;
                        $('#VideoDescription').focus();
                    }
                    if (isUploadValid === false) return false;
                    if (videoInput.files && videoInput.files.length > 0 && videoDesc !== '') {
                        $('.upload-progress-box').show();
                    }
                }

                _useInlineLoader ? showInlineLoader('reviewModalLoader') : App.loader.showLoader()

                var fd = generateFormData();
                if (enableUpload) {
                    if (imageInput.files && imageInput.files[0] && $.trim($('#imgCropper').attr('src')).length > 0) {
                        fd.append('ImageFilename', $(imageInput).val().split('\\').pop());
                    }
                    if (videoInput.files && videoInput.files.length > 0 && videoDesc !== '') {
                        fd.append('VideoFilename', $(videoInput).val().split('\\').pop());
                    }
                }
                $.ajax({
                    url: form.attr('action'),
                    type: 'POST',
                    data: fd,
                    contentType: false,
                    processData: false
                }).fail(function (jqXHR, textStatus, errorThrown) {
                    _useInlineLoader ? hideInlineLoader('reviewModalLoader') : App.loader.hideLoader();
                    App.notify.Warning(textStatus + ': ' + errorThrown);
                }).done(function (data, textStatus, jqXHR) {
                    var redirectUrl = data.uri;
                    if (data.status === 1) {
                        _useInlineLoader ? hideInlineLoader('reviewModalLoader') : App.loader.hideLoader();
                        if (_reviewCallback != null) eval(_reviewCallback);
                        else window.location.replace(redirectUrl); // redirect and replace browser history (not in click back)
                    } else if (data.status === 2) { // Upload files to S3                                                 
                        if (data.awspost.length > 1) { // Uploaded two files: image and video
                            var cropperDataUrl = App.toScaledImage($('#imgCropper').get(0));
                            var aws4D1 = data.awspost[0]; // image
                            var fd1 = App.createFormDataAWS4(aws4D1);
                            fd1.append('file', App.dataURItoBlob(cropperDataUrl));
                            var aws4D2 = data.awspost[1]; // video
                            var fd2 = App.createFormDataAWS4(aws4D2);
                            fd2.append('file', videoInput.files[0]);
                            $.when($.ajax({
                                url: aws4D1.PostActionUrl,
                                type: 'POST',
                                data: fd1,
                                contentType: false,
                                processData: false,
                                cache: false
                            }), $.ajax({
                                xhr: videoUploadProgress, // xhr for video upload
                                url: aws4D2.PostActionUrl,
                                type: 'POST',
                                data: fd2,
                                contentType: false,
                                processData: false,
                                cache: false
                            })).then(function () { // success
                                _useInlineLoader ? hideInlineLoader('reviewModalLoader') : App.loader.hideLoader();
                                if (_reviewCallback != null) eval(_reviewCallback)
                                else window.location.replace(redirectUrl); // redirect and replace browser history (not in click back)
                            }, function () { // failure
                                _useInlineLoader ? hideInlineLoader('reviewModalLoader') : App.loader.hideLoader();
                                App.notify.Warning(_config.T_ErrorProcessingRequest); // delete data entry for review text and uploads
                                $.post(_config.removeReviewUploadsUrl, {
                                    reviewId: aws4D1.ReviewId,
                                    reviewSha1: aws4D1.ReviewId_sha1,
                                    uploadId1: aws4D1.UploadId,
                                    uploadId2: aws4D2.UploadId
                                });
                            });
                        } else { // Uploaded one file only
                            var aws4D = data.awspost[0];
                            var fdFile = App.createFormDataAWS4(aws4D);
                            if (aws4D.ContentType.indexOf('image') > -1) { // image upload
                                var cropperData = App.toScaledImage($('#imgCropper').get(0));
                                fdFile.append('file', App.dataURItoBlob(cropperData));
                            } else if (aws4D.ContentType.indexOf('video') > -1) { // video upload
                                fdFile.append('file', videoInput.files[0]);
                            }
                            $.ajax({
                                xhr: videoUploadProgress, // progress bar for video upload
                                url: aws4D.PostActionUrl,
                                type: 'POST',
                                data: fdFile,
                                contentType: false,
                                processData: false,
                                cache: false
                            }).done(function (data, textStatus, jqXHR) {
                                _useInlineLoader ? hideInlineLoader('reviewModalLoader') : App.loader.hideLoader();
                                if (_reviewCallback != null) eval(_reviewCallback)
                                else window.location.replace(redirectUrl); // redirect and replace browser history (not in click back)
                            }).fail(function (jqXHR, textStatus, errorThrown) {
                                _useInlineLoader ? hideInlineLoader('reviewModalLoader') : App.loader.hideLoader();
                                App.notify.Warning(textStatus + ': ' + errorThrown); // delete data entry for review text and upload
                                $.post(_config.removeReviewUploadsUrl, {
                                    reviewId: aws4D.ReviewId,
                                    reviewSha1: aws4D.ReviewId_sha1,
                                    uploadId1: aws4D.UploadId,
                                    uploadId2: 0
                                });
                            });
                        }
                    } else {
                        _useInlineLoader ? hideInlineLoader('reviewModalLoader') : App.loader.hideLoader();
                        App.notify.Warning(data.message);
                    }
                });
                return false;
            });
            $('#chkTerms').on('click', function () {
                var isChecked = $(this).is(':checked');
                if (isChecked) {
                    $scope.$apply(function () {
                        $scope.obj.showSpecifyTerms = false;
                    });
                } else if ($scope.obj.formSubmitted) {
                    $scope.$apply(function () {
                        $scope.obj.showSpecifyTerms = true;
                    });
                }
            });
            $('#rateProduct').raty({
                hints: _config.ratingHints,
                starOff: 'fa fa-star fa-star-open',
                starOn: 'fa fa-star',
                size: 24,
                targetKeep: true,
                target: '#rateProductHint',
                score: _config.initialScore === 'undefined' ? 'undefined' : parseFloat(_config.initialScore),
                click: function click(score, evt) {
                    $('#StarRating').val(score);
                    $('span[data-valmsg-for="StarRating"]').remove(); // remove error message
                    return false;
                }
            });
            $('button[name=btnHaveTriedYes]').click(function (e) {
                e.preventDefault();
                var $this = $(this);
                $scope.obj.HaveTried = true;
                $('input[name=HaveTried]').val('True');
                $this.addClass('active');
                $('button[name=btnHaveTriedNo]').removeClass('active');
                $('span[data-valmsg-for="HaveTried"]').remove(); // remove error message
                $('#divHaveTried').removeClass('hidden');
                $('#divHaveNotTried').addClass('hidden');
                $('[name=btnReviewTriedSubmit]').removeClass('hidden');
                $('[name=btnReviewNotTriedSubmit]').addClass('hidden');
            });
            $('button[name=btnHaveTriedNo]').click(function (e) {
                e.preventDefault();
                var $this = $(this);
                $scope.obj.HaveTried = false;
                $('input[name=HaveTried]').val('False');
                $this.addClass('active');
                $('button[name=btnHaveTriedYes]').removeClass('active');
                $('span[data-valmsg-for="HaveTried"]').remove(); // remove error message
                $('#divHaveTried').addClass('hidden');
                $('#divHaveNotTried').removeClass('hidden');
                $('[name=btnReviewTriedSubmit]').addClass('hidden');
                $('[name=btnReviewNotTriedSubmit]').removeClass('hidden');
            });
            $('.lnkTermsConditions').click(function (e) {
                e.preventDefault();
                $('#myReviewTab a[href="#termstab"]').tab('show');
                $('#modalLeaveReview').scrollTop(0);
            });
            $('#frmProductReview').removeClass('hide');
            $('#HaveTried').click(function () {
                var isChecked = $(this).is(':checked');
                if (isChecked) {
                    $(this).val('false');
                    $('#rateProduct').raty('readOnly', false);
                    selectizeMonth.enable();
                    selectizeYear.enable();
                } else {
                    $(this).val('true');
                    $('#rateProduct').raty('cancel', false); // reset ratings
                    $('#rateProduct').raty('readOnly', true); // make it not clickable
                    selectizeMonth.disable();
                    selectizeYear.disable();
                    $('#StarRating').val(''); // reset model ratings
                    $('span[data-valmsg-for="StarRating"]').remove(); // remove error message
                }
            });
            $('#btnAddPhoto').on('click', function (e) {
                e.preventDefault();
                var $this = $(this);
                $this.addClass('active');
                $('#btnAddVideo').removeClass('active');
                if ($.trim($('#imgCropper').attr('src')).length === 0) {
                    $('#imageInputFile').click();
                }
                $('#divReviewImgRotate').removeClass('hidden');
                $('#divImageUpload').removeClass('hide');
                $('#divVideoUpload').addClass('hide');
            });
            $('#btnAddVideo').on('click', function (e) {
                e.preventDefault();
                var $this = $(this);
                $this.addClass('active');
                $('#btnAddPhoto').removeClass('active');
                var videoInput = $('#UploadVideo').get(0);
                if (videoInput.files.length === 0) {
                    $('#UploadVideo').click();
                }
                $('#divImageUpload').addClass('hide'); //$('#divCropBox').addClass('hide');
                $('#divVideoUpload').removeClass('hide');
            });
            $('#cancelPhotoFile').on('click', function () {
                clearImageInputs();
                $('#divImageUpload').addClass('hide');
                $('#btnAddPhoto').removeClass('active');
            });
            $('#cancelVideoFile').on('click', function () {
                clearVideoInputs();
                $('#divVideoUpload').addClass('hide');
                $('#btnAddVideo').removeClass('active');
                var $source = $('#vidPreview');
                $source.addClass('hidden');
                var videoElement = $source[0];
                videoElement.pause();
                videoElement.removeAttribute('src'); // empty source
                videoElement.load();
            });
            $('#btnPlayReviewVideo').on('click', function () {
                $(this).addClass('hide');
                var player = $('#vidPreview')[0];
                player.controls = true;
                player.play();
            });
            $('#vidPreview').on('ended', function () {
                $('#btnPlayReviewVideo').removeClass('hide');
            });
            $('#imageInputFile').change(function () {
                var $obj = $(this);
                if (this.files && this.files[0]) {
                    var file = this.files[0];
                    App.getImageOrientation(file, function (ox) {
                        var reader = new FileReader();
                        $('#divImageUpload').removeClass('hide');
                        $('#divReviewImgRotate').removeClass('hidden');
                        $('#divVideoUpload').addClass('hide');
                        $('#imgCropper').cropper('destroy');

                        App.loader.showLoader();
                        reader.onload = function (e) {
                            App.resetImageOrientation(e.target.result, ox, function (b64) {
                                $('span[data-valmsg-for="imageInputFile"]').hide();
                                $('#cancelPhotoFile').removeClass('hide');

                                // initialize cropper image
                                var $imageCrop = $('#imgCropper');
                                $imageCrop.attr('src', b64);
                                var cropperOptions = {
                                    aspectRatio: 1 / 1,
                                    preview: '#imgPreview',
                                    autoCrop: false,
                                    zoomable: false,
                                    cropBoxMovable: false,
                                    cropBoxResizable: false,
                                    dragMode: 'none'
                                };
                                if (_config.isMobile) {
                                    cropperOptions.crop = function (data) {
                                        if (!window._cropperData) window._cropperData = data;
                                    };

                                    // don't allow rotation/cropping for mobile
                                    cropperOptions.aspectRatio = NaN;
                                    cropperOptions.autoCrop = false;
                                    cropperOptions.rotatable = true;
                                }
                                $imageCrop.cropper(cropperOptions);
                                $imageCrop.on('built.cropper', function () {
                                    App.loader.hideLoader();
                                });
                            })
                        }

                        reader.readAsDataURL(file);
                        var frag = file.name.split('.');
                        $('#imgCropper').data('filename', $obj.val().replace(/.*[\/\\]/, ''));
                        $('#imgCropper').data('ext', frag[frag.length - 1]);
                    })
                }
            });
            $('#btnReviewRotateLeft, #btnReviewRotateRight').click(function () {
                var degree = parseInt($(this).data('degree'));
                App.rotateCropperImage($('#imgCropper'), degree);
                if (_config.isMobile) {
                    window._cropperData = $('#imgCropper').cropper('getData');
                }
            });
            $('#UploadVideo').change(function () {
                var $obj = $(this);
                App.loader.showLoader();
                if (this.files && this.files[0]) {
                    $('#divVideoUpload').removeClass('hide');
                    $('#divImageUpload').addClass('hide');
                    $('[data-valmsg-for=UploadVideo]').html('').removeClass('field-validation-error');
                    var $source = $('#vidPreview');
                    $source.removeClass('hidden');
                    $source[0].src = URL.createObjectURL(this.files[0]);
                    var reader = new FileReader();
                    reader.onload = function (e) {
                        $('span[data-valmsg-for="UploadVideo"]').hide();
                        $('#spanVideoFile').text('[' + $obj.val().replace(/.*[\/\\]/, '') + ']');
                        $('#cancelVideoFile').removeClass('hide');
                        $('#btnPlayReviewVideo').removeClass('hide');
                        App.loader.hideLoader();
                    };
                    reader.readAsDataURL(this.files[0]);
                } else { //$('#btnAddVideo').removeClass('active');
                    //$('#spanVideoFile').text('');
                    //$('#cancelVideoFile').addClass('hide');
                    //$('#divVideoFile').addClass('hide');
                    App.loader.hideLoader();
                }
            }); // For RequiredIf fields:
            // add post-initialization rule for each requiredif field to make custom requiredif rule work, on top of MVC unobtrusive rules
            $('#Nickname').rules('add', {
                requiredif: true,
                messages: {
                    requiredif: $('#Nickname').attr('data-val-requiredif')
                }
            });
            $('#StarRating').rules('add', {
                requiredif: true,
                messages: {
                    requiredif: $('#StarRating').attr('data-val-requiredif')
                }
            }); // End RequiredIf fields
            if (_config.customBv && _config.customBv.length > 0) {
                for (var i in _config.customBv) {
                    var bv = _config.customBv[i];
                    $('#' + bv).rules('add', {
                        requiredif: true,
                        messages: {
                            requiredif: $('#' + bv).attr('data-val-requiredif')
                        }
                    });
                    $('#rate_' + bv).raty({
                        hints: _config.ratingHints,
                        starOff: 'fa fa-star',
                        starOn: 'fa fa-star fa-star-pink',
                        size: 24,
                        target: '#hint_' + bv,
                        targetKeep: true,
                        score: _config.initialScore === 'undefined' ? 'undefined' : parseFloat(_config.initialScore),
                        click: function click(score, evt) {
                            $('#' + bv).val(score);
                            $('span[data-valmsg-for="' + bv + '"]').html(''); // remove error message
                            return false;
                        }
                    });
                }
            }
        });
    };
    var clearImageInputs = function clearImageInputs() {
        $('#spanPhotoFile').text('');
        $('#cancelPhotoFile').addClass('hide');
        $('#imageInputFile').val('');
        $('#ImageDescription').val('');
        $('#imgCropper').attr('src', '');
        $('#imgCropper').cropper('destroy');
        $('#imgCropper').data('filename', '');
        $('#imgCropper').data('ext', ''); //$('#divCropBox').addClass('hide');
        $('span[data-valmsg-for="imageInputFile"]').show();
        $('#divReviewImgRotate').addClass('hidden');
    };
    var clearVideoInputs = function clearVideoInputs() {
        $('#spanVideoFile').text('');
        $('#UploadVideo').val('');
        $('#cancelVideoFile').addClass('hide');
        $('#btnPlayReviewVideo').addClass('hide');
        $('#VideoDescription').val('');
    };
    var onPauseReviewVideo = function onPauseReviewVideo() {
        var player = $('#vidPreview')[0];
        player.controls = false;
        $('#btnPlayReviewVideo').removeClass('hide');
    };
    return {
        init: init,
        onPauseReviewVideo: onPauseReviewVideo
    };
})();

// Modal edit review functions
App.Product._EditReview = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);
        }
        var $scope = angular.element($('body')).scope(); // get angular scope
        var _reviewCallback = null;
        var _useInlineLoader = false;

        this.useInlineLoader = function (value) {
            _useInlineLoader = value;
        }


        this.reviewCallback = function (newCallBack) {
            return arguments.length > 0 ? (_reviewCallback = newCallBack) : _reviewCallback;
        }
        $scope.obj.isMobile = _config.isMobile;
        $scope.obj.reviewMinLength = _config.reviewMinLength;
        $scope.obj.reviewMaxLength = _config.reviewMaxLength;
        $scope.obj.formSubmittedEdit = false;
        $scope.obj.HaveTriedEdit = false;
        $scope.obj.ReviewHintTextEdit = _config.T_OverallOpinionOfProduct;
        $scope.obj.reviewEditHints = function () {
            $scope.obj.ReviewTextEditCount = '(' + $scope.obj.ReviewTextEdit.length + '/1000)';
            if ($scope.obj.ReviewTextEdit.length < $scope.obj.reviewMinLength) {
                $scope.obj.ReviewTextEditPercent = '0%';
            } else {
                $scope.obj.ReviewTextEditPercent = Math.round($scope.obj.ReviewTextEdit.length / 176 * 100) + '%';
            }
            if ($scope.obj.HaveTriedEdit === true) {
                if ($scope.obj.ReviewTextEdit.length <= 49) {
                    $scope.obj.ReviewHintTextEdit = _config.T_OverallOpinionOfProduct;
                } else if ($scope.obj.ReviewTextEdit.length >= 50 && $scope.obj.ReviewTextEdit.length <= 70) {
                    $scope.obj.ReviewHintTextEdit = _config.T_WhyDidYouFeelThatWay;
                } else if ($scope.obj.ReviewTextEdit.length >= 71 && $scope.obj.ReviewTextEdit.length <= 105) {
                    $scope.obj.ReviewHintTextEdit = _config.T_WhatDidYouLikeTheProduct;
                } else if ($scope.obj.ReviewTextEdit.length >= 106 && $scope.obj.ReviewTextEdit.length <= 140) {
                    $scope.obj.ReviewHintTextEdit = _config.T_AnyImprovementsYouThink;
                } else if ($scope.obj.ReviewTextEdit.length >= 141 && $scope.obj.ReviewTextEdit.length <= 175) {
                    $scope.obj.ReviewHintTextEdit = _config.T_WouldYouRecommendThis;
                } else if ($scope.obj.ReviewTextEdit.length >= 176) {
                    $scope.obj.ReviewHintTextEdit = _config.T_AwesomeReviewThanks; // hide progress bar
                    $scope.obj.ReviewTextEditPercent = '0%';
                }
            } else {
                if ($scope.obj.ReviewTextEdit.length >= 176) {
                    $scope.obj.ReviewHintTextEdit = _config.T_AwesomeReviewThanks; // hide progress bar
                    $scope.obj.ReviewTextEditPercent = '0%';
                } else {
                    $scope.obj.ReviewHintTextEdit = _config.T_FocusOnFactualAndObjective;
                }
            }
        };

        function showInlineLoader(id) {
            $('#' + id).fadeIn(400);
        }

        function hideInlineLoader(id) {
            $('#' + id).fadeOut(400);
        }

        function scrollToReviewEditModal(elementId) {
            $('#modalLeaveReview').animate({
                scrollTop: $(elementId).offset().top - 10
            }, 500);
        }

        function editVideoUploadProgress() {
            var xhr = new window.XMLHttpRequest();
            var form = $('#frmProductReviewEdit');
            xhr.upload.addEventListener("progress", function (evt) {
                if (evt.lengthComputable) {
                    var percentComplete = evt.loaded / evt.total;
                    percentComplete = parseInt(percentComplete * 100);
                    form.find('.upload-progress-box .upload-progress').css('width', percentComplete + '%');
                    if (percentComplete === 100) {
                        form.find('.upload-progress-box').hide();
                        form.find('.upload-progress-box .upload-progress').css('width', '0px');
                        _useInlineLoader ? showInlineLoader('reviewModalLoader') : App.loader.showLoader();                    }
                }
            }, false);
            return xhr;
        }

        function generateFormDataEdit() { // create a new FormData from frmProductReviewEdit to avoid using FormData.delete
            // FormData.delete not support on older android chrome browser
            var form = $('#frmProductReviewEdit');
            var fd = new FormData();
            fd.append('__RequestVerificationToken', form.find('[name=__RequestVerificationToken]').val());
            fd.append('CommentId', $('#CommentId').val());
            fd.append('CommentId_sha1', $('#CommentId_sha1').val());
            fd.append('ForumId', $('#ForumId').val());
            fd.append('ForumType', $('#ForumType').val());
            fd.append('HaveTriedEdit', $('#HaveTriedEdit').val());
            fd.append('StarRatingEdit', $('#StarRatingEdit').val());
            fd.append('ReviewTitleEdit', $('#ReviewTitleEdit').val());
            fd.append('ReviewTextEdit', $('#ReviewTextEdit').val());
            fd.append('EditImageDescription', $('#EditImageDescription').val());
            fd.append('EditVideoDescription', $('#EditVideoDescription').val()); // don't add image/video file input here
            return fd;
        }
        $(function () {
            $.validator.setDefaults({
                ignore: null
            });
            App.formValidateReset('#frmProductReviewEdit');
            $scope.$apply(function () {
                $scope.obj.HaveTriedEdit = $('#HaveTriedEdit').val() === 'True' ? true : false;
                $scope.obj.reviewEditHints();
            });
            $('#rateProductEdit').raty({
                starOff: 'fa fa-star fa-star-open',
                starOn: 'fa fa-star',
                size: 24,
                targetKeep: true,
                score: _config.initialScore === 'undefined' ? 'undefined' : parseFloat(_config.initialScore),
                click: function click(score, evt) {
                    $('#StarRatingEdit').val(score);
                    $('span[data-valmsg-for="StarRatingEdit"]').remove(); // remove error message
                    return false;
                }
            });
            $('#frmProductReviewEdit').on('submit', function (e) {
                e.preventDefault();
                var form = $(this);
                $scope.$apply(function () {
                    $scope.obj.formSubmitted = true;
                });
                var reviewTextNotValid = $scope.obj.ReviewTextEdit.length < $scope.obj.reviewMinLength || $scope.obj.ReviewTextEdit.length > $scope.obj.reviewMaxLength;
                var msgYR = $('#ReviewTextEdit').data('val-required'); // focus on the first invalid item
                if (form.valid() === false) { // scroll to the first error                          
                    if ($('#StarRatingEdit').valid() === false) {
                        scrollToReviewEditModal('#StarRatingEdit');
                    } else if ($('#ReviewTitleEdit').valid() === false) {
                        scrollToReviewEditModal('#ReviewTitleEdit');
                        $('#ReviewTitleEdit').focus();
                    } else if (reviewTextNotValid) {
                        scrollToReviewEditModal('#ReviewTextEdit');
                        $('#ReviewTextEdit').focus();
                        $('[data-valmsg-for="ReviewTextEdit"]').addClass('field-validation-error').text(msgYR).show();
                    }
                    return false;
                } else if (reviewTextNotValid) {
                    scrollToReviewEditModal('#ReviewTextEdit');
                    $('#ReviewTextEdit').focus();
                    $('[data-valmsg-for="ReviewTextEdit"]').addClass('field-validation-error').text(msgYR).show();
                    return false;
                }
                var enableUpload = true; // set to true to enable upload                
                var imageInput = form.find('#EditImageInputFile').get(0);
                var videoInput = form.find('#EditInputVideoFile').get(0);
                if (enableUpload) { // remove any previous error for video and photo if have
                    $('[data-valmsg-for=EditImageDescription]').html('').removeClass('field-validation-error');
                    $('[data-valmsg-for=EditVideoDescription]').html('').removeClass('field-validation-error');
                    var isUploadValid = true; // Photo is not required, but if photo is inputted, user must also add its description and accept terms.                    
                    var photoDesc = $.trim($('#EditImageDescription').val());
                    if (imageInput && imageInput.files && imageInput.files.length > 0 && photoDesc === '') {
                        var msgImgDesc = $('#EditImageDescription').data('val-required');
                        $('span[data-valmsg-for="EditImageDescription"]').addClass('field-validation-error').text(msgImgDesc).show();
                        isUploadValid = false;
                        $('#EditImageDescription').focus();
                    } // Video is not required, but if video is inputted, user must also add its description and accept terms.                    
                    var videoDesc = $.trim($('#EditVideoDescription').val());
                    if (videoInput && videoInput.files && videoInput.files.length > 0 && videoDesc === '') {
                        var msgVD = $('#EditVideoDescription').data('val-required');
                        $('span[data-valmsg-for="EditVideoDescription"]').addClass('field-validation-error').text(msgVD).show();
                        isUploadValid = false;
                        $('#EditVideoDescription').focus();
                    }
                    if (isUploadValid === false) return false;
                    if (videoInput && videoInput.files && videoInput.files.length > 0 && videoDesc !== '') {
                        form.find('.upload-progress-box').show();
                    }
                }
                _useInlineLoader ? showInlineLoader('reviewModalLoader') : App.loader.showLoader();
                var fd = generateFormDataEdit();
                if (enableUpload) {
                    if (imageInput && imageInput.files && imageInput.files[0] && $.trim($('#imgEditCropper').attr('src')).length > 0) {
                        fd.append('EditImageFilename', $(imageInput).val().split('\\').pop());
                    }
                    if (videoInput && videoInput.files && videoInput.files.length > 0 && videoDesc !== '') {
                        fd.append('EditVideoFilename', $(videoInput).val().split('\\').pop());
                    }
                } // Test: display the key/value pairs
                /* for (var pair of fd.entries()) { console.log(pair[0] + ', ' + pair[1]); } */
                $.ajax({
                    url: form.attr('action'),
                    type: 'POST',
                    data: fd,
                    contentType: false,
                    processData: false
                }).fail(function (jqXHR, textStatus, errorThrown) {
                    _useInlineLoader ? hideInlineLoader('reviewModalLoader') : App.loader.hideLoader();
                    App.notify.Warning(textStatus + ': ' + errorThrown);
                }).done(function (data, textStatus, jqXHR) {
                    var redirectUrl = data.uri;
                    if (data.status === 1) {
                        _useInlineLoader ? hideInlineLoader('reviewModalLoader') : App.loader.hideLoader();
                        if (_reviewCallback != null) eval(_reviewCallback)
                        else window.location = data.uri; // redirect allow click back
                    } else if (data.status === 2) { // Upload files to S3                                                             
                        if (data.awspost.length > 1) { // Uploaded two files: image and video
                            var cropperDataUrl = App.toScaledImage($('#imgEditCropper').get(0));
                            var aws4D1 = data.awspost[0]; // image
                            var fd1 = App.editCreateFormDataAWS4(aws4D1);
                            fd1.append('file', App.dataURItoBlob(cropperDataUrl));
                            var aws4D2 = data.awspost[1]; // video
                            var fd2 = App.editCreateFormDataAWS4(aws4D2);
                            fd2.append('file', videoInput.files[0]); // Concurrent ajax request (image and video post)
                            $.when($.ajax({
                                url: aws4D1.PostActionUrl,
                                type: 'POST',
                                data: fd1,
                                contentType: false,
                                processData: false,
                                cache: false
                            }), $.ajax({
                                xhr: editVideoUploadProgress, // progress bar for video upload
                                url: aws4D2.PostActionUrl,
                                type: 'POST',
                                data: fd2,
                                contentType: false,
                                processData: false,
                                cache: false
                            })).then(function () { // success
                                _useInlineLoader ? hideInlineLoader('reviewModalLoader') : App.loader.hideLoader();
                                if (_reviewCallback != null) eval(_reviewCallback)
                                else window.location = redirectUrl; // redirect and allow click back
                            }, function () { // failure
                                _useInlineLoader ? hideInlineLoader('reviewModalLoader') : App.loader.hideLoader();
                                App.notify.Warning(_config.T_ErrorProcessingRequest); // delete data entry for review text and uploads
                                $.post(_config.removeReviewUploadsUrl, {
                                    reviewId: aws4D1.ReviewId,
                                    reviewSha1: aws4D1.ReviewId_sha1,
                                    uploadId1: aws4D1.UploadId,
                                    uploadId2: aws4D2.UploadId,
                                    isEdit: true
                                });
                            });
                        } else { // Uploaded one file only
                            var aws4D = data.awspost[0];
                            var fdFile = App.editCreateFormDataAWS4(aws4D);
                            if (aws4D.ContentType.indexOf('image') > -1) { // image upload
                                var cropperData = App.toScaledImage($('#imgEditCropper').get(0));
                                fdFile.append('file', App.dataURItoBlob(cropperData));
                            } else if (aws4D.ContentType.indexOf('video') > -1) { // video upload
                                fdFile.append('file', videoInput.files[0]);
                            }
                            $.ajax({
                                xhr: editVideoUploadProgress, // progress bar for video upload
                                url: aws4D.PostActionUrl,
                                type: 'POST',
                                data: fdFile,
                                contentType: false,
                                processData: false,
                                cache: false
                            }).done(function (data, textStatus, jqXHR) {
                                _useInlineLoader ? hideInlineLoader('reviewModalLoader') : App.loader.hideLoader();
                                if (_reviewCallback != null) eval(_reviewCallback)
                                else window.location = redirectUrl; // redirect and allow click back
                            }).fail(function (jqXHR, textStatus, errorThrown) {
                                _useInlineLoader ? hideInlineLoader('reviewModalLoader') : App.loader.hideLoader();
                                App.notify.Warning(textStatus + ': ' + errorThrown); // delete data entry for review text and upload
                                $.post(_config.removeReviewUploadsUrl, {
                                    reviewId: aws4D.ReviewId,
                                    reviewSha1: aws4D.ReviewId_sha1,
                                    uploadId1: aws4D.UploadId,
                                    uploadId2: 0,
                                    isEdit: true
                                });
                            });
                        }
                    } else {
                        _useInlineLoader ? hideInlineLoader('reviewModalLoader') : App.loader.hideLoader();
                        App.notify.Warning(data.message);
                    }
                });
                return false;
            });
            $('#btnEditAddPhoto').on('click', function (e) {
                e.preventDefault();
                var $this = $(this);
                $this.addClass('active');
                $('#btnEditAddVideo').removeClass('active');
                if ($.trim($('#imgEditCropper').attr('src')).length === 0) {
                    $('#EditImageInputFile').click();
                }
                $('#divEditReviewImgRotate').removeClass('hidden');
                $('#divEditImageUpload').removeClass('hide');
                $('#divEditVideoUpload').addClass('hide');
            });
            $('#btnEditAddVideo').on('click', function (e) {
                e.preventDefault();
                var $this = $(this);
                $this.addClass('active');
                $('#btnEditAddPhoto').removeClass('active');
                var videoInput = $('#EditInputVideoFile').get(0);
                if (videoInput.files.length === 0) {
                    $('#EditInputVideoFile').click();
                }
                $('#divEditImageUpload').addClass('hide');
                $('#divEditVideoUpload').removeClass('hide');
            });
            $('#cancelEditPhotoFile').on('click', function () {
                clearImageInputs();
                $('#divEditImageUpload').addClass('hide');
                $('#btnEditAddPhoto').removeClass('active');
            });
            $('#cancelEditVideoFile').on('click', function () {
                clearVideoInputs();
                $('#divEditVideoUpload').addClass('hide');
                $('#btnEditAddVideo').removeClass('active');
                var $source = $('#vidEditPreview');
                $source.addClass('hidden');
                var videoElement = $source[0];
                videoElement.pause();
                videoElement.removeAttribute('src'); // empty source
                videoElement.load();
            });
            $('#btnPlayEditReviewVideo').on('click', function () {
                $(this).addClass('hide');
                var player = $('#vidEditPreview')[0];
                player.controls = true;
                player.play();
            });
            $('#vidEditPreview').on('ended', function () {
                $('#btnPlayEditReviewVideo').removeClass('hide');
            });
            $('#EditImageInputFile').change(function () {
                var $obj = $(this);
                if (this.files && this.files[0]) {
                    var file = this.files[0];
                    App.getImageOrientation(file, function (ox) {
                        var reader = new FileReader();
                        $('#divEditImageUpload').removeClass('hide');
                        $('#divEditVideoUpload').addClass('hide');
                        $('#divEditReviewImgRotate').removeClass('hidden');
                        $('#imgEditCropper').cropper('destroy');

                        App.loader.showLoader();
                        reader.onload = function (e) {
                            App.resetImageOrientation(e.target.result, ox, function (b64) {
                                $('span[data-valmsg-for="EditImageInputFile"]').hide();
                                $('#cancelEditPhotoFile').removeClass('hide'); // initialize cropper image
                                var $imageCrop = $('#imgEditCropper');

                                $imageCrop.attr('src', b64);
                                var cropperOptions = {
                                    aspectRatio: 1 / 1,
                                    preview: '#imgPreview',
                                    autoCrop: false,
                                    zoomable: false,
                                    cropBoxMovable: false,
                                    cropBoxResizable: false,
                                    dragMode: 'none'
                                };
                                if (_config.isMobile) {
                                    cropperOptions.crop = function (data) {
                                        if (!window._cropperData) window._cropperData = data;
                                    };

                                    // don't allow rotation/cropping for mobile
                                    cropperOptions.aspectRatio = NaN;
                                    cropperOptions.autoCrop = false;
                                    cropperOptions.rotatable = true;
                                }
                                $imageCrop.cropper(cropperOptions);
                                $imageCrop.on('built.cropper', function () {
                                    App.loader.hideLoader();
                                });
                            })
                        }

                        reader.readAsDataURL(file);
                        var frag = file.name.split('.');
                        $('#imgCropper').data('filename', $obj.val().replace(/.*[\/\\]/, ''));
                        $('#imgCropper').data('ext', frag[frag.length - 1]);
                    })
                }
            });
            $('#btnEditReviewRotateLeft, #btnEditReviewRotateRight').click(function () {
                var degree = parseInt($(this).data('degree'));
                App.rotateCropperImage($('#imgEditCropper'), degree);
                if (_config.isMobile) {
                    window._cropperData = $('#imgEditCropper').cropper('getData');
                }
            });
            $('#EditInputVideoFile').change(function () {
                var $obj = $(this);
                App.loader.showLoader();
                if (this.files && this.files[0]) {
                    $('#divEditVideoUpload').removeClass('hide');
                    $('#divEditImageUpload').addClass('hide');
                    $('[data-valmsg-for=EditInputVideoFile]').html('').removeClass('field-validation-error');
                    var $source = $('#vidEditPreview');
                    $source.removeClass('hidden');
                    $source[0].src = URL.createObjectURL(this.files[0]);
                    var reader = new FileReader();
                    reader.onload = function (e) {
                        $('span[data-valmsg-for="EditInputVideoFile"]').hide();
                        $('#spanEditVideoFile').text('[' + $obj.val().replace(/.*[\/\\]/, '') + ']');
                        $('#cancelEditVideoFile').removeClass('hide');
                        $('#btnPlayEditReviewVideo').removeClass('hide');
                        App.loader.hideLoader();
                    };
                    reader.readAsDataURL(this.files[0]);
                } else {
                    App.loader.hideLoader();
                }
            }); // For RequiredIf fields:
            // add post-initialization rule for each requiredif field to make custom requiredif rule work, on top of MVC unobtrusive rules                
            $('#StarRatingEdit').rules('add', {
                requiredif: true,
                messages: {
                    requiredif: $('#StarRatingEdit').attr('data-val-requiredif')
                }
            });
            $('#ReviewTitleEdit').rules('add', {
                requiredif: true,
                messages: {
                    requiredif: $('#ReviewTitleEdit').attr('data-val-requiredif')
                }
            }); // End RequiredIf fields
        });
    };
    var clearImageInputs = function clearImageInputs() {
        $('#cancelEditPhotoFile').addClass('hide');
        $('#EditImageInputFile').val('');
        $('#EditImageDescription').val('');
        $('#imgEditCropper').attr('src', '');
        $('#imgEditCropper').cropper('destroy');
        $('#imgEditCropper').data('filename', '');
        $('#imgEditCropper').data('ext', '');
        $('span[data-valmsg-for="EditImageInputFile"]').show();
        $('#divEditReviewImgRotate').addClass('hidden');
    };
    var clearVideoInputs = function clearVideoInputs() {
        $('#spanEditVideoFile').text('');
        $('#EditInputVideoFile').val('');
        $('#cancelEditVideoFile').addClass('hide');
        $('#btnPlayEditReviewVideo').addClass('hide');
        $('#EditVideoDescription').val('');
    };
    var onPauseEditReviewVideo = function onPauseEditReviewVideo() {
        var player = $('#vidEditPreview')[0];
        player.controls = false;
        $('#btnPlayEditReviewVideo').removeClass('hide');
    };
    return {
        init: init,
        onPauseEditReviewVideo: onPauseEditReviewVideo
    };
})();

App.Product.Review = (function () {
    var _config = {
        'ratingHints': [],
        'months': [],
        'years': [],
        'purchasedMonth': 1,
        'purchasedYear': 2017,
        'initialScore': ''
    };
    var init = function init(config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);
        }

        App.angular.controller('MainController', ['$scope', '$http', function ($scope, $http) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};
            $scope.months = _config.months;
            $scope.years = _config.years;
            $scope.purchasedMonth = _config.purchasedMonth;
            $scope.purchasedYear = _config.purchasedYear;
            $scope.obj.reviewMinLength = _config.reviewMinLength;
            $scope.obj.reviewMaxLength = _config.reviewMaxLength;
            $scope.obj.formSubmitted = false;
            $scope.obj.isPurchaseDatePast = function () {
                if (isNaN($scope.purchasedMonth) || isNaN($scope.purchasedYear)) return true; // don't show if user has not selected any yet
                var now = new Date();
                var nowMonth = now.getMonth() + 1;
                var nowYear = now.getFullYear();
                if ($scope.purchasedYear === nowYear && $scope.purchasedMonth > nowMonth) return false;
                return true;
            };
            $scope.obj.isPurchaseDateValid = function () {
                if (!$scope.obj.submitReviewClicked) return true;
                if (isNaN($scope.purchasedMonth) || isNaN($scope.purchasedYear)) return false; // don't show if user has not selected any yet
                return true;
            };
            $scope.obj.thumbClicked = function (value) {
                $scope.obj.thumbValue = value;
                $('[data-valmsg-for="Recommended"]').parent().remove();
            };
            $scope.obj.nagReviewText = 'What’s your overall opinion on this product?';
            $scope.obj.nagNotice = function () {
                var len = $scope.obj.ReviewText === null ? 0 : $scope.obj.ReviewText.length;
                var notice = len.isBetween(0, 25) ? 'What’s your overall opinion on this product?' : len.isBetween(25, 50) ? 'Why did you feel that way?' : len.isBetween(50, 75) ? 'What did you like the most about this product?' : len.isBetween(75, 125) ? 'Any improvements that you think could be made' : len.isBetween(125, 200) ? 'Would you recommend this?' : 'Awesome review. Thanks!';
                $scope.obj.nagReviewText = notice;
            };
            angular.element(document).ready(function () { // Allow validation for hidden fields, e.g. Recommended hidden field as its value is set by js
                $.validator.setDefaults({
                    ignore: null
                });
                App.formValidateReset('#frmProductReview');
                $('#rateProduct').raty({
                    hints: _config.ratingHints,
                    starOff: 'fa fa-star fa-star-open',
                    starOn: 'fa fa-star',
                    size: 24,
                    target: '#rateProductHint', // disable hint
                    targetKeep: true,
                    score: _config.initialScore === 'undefined' ? 'undefined' : parseFloat(_config.initialScore),
                    click: function click(score, evt) {
                        $('#StarRating').val(score);
                        $('span[data-valmsg-for="StarRating"]').remove(); // remove error message
                        return false;
                    }
                });
                $('button[name=btnHaveTriedYes]').click(function (e) {
                    e.preventDefault();
                    var $this = $(this);
                    $('input[name=HaveTried]').val('True');
                    $this.addClass('active');
                    $('button[name=btnHaveTriedNo]').removeClass('active');
                    $('span[data-valmsg-for="HaveTried"]').remove(); // remove error message
                    $('#divHaveTried').removeClass('hidden'); //$('#divHaveTriedUpload').removeClass('hidden'); // uncomment for photo/video upload
                    $('#divHaveNotTried').addClass('hidden');
                    $('[name=btnReviewTriedSubmit]').removeClass('hidden');
                    $('[name=btnReviewNotTriedSubmit]').addClass('hidden');
                });
                $('button[name=btnHaveTriedNo]').click(function (e) {
                    e.preventDefault();
                    var $this = $(this);
                    $('input[name=HaveTried]').val('False');
                    $this.addClass('active');
                    $('button[name=btnHaveTriedYes]').removeClass('active');
                    $('span[data-valmsg-for="HaveTried"]').remove(); // remove error message
                    $('#divHaveTried').addClass('hidden'); //$('#divHaveTriedUpload').addClass('hidden');  // uncomment for photo/video upload
                    $('#divHaveNotTried').removeClass('hidden');
                    $('[name=btnReviewTriedSubmit]').addClass('hidden');
                    $('[name=btnReviewNotTriedSubmit]').removeClass('hidden');
                });
                $('button[name=btnReviewTriedSubmit], button[name=btnReviewNotTriedSubmit]').click(function (e) {
                    $scope.$apply(function () {
                        $scope.obj.formSubmitted = true;
                    });
                    e.preventDefault();
                    var $chkTerms = $('#chkTerms');
                    var isChecked = $chkTerms.is(':checked');
                    if ($chkTerms.length > 0 && !isChecked && $('#frmProductReview').valid()) {
                        $('#dialogAgreeTerms').modal('show');
                    } else {
                        $('#frmProductReview').submit();
                    }
                });
                $('.lnkTermsConditions').click(function (e) {
                    e.preventDefault();
                    $('#dialogTermsConditions').modal('show');
                });
                $('#frmProductReview').on('submit', function (e) {
                    e.preventDefault();
                    $scope.obj.submitReviewClicked = true;
                    var form = $(this);
                    console.log({
                        purchase: !$scope.obj.isPurchaseDateValid() || !$scope.obj.isPurchaseDatePast(),
                        valid: form.valid(),
                        ht: $('input[name=HaveTried]').val()
                    });
                    if (!$scope.obj.isPurchaseDateValid() || !$scope.obj.isPurchaseDatePast()) return false;
                    var haveTried = $('input[name=HaveTried]').val();
                    if (haveTried === 'False') {
                        if ($scope.obj.ReviewTextNotTried.length < $scope.obj.reviewMinLength || $scope.obj.ReviewTextNotTried.length > $scope.obj.reviewMaxLength) {
                            $('#YourReviewNotTried').focus();
                            var msgYRNT = $('#YourReviewNotTried').data('val-required');
                            $('[data-valmsg-for="YourReviewNotTried"]').addClass('field-validation-error').text(msgYRNT).show();
                            return false;
                        }
                    } else if ($scope.obj.ReviewText.length < $scope.obj.reviewMinLength || $scope.obj.ReviewText.length > $scope.obj.reviewMaxLength) {
                        $('#YourReview').focus();
                        var msgYR = $('#YourReview').data('val-required');
                        $('[data-valmsg-for="YourReview"]').addClass('field-validation-error').text(msgYR).show();
                        return false;
                    }
                    if (!form.valid() && haveTried === 'True') return false;
                    App.loader.showLoader();
                    $http.post($(this).attr('action'), $(this).serialize()).then(function (d) {
                        if (d.status === 200) { //success
                            if (d.data.status === 1) {
                                window.location = d.data.uri;
                                return;
                            } else App.notify.Warning(d.data.message);
                        }
                        App.loader.hideLoader();
                    }, function () {
                        App.loader.hideLoader();
                    });
                });
                $('#frmProductReview').removeClass('hide');
                $('.lnkTermsConditions').click(function (e) {
                    e.preventDefault();
                    $('#dialogTermsConditions').modal('show');
                });
                $('#HaveTried').click(function () {
                    var isChecked = $(this).is(':checked');
                    if (isChecked) {
                        $(this).val('false');
                        $('#rateProduct').raty('readOnly', false);
                        selectizeMonth.enable();
                        selectizeYear.enable();
                    } else {
                        $(this).val('true');
                        $('#rateProduct').raty('cancel', false); // reset ratings
                        $('#rateProduct').raty('readOnly', true); // make it not clickable
                        selectizeMonth.disable();
                        selectizeYear.disable();
                        $('#StarRating').val(''); // reset model ratings
                        $('span[data-valmsg-for="StarRating"]').remove(); // remove error message
                    }
                });
                $('input[name=ShareToFB]').click(function () {
                    var isChecked = $(this).is(':checked');
                    if (isChecked) {
                        $(this).val('true');
                    } else {
                        $(this).val('false');
                    }
                }); // For RequiredIf fields:
                // add post-initialization rule for each requiredif field to make custom requiredif rule work, on top of MVC unobtrusive rules
                $('#Nickname').rules('add', {
                    requiredif: true,
                    messages: {
                        requiredif: $('#Nickname').attr('data-val-requiredif')
                    }
                });
                $('#StarRating').rules('add', {
                    requiredif: true,
                    messages: {
                        requiredif: $('#StarRating').attr('data-val-requiredif')
                    }
                }); // End RequiredIf fields
                if (_config.customBv && _config.customBv.length > 0) {
                    for (var i in _config.customBv) {
                        var bv = _config.customBv[i];
                        $('#' + bv).rules('add', {
                            requiredif: true,
                            messages: {
                                requiredif: $('#' + bv).attr('data-val-requiredif')
                            }
                        });
                        $('#rate_' + bv).raty({
                            hints: _config.ratingHints,
                            starOff: 'fa fa-star',
                            starOn: 'fa fa-star fa-star-pink',
                            size: 24,
                            target: '#hint_' + bv,
                            targetKeep: true,
                            score: _config.initialScore === 'undefined' ? 'undefined' : parseFloat(_config.initialScore),
                            click: function click(score, evt) {
                                $('#' + bv).val(score);
                                $('span[data-valmsg-for="' + bv + '"]').html(''); // remove error message
                                return false;
                            }
                        });
                    }
                }
            });
        }]);
    };
    return {
        init: init
    };
})();

App.Product.EditReview = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);
        }
        App.angular.controller('MainController', ['$scope', '$http', function ($scope, $http) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};
            $scope.obj.reviewMinLength = _config.reviewMinLength;
            $scope.obj.reviewMaxLength = _config.reviewMaxLength;
            $scope.obj.formSubmitted = false;
            angular.element(document).ready(function () {
                $('#rateProduct').raty({
                    hints: _config.ratingHints,
                    starOff: 'fa fa-star fa-star-open',
                    starOn: 'fa fa-star',
                    size: 24,
                    target: '#rateProductHint',
                    targetKeep: true,
                    score: _config.initialScore === 'undefined' ? 'undefined' : parseFloat(_config.initialScore),
                    click: function click(score, evt) {
                        $('#StarRatingEdit').val(score);
                        $('span[data-valmsg-for="StarRatingEdit"]').remove(); // remove error message
                        return false;
                    }
                });
                $('#frmProductReview').on('submit', function (e) {
                    e.preventDefault();
                    $scope.$apply(function () {
                        $scope.obj.formSubmitted = true;
                    });
                    if ($scope.obj.ReviewText.length < $scope.obj.reviewMinLength || $scope.obj.ReviewText.length > $scope.obj.reviewMaxLength) {
                        $('#YourReview').focus();
                        var msgYRNT = $('#YourReview').data('val-required');
                        $('[data-valmsg-for="YourReview"]').addClass('field-validation-error').text(msgYRNT).show();
                        return false;
                    }
                    var form = $(this);
                    if (!form.valid()) return false;
                    App.loader.showLoader();
                    $http.post(form.attr('action'), form.serialize()).then(function (d) {
                        if (d.status === 200) { //success
                            if (d.data.status === 1) {
                                window.location = d.data.uri;
                                return;
                            } else App.notify.Warning(d.data.message);
                        }
                        App.loader.hideLoader();
                    }, function () {
                        App.loader.hideLoader();
                    });
                    return false;
                }); // Allow validation for hidden fields, checkbox, radios, e.g. Recommended hidden field as its value is set by js
                $("#frmProductReview").data("validator").settings.ignore = ""; // For RequiredIf fields:
                // add post-initialization rule for each requiredif field to make custom requiredif rule work, on top of MVC unobtrusive rules                
                $('#StarRatingEdit').rules('add', {
                    requiredif: true,
                    messages: {
                        requiredif: $('#StarRatingEdit').attr('data-val-requiredif')
                    }
                });
                $('#ReviewTitleEdit').rules('add', {
                    requiredif: true,
                    messages: {
                        requiredif: $('#ReviewTitleEdit').attr('data-val-requiredif')
                    }
                }); // End RequiredIf fields
            });
        }]);
    };
    return {
        init: init
    };
})();

App.Product.Uploads = (function () {
    var _config = {
        'isMobile': false,
        'T_ImageUploadSuccess': '',
        'T_VideoUploadSuccess': '',
        'T_ImageDeleteSuccess': '',
        'T_VideoDeleteSuccess': ''
    };
    var T_ImageDeleteSuccess = 'test';
    var T_VideoDeleteSuccess = '';
    var init = function init(config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);
        }
        App.Product.Uploads.T_ImageDeleteSuccess = _config.T_ImageDeleteSuccess;
        App.Product.Uploads.T_VideoDeleteSuccess = _config.T_VideoDeleteSuccess;

        App.angular.controller('MainController', ['$scope', '$http', function ($scope, $http) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};
            $scope.obj.isMobile = _config.isMobile;
            $scope.obj.shareToFb = function () {
                App.loader.showLoader();
                App.fbFeedDialog(_config.linkToShare, function () {
                    $http.post(_config.fbShare).then(function (response) { // success
                        if (response.data.status === 1) {
                            App.notify.Success(_config.t_success);
                        } else {
                            App.notify.Warning('Share to FB failed');
                        }
                        App.loader.hideLoader();
                    }, function (response) { // error                                                
                    });
                });
            };
            $scope.obj.SimilarProducts = [];
            $scope.obj.similarProductsPage = 1;
            $scope.obj.similarProductsPagesize = 21;
            $scope.getSimilarProducts = function (page, $targetContainer, callback) {
                if (_config.productCategoryId === '') return;
                if (typeof $targetContainer !== 'undefined') {
                    $targetContainer.loadingOverlay();
                }
                var url = _config.similarProductsUrl + '?page=' + page + '&category=' + _config.productCategoryId + '&pageSize=' + $scope.obj.similarProductsPagesize;
                url += $scope.obj.isDebug ? '&debug=1' : '';
                $http.get(url).then(function (response) {
                    $scope.obj.Queries = response.data.Queries; // append new data to SimilarProducts
                    $scope.obj.SimilarProducts.push.apply($scope.obj.SimilarProducts, response.data.SimilarProducts);
                    if (response.data.SimilarProducts.length < $scope.obj.similarProductsPagesize) {
                        $scope.obj.showMoreSimilarProducts = false;
                    } else {
                        $scope.obj.showMoreSimilarProducts = true;
                    }
                    setTimeout(function () { // colorize stars based on product ratings
                        $('.js-star-rating').makeStars();
                    }, 100); // call callback if provided
                    if (typeof callback !== 'undefined') callback();
                }, function (response) { // error 
                    console.log(response.statusText);
                })['finally'](function () { // 
                    if (typeof $targetContainer !== 'undefined') {
                        $targetContainer.loadingOverlay('remove');
                    }
                });
            };
            $scope.formatVideoUrl = function (filename) {
                return 'https://d13isgnnvtd7yz.cloudfront.net/' + filename;
            };
            $scope.obj.UsersUploadsImages = [];
            $scope.obj.UsersUploadsVideos = [];
            angular.element(function () {
                var slickOptions3 = {
                    dots: false,
                    infinite: false,
                    speed: 300,
                    slidesToShow: 3,
                    slidesToScroll: 3,
                    responsive: [{
                        breakpoint: 920,
                        settings: {
                            slidesToShow: 2,
                            slidesToScroll: 2
                        }
                    }, {
                        breakpoint: 700,
                        settings: {
                            slidesToShow: 1,
                            slidesToScroll: 1
                        }
                    }]
                };
                $(document).on('click', '#btnPlayModalVideo', function (e) {
                    $(this).hide();
                    var player = $('#modalVideoPlayer')[0];
                    player.controls = true;
                    player.play();
                }); // Get similar products
                var slickSimilarProd;
                $scope.getSimilarProducts(1, undefined, function () {
                    setTimeout(function () {
                        slickSimilarProd = $('#productsCarousel .custom-carousel').slick(slickOptions3);
                    }, 300);
                });
                App.fixCommentsUserImage();
                $('.txt-fbshare') // highlight text
                    .on("focus keyup", function (e) {
                        var keycode = e.keyCode ? e.keyCode : e.which ? e.which : e.charCode;
                        if (keycode === 9 || !keycode) { // select
                            var $this = $(this);
                            $this.select(); // For Chrome's bug
                            $this.on("mouseup", function () { // Unbindl mouseup
                                $this.off("mouseup");
                                return false;
                            });
                        }
                    }); // Override App scroll as its offset is 200
                if (window.location.hash && $('#' + window.location.hash.replace(/[^a-z0-9A-Z\-\_]*/gi, '')).length > 0) { // smooth scroll to the anchor id
                    $('html, body').animate({
                        scrollTop: $('#' + window.location.hash.replace(/[^a-z0-9A-Z\-\_]*/gi, '')).offset().top - 0 + 'px'
                    }, 500, 'swing');
                } // apply fb share if toggle true from review page
                if (_config.shareFb && _config.hasFbConnect) { // share with FB
                    $scope.obj.shareToFb();
                } else if (_config.shareFb && !_config.hasFbConnect) { // connect to FB
                    App.loader.showLoader();
                    window.location = _config.fbConnect;
                }
            });
        }]);
    };

    var onPauseVideo = function onPauseVideo() {
        var player = $('#modalVideoPlayer')[0];
        player.controls = false;
        $('#btnPlayModalVideo').show();
    };
    return {
        init: init,
        onPauseVideo: onPauseVideo
    };
})();

App.Product._deleteMediaUpload = function (el) {
    var mid = el.attr('data-mid'); // .data() is caching previous value
    var vid = el.attr('data-vid');
    var url = el.attr('data-del-url');
    var type = el.attr('data-type'); // delete photo
    App.loader.showLoader();
    $.ajax({
        url: url,
        type: 'POST',
        data: {
            'uploadId': mid,
            'videoId': vid
        }
    }).fail(function (jqXHR, textStatus, errorThrown) {
        App.notify.Warning(errorThrown);
        App.loader.hideLoader(); // .always() not working in iphone
    }).done(function (data, textStatus, jqXHR) {
        App.loader.hideLoader(); // .always() not working in iphone
        // remove photo from display
        $('div[data-mid=' + mid + ']').remove(); // remove the row
        if (type === 'image') {
            var divContainer = $('.div-user-uploaded-photo');
            if (divContainer.find('.media-description').length === 0) {
                divContainer.parent().addClass('hide');
            }
            App.notify.Success(App.Product.Uploads.T_ImageDeleteSuccess);
        } else if (type === 'video') {
            var divContainerV = $('.div-user-uploaded-video');
            if (divContainerV.find('.media-description').length === 0) {
                divContainerV.parent().addClass('hide');
            }
            App.notify.Success(App.Product.Uploads.T_VideoDeleteSuccess);
        }
    });
};

App.Product.Brand = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);
        }
        App.angular.controller('MainController', function () {
            $(function () { // colorize stars based on product ratings
                $('.js-star-rating').makeStars();
            });
        });
    };
    return {
        init: init
    };
})();

App.Product._UserQuestions = (function () {
    var _config = {};

    function answerQAPanelToogle(qpanel) {
        if (qpanel.hasClass('in')) {
            qpanel.removeClass('in');
        } else {
            qpanel.addClass('in');
        } // trigger click on its post answer button
        qpanel.find('[name=lnkAnswerQuestionModal]').trigger('click');
    }

    var init = function init(config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);
        }
        var $scope = angular.element($('body')).scope(); // get angular scope
        //$scope.obj = {}; do not reset obj here to maintain details page obj
        $scope.obj.uId = _config.uId;

        $scope.obj.answerQuestionCallback = function () {
            var obj = arguments[0];
            var parentId = obj.parentId;
            var data = obj.data;
            var answerTxt = obj.answerTxt;
            var $responses = $('#qpanel-' + parentId).find('.responses');

            // append new answer
            var tmpHtml = $('#answerTemplate').clone().html().replace(/%cc_id%/g, data.result)
                .replace(/%cc_description%/g, answerTxt)
                .replace(/%cc_datecreated%/g, $scope.getCurrDate());

            $responses.append(tmpHtml);
            // increment answer count
            var qDiv = $('#question-' + parentId);
            var answerCount = parseInt(qDiv.data('answercount')) + 1;
            qDiv.data('answercount', answerCount);
            qDiv.find('.answer-count').html(answerCount + " " + (answerCount > 1 ? _config.T_Answers : _config.T_Answer));

            // rebind angularjs scope                        
            angular.element(document).injector().invoke(
                [
                    "$compile", function ($compile) {
                        $compile($responses.find("div.answer-wrapper:last-child").contents())($scope);
                    }
                ]);

            obj.modal.modal('hide');
        }

        $scope.updateQALikes = function ($event, questionId, likedCount) {
            if ($scope.obj.uId === 0) {
                return window.location = _config.loginUrl + '?returnurl=' + encodeURIComponent(_config.productUrl + $scope.getPageParam() + '#question-' + questionId);
            }
            var currTarget = $($event.currentTarget);
            currTarget.find('img').attr('src', '/images/heart-outline-purple.gif'); // change to animated heart                    
            angular.element($event.currentTarget).unbind('click'); // remove ng-click
            var postData = {
                id: questionId,
                theTable: _config.tableToVoteUserQuestions,
                type: 1
            };
            var jqxhr = $.post(_config.addEmojiCommentUrl, postData, function (data) { // post success       
                if (!data.hasError) { // increment likes
                    likedCount += 1; // remove ng-click
                    angular.element($event.currentTarget).unbind('click'); // add tooltip                    
                    currTarget.find('img').attr('src', '//d2vtntcxpdw15n.cloudfront.net/img3/heart-solid-purple.png'); // change to filled heart
                    currTarget.attr('data-original-title', data).addClass('tooltips');
                    currTarget.next().find('.like-count').removeClass('hide').text(likedCount); // update count
                    $(".tooltips").tooltip({
                        trigger: "hover"
                    });
                } else {
                    App.notify.Warning(data.message);
                    currTarget.find('img').attr('src', '//d2vtntcxpdw15n.cloudfront.net/img3/heart-outline-purple.png');
                    angular.element($event.currentTarget).bind('click');
                }
            }).fail(function () {
                App.notify.Danger(_config.T_ErrorProcessingRequest);
                currTarget.find('img').attr('src', '//d2vtntcxpdw15n.cloudfront.net/img3/heart-outline-purple.png');
                angular.element($event.currentTarget).bind('click');
            }).always(function () {});
        };
        $scope.getUrlParameter = function (sParam) {
            var sPageURL = window.location.search.substring(1),
                sURLVariables = sPageURL.split('&'),
                sParameterName, i;
            for (i = 0; i < sURLVariables.length; i++) {
                sParameterName = sURLVariables[i].split('=');
                if (sParameterName[0] === sParam) {
                    return sParameterName[1] === undefined ? true : decodeURIComponent(sParameterName[1]);
                }
            }
        }; /* Ask question functions */
        $scope.obj.userQuestionPage = 1;
        $scope.obj.showMoreQuestions = true;
        $scope.getMoreUsersQuestions = function () {
            $scope.obj.userQuestionPage++;
            var url = _config.askQuestionMoreUrl + '&page=' + $scope.obj.userQuestionPage + '&pageSize=' + _config.askQuestionPageSize;
            $.get(url).done(function (response) {
                if ($.trim(response) === '') {
                    $scope.$apply(function () {
                        $scope.obj.showMoreQuestions = false;
                    });
                    return;
                }
                var $divQ = $('#divTheQuestions');
                $divQ.append(response);
                var totRows = $divQ.data('totrows');
                var actRows = $divQ.find('.review-container:last').data('pagerows');
                if (actRows < _config.askQuestionPageSize) {
                    $scope.obj.showMoreQuestions = false;
                } else {
                    $scope.obj.showMoreQuestions = true;
                }
                $(".tooltips").tooltip({
                    trigger: "hover"
                });
                setTimeout(function () { // fix avatar image of comments
                    $scope.fixUserImage();
                }, 300);
            }).fail(function (jqXHR, textStatus, errorThrown) {
                console.log('Error:' + textStatus);
            }).always(function () {});
        }; // Get $location service
        var $location = $('html').injector().get('$location');
        $(function () { // accordion panel collapse event            
            $('#divUserQuestions .panel-collapse').on('show.bs.collapse', function () {
                $(this).prev().find('i').removeClass('glyphicon-chevron-down').addClass('glyphicon-chevron-up');
            });
            $('#divUserQuestions .panel-collapse').on('hide.bs.collapse', function () {
                $(this).prev().find('i').removeClass('glyphicon-chevron-up').addClass('glyphicon-chevron-down');
            });
            $('.question-user-info .answer-count').on('click', function () {
                $(this).closest('.panel-heading').next().collapse('toggle');
            });
            
            var id = window.location.hash.substring(1);
            var act = $scope.getUrlParameter('act');
            var scrollToAct = false; // open respond box if it was click before login
            if (typeof act !== 'undefined') {
                if (act === 'answer') { // open question panel, 
                    answerQAPanelToogle($('#qpanel-' + id));
                    scrollToAct = true;
                }
            }
            $(".tooltips").tooltip({
                trigger: "hover"
            });
            setTimeout(function () { // fix avatar image of comments
                $scope.fixUserImage(); // scroll to id 
                if (id !== '' && scrollToAct) {
                    $('html, body').animate({
                        scrollTop: $("#question-" + id).offset().top
                    }, 300);
                }
            }, 300);
        });
    };
    var beforeReportUserQuestion = function beforeReportUserQuestion(el) {
        var id = el.data('cid');
        if (_config.uId === 0) {
            var ng = angular.element($('body')).scope(); // get angular scope
            window.location = _config.loginUrl + '?returnurl=' + encodeURIComponent(_config.productUrl + ng.getPageParam() + '#question-' + id);
            return false;
        }
        return true;
    };
    var reportUserQuestion = function reportUserQuestion(el) { // report user question
        var id = el.data('cid');
        if (id === 0) return;
        if (_config.uId === 0) {
            var ng = angular.element($('body')).scope(); // get angular scope
            return window.location = _config.loginUrl + '?returnurl=' + encodeURIComponent(_config.productUrl + ng.getPageParam() + '#question-' + id);
        }
        App.loader.showLoader();
        var jqxhr = $.post(_config.reportUserQuestionUrl + '/' + id, function (data) { // success, remove response box          
            if (data.result > 0) {
                $('#question-' + id).remove();
            } else if (data.message !== '') {
                App.notify.Warning(data.message);
            }
        }).fail(function () {
            App.notify.Warning(_config.T_ErrorProcessingRequest);
        }).always(function () {
            App.loader.hideLoader();
        });
    };
    var beforeReportUserAnswer = function beforeReportUserAnswer(el) {
        var id = el.data('cid');
        if (_config.uId === 0) {
            var ng = angular.element($('body')).scope(); // get angular scope
            window.location = _config.loginUrl + '?returnurl=' + encodeURIComponent(_config.productUrl + ng.getPageParam() + '#answer-' + id);
            return false;
        }
        return true;
    };
    var reportUserAnswer = function reportUserAnswer(el) { // report user question
        var id = el.data('cid');
        if (id === 0) return;
        if (_config.uId === 0) {
            var ng = angular.element($('body')).scope(); // get angular scope
            return window.location = _config.loginUrl + '?returnurl=' + encodeURIComponent(_config.productUrl + ng.getPageParam() + '#question-' + id);
        }
        App.loader.showLoader();
        var jqxhr = $.post(_config.reportUserQuestionUrl + '/' + id, function (data) { // success, remove response box          
            if (data.result > 0) { // decrement the answer count
                var $answer = $('#answer-' + id);
                var panel = $answer.closest('.panel').parent();
                var answerCount = parseInt(panel.data('answercount')) - 1;
                panel.data('answercount', answerCount);
                panel.find('.panel-heading .answer-count').html(answerCount + ' ' + (answerCount > 1 ? _config.T_Answers.toLowerCase() : _config.T_Answer.toLowerCase()));
                panel.find('.panel-body .answer-count').html(answerCount + ' ' + (answerCount > 1 ? _config.T_Answers : _config.T_Answer));
                $answer.remove();
            } else if (data.message !== '') {
                App.notify.Warning(data.message);
            }
        }).fail(function () {
            App.notify.Warning(_config.T_ErrorProcessingRequest);
        }).always(function () {
            App.loader.hideLoader();
        });
    };
    var deleteUserQuestion = function deleteUserQuestion(el) { // delete user question        
        var cid = el.data('cid');
        if (cid === 0) return;
        App.loader.showLoader();
        var jqxhr = $.post(_config.deleteUserQuestionUrl + '/' + cid, function (data) { // success, remove response box                  
            if (data.result > 0) {
                var closeBtn = $('button[data-closecid=' + cid + ']');
                var commentBox = closeBtn.closest('.child-comment-box');
                commentBox.animate({
                    height: 0
                }, 1000, function () {
                    commentBox.parent().parent().empty();
                });
            }
        }).fail(function () {
            alert(_config.T_ErrorProcessingRequest);
        }).always(function () {
            App.loader.hideLoader();
        });
    };
    return {
        init: init,
        beforeReportUserQuestion: beforeReportUserQuestion,
        reportUserQuestion: reportUserQuestion,
        deleteUserQuestion: deleteUserQuestion,
        beforeReportUserAnswer: beforeReportUserAnswer,
        reportUserAnswer: reportUserAnswer
    };
})();;
'use strict';

if (typeof App == 'undefined') var App = {};

App.Reviews = (function () {
    return {};
})();

App.Reviews.Categories = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);
        }

        App.angular.controller('MainController', ['$scope', function ($scope) {
            $scope.obj = {};

            angular.element(function () {
                // category slider
                var sliderItems = $('.home-main-slider .bxslider li').length;
                var homeMainSlider = $('.home-main-slider .bxslider').bxSlider({
                    auto: sliderItems > 1 ? true : false,
                    speed: 1000,
                    pause: 10000,
                    touchEnabled: false,
                    onSlideBefore: function onSlideBefore() {
                        $('.home-main-slider .bx-default-pager').hide();
                    },
                    onSlideAfter: function onSlideAfter() {
                        $('.home-main-slider .bx-default-pager').show();
                    },
                    onSliderLoad: function onSliderLoad() {
                        $('.home-main-slider .bx-prev, .home-main-slider .bx-next').hide();
                        //var nextTxt = $('.home-main-slider .bx-next').text();
                        //$('.home-main-slider .bx-next').empty().append('<span class="spn-bx-next hidden-xs">' + _config.sliderNext + '</span><i class="fa fa-angle-right white-color"></i>')
                        var defaultPager = $('.home-main-slider .bx-default-pager');
                        if (this.getSlideCount() > 1) defaultPager.show();
                        else defaultPager.hide();

                        $('.home-main-slider .slider-link').removeClass('hidden');
                    }
                });

                // stop auto play on slider when clicking the pager
                $('.home-main-slider .bx-pager-link').on('click', function () {
                    homeMainSlider.stopAuto(false);
                });

                homeMainSlider.swipe({
                    swipeRight: function swipeRight(event, direction, distance, duration, fingerCount) {
                        homeMainSlider.goToPrevSlide();
                    },
                    swipeLeft: function swipeLeft(event, direction, distance, duration, fingerCount) {
                        homeMainSlider.goToNextSlide();
                    },
                    threshold: 100
                });
            });
        }]);
    };

    return {
        init: init
    };
})();

App.Reviews.CategoryDetail = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);
        }
        window.over_brandLink = function (theID) {

            $('#topHome1').slideToggle("slow");
            $('#brand' + theID).slideToggle("slow");
        };
        window.out_brandLink = function (theID) {
            $('#brand' + theID).slideToggle("slow");
            $('#topHome1').slideToggle("slow", function () {
                App.scrollTo('#topHome1');
            });
        };
        App.angular.controller('MainController', ['$scope', '$http', function ($scope, $http) {
            //$http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};
            $scope.obj.copy = function () {
                var result = App.copyTextToClipboard(_config.urlToShare);
                App.inlineSuccessAlert('#txtCopyBox', _config.successTxt, App.placement.after);
            };
            $scope.obj.shareFb = function () {
                var uri = _config.shareToFbUri;
                App.loader.showLoader();
                App.fbFeedDialog(_config.linkToShare, function () {
                    $http.post(uri).then(function (res) {
                        if (res.status == 200) {
                            if (res.data.status == 1) {
                                //App.notify.Success(_config.successTxt);
                                App.inlineSuccessAlert('#networkDiv', _config.successTxt);
                                $scope.obj.shareMessage = null;
                            }
                            //else
                            //    App.notify.Warning(res.data.message);

                            App.loader.hideLoader();
                        }
                    });
                });
            };

            // arc height, radius (unit), angle (degrees)
            function arcHeight(r, a) {
                return r - r * Math.cos(a * Math.PI / 180);
            }

            function isAngleUpperHalf(deg) {
                return deg >= 0 && deg <= 90 || deg >= 270 && deg <= 360;
            }

            function positionLabels() {
                var $deg = $('[data-perc]');
                var tDeg = 0,
                    heightOffset = 157,
                    radii = 152;
                for (var i = 0; i < $deg.length; i++) {
                    var $elem = $deg.eq(i);
                    var perc = parseFloat($elem.data('perc'));
                    var midPerc = perc / 2;
                    var deg = 360 * (tDeg + midPerc);
                    var h = arcHeight(radii, deg);
                    h = h < 20 ? -50 : h;

                    var isUpperHalf = isAngleUpperHalf(deg);
                    var o = heightOffset + h - 25; // determin Y position of the label
                    var posObj = deg >= 0 && deg <= 30 ? {
                            'right': '50px'
                        } : // determin the X position of the label
                        deg >= 30 && deg <= 110 ? {
                            'right': '30px'
                        } : deg >= 110 && deg <= 180 ? {
                            'right': '40px'
                        } : deg >= 180 && deg <= 210 ? {
                            'left': '70px'
                        } : deg >= 210 && deg <= 320 ? {
                            'left': '30px'
                        } : deg >= 320 && deg <= 340 ? {
                            'left': '100px'
                        } : deg >= 340 && deg <= 360 ? {
                            'right': '200px'
                        } : {
                            'left': '30px'
                        };

                    posObj.top = o + 'px';
                    $elem.css(posObj);
                    //console.log({ h: h, o: o, perc: perc, total: tDeg, deg: deg });
                    tDeg += perc;
                }
            }

            angular.element(function () {
                positionLabels();
                $('.js-star-rating').makeStars();
                $('.navbar-top-menu').addClass(_config.theme).show();
                $('.navbar-top-menu .navbar-wrapper:first').addClass('bipolar-bg').removeClass('primary-purple-background');;
                (function () {
                    /*
                     * SVG Pie Chart Generator 
                     *
                     * Inserts a SVG pie chart inside elements with a `data-pie` attribute containing the colors and numbers. 
                     Total is generated dynamically, so the numbers do not have to be a percentage.
                     * Example: `<div data-pie="#fab484 5, #fe8e3f 3, #f96b07 3, #b45919 3, #7f4319 1"></div>`
                     */

                    var template = {
                        open: '<svg viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" ><defs><circle id="graph" r="15.9154943092" cx="16" cy="16" transform="rotate(-90 16 16)" /><mask id="clip"><use xlink:href="#graph" fill="#FFF" /></mask></defs><g class="graph" mask="url(#clip)" stroke-width="32">',
                        piece: '<use class="graph__percent graph__percent--{{num}}" xlink:href="#graph" fill="none" stroke="{{color}}" stroke-dasharray="0 {{offset}} {{percent}} 100" />',
                        close: '</g></svg>'
                    };
                    var regex = {
                        number: /([0-9]+)$/i,
                        color: /(#[0-9A-Z]+)/i
                    };

                    function Piece(data) {
                        data = data.trim();
                        this.number = parseInt(data.match(regex.number));
                        this.color = data.match(regex.color)[1];
                    }

                    Piece.prototype.render = function (total, num) {
                        return template.piece.replace('{{num}}', num).replace('{{color}}', this.color).replace('{{offset}}', this.offset / total * 100).replace('{{percent}}', this.number / total * 100);
                    };

                    function Pie(elem) {
                        this.data = elem.getAttribute('data-pie').split(',');
                        this.pieces = [];
                        this.total = 0;

                        var output = "",
                            len = this.data.length,
                            piece,
                            i;

                        for (var i = 0; i < len; i++) {
                            piece = new Piece(this.data[i]);
                            piece.offset = this.total;
                            this.total += piece.number;
                            this.pieces.push(piece);
                        }

                        len = this.pieces.length;
                        for (var i = 0; i < len; i++) {
                            output += this.pieces[i].render(this.total, i);
                        }

                        elem.innerHTML = template.open + output + template.close;
                    }

                    var pies = document.querySelectorAll('[data-pie]');

                    for (var i = 0; i < pies.length; i++) {
                        new Pie(pies[i]);
                    }
                })();
            });
        }]);
    };

    return {
        init: init
    };
})();

App.Reviews.Index = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config == 'object') {
            $.extend(true, _config, config);
        }

        App.angular.controller('MainController', ['$http', function ($http) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

            $(function () {
                // add scripts here
            });
        }]);

        App.angular.controller('reviewsController', ['$scope', 'searchService', function ($scope, searchService) {
            var reviews = this;

            var ALL_PRODUCTS = 1;
            var FEATURED = 2;
            var HOME_TESTED = 4;

            var _reviewsRoot = window.location;
            reviews.searchService = searchService;
            reviews.selected = {};
            reviews.searchService.page(_config.page);

            if (_config.categories !== undefined) {
                reviews.searchService.categories(_config.categories);
            }

            if (_config.sortBy !== undefined) {
                reviews.searchService.sortBy(_config.sort);
            }

            if (_config.brandId !== undefined) {
                reviews.searchService.brandId(_config.brandId);
            }

            if (_config.showCount !== undefined) {
                reviews.searchService.showCount(_config.showCount);
            }

            if (_config.searchString !== undefined) {
                reviews.searchService.searchString(_config.searchString);
            }

            if (_config.brandString !== undefined) {
                reviews.searchService.brandString(_config.brandString);
            }

            if (_config.productCount !== undefined) {
                reviews.searchService.productCount(_config.productCount);
            }

            if (_config.totalCount !== undefined) {
                reviews.searchService.totalCount(_config.totalCount);
            }

            if (_config.reviewsRoot !== undefined) {
                _reviewsRoot = _config.reviewsRoot;
            }

            reviews.searchService.reviewRoot(_reviewsRoot);

            // if we are initializing the page to "Trending" then ensure that all categories are selected
            // as well.
            if (reviews.searchService.sortBy() == reviews.searchService.sortByEnum.Trending) {
                reviews.searchService.selectAllCategoriesAndTypes();
            }

            reviews.all = function (newAll) {
                return arguments.length > 0 ? searchService.all(newAll) : searchService.all();
            };

            reviews.selectedCategory = function (selectedCategory) {
                return arguments.length > 0 ? searchService.selectedCategory(selectedCategory) : searchService.selectedCategory();
            };

            reviews.crumbs = function (newCrumbs) {
                return arguments.length > 0 ? searchService.crumbs(newCrumbs) : searchService.crumbs();
            };

            reviews.featured = function (newFeatured) {
                return arguments.length > 0 ? searchService.featured(newFeatured) : searchService.featured();
            };

            reviews.homeTested = function (newHomeTested) {
                return arguments.length > 0 ? searchService.homeTested(newHomeTested) : searchService.homeTested();
            };

            reviews.sortBy = function (newSortBy) {
                return arguments.length > 0 ? searchService.sortBy(newSortBy) : searchService.sortBy();
            };

            reviews.showCategories = function () {
                return searchService.categories().length > 0;
            };

            reviews.categoriesBootstrapClass = function () {
                var result = reviews.showCategories() ? 'col-md-9' : 'col-md-12';
                return result;
            };

            reviews.categories = function () {
                return searchService.categories();
            };

            reviews.parentCategories = function () {
                return searchService.parentCategories();
            };

            reviews.childCategories = function () {
                return searchService.childCategories();
            };

            reviews.grandChildCategories = function () {
                return searchService.grandChildCategories();
            };

            reviews.loadMoreProducts = function () {
                reviews.searchService.loadMoreProducts();
            };

            reviews.onCategoryChanged = function () {
                reviews.searchService.onCategoryChanged();
            };

            reviews.onFilterChanged = function () {
                reviews.searchService.onFilterChanged();
            };

            reviews.closeFilteredView = function () {
                if (reviews.searchService.brandId() > 0) {
                    // We just need to relocate to the root reviews page with no filter
                    window.location = _reviewsRoot;
                } else {
                    // reset the search content
                    reviews.resetProductsGrid();
                }
                reviews.searchService.showResultText(false);

                angular.element(function () {
                    reviews.toggleCategoryListing();
                });
            };

            reviews.resetProductsGrid = function () {
                reviews.searchService.resetProductsGrid();
            };

            reviews.startFilterTimer = function () {
                reviews.searchService.startFilterTimer();
                angular.element(function () {
                    reviews.toggleCategoryListing();
                });
            };

            reviews.getProductCount = function () {
                return searchService.productCount();
            };

            reviews.getTotalCount = function () {
                return searchService.totalCount();
            };

            reviews.showCount = function (newShowCount) {
                return arguments.length > 0 ? searchService.showCount(newShowCount) : searchService.showCount();
            };

            reviews.showParents = function () {
                var cats = searchService.categories();
                return _.filter(cats, function (x) {
                    return x.selected == true;
                }).length == 0;
            };

            reviews.showChildren = function () {
                if (searchService.childCategories() == null) return false;

                return searchService.childCategories().length > 0;
            };

            reviews.showGrandChildren = function () {
                if (searchService.grandChildCategories() == null) return false;

                return searchService.grandChildCategories().length > 0;
            };

            reviews.isLastChild = function () {
                return searchService.isLastChild();
            };

            reviews.getDisplayName = function (category) {
                if (category == null || category.name == null) return null;

                return category.name.length == 0 ? category.description : category.name;
            };

            reviews.getParent = function (c) {
                var parentId = c.parentId;
                if (parentId == 0) return null;

                return _.find(searchService.categories(), function (x) {
                    return x.id == parentId;
                });
            };

            reviews.closeSearch = function () {
                reviews.showCount(false);
                reviews.searchService.resetSearchString('');
                $('.search-result-suggestion').remove(); // auto suggest box
                setTimeout(function () {
                    $('#search-product').focus();
                }, 100);
            };

            reviews.setCrumbs = function () {
                if (reviews.showParents() || searchService.selectedCategory() == null || searchService.selectedCategory().id == 0) {
                    reviews.crumbs([]);
                    return;
                }

                var top = {
                    id: 0,
                    selected: false,
                    parentId: 0,
                    name: _config.allProdTxt,
                    description: ''
                };
                var crumbs = [];

                if (reviews.showGrandChildren()) {
                    var cats = searchService.categories();
                    var item = _.find(cats, function (x) {
                        return x.selected == true;
                    });

                    while (item.parentId > 0) {
                        var parent = _.find(cats, function (x) {
                            return x.id == item.parentId;
                        });
                        crumbs.push(parent);

                        item = parent;
                    }
                }

                crumbs.push(top);
                crumbs = crumbs.reverse();
                reviews.crumbs(crumbs);
            };
            reviews.selected = {};
            reviews.sync = function (item) {
                // toggle radio button selection
                //if (item.id > 0)
                //    $('#cat-' + item.id + ',#top-' + item.id).prop('checked', true);
                //else
                //    $('.category-select').prop('checked', false);

                // any action taken on categories should clear search
                // HTCNEW-923: "Fixing" filter and category functionality within search
                // reviews.searchService.searchString('');
                // reviews.searchService.showCount(false);
                searchService.selectedCategory(item);
                var categories = searchService.categories();

                // reset automatic loading of products               
                searchService.resetLoadingMore();

                // If this is "All" then force the state change on all categories
                if (item.id === 0) {
                    categories.every(function (category) {
                        category.selected = false;
                        return true;
                    });
                }

                // else if "All" is still selected and this item's state is unselected
                // we want to actually set this item's state to selected and unselect everything else
                else /*if (categories[0].selected == true && item.selected == false)*/ {
                    categories.every(function (category) {
                        if (category.id != item.id) {
                            category.selected = false;
                        } else {
                            category.selected = true;
                        }
                        return true;
                    });
                }

                // set crumbs
                reviews.setCrumbs();

                // start a timer so that products get reloaded
                reviews.searchService.startFilterTimer();

                angular.element(function () {
                    reviews.toggleCategoryListing();
                });
            };

            reviews.handleFilterChange = function (selectAllCategories) {
                // any action taken on categories should clear search
                // HTCNEW-923: "Fixing" filter and category functionality within search
                // reviews.searchService.searchString('');

                // for Trending we need to select all categories
                if (selectAllCategories == true) {
                    reviews.searchService.selectAllCategoriesAndTypes();
                }

                reviews.searchService.showCount(false);
                reviews.startFilterTimer();
            };

            reviews.setItemOnLoad = function () {
                if (reviews.showParents()) return;

                var selected = searchService.setSelectedOnLoad();
                if (selected.length > 0) {
                    searchService.selectedCategory(selected[0]);
                    searchService.setSelected(selected[0]);
                }
            };

            reviews.toggleCategoryListing = function () {
                var selected = searchService.selectedCategory();
                $('[data-parentcatid]').hide();
                $('.search-result-suggestion').remove();

                if (selected == null) {
                    $('[data-parentcatid="0"]').fadeIn();
                    return;
                } // parents
                else {
                    var categories = reviews.categories();
                    if (_.filter(categories, function (x) {
                            return x.parentId == selected.id;
                        }).length > 0) $('[data-parentcatid="' + selected.id + '"]').fadeIn();
                    else {
                        var parent = _.find(categories, function (x) {
                            return x.id == selected.parentId;
                        }); // last child
                        $('[data-parentcatid="' + parent.id + '"]').show();
                    }
                }

                console.log('catch', {
                    all: reviews.all(),
                    featured: reviews.featured(),
                    hometested: reviews.homeTested()
                });
                if (!reviews.all() || !reviews.featured() || !reviews.homeTested()) $('[data-parentcatid]:visible').each(function (i, o) {
                    var d = $(o).data();
                    var t = d.types;
                    var show = reviews.all() && t.indexOf('P') > -1 || reviews.featured() && t.indexOf('S') > -1 || reviews.homeTested() && t.indexOf('T') > -1;

                    if (!show) $(o).hide();
                });
            };

            reviews.searchService.all((_config.show & ALL_PRODUCTS) != 0);
            reviews.searchService.featured((_config.show & FEATURED) != 0);
            reviews.searchService.homeTested((_config.show & HOME_TESTED) != 0);
            reviews.setItemOnLoad();
            reviews.setCrumbs();

            angular.element(function () {
                // colorize stars based on product ratings
                $('.js-star-rating').makeStars();

                // store off the product grid
                reviews.searchService.productsGrid($('.product-reviews'));

                // store off the load more products div
                reviews.searchService.loadMoreProductsButton($('.load-more-products'));

                reviews.searchService.isAllDataLoaded(true);
                reviews.toggleCategoryListing();

                // if we have a search string, the hide the load more products button right out of the gate
                var hideLoadMore = reviews.searchService.searchString() !== undefined && reviews.searchService.searchString().length > 0 || reviews.searchService.brandString().length > 0;
                if (hideLoadMore) {
                    //reviews.searchService.loadMoreProductsButton().hide();
                    reviews.showCount(true);
                }

                // stop closing dropdown if clicking inside
                $(document).on('click', '.dropdown .dropdown-menu', function (e) {
                    e.stopPropagation();
                });

                $(document).on('scroll resize', function () {
                    if ($('.rp-hero-search').isInViewport() || $('#back-to-top').isInViewport()) $('[data-toggle="scroll-to-top"]:not([id="back-to-top"])').hide();
                    else $('[data-toggle="scroll-to-top"]:not([id="back-to-top"])').show();

                    if (reviews.searchService.isAllDataLoaded() && $('.rp-search_btn').isInViewport() && reviews.searchService.brandString().length === 0) {
                        var currentPage = reviews.searchService.page();
                        var items = 21;
                        var totalInView = currentPage * items;
                        var isSearch = reviews.searchService.searchString().length > 0;

                        if (isSearch && totalInView >= reviews.searchService.totalCount()) {
                            reviews.searchService.loadMoreProductsButton().hide();
                            return;
                        }

                        isSearch ? reviews.searchService.searchForProducts() : reviews.loadMoreProducts();
                    }
                });

                // category mobile toggle
                $('#headingOne').click(function () {
                    if (!$('#headingOne .salmon-color i').is(':visible')) return;

                    var $header = $(this);
                    var $list = $('#collapseOne'),
                        $xsFilter = $('#headingTwo');
                    if ($list.is(':visible')) {
                        $xsFilter.show();
                        $list.slideUp(300, function () {
                            $header.find('.salmon-color i').removeClass('fa-angle-up').addClass('fa-angle-down');
                        });
                    } else {
                        $xsFilter.hide();
                        $list.slideDown(300, function () {
                            $header.find('.salmon-color i').addClass('fa-angle-up').removeClass('fa-angle-down');
                        });
                    }
                });
            });
        }]);
    };

    return {
        init: init
    };
})();;
'use strict';

if (typeof App == 'undefined') var App = {};

App.Search = (function () {
   return {};
})();

App.Search.Index = (function () {
   var _config = {};
   var init = function init(config) {
      if (config && typeof config == 'object') {
         $.extend(true, _config, config);
      }

      App.angular.controller('MainController', ['$scope', '$http', function ($scope, $http) {
         $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
         $scope.obj = {};

         $(function () {
            // add scripts here
         });
      }]);

      App.angular.controller('searchController', ['searchService', '$anchorScroll', function (searchService, $anchorScroll) {
         var search = this;

         search.searchService = searchService;

         angular.element(function () {
            if (search.searchService.searchString() !== undefined && search.searchService.searchString().length > 0) {
               // Scroll the search results to the top
               $anchorScroll('product-reviews');
            }
         });

         search.showCount = function (newSearchString) {
            return arguments.length > 0 ? search.searchService.showCount(newSearchString) : search.searchService.showCount();
         };

         search.searchString = function (newSearchString) {
            return arguments.length > 0 ? search.searchService.searchString(newSearchString) : search.searchService.searchString();
         };

         search.searchForProducts = function (resetCategoriesAndTypes, storeHistory) {
            search.showCount(true);
            search.searchService.searchForProducts(resetCategoriesAndTypes, storeHistory);
         };
      }]);
   };
   return {
      init: init
   };
})();;
'use strict';
if (typeof App == 'undefined') var App = {};

App.Shared = (function () {
    return {};
})();

App.Shared._DynamicContactLookup = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config == 'object') {
            $.extend(true, _config, config);
        }
        // Note: Don't enclose init function in $()
        App.angular.controller('addressController', ['$scope', '$http', 'unitOfWork', function ($scope, $http, unitOfWork) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {
                hasGlobalLookup: _config.hasGlobalLookup,
                phone: _config.phone,
                userPin: _config.userPin,
                addressMain: _config.userAddress,
                userAddress4: _config.userAddress4,
                userAddress3: _config.area
            };
            $scope.obj.dynamicFields = _config.dynamicFields;
            $scope.obj.marketSelected = _config.market;
            $scope.obj.nameSpace = _config.nameSpace;
            $scope.obj.showCountryOption = _config.showCountryOption;
            $scope.obj.hasPostcodeLookup = _config.hasPostcodeLookup;
            $scope.obj.userState = _config.state;
            $scope.obj.stateList = _config.stateList;
            $scope.obj.userSuburb = _config.indoDistrict;
            $scope.obj.userAddress2 = _config.indoSubDistrict;
            $scope.obj.hasDynamicSuburb = function () {
                return _.filter(_config.dynamicSuburbCountries, function (x) {
                    return x == $scope.obj.marketSelected;
                }).length > 0;
            };
            $scope.obj.hasLookupData = function () {
                return !$.isEmptyObject($scope.obj.lookupData);
            };
            $scope.obj.hasReturnedLookup = false;
            $scope.obj.postcodeAreaListing = [];
            $scope.obj.suburbFiltered = function () {
                if (!$scope.obj.dynamicFields.hasNoPost || $scope.obj.userState == null) return $scope.obj.suburbList;
                return _.filter($scope.obj.suburbList, function (s) {
                    return $scope.obj.userState == s.state;
                });
            };
            $scope.obj.canShowInput = function () {
                return !$scope.obj.hasGlobalLookup || $scope.obj.hasGlobalLookup && $scope.obj.hasReturnedLookup;
            };
            $scope.obj.dynamicPostCode = function () {
                if (!$scope.obj.hasGlobalLookup || !!!$scope.obj.userPostCode || $.trim($scope.obj.userPostCode).length < 2) return;
                App.loader.showLoader();
                $http.post(_config.getDynamicPcListUri, $.param({
                    code: $scope.obj.userPostCode,
                    country: $scope.obj.marketSelected
                })).then(function (d) {
                    if (d.status == 200) { //success
                        $scope.obj.hasReturnedLookup = true;
                        $('#btnRegisterDelivery').removeClass('hide');
                        var data = d.data;
                        if (data.status == 0) {
                            $scope.obj.lookupData = {};
                            $scope.obj.stateList = data.states;
                            $scope.obj.suburbList = [];
                            $scope.obj.address3List = [];
                            $scope.obj.address4List = []; // handle noState re assignemnt
                            if ($scope.obj.stateList.length == 1 || $scope.obj.dynamicFields.noState == 1) {
                                $scope.obj.userState = $scope.obj.stateList[0].State;
                                $scope.obj.userStateName = $scope.obj.stateList[0].Name;
                            }
                            clearLookup();
                            App.loader.hideLoader();
                            angular.element(function () {
                                unitOfWork.util.resetFormError("#frmDelivery");
                                unitOfWork.util.formValidateReset("#frmDelivery");
                            });
                            return;
                        }
                        $scope.obj.lookupData = data;
                        $scope.obj.setLookupData(data);
                    }
                    App.loader.hideLoader();
                }, function () {
                    App.loader.hideLoader();
                });
            };

            function clearLookup() {
                $scope.obj.userSuburb = null;
                if ($scope.obj.dynamicFields.noState !== 1) // clear state for nostate = 0
                    $scope.obj.userState = null;
                $scope.obj.userAddress3 = null;
                $scope.obj.userAddress4 = null;
                $scope.obj.userStateName = null;
                $scope.obj.userSuburb_Text = null;
                $scope.obj.userAddress_3_Text = null;
                $scope.obj.userAddress4_Text = null;
            }
            var returnLocation = function returnLocation(x) {
                var text = (x.Eng || '').length == 0 && (x.Local || '').length > 0 ? x.Local : (x.Eng || '') + ($.trim(x.Local || '').length > 0 && $.trim(x.Eng || '').length > 0 ? '-' : '') + (x.Local || '');
                return {
                    state: x.State,
                    text: text,
                    val: $.trim(x.Local || '').length > 0 ? x.Local : x.Eng
                };
            };
            var firstOrDefault = function firstOrDefault(x, k) {
                if (!!!x || x == null || x.length == 0) return null;
                return x[0][k];
            };
            $scope.obj.isSingleItemArr = function (arr) {
                return arr && arr.length == 1;
            };
            $scope.obj.setLookupData = function (data) {
                clearLookup();
                $scope.obj.stateList = data.States;
                $scope.obj.suburbList = _.map(data.Suburbs, returnLocation); //_.pluck(data.Suburbs, 'Eng');
                $scope.obj.address3List = _.map(data.Address3s, returnLocation); //_.pluck(data.Address3s, 'Eng');
                $scope.obj.address4List = _.map(data.Address4s, returnLocation); //_.pluck(data.Address4s, 'Eng');
                if ($scope.obj.stateList.length == 1 || $scope.obj.dynamicFields.noState == 1) {
                    $scope.obj.userState = $scope.obj.stateList[0].State;
                    $scope.obj.userStateName = $scope.obj.stateList[0].Name;
                }
                if ($scope.obj.suburbList.length <= 1) {
                    $scope.obj.userSuburb = firstOrDefault($scope.obj.suburbList, 'val');
                    $scope.obj.userSuburb_Text = firstOrDefault($scope.obj.suburbList, 'text');
                }
                if ($scope.obj.address3List.length <= 1) {
                    $scope.obj.userAddress3 = firstOrDefault($scope.obj.address3List, 'val');
                    $scope.obj.userAddress_3_Text = firstOrDefault($scope.obj.address3List, 'text');
                }
                if ($scope.obj.address4List.length <= 1) {
                    $scope.obj.userAddress4 = firstOrDefault($scope.obj.address4List, 'val');
                    $scope.obj.userAddress4_text = firstOrDefault($scope.obj.address4List, 'text');
                }
                angular.element(function () {
                    unitOfWork.util.resetFormError("#frmDelivery");
                    unitOfWork.util.formValidateReset("#frmDelivery");
                });
            };
            $scope.obj.changeCountry = function () { // enable country drop list
                $('#hdnCountry').remove();
                $('#' + $scope.obj.nameSpace + '_Country').prop('disabled', false);
                $('#' + $scope.obj.nameSpace + '_Country').change(function () {
                    var countrySelected = $('#' + $scope.obj.nameSpace + '_Country').val();
                    $scope.obj.marketSelected = countrySelected;
                    App.loader.showLoader();
                    $http.post(_config.getStatesUri, $.param({
                        c: countrySelected
                    })).then(function (d) {
                        if (d.status == 200) { //success
                            $scope.obj.stateList = d.data.states;
                            $scope.obj.dynamicFields = d.data.dynamicFields;
                            $scope.obj.userState = '';
                            $scope.obj.userSuburb = '';
                            $scope.obj.userAddress2 = '';
                            angular.element(function () {
                                unitOfWork.util.formValidateReset("#frmUserInfo");
                            });
                        }
                        App.loader.hideLoader();
                    }, function () {
                        App.loader.hideLoader();
                    });
                });
            };
            angular.element(function () {
                $scope.obj.userPostCode = _config.userPostCode;
                $scope.obj.userSuburb = _config.userSuburb; // assign district
                $scope.obj.userAddress2 = _config.subDistrict; // assign subdistrict
                $scope.obj.userAddress3 = _config.area; // assign area
                if (!$scope.obj.hasGlobalLookup) $('#btnRegisterDelivery').removeClass('hide');
                if ($scope.obj.dynamicFields.hasNoPost) // immediately load details for no postcode with global address
                    $scope.obj.dynamicPostCode(); // Note: commented auto lookup on load
                //if ($scope.obj.hasGlobalLookup && !$.isEmptyObject(_config.lookupData)) {
                //    $scope.obj.hasReturnedLookup = true;
                //    $scope.obj.lookupData = _config.lookupData;
                //    $scope.obj.setLookupData(_config.lookupData);
                //    $('#btnRegisterDelivery').removeClass('hide');
                //}
            });
        }]);
    };
    return {
        init: init
    };
})();
App.Shared._DynamicContactFields = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config == 'object') {
            $.extend(true, _config, config);
        } // Note: Don't enclose init function in $()
        App.angular.controller('addressController', ['$scope', '$http', 'unitOfWork', 'ScopeStorage', function ($scope, $http, unitOfWork, ScopeStorage) {
            ScopeStorage.store('addressController', $scope);
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {
                userPin: _config.userPin,
                userAddress4: _config.userAddress4,
                userAddress3: _config.area
            };
            $scope.obj.dynamicFields = _config.dynamicFields;
            $scope.obj.marketSelected = _config.market;
            $scope.obj.nameSpace = _config.nameSpace;
            $scope.obj.showCountryOption = _config.showCountryOption;
            $scope.obj.hasPostcodeLookup = _config.hasPostcodeLookup;
            $scope.obj.userState = _config.state;
            $scope.obj.stateList = _config.stateList;
            $scope.obj.userSuburb = _config.indoDistrict;
            $scope.obj.userAddress2 = _config.indoSubDistrict;
            $scope.obj.userAddress = _config.userAddress;
            $scope.obj.userPhone = _config.userPhone;
            $scope.obj.userPostCode = _config.userPostCode;
            $scope.obj.hasDynamicPostCode = function () {
                return _.filter(_config.dynamicPostCountries, function (x) {
                    return x == $scope.obj.marketSelected;
                }).length > 0;
            };
            $scope.obj.hasDynamicSuburb = function () {
                return _.filter(_config.dynamicSuburbCountries, function (x) {
                    return x == $scope.obj.marketSelected;
                }).length > 0;
            };
            $scope.obj.postcodeAreaListing = [];
            $scope.obj.suburbInList = function () {
                if ($scope.obj.suburbList.length == 0 || $scope.obj.suburbList[0] == null) return false;
                if ($scope.obj.suburbList.length > 0 && ($scope.obj.userSuburb == null || $.trim($scope.obj.userSuburb).length == 0)) return true;
                return _.filter($scope.obj.suburbList, function (x) {
                    return x == $scope.obj.userSuburb;
                }).length > 0;
            };
            $scope.obj.address2InList = function () {
                if ($scope.obj.address2List.length == 0 || $scope.obj.address2List[0] == null) return false;
                if ($scope.obj.address2List.length > 0 && ($scope.obj.userAddress2 == null || $.trim($scope.obj.userAddress2).length == 0)) return true;
                return _.filter($scope.obj.address2List, function (x) {
                    return x == $scope.obj.userAddress2;
                }).length > 0;
            };
            $scope.obj.dynamicPostCode = function () {
                if (!$scope.obj.hasDynamicPostCode() || !!!$scope.obj.userPostCode || $.trim($scope.obj.userPostCode).length < 4) return;
                App.loader.showLoader();
                $http.post(_config.getDynamicPcListUri, $.param({
                    code: $scope.obj.userPostCode,
                    market: $scope.obj.marketSelected
                })).then(function (d) {
                    if (d.status == 200) { //success
                        $scope.obj.postcodeAreaListing = d.data;
                    }
                    App.loader.hideLoader();
                }, function () {
                    App.loader.hideLoader();
                });
            };
            $scope.obj.setLocationByPostCode = function (_data) {
                App.loader.showLoader();
                $scope.obj.userState = _.find($scope.obj.stateList, function (x) {
                    return $.trim(x.State).toLowerCase() == $.trim(_data.Province).toLowerCase();
                }).State; // assign state
                $scope.obj.setIdState(function () { // load district list
                    $scope.obj.userSuburb = _data.District; // assign district
                    $scope.obj.setIdSuburb(function () { // load subdistrict
                        $scope.obj.userAddress2 = _data.SubDistrict; // assign subdistrict
                        $scope.obj.userAddress3 = _data.Area; // assign area
                        $scope.obj.userPostCode = _data.PostCode; // assign postcode
                        $scope.obj.postcodeAreaListing = [];
                        App.loader.hideLoader();
                    });
                });
            };
            $scope.obj.setIdState = function (callback) {
                if (!!!_config.preloadAddress || !!!$scope.obj.userState || $scope.obj.userState.length == 0 || !$scope.obj.hasDynamicSuburb()) return;
                if (!callback) App.loader.showLoader();
                $scope.obj.userSuburb = '';
                $http.post(_config.getSuburbListUri, $.param({
                    state: $scope.obj.userState,
                    code: $scope.obj.marketSelected
                })).then(function (d) {
                    if (d.status == 200 && d.data.status == 1) { //success
                        $scope.obj.suburbList = d.data.list;
                        $scope.obj.address2List = [];
                        if (callback) callback();
                    }
                    if (!callback) App.loader.hideLoader();
                }, function () {
                    App.loader.hideLoader();
                });
            };
            $scope.obj.setIdSuburb = function (callback) {
                if (!!!_config.preloadAddress || !!!$scope.obj.userSuburb || $scope.obj.userSuburb.length == 0 || !$scope.obj.hasDynamicSuburb()) return;
                if (!callback) App.loader.showLoader();
                $http.post(_config.getAddress2ListUri, $.param({
                    suburb: $scope.obj.userSuburb,
                    code: $scope.obj.marketSelected
                })).then(function (d) {
                    if (d.status == 200 && d.data.status == 1) { //success
                        $scope.obj.address2List = d.data.list;
                        if (d.data.list.length > 0 && d.data.list[0].length > 0) $scope.obj.userAddress2 = '';
                        if (callback) callback();
                    }
                    if (!callback) App.loader.hideLoader();
                }, function () {
                    App.loader.hideLoader();
                });
            };
            $scope.obj.changeCountry = function () { // enable country drop list
                $('#hdnCountry').remove();
                $('#' + $scope.obj.nameSpace + '_Country').prop('disabled', false);
                $('#' + $scope.obj.nameSpace + '_Country').change(function () {
                    var countrySelected = $('#' + $scope.obj.nameSpace + '_Country').val();
                    $scope.obj.marketSelected = countrySelected;
                    App.loader.showLoader();
                    $http.post(_config.getStatesUri, $.param({
                        c: countrySelected
                    })).then(function (d) {
                        if (d.status == 200) { //success
                            $scope.obj.stateList = d.data.states;
                            $scope.obj.address2List = [];
                            $scope.obj.suburbList = [];
                            $scope.obj.dynamicFields = d.data.dynamicFields;
                            $scope.obj.userState = $scope.obj.dynamicFields.noState != 0 ? countrySelected : '';
                            $scope.obj.userSuburb = '';
                            $scope.obj.userAddress2 = '';
                            if (!!_config.preloadAddress && $scope.obj.dynamicFields.noState == 1) $scope.obj.setIdState(function () {});
                            angular.element(function () {
                                unitOfWork.util.formValidateReset("#frmUserInfo");
                            });
                            App.loader.hideLoader();
                        } else App.loader.hideLoader();
                    }, function () {
                        App.loader.hideLoader();
                    });
                });
            };
            $scope.obj.loadAddressPreset = function () {
                if (!_config.isConfirmPage && $scope.obj.hasDynamicSuburb() && _config.userSuburb != null && $.trim(_config.userSuburb).length > 0) {
                    App.loader.showLoader();
                    $scope.obj.userPostCode = _config.userPostCode;
                    $scope.obj.setIdState(function () { // load district list
                        $scope.obj.userSuburb = _config.userSuburb; // assign district
                        $scope.obj.setIdSuburb(function () { // load subdistrict
                            $scope.obj.userAddress2 = _config.subDistrict; // assign subdistrict
                            $scope.obj.userAddress3 = _config.area; // assign area
                            App.loader.hideLoader();
                        });
                    });
                }
            };
            angular.element(function () {
                if (!!_config.preloadAddress) $scope.obj.loadAddressPreset();
            });
        }]);
    };
    return {
        init: init
    };
})();

var questionsFunction = function questionsFunction(set) {
    var _config = {
        surveyData: {},
        callback: null,
        surveyImage: '',
        surveyTitle: ''
    };
    var init = function init(config) {
        if (config && typeof config == 'object') {
            $.extend(true, _config, config);
        }

        // on purpose to avoid bundling
        var test = function (callback) { if (callback) callback() }
        test(() => { });

        App.angular.controller('questionController' + set, ['$scope', '$http', '$sce', '$timeout', '$anchorScroll', '$q', function ($scope, $http, $sce, $timeout, $anchorScroll, $q) { // private fields
            var _termsAccepted = false;
            var _surveyData = _config['surveyData' + set];
            var _formSelector = "#frmQuestions" + set;
            var _formId = 'frmQuestions' + set; // public fields
            $scope.obj = {
                set: set,
                optionValues: _surveyData.optionValues,
                isPoker: function isPoker(q) {
                    var isGroup = q.Groups > 0;
                    if (!isGroup) return false;
                    var group = $scope.obj.getGroupOptions(q);
                    var hasPokerFlag = _.filter(group, function (g) {
                        return [112, 122].indexOf(g.JumptTo) > -1;
                    }).length > 0;
                    return hasPokerFlag;
                },
                isSlider: function isSlider(q) {
                    return [133, 134].indexOf(q.JumptTo) > -1;
                },
                isHeatMap: function isHeatMap(q) {
                    var hmOpt = $scope.obj.getOptionCustomSettingByType(q, 'HEATMAP');
                    return hmOpt != null && hmOpt.length > 0;
                },
                isVox: function isVox(q) {
                    return q.JumptTo === 139;
                },
                hasCustomSearchList: function hasCustomSearchList(q) {
                    return q.CustomItemList != null && q.CustomItemList.length > 0;
                },
                isQHasForShare: function isQHasForShare(q, i) {
                    return q.IsForShare && q.IsForShare === i;
                },
                heatMapClick: function heatMapClick(e, q) {
                    var $target = $(e.target);
                    var $this = $(e.currentTarget); // or use $(e.target) in some cases;
                    var $box = $(_formSelector + ' input[name="[' + (q.OrderNum - 1) + '].CustomText"]');
                    if ($target.hasClass('heatmap-point')) { // remove existing point on click
                        $target.remove();
                    } else { // assign heat points
                        var hmOpt = $scope.obj.getOptionCustomSettingByType(q, 'HEATMAP');
                        var bgc = hmOpt != null && hmOpt.length > 0 ? hmOpt[0].HTML : '#f40650';
                        var offset = $this.offset();
                        var width = $this.width();
                        var height = $this.height();
                        var posX = offset.left;
                        var posY = offset.top;
                        var x = e.pageX - posX;
                        x = parseFloat(x / width * 100);
                        x = x < 0 ? 0 : x;
                        x = x > 100 ? 100 : x;
                        var y = e.pageY - posY;
                        y = parseFloat(y / height * 100);
                        y = y < 0 ? 0 : y;
                        y = y > 100 ? 100 : y;
                        var id = App.guid().replace(/\-/gi, '');
                        var divString = '<div data-coord="' + x.toFixed(4) + ':' + y.toFixed(4) + '" id="' + id + '" class="heatmap-point" style="top:' + y + '%;left:' + x + '%;background-color:' + bgc + '"></div>';
                        $this.append(divString);
                    }
                    var points = $this.find('[data-coord]');
                    var heatMapText = '';
                    for (var i in points) {
                        if (typeof points.eq(i).data('coord') != 'undefined') heatMapText += (i > 0 ? ',' : '') + points.eq(i).data('coord');
                    }
                    q.heatMapText = heatMapText;
                    $box.val(heatMapText);
                    $scope.obj.reValidateOptions(q);
                },
                starOnMouseEnter: function starOnMouseEnter(q, o) {
                    q.starRatingText = _surveyData.starHoverTexts[o.option - 1];
                },
                starOnMouseLeave: function starOnMouseLeave(q) {
                    q.starRatingText = typeof q.rdoVal === 'undefined' ? null : q.starRatingText;
                }
            };
            $scope.obj.fileTypes = {
                na: 0,
                image: 1,
                youtube: 2,
                imagemap: 3
            };
            $scope.obj.questionTypes = {
                na: 0,
                userprofile: 1,
                learnwin: 2,
                prequal: 3,
                survey: 4
            };
            $scope.obj.currentType = $scope.obj.questionTypes[_surveyData.currentType];
            $scope.obj.questions = _surveyData.questions;
            $scope.obj.answers = _surveyData.answers;
            $scope.obj.questionNumber = 1;
            $scope.obj.surveyImage = _config.surveyImage;
            $scope.obj.surveyDesc = _config.surveyDesc;
            $scope.obj.surveyTitle = _config.surveyTitle;
            $scope.obj.showTermsWarning = false;
            $scope.obj.isTermAccepted = false;
            $scope.obj.hasSurveyPromo = !$.isEmptyObject(_surveyData.surveyPromo);
            $scope.obj.surveyPromo = _surveyData.surveyPromo;
            $scope.obj.showSurveyPromoTerms = false;
            $scope.obj.parentPokerAnswers = _surveyData.parentPokerAnswers;
            $scope.obj.surveyTable = _surveyData.surveyTable;
            $scope.obj.parentAnswerLoaded = 0;
            $scope.obj.isVerticalStyle = _surveyData.isVerticalStyle;
            var wait = {
                passed: 0,
                previous: 0,
                hasWait: _surveyData.hasWait,
                start: function start() {
                    if (!wait.hasWait) return;
                    wait.stop();
                    wait.passed = 0;
                    wait.timer = setInterval(function () {
                        wait.passed++;
                    }, 1);
                },
                stop: function stop() {
                    if (!wait.hasWait) return;
                    if (wait.timer) {
                        clearInterval(wait.timer);
                        wait.timer = null;
                    }
                    wait.previous = wait.passed;
                },
                set: function set(q) {
                    if (!wait.hasWait) return;
                    var $wait = $(_formSelector + ' input[name="[' + (q.OrderNum - 1) + '].Wait"]');
                    var cv = $wait.val();
                    cv = typeof cv == 'undefined' || cv.isNullOrEmpty() ? 0 : parseInt(cv);
                    cv += wait.previous;
                    $wait.val(cv);
                },
                run: function run(q) {
                    if (!wait.hasWait) return;
                    wait.stop();
                    if (q.Groups > 0) {
                        var groups = $scope.obj.getGroupOptions(q);
                        for (var g in groups) {
                            wait.set(groups[g]);
                        }
                    } else wait.set(q);
                    wait.start();
                }
            };
            $scope.obj.termsAccepted = function () {
                if (!_surveyData.hasTerms) return true; // no terms available
                _termsAccepted = $scope.obj.isTermAccepted;
                if ($scope.obj.isTermAccepted) { // don't show the terms warning anymore
                    $scope.obj.showTermsWarning = false;
                }
                return _termsAccepted;
            };
            $scope.obj.hasRelatedFile = function (q) {
                return q.RelatedFile != null && $.trim(q.RelatedFile).length > 0;
            };
            $scope.obj.getFrameSrc = function (q) {
                return $sce.trustAsResourceUrl('https://www.youtube.com/embed/' + $scope.obj.getYtId(q) + '?autohide=0&controls=0&rel=0&showinfo=0');
            };
            $scope.obj.getYtId = function (q) {
                var rx = /https?:\/\/(www.)?(youtube.com|youtu.be)(\/)?(watch\?v\=)?/gi;
                return q.RelatedFile.replace(rx, '');
            };
            $scope.obj.fileType = function (q) {
                var imgTypes = [".png", ".jpg", ".jpeg", ".gif"];
                if (_.filter(imgTypes, function (x) {
                        return q.RelatedFile.toLowerCase().indexOf(x) > -1;
                    }).length > 0) {
                    if ($scope.obj.isHeatMap(q)) return $scope.obj.fileTypes.imagemap;
                    return $scope.obj.fileTypes.image;
                } else if (q.RelatedFile.toLowerCase().indexOf('yout') > -1) return $scope.obj.fileTypes.youtube;
                return $scope.obj.fileTypes.na;
            };
            $scope.obj.insertHtml = function (s) {
                return $sce.trustAsHtml($.trim(s));
            };
            $scope.obj.isQuestionSubGroup = function (q) {
                if (q.Groups == 0) return false;
                var firstGroup = $scope.obj.getGroupOptions(q)[0];
                return firstGroup.OrderNum != q.OrderNum;
            };
            $scope.obj.hasSecondText = function (g) {
                var firstGroup = $scope.obj.getGroupOptions(g)[0];
                return firstGroup.QuestionText.split('^').length > 2 && g.QuestionText.indexOf('^') > -1;
            };
            $scope.obj.secondText = function (g) {
                return g.QuestionText.split('^').length > 2 ? g.QuestionText.split('^')[2] : g.QuestionText.split('^')[1];
            };
            $scope.obj.getOptionRange = function (q) {
                var range = _.range(1, q.TotOptions + 1);
                if ($scope.obj.isPoker(q) || q.MainQuestion == 5 && q.Option1.indexOf('1') < 0) // inverse range for poker
                    return _.sortBy(range, function (x) {
                        return -x;
                    }); //if (q.JumptTo == 10) // set random order for options
                var rndOptions = $scope.obj.getOptionCustomSettingByType(q, 'RND');
                if (rndOptions != null && rndOptions.length > 0) return _.shuffle(range);
                rndOptions = $scope.obj.getOptionCustomSettingByType(q, 'RNDELAST');
                if (rndOptions != null && rndOptions.length > 0) {
                    var rndOpt = rndOptions[0];
                    var exc = (rndOpt.Maximum || 1) == 0 ? 1 : rndOpt.Maximum; // exclude a certain amount of options trailing the end
                    range = _.shuffle(_.range(1, q.TotOptions - (exc - 1)));
                    for (var i = exc - 1; i >= 0; i--) {
                        range.push(q.TotOptions - i);
                    }
                    return range;
                }
                return range;
            };
            $scope.obj.getOptionRangeObjects = function (q) {
                var range = $scope.obj.getOptionRange(q);
                return _.map(range, function (x) {
                    return {
                        option: x
                    };
                });
            };
            $scope.obj.hideProgress = function (q) {
                var endOptions = $scope.obj.getOptionCustomSettingByType(q, 'END');
                var heroOption = $scope.obj.getOptionCustomSettingByType(q, 'END');
                var hasEndOption = typeof endOptions != 'undefined' && endOptions.length > 0;
                var hasHeroOption = typeof heroOption != 'undefined' && heroOption.length > 0;
                return $scope.obj.isToSubmit || hasEndOption || hasHeroOption;
            };
            $scope.obj.getProgPerc = function (q) {
                var isEndSelected = $scope.obj.isCustomOptionSelected(q, 'END');
                var isHeroSelected = $scope.obj.isCustomOptionSelected(q, 'HERO');
                if (($scope.obj.isToSubmit || !isHeroSelected && isEndSelected || $scope.obj.currentType == $scope.obj.questionTypes.userprofile || $scope.obj.questions.length == 1) && !$scope.obj.isNextCssDisabled(q)) return 100;
                var groups = $scope.obj.getGroupOptions(q);
                var inc = groups == null || groups.length == 0 ? 0 : groups.length - 1;
                return Math.round((q.OrderNum - 1 + inc) / $scope.obj.questions.length * 100);
            };
            $scope.obj.assignMinHeight = function (q, options) {
                if (options.length < 4) return 50;
                var isheight70Len = _.filter(options, function (o) {
                    return $scope.obj.getOptionDetail(q, o).text.length >= 35;
                }).length > 0;
                var isheight100Len = _.filter(options, function (o) {
                    return $scope.obj.getOptionDetail(q, o).text.length >= 65;
                }).length > 0;
                var hasImage = _.filter(options, function (o) {
                    var t = $scope.obj.getOptionDetail(q, o).text;
                    return t.indexOf('img-responsive') > -1 || t.indexOf('<img') > -1;
                }).length > 0;
                if (hasImage) return 'auto';
                return (isheight100Len ? 105 : isheight70Len ? 80 : 50) + 'px';
            };
            $scope.obj.getOptionDetail = function (q, i) {
                var text = q['Option' + i];
                var val = $scope.obj.optionValues[i - 1];
                if (q.RelatedFile != null && q.RelatedFile.toLowerCase() == 'kidsage' && q.TotOptions >= 15 && i > 1) {
                    q.TotOptions = 19;
                    var year = new Date().getFullYear() - i + 2;
                    text = year.toString();
                    val = year.toString().substr(2);
                }
                text = $.trim(text).length == 0 ? '&nbsp;' : $.trim(text);
                return {
                    text: text,
                    val: val
                };
            };
            $scope.obj.areOptionsSequence = function (q) {
                if ($.trim(q.Option1).length == 0) return false;
                var range = $scope.obj.getOptionRange(q);
                var opVals = [];
                for (var i in range) {
                    var t = q['Option' + range[i]];
                    if (new RegExp(/[a-bA-B\s\t]/gi).test($.trim(t))) return false;
                    if (isNaN(parseInt($.trim(t)))) return false;
                    opVals.push(parseInt($.trim(t)));
                }
                var g = _.groupBy(opVals);
                var max = _.max(opVals);
                var min = _.min(opVals);
                var count = 0;
                for (var key in g)
                    if (g.hasOwnProperty(key)) count++;
                return min == 1 && max == range.length && count == range.length;
            };
            $scope.obj.getGroupQuestionText = function (g) {
                return $scope.obj.isQuestionSubGroup(g) ? g.QuestionText.indexOf('^') > -1 ? g.QuestionText.split('^')[0] : g.QuestionText : g.QuestionText.split('^')[1];
            };
            $scope.obj.getGroupOptions = function (q) {
                if (q.Groups == 0) return null;
                return _.filter($scope.obj.questions, function (x) {
                    return x.Groups == q.Groups;
                });
            };
            var validationTypes = {
                noAnswer: 0,
                overMax: 1,
                emptyText: 2,
                groupMissingAnswer: 3,
                groupAnswersNotRanked: 4,
                maxMinError: 5,
                overMaxPoker: 6,
                minPoker: 7,
                onlyZeroPoker: 8,
                emptyHeatMap: 9
            }; // check whether the other option is selected
            $scope.obj.hasOtherOptionChecked = function (q) {
                var allAnswers = $(_formSelector).serializeArray();
                if (q.Groups > 0 || q.Types === null || q.Types === 0) return false;
                var name = "[" + (q.OrderNum - 1) + "].Answer"; //var emptyQ1Text = $.trim(q.Option1).length === 0;
                var answerObj = _.filter(allAnswers, function (x) {
                    return x.name === name;
                });
                var getAnswers = _.chain(answerObj).pluck('value').filter(function (x) {
                    return $.trim(x).length > 0;
                }).value(); //var len = answerObj === null ? 0 : answerObj.length;
                //var hasOther = q.Types !== null && q.Types > 0;
                var otherOptionAnswer = String.fromCharCode(q.TotOptions - 1 + 97).toUpperCase(); //var otherCustomOption = $scope.obj.getOptionCustomSettingByType(q, 'OTHER');
                //var otherCustomAnswers = typeof otherCustomOption != 'undefined' && otherCustomOption.length > 0 ? String.fromCharCode((otherCustomOption.OrderNum - 1) + 97).toUpperCase() : null;
                //var hasCustomOtherSelected = typeof otherCustomOption != 'undefined' && otherCustomOption.length > 0 && otherCustomAnswers != null && _.filter(getAnswers, function (x) { return x == otherCustomAnswers }).length > 0;
                var hasCustomOtherSelected = $scope.obj.isCustomOptionSelected(q, 'OTHER');
                return _.filter(getAnswers, function (x) {
                    return x === otherOptionAnswer;
                }).length > 0 || hasCustomOtherSelected;
            };
            $scope.obj.isQuestionValidated = function (q) {
                var allAnswers = $(_formSelector).serializeArray();
                if (q.Groups == 0) { // single question validation
                    var name = "[" + (q.OrderNum - 1) + "].Answer";
                    var emptyQ1Text = $.trim(q.Option1).length == 0;
                    var answerObj = _.filter(allAnswers, function (x) {
                        return x.name == name;
                    });
                    var getAnswers = _.chain(answerObj).pluck('value').filter(function (x) {
                        return $.trim(x).length > 0;
                    }).value();
                    var len = answerObj == null ? 0 : getAnswers.length;
                    var hasOther = q.Types != null && q.Types > 0 && !$scope.obj.hasCustomSearchList(q);
                    var isNota = $scope.obj.isNota(q);
                    if (!emptyQ1Text) { // check options only if q1 is not empty
                        if (answerObj == null || len == 0) return {
                            v: false,
                            t: validationTypes.noAnswer
                        };
                        if (q.MaxOption == 1 && len == 0) // radio group, none selected
                            return {
                                v: false,
                                t: validationTypes.noAnswer
                            };
                        else if (q.MaxOption > 1 && len > 1 && len > q.MaxOption) // check box selections, more than max
                            return {
                                v: false,
                                t: validationTypes.overMax
                            };
                        else if (q.MaxOption > 1 && len == 0) // check box selections, none selected
                            return {
                                v: false,
                                t: validationTypes.noAnswer
                            };
                    } // validate custom searchable result answer
                    if ($scope.obj.hasCustomSearchList(q) && (q.OtherText == null || $.trim(q.OtherText).length == 0)) return {
                        v: false,
                        t: validationTypes.noAnswer
                    };
                    var otherOptionAnswer = String.fromCharCode(q.TotOptions - 1 + 97).toUpperCase();
                    var hasOtherChecked = _.filter(getAnswers, function (x) {
                        return x == otherOptionAnswer;
                    }).length > 0;
                    var otherAnswers = _.filter(allAnswers, function (x) {
                        return x.name == "[" + (q.OrderNum - 1) + "].Other";
                    });
                    var hasNoOtherAnswer = otherAnswers == null || otherAnswers.length == 0 || $.trim(otherAnswers[0].value).length == 0;
                    var hasHeatMap = $scope.obj.isHeatMap(q); // custom option OTHER validation
                    //var otherCustomOption = $scope.obj.getOptionCustomSettingByType(q, 'OTHER');
                    //var otherCustomAnswers = typeof otherCustomOption != 'undefined' && otherCustomOption.length > 0 ? String.fromCharCode((otherCustomOption[0].OrderNum - 1) + 97).toUpperCase() : null;
                    //var hasCustomOtherSelected = typeof otherCustomOption != 'undefined' && otherCustomOption.length > 0 && otherCustomAnswers != null && _.filter(getAnswers, function (x) { return x == otherCustomAnswers }).length > 0;
                    if (hasHeatMap && (!q.heatMapText || q.heatMapText.isNullOrEmpty())) {
                        return {
                            v: false,
                            t: validationTypes.emptyHeatMap
                        };
                    }
                    var hasCustomOtherSelected = $scope.obj.isCustomOptionSelected(q, 'OTHER');
                    if (!isNota && hasOther && (hasOtherChecked || emptyQ1Text || hasCustomOtherSelected) && hasNoOtherAnswer) //other is selected but no text input 
                        return {
                            v: false,
                            t: validationTypes.emptyText
                        };
                    if (!isNota && $scope.obj.hasMinMax(q)) {
                        var settings = $scope.obj.maxMinOtherSettings(q);
                        if (q.OtherText.length < settings.min || q.OtherText.length > settings.max) return {
                            v: false,
                            t: validationTypes.maxMinError
                        };
                    }
                } else { // grouped questions validation
                    var getGroups = $scope.obj.getGroupOptions(q);
                    var isRanked = q.IsRank != null && q.IsRank > 0;
                    var isPokerGroup = $scope.obj.isPoker(getGroups[0]);
                    var groupAnswers = [];
                    var groupValid = true; // to determine all item with errors, complete the group loop
                    var indexWithError = [];
                    var isSubjectToFilter = q.JumptTo === 111;
                    var isSubjectToExclusion = q.JumptTo === 141;
                    for (var i in getGroups) { // validate if atleast 1 group question is unanswered
                        var g = getGroups[i];
                        var gAnswers = _.filter(allAnswers, function (x) {
                            return x.name == "[" + (g.OrderNum - 1) + "].Answer";
                        });
                        if (gAnswers.length == 0 || $.trim(gAnswers[0].value).length == 0) {
                            if (!isSubjectToFilter && !isSubjectToExclusion || (isSubjectToFilter || isSubjectToExclusion) && $('#group_row_' + q.Groups + '_' + g.Id).is(':visible')) { // validate for filtered/excluded groups
                                // allow empty answers for hidden/filtered rows
                                groupValid = false;
                                indexWithError.push(parseInt(i));
                            }
                        } else groupAnswers.push(gAnswers[0].value);
                    }
                    if (!groupValid) {
                        return {
                            v: groupValid,
                            t: validationTypes.groupMissingAnswer,
                            ix: indexWithError
                        };
                    }
                    if (isRanked) { // validate if the grouped answers are ranked
                        var cout = _.groupBy(groupAnswers);
                        for (var i in cout) {
                            if (cout[i].length > 1) return {
                                v: false,
                                t: validationTypes.groupAnswersNotRanked
                            };
                        }
                    } else if (isPokerGroup) {
                        var belowRating = eval(getPokerRating(q)) < 1;
                        if (belowRating) return {
                            v: false,
                            t: validationTypes.minPoker
                        };
                    }
                }
                return {
                    v: true
                };
            }; //#region Promotions
            $scope.obj.acceptSurveyPromo = function () {
                if (!$scope.obj.isSurveyAccepted) {
                    $('#acceptSurveyPromo').focus();
                    $scope.obj.surveyPromoAccepted = false;
                    return;
                }
                $scope.obj.surveyPromoAccepted = true;
            };
            $scope.obj.showAcceptError = function () {
                return $scope.obj.surveyPromoAccepted != null && typeof $scope.obj.surveyPromoAccepted != 'undefined' && !$scope.obj.surveyPromoAccepted;
            }; //#endregion
            //#region NOTA
            $scope.obj.notaAction = function (q, o) { // uncheck all boxes except the NOTA option and hide the rest of the options
                var notaAnswerValue = '';
                var isNotaSelected = false;
                if (q.Feature == 'NOTA') {
                    notaAnswerValue = $(_formSelector + ' input[name="[' + (q.OrderNum - 1) + '].Answer"]').last().val();
                    isNotaSelected = $scope.obj.isFeatureSelected(q, 'NOTA');
                } else {
                    var notaOption = $scope.obj.getOptionCustomSettingByType(q, 'NOTA');
                    if (typeof notaOption == 'undefined' || notaOption.length == 0) return false;
                    notaAnswerValue = $scope.obj.getOptionDetail(q, notaOption[0].OrderNum).val;
                    isNotaSelected = $scope.obj.isCustomOptionSelected(q, 'NOTA');
                }
                $(_formSelector + ' input[name="[' + (q.OrderNum - 1) + '].Answer"]:not([value="' + notaAnswerValue + '"])').parent().parent().show();
                if (isNotaSelected) {
                    $(_formSelector + ' input[name="[' + (q.OrderNum - 1) + '].Answer"]:not([value="' + notaAnswerValue + '"])').parent().parent().hide();
                    $(_formSelector + ' input[name="[' + (q.OrderNum - 1) + '].Answer"]:not([value="' + notaAnswerValue + '"])').prop('checked', false);
                }
                return isNotaSelected;
            };
            $scope.obj.isFeatureSelected = function (q, f) {
                if (f == 'NOTA') {
                    var notaAnswerValue = $(_formSelector + ' input[name="[' + (q.OrderNum - 1) + '].Answer"]').last().val();
                    var formJson = $(_formSelector).serializeArray();
                    var answers = _.chain(formJson).filter(function (x) {
                        return x.name == '[' + (q.OrderNum - 1) + '].Answer';
                    }).pluck('value').value();
                    return _.filter(answers, function (x) {
                        return x == notaAnswerValue;
                    }).length > 0;
                }
                return false;
            };
            $scope.obj.isNota = function (q) {
                if (q.Feature == 'NOTA') return $scope.obj.isFeatureSelected(q, 'NOTA');
                return $scope.obj.isCustomOptionSelected(q, 'NOTA');
            }; //#endregion
            $scope.obj.otherTextChange = function (q) {
                if (!$scope.obj.hasMinMax(q)) {
                    q.isNextDisabled = q.OtherText.length == 0;
                    q.inlineAlertHtml = '';
                }
                if ($scope.obj.currentType != $scope.obj.questionTypes.userprofile) {
                    if ($scope.obj.hasMinMax(q) && q.OtherText.length >= $scope.obj.maxMinOtherSettings(q).min && q.OtherText.length <= $scope.obj.maxMinOtherSettings(q).max) {
                        q.isNextDisabled = false;
                        q.inlineAlertHtml = '';
                    }
                }
            };
            $scope.obj.hasOtherActive = function (q) {
                return q.Option1 == null || $.trim(q.Option1).length == 0 || q.showOtherBox;
            };
            $scope.obj.isNextCssDisabled = function (q) {
                if ($scope.obj.currentType == $scope.obj.questionTypes.userprofile) return false;
                if (q.inlineAlertHtml && q.inlineAlertHtml.length > 0 && !$scope.obj.isStopped) return true;
                if ($scope.obj.currentType != $scope.obj.questionTypes.userprofile) {
                    if (q.isNextDisabled) return true; // validate for OTHER option text with min/max length
                    if ($scope.obj.hasOtherActive(q) && $scope.obj.hasMinMax(q) && (q.OtherText.length < $scope.obj.maxMinOtherSettings(q).min || q.OtherText.length > $scope.obj.maxMinOtherSettings(q).max)) return true;
                    else if ($scope.obj.hasOtherActive(q) && q.OtherText.length == 0) return true; // validate for regular OTHER option text
                }
                return false;
            };
            $scope.obj.isCustomOptionSelected = function (q, t) {
                var customOptions = $scope.obj.getOptionCustomSettingByType(q, t);
                if (typeof customOptions == 'undefined' || customOptions.length == 0) return false;
                var formJson = $(_formSelector).serializeArray();
                var answers = _.chain(formJson).filter(function (x) {
                    return x.name == '[' + (q.OrderNum - 1) + '].Answer';
                }).pluck('value').value();
                var customAnswersArr = [];
                for (var i in customOptions) {
                    var c = customOptions[i];
                    var a = $scope.obj.getOptionDetail(q, c.OrderNum).val;
                    customAnswersArr.push(a);
                }
                return _.filter(answers, function (x) {
                    return customAnswersArr.indexOf(x) >= 0;
                }).length > 0;
            };
            $scope.obj.isHtmlTypeClicked = function (q) {
                return $scope.obj.isCustomOptionSelected(q, 'HTML') && q.inlineAlertHtml && q.inlineAlertHtml.length > 0;
            };
            $scope.obj.goExit = function (q) {
                App.loader.showLoader();
                window.location = _surveyData.reviewHomeLink;
            };
            $scope.obj.getOptionCustomSettingByType = function (q, t) {
                return _.filter(q.SurveyCustomOption, function (x) {
                    return x.Types == t;
                });
            };
            $scope.obj.filterOptionCustomSettingByType = function (q, t) {
                return _.filter(q.SurveyCustomOption, function (x) {
                    return x.Types == t;
                });
            };
            $scope.obj.getCustomOptionByOrderNum = function (q, o) {
                if (q.SurveyCustomOption == null || q.SurveyCustomOption.length == 0) return null;
                return _.filter(q.SurveyCustomOption, function (x) {
                    return x.OrderNum == o;
                });
            };
            $scope.obj.getPercentTextLen = function (q) {
                var result = (q.OtherText.length || 0) / $scope.obj.maxMinOtherSettings(q).max * 100;
                return result;
            };
            $scope.obj.hasMinMax = function (q) {
                if (!$scope.obj.hasOtherActive(q)) return false; // don't apply min max if other option is not enabled
                if (q.MaxChar > 0 || q.MinChar > 0) return true;
                var t = $scope.obj.getOptionCustomSettingByType(q, "MAXMIN");
                if (typeof t != 'undefined' && t.length > 0) return true;
                if (q.AddToComments > 0 || q.JumptTo == 1 || q.JumptTo == 5 || q.TotOptions == 0 && q.TotInGroup > 0) return true;
                return false;
            };
            $scope.obj.maxMinOtherSettings = function (q) {
                var t = $scope.obj.getOptionCustomSettingByType(q, "MAXMIN");
                var max = 1000,
                    min = 50;
                if (q.MaxChar > 0 || q.MinChar > 0) {
                    max = q.MaxChar != null ? q.MaxChar : 1000;
                    min = q.MinChar != null ? q.MinChar : 5;
                } else if (typeof t != 'undefined' && t.length > 0) {
                    max = t[0].Maximum;
                    min = t[0].Minimum;
                } else if (q.AddToComments > 0 || q.JumptTo == 1 || q.JumptTo == 5) {
                    min = q.JumptTo == 1 || q.JumptTo == 5 ? 5 : 50;
                    max = q.JumptTo == 1 ? 40 : q.JumptTo == 5 ? 15 : 1000;
                } else if (q.TotOptions == 0 && q.TotInGroup > 0) {
                    min = q.TotInGroup;
                    max = 1000;
                }
                return {
                    min: min,
                    max: max
                };
            };
            $scope.obj.reValidateOptions = function (q) { // check if next button should be disabled or not
                var validation = $scope.obj.isQuestionValidated(q);
                if (!validation.v) { // invalid answer
                    q.isNextDisabled = true;
                    showAlertValidate(validation, q);
                } else {
                    q.isNextDisabled = false;
                    q.inlineAlertHtml = null;
                }
            };
            $scope.obj.onRangeChange = function (q) {
                q.isNextDisabled = false;
            };
            $scope.obj.onSingleCheckChange = function (q, o, pix) { // radio and checkbox change event
                if (q.disabledByHtml) return;
                pix = !pix ? -1 : pix;
                o = typeof o == 'undefined' && typeof q.bufferSelectAnswer != 'undefined' ? q.bufferSelectAnswer : o; // check if next button should be disabled or not
                $scope.obj.reValidateOptions(q);
                $scope.obj.stopInlineAlertHtml = '';
                var formJson = $(_formSelector).serializeArray();
                var answers = _.chain(formJson).filter(function (x) {
                    return x.name == '[' + (q.OrderNum - 1) + '].Answer';
                }).pluck('value').value();
                var optAnswerValue = $scope.obj.getOptionDetail(q, o).val;
                $scope.obj.isNotaSelected = $scope.obj.isNota(q);
                $scope.obj.isStopped = false;
                if (q.IsCustomColumn) {
                    var options = $scope.obj.getCustomOptionByOrderNum(q, o);
                    if (options != null && options.length > 0 && _.filter(answers, function (x) {
                            return x == optAnswerValue;
                        }).length > 0) {
                        for (var i in options) {
                            var co = options[i];
                            if (co.Types == 'HTML') { // show modal box and immediately redirect to review home once selected
                                //q.inlineAlertHtml = co.HTML.replace('%%IMG%%', _surveyData.boxImage);
                                $scope.obj.stopInlineAlertHtml = co.HTML.replace('%%IMG%%', _surveyData.boxImage);
                                q.disabledByHtml = true;
                                $scope.obj.isStopped = true;
                                angular.element(function () {
                                    $('#modalStopSurvey').modal('show');
                                });
                            }
                        }
                    } else if ($scope.obj.hasCustomSearchList(q)) { // custom search list item
                        q.isNextDisabled = q.OtherText.length === 0;
                    }
                }
                q.showOtherBox = $scope.obj.hasOtherOptionChecked(q); // show textarea if OTHER option is selected
                if (!q.showOtherBox && !$scope.obj.hasCustomSearchList(q)) q.OtherText = null;
                if (q.MainQuestion == 5) {
                    q.starSelect = o;
                    q.starOver = null;
                    $timeout(function () {
                        var ixAnswer = -1;
                        pix = pix < 0 ? 0 : pix;
                        $('[id^="chk3_' + pix + '_"]').each(function (i, o) {
                            $(this).next().removeClass('lower-star');
                            if ($(this).prop('checked')) ixAnswer = i;
                            if (!$(this).prop('checked') && ixAnswer == -1) {
                                $(this).next().addClass('lower-star');
                            }
                        });
                    }, 100);
                } // user profile kids script
                $scope.obj.setupKidOptions(q); // action nota
                $scope.obj.notaAction(q);
            };
            $scope.obj.setupKidOptions = function (q) {
                var isHorizontalProfile = $scope.obj.currentType == $scope.obj.questionTypes.userprofile && !$scope.obj.isVerticalStyle; // user profile kids script
                if (q.RelatedFile != null && q.RelatedFile.toLowerCase() == "totkids") {
                    var isASelectOption = q.MaxOption == 1 && q.Groups == 0 && $scope.obj.currentType == $scope.obj.questionTypes.userprofile;
                    var optionRange = $scope.obj.getOptionRange(q);
                    var lastOption = isASelectOption ? _.chain(optionRange).map(function (x) {
                        return $scope.obj.getOptionDetail(q, x);
                    }).find(function (x) {
                        return x.text.toLowerCase() == "none" || x.text.toLowerCase() == "na" || x.text.toLowerCase() == "0" || /[1-9]/gi.test(x.text);
                    }).value() : $scope.obj.getOptionDetail(q, optionRange[optionRange.length - 1]);
                    var kidsAgeQuestion = _.find($scope.obj.questions, function (x) {
                        return x.RelatedFile == 'kidsAge';
                    });
                    var formJson = $(_formSelector).serializeArray();
                    var answers = _.chain(formJson).filter(function (x) {
                        return x.name == '[' + (q.OrderNum - 1) + '].Answer';
                    }).pluck('value').value();
                    var answeredNone = typeof _.find(answers, function (x) {
                        return x == lastOption.val;
                    }) != 'undefined';
                    var name = _formSelector + ' [name="[' + (kidsAgeQuestion.OrderNum - 1) + '].Answer"]'; //console.log({ 'isHorizontalProfile': isHorizontalProfile, answeredNone: answeredNone });
                    if (answeredNone) { // if noKids is selected
                        $(_formSelector + ' [name="[' + (q.OrderNum - 1) + '].Answer"]:not(:last)').parent().parent().hide();
                        $(_formSelector + ' [name="[' + (q.OrderNum - 1) + '].Answer"]:not(:last)').prop('checked', false);
                        $(name + ':not(:first)').parent().parent().hide();
                        $(name).prop('checked', false);
                        $(name + ':first').prop('checked', true);
                        $(name + ':first').parent().parent().show();
                        if (!isHorizontalProfile) $(name + ':first').parents('div[id^="div_"]').eq(0).hide();
                    } else {
                        $(_formSelector + ' [name="[' + (q.OrderNum - 1) + '].Answer"]:not(:last)').parent().parent().show(); // show kids year section
                        $(name + ':first').parents('div[id^="div_"]').eq(0).show();
                        $(name + ':first').prop('checked', false);
                        $(name + ':not(:first)').parent().parent().show();
                        $(name + ':first').parent().parent().hide();
                    }
                    if (!isHorizontalProfile && (answers == null || answers.length == 0 || answers[0] == '')) { // no answers for hasKids
                        $(name + ':first').parents('div[id^="div_"]').eq(0).hide();
                    }
                }
            };
            var getPokerRating = function getPokerRating(q) {
                var groups = $scope.obj.getGroupOptions(q);
                var maxChip = groups[0].TotOptions - 1;
                var currentChip = getChipRating(groups);
                return currentChip + "/" + maxChip;
            };
            $scope.obj.ratingDisplay = function (q) {
                return getPokerRating(q);
            };
            var getChipRating = function getChipRating(getGroups) {
                var currentChipRating = 0;
                $.each(getGroups, function (i, obj) {
                    if ($(_formSelector + ' select[name="[' + (obj.OrderNum - 1) + '].Answer"]').val() == null || $.trim($(_formSelector + ' select[name="[' + (obj.OrderNum - 1) + '].Answer"]').val()).length == 0) return;
                    var val = parseInt($.trim($(_formSelector + ' select[name="[' + (obj.OrderNum - 1) + '].Answer"]').val()));
                    currentChipRating += isNaN(val) ? 0 : val;
                });
                return currentChipRating;
            };
            var chipRatingHasZero = function chipRatingHasZero(getGroups) {
                var zeroCount = 0;
                $.each(getGroups, function (i, obj) {
                    if (!$(_formSelector + ' select[name="[' + (obj.OrderNum - 1) + '].Answer"]').is(':visible') || $(_formSelector + ' select[name="[' + (obj.OrderNum - 1) + '].Answer"]').val() == null || $.trim($(_formSelector + ' select[name="[' + (obj.OrderNum - 1) + '].Answer"]').val()).length == 0) return;
                    var val = parseInt($.trim($(_formSelector + ' select[name="[' + (obj.OrderNum - 1) + '].Answer"]').val()));
                    zeroCount += isNaN(val) || val == 0 ? 1 : 0;
                });
                return zeroCount > 0;
            };
            var chipHasAnswers = function chipHasAnswers(getGroups) {
                var zeroCount = 0;
                $.each(getGroups, function (i, obj) {
                    if ($(_formSelector + ' select[name="[' + (obj.OrderNum - 1) + '].Answer"]').val() == null || $.trim($(_formSelector + ' select[name="[' + (obj.OrderNum - 1) + '].Answer"]').val()).length == 0) return;
                    var drpVal = $(_formSelector + ' select[name="[' + (obj.OrderNum - 1) + '].Answer"]').val();
                    var val = parseInt($.trim(drpVal));
                    zeroCount += 1;
                });
                return zeroCount;
            };
            $scope.obj.onGroupSelectChange = function (q, o, val, qt) {
                var getGroups = $scope.obj.getGroupOptions(q);
                if (getGroups == null || getGroups.length == 0) return; // check if next button should be disabled or not                
                $timeout(function () {
                    var validation = $scope.obj.isQuestionValidated(qt);
                    qt.isNextDisabled = !validation.v;
                }, 200);
                var $currentOption = $(_formSelector + ' select[name="[' + (q.OrderNum - 1) + '].Answer"]');
                if ($scope.obj.isPoker(q)) { // poker chips service
                    var maxChip = getGroups[0].TotOptions - 1;
                    getGroups[0].inlineAlertHtml = '';
                    $timeout(function () {
                        var hasAnsweredAll = chipHasAnswers(getGroups) == q.TotInGroup;
                        if (eval(getPokerRating(q)) == 1 && !hasAnsweredAll && !chipRatingHasZero(getGroups)) { // tell users that they can only choose none/zeroes from now on
                            showAlertValidate({
                                v: false,
                                t: validationTypes.onlyZeroPoker
                            }, getGroups[0]);
                        } else if (eval(getPokerRating(q)) > 1) { // disable current selection and show alert/current rating
                            $currentOption.val('');
                            showAlertValidate({
                                v: false,
                                t: validationTypes.overMaxPoker
                            }, getGroups[0]);
                        } else if (eval(getPokerRating(q)) < 1 && hasAnsweredAll) { // disable current selection and show alert/current rating
                            showAlertValidate({
                                v: false,
                                t: validationTypes.minPoker
                            }, getGroups[0]);
                            $currentOption.val('');
                        }
                    }, 100);
                }
            };
            $scope.obj.onGroupCheckChange = function (q, o, val, qt) { // grouped radio and checkbox click event (can't use onchange because we don't use ng-model)
                var getGroups = $scope.obj.getGroupOptions(q);
                if (getGroups == null || getGroups.length == 0) return; // check if next button should be disabled or not                
                $timeout(function () {
                    var validation = $scope.obj.isQuestionValidated(qt);
                    if (!validation.v) { // invalid answer
                        qt.isNextDisabled = true;
                    } else {
                        qt.isNextDisabled = false;
                        qt.inlineAlertHtml = null;
                    }
                }, 200);
                var $currentOption = $(_formSelector + ' input[name="[' + (q.OrderNum - 1) + '].Answer"][value="' + val + '"]');
                if (q.IsRank != null && q.IsRank > 0) { // ranking services
                    var setToFalse = false;
                    if ($currentOption.prop('checked')) setToFalse = true;
                    $timeout(function () {
                        if (setToFalse && !$currentOption.prop('disabled')) // delayed set due to radio behavior
                            $currentOption.prop('checked', false);
                        if ($currentOption.prop('disabled')) {
                            var prevHorizontal = $(_formSelector + ' input[name="[' + (q.OrderNum - 1) + '].Answer"]:checked').length > 0 ? $(_formSelector + ' input[name="[' + (q.OrderNum - 1) + '].Answer"]:checked').val() : null;
                            if (prevHorizontal != null) {
                                $(_formSelector + ' input[name="[' + (q.OrderNum - 1) + '].Answer"]:checked').prop('checked', false);
                                resetRankedOptionSelected(q, getGroups, prevHorizontal);
                            }
                            $.each(getGroups, function (i, obj) {
                                if (!$(_formSelector + ' input[name="[' + (obj.OrderNum - 1) + '].Answer"][value="' + val + '"]').prop('checked')) return;
                                var prevVertical = $(_formSelector + ' input[name="[' + (obj.OrderNum - 1) + '].Answer"][value="' + val + '"]').val();
                                $(_formSelector + ' input[name="[' + (obj.OrderNum - 1) + '].Answer"][value="' + val + '"]').prop('checked', false);
                                resetRankedOptionSelected(obj, getGroups, prevVertical);
                            });
                            $currentOption.prop('disabled', false);
                            $currentOption.prop('checked', true);
                        }
                        if ($currentOption.prop('checked')) { // disabled remaining options
                            $(_formSelector + ' input[name="[' + (q.OrderNum - 1) + '].Answer"]:not(:checked)').prop('disabled', true);
                            $.each(getGroups, function (i, obj) {
                                if (obj.OrderNum == q.OrderNum) return;
                                if ($(_formSelector + ' input[name="[' + (obj.OrderNum - 1) + '].Answer"][value="' + val + '"]').prop('checked')) // if another option is checked in the same column, uncheck
                                    $(_formSelector + ' input[name="[' + (obj.OrderNum - 1) + '].Answer"][value="' + val + '"]').prop('checked', false);
                                $(_formSelector + ' input[name="[' + (obj.OrderNum - 1) + '].Answer"][value="' + val + '"]').prop('disabled', true);
                            });
                        } else { // reset options to be selectable
                            resetRankedOptionSelected(q, getGroups, val);
                        }
                    }, 200);
                } // reset group timeout promise and reset
                if (groupTimeoutPromise != null) $timeout.cancel(groupTimeoutPromise);
                if (q.Groups > 0 && !$scope.obj.isPoker(q)) {
                    qt.inlineAlertHtml = null;
                    qt.optionAlertIndex = [];
                    groupTimeoutPromise = $timeout(function () {
                        $scope.obj.validateGroupedQuestion(qt);
                    }, groupTimeoutSeconds);
                }
            };
            var resetRankedOptionSelected = function resetRankedOptionSelected(q, getGroups, val) {
                var formJson = $(_formSelector).serializeArray();
                var answers = [];
                $.each(getGroups, function (i, obj) {
                    if (obj.OrderNum == q.OrderNum) return;
                    var ans = _.chain(formJson).filter(function (x) {
                        return x.name == '[' + (obj.OrderNum - 1) + '].Answer';
                    }).pluck('value').value();
                    if (ans.length > 0 && ans[0].length > 0) answers.push(ans[0]);
                });
                var nots = '';
                if (answers.length > 0) {
                    for (var ix in answers) {
                        nots += ':not([value="' + answers[ix] + '"])';
                    }
                }
                $(_formSelector + ' input[name="[' + (q.OrderNum - 1) + '].Answer"]:not(:checked)' + nots).prop('disabled', false);
                $.each(getGroups, function (i, obj) {
                    if (obj.OrderNum == q.OrderNum || _.chain(formJson).filter(function (x) {
                            return x.name == '[' + (obj.OrderNum - 1) + '].Answer';
                        }).value().length > 0) return;
                    $(_formSelector + ' input[name="[' + (obj.OrderNum - 1) + '].Answer"][value="' + val + '"]').prop('disabled', false);
                });
            };
            $scope.obj.removeHighlight = function (event, q, ix) {
                var target = $(event.target);
                if (target.prop('checked') && typeof q.optionAlertIndex != 'undefined') { // remove row highlight
                    var index = q.optionAlertIndex.indexOf(ix);
                    if (index > -1) {
                        q.optionAlertIndex.splice(index, 1);
                    }
                }
            };
            $scope.obj.getCellWidth = function (options, has2ndText) {
                var total = options.length + 1 + (has2ndText ? 1 : 0);
                var perc = 100.00 / total;
                return perc;
            };
            $scope.obj.goSubmit = function () { // for user profile
                for (var i in $scope.obj.questions) {
                    var q = $scope.obj.questions[i];
                    q.inlineAlertHtml = null;
                    q.optionAlertIndex = null;
                    var validation = $scope.obj.isQuestionValidated(q);
                    if (!validation.v) { // invalid answer
                        showAlertValidate(validation, q);
                        $('html, body').animate({
                            scrollTop: $("#div_" + q.Id + $scope.obj.set).offset().top
                        }, 500);
                        return;
                    } else if (!$scope.obj.termsAccepted()) { // terms were not accepted
                        $scope.obj.showTermsWarning = true;
                        $('html, body').animate({
                            scrollTop: $("#chkTerms").next().offset().top
                        }, 500);
                        return;
                    }
                }
                var formData = new FormData(document.getElementById(_formId));
                App.loader.showLoader();
                $http({
                    url: $(_formSelector).attr("action"),
                    method: 'POST',
                    data: formData, //assign content-type as undefined, the browser
                    //will assign the correct boundary for us
                    headers: {
                        'Content-Type': undefined
                    }, //prevents serializing payload.  don't do it.
                    transformRequest: angular.identity
                }).then(function (d) {
                    $timeout(function () {
                        App.fireDatalayerEvent('click-' + _surveyData.controller + '-' + _surveyData.action + '-' + _surveyData.currentType, _surveyData.controller + '/' + _surveyData.action, document.title);
                        if (d.status == 200) { //App.loader.hideLoader();
                            angular.element(function () {
                                if (d.data.answers) { // assign answerid if necessary
                                    $.each($scope.obj.questions, function (i, o) {
                                        var answer = _.find(d.data.answers, function (x) {
                                            return x.QuestionID == o.Id;
                                        });
                                        console.log(answer);
                                        var orderNum = o.OrderNum;
                                        var answerIdOption = "[" + (orderNum - 1) + "].AnswerId";
                                        var curId = $(_formSelector + ' input[name="' + answerIdOption + '"]').val();
                                        if (typeof answer !== 'undefined' && (curId == null || curId.length == 0)) $(_formSelector + ' input[name="' + answerIdOption + '"]').val(answer.Id);
                                    });
                                }
                                if (_config.callback) _config.callback();
                            });
                        }
                    });
                });
            };
            $scope.obj.isSubmitActionText = function (q, hideProgress) {
                return $scope.obj.isToSubmit || $scope.obj.currentType == $scope.obj.questionTypes.userprofile && $scope.obj.isVerticalStyle || $scope.obj.questions.length == 1 || !hideProgress && $scope.obj.isCustomOptionSelected(q, 'END') && !$scope.obj.isCustomOptionSelected(q, 'HERO');
            };
            $scope.obj.goPrevious = function (q) {
                if ($scope.obj.questionNumber <= 1) return;
                $scope.obj.questionNumber--;
                q.showCard = false;
                var index = 0;
                if (!!q.prevLinkOrderNum) //is linked to a skipped question
                    index = q.prevLinkOrderNum - 1;
                else {
                    var groups = $scope.obj.getGroupOptions($scope.obj.questions[q.OrderNum - 2]);
                    index = groups == null ? q.OrderNum - 2 : q.OrderNum - 1 - groups.length;
                } // clear current answers
                var groups = $scope.obj.getGroupOptions(q);
                groups != null && groups.length > 0 ? groups.forEach(function (o, i) {
                    clearCurrentAnswers(o);
                }) : clearCurrentAnswers(q);
                $scope.obj.questions[index].showCard = true;
                $scope.obj.isToSubmit = false;
                q.prevLinkOrderNum = null;
                q.isNextDisabled = true; // disable next button
                $('.question-text-clone').remove(); // remove all floating question text
                // timer wait check
                wait.run(q);
            };
            var clearCurrentAnswers = function clearCurrentAnswers(q) { // clear current answers
                $(_formSelector + (' input[name="[' + (q.OrderNum - 1) + '].Answer"]')).prop('checked', false);;
                $(_formSelector + (' input[name="[' + (q.OrderNum - 1) + '].Other"]')).val(null);
                $(_formSelector + (' input[name="[' + (q.OrderNum - 1) + '].CustomText"]')).val(null);
                console.log('clear: ' + q.OrderNum);
            };
            var showAlertValidate = function showAlertValidate(validation, q) {
                var inlineHtml = '';
                switch (validation.t) {
                    case validationTypes.noAnswer:
                        inlineHtml = _surveyData.validateMessages.noAnswer;
                        break;
                    case validationTypes.overMax:
                        inlineHtml = _surveyData.validateMessages.overMax.replace('%maxoption%', q.MaxOption);
                        break;
                    case validationTypes.emptyText:
                        inlineHtml = _surveyData.validateMessages.emptyText;
                        break;
                    case validationTypes.groupMissingAnswer:
                        inlineHtml = _surveyData.validateMessages.groupMissingAnswer;
                        break;
                    case validationTypes.groupAnswersNotRanked:
                        inlineHtml = _surveyData.validateMessages.groupAnswersNotRanked;
                        break;
                    case validationTypes.maxMinError: {
                        var settings = $scope.obj.maxMinOtherSettings(q);
                        inlineHtml = _surveyData.validateMessages.maxMinError.replace('%max%', settings.max).replace('%min%', settings.min);
                        break;
                    }
                    case validationTypes.overMaxPoker: {
                        inlineHtml = _surveyData.validateMessages.overMaxPoker.replace('#currentpokervalue#', eval(getPokerRating(q).replace('/', '-')) * -1);
                        break;
                    }
                    case validationTypes.minPoker: {
                        inlineHtml = _surveyData.validateMessages.minPoker + " (" + getPokerRating(q) + ")";
                        break;
                    }
                    case validationTypes.onlyZeroPoker: {
                        inlineHtml = _surveyData.validateMessages.onlyZeroPoker + " (" + getPokerRating(q) + ")";
                        break;
                    }
                }
                q.inlineAlertHtml = inlineHtml;
                q.optionAlertIndex = validation.ix;
                $anchorScroll('div_' + q.Id + $scope.obj.set);
            };
            var groupTimeoutPromise, groupTimeoutSeconds = 30 * 1000;
            $scope.obj.goNext = function (q) {
                if (!$scope.obj.termsAccepted()) { // terms were not accepted
                    $scope.obj.showTermsWarning = true;
                    $('html, body').animate({
                        scrollTop: $("#chkTerms").next().offset().top
                    }, 500);
                    return;
                }
                if (groupTimeoutPromise != null) $timeout.cancel(groupTimeoutPromise); // cancel group timeout promise if available
                var validation = $scope.obj.isQuestionValidated(q);
                if (!validation.v) { // invalid answer
                    showAlertValidate(validation, q);
                    return;
                } else q.inlineAlertHtml = null;
                wait.run(q); // collect timer
                $('.question-text-clone').remove(); // remove all floating question text
                var skipConfigs = $scope.obj.filterOptionCustomSettingByType(q, 'SKIP');
                var isOpenEndedQuestion = q.Types > 0 && (q.Option1 == null || $.trim(q.Option1).length == 0);
                var formJson = $(_formSelector).serializeArray();
                var answers = _.chain(formJson).filter(function (x) {
                    return x.name == '[' + (q.OrderNum - 1) + '].Answer';
                }).pluck('value').value();
                var skipSelected = answers.length == 0 && isOpenEndedQuestion ? _.find(skipConfigs, function (x) {
                        return x.Question02Id == q.Id;
                    }) : // skip option for open ended question
                    _.find(skipConfigs, function (x) {
                        return _.filter(answers, function (y) {
                            return y == String.fromCharCode(x.OrderNum - 1 + 97).toUpperCase();
                        }).length > 0;
                    }); // skip option for radio/checkbox type questions
                var isSkipSelected = typeof skipSelected != 'undefined';
                var isHeroSelected = $scope.obj.isCustomOptionSelected(q, 'HERO');
                var isEndSelected = $scope.obj.isCustomOptionSelected(q, 'END');
                var isXSkipNotSelected = $scope.obj.filterOptionCustomSettingByType(q, 'XSKIP').length > 0 && !$scope.obj.isCustomOptionSelected(q, 'XSKIP');
                var lastItem = $scope.obj.questions[$scope.obj.questions.length - 1];
                var formData = new FormData(document.getElementById(_formId));
                var groups = $scope.obj.getGroupOptions(q);
                var index = groups == null ? q.OrderNum : q.OrderNum + groups.length - 1;
                var isUserProfile = $scope.obj.currentType == $scope.obj.questionTypes.userprofile;
                var isHorizontalProfile = isUserProfile && !$scope.obj.isVerticalStyle;
                var hasKidsAge = isHorizontalProfile && q.RelatedFile != null && q.RelatedFile.toLowerCase() == "totkids";
                var kidsAnsweredNone = false;
                if (isUserProfile) {
                    var dataLayerList = [{
                        file: 'totpeople',
                        key: 'account-submit-people-' + _config.route
                    }, {
                        file: 'totkids',
                        key: 'account-submit-children-' + _config.route
                    }, {
                        file: 'income',
                        key: 'account-submit-household-' + _config.route
                    }, {
                        file: 'totshop',
                        key: 'account-submit-grocery-' + _config.route
                    }];
                    var dlItem = _.filter(dataLayerList, function (x) {
                        return x.file == q.RelatedFile.toLowerCase();
                    });
                    if (dlItem && dlItem.length > 0) App.fireDatalayerEvent(dlItem[0].key.toLowerCase(), _config.controller + '/register' + _config.action, document.title);
                    if (hasKidsAge) {
                        var isASelectOption = q.MaxOption == 1 && q.Groups == 0;
                        var optionRange = $scope.obj.getOptionRange(q);
                        var lastOption = isASelectOption ? _.chain(optionRange).map(function (x) {
                            return $scope.obj.getOptionDetail(q, x);
                        }).find(function (x) {
                            return x.text.toLowerCase() == "none" || x.text.toLowerCase() == "na" || x.text.toLowerCase() == "0" || /[1-9]/gi.test(x.text);
                        }).value() : $scope.obj.getOptionDetail(q, optionRange[optionRange.length - 1]);
                        var kidsAgeQuestion = _.find($scope.obj.questions, function (x) {
                            return x.RelatedFile == 'kidsAge';
                        });
                        kidsAnsweredNone = typeof _.find(answers, function (x) {
                            return x == lastOption.val;
                        }) != 'undefined';
                    }
                }
                if (isEndSelected && !isHeroSelected || q.OrderNum == lastItem.OrderNum || groups != null && groups.length - 1 + q.OrderNum == lastItem.OrderNum) { // final submit
                    wait.stop();
                    App.loader.showLoader();
                    App.fireDatalayerEvent('click-' + _surveyData.controller + '-' + _surveyData.action + '-' + _surveyData.currentType, _surveyData.controller + '/' + _surveyData.action, document.title), $http({
                        url: $(_formSelector).attr("action"),
                        method: 'POST',
                        data: formData, //assign content-type as undefined, the browser
                        //will assign the correct boundary for us
                        headers: {
                            'Content-Type': undefined
                        }, //prevents serializing payload.  don't do it.
                        transformRequest: angular.identity
                    }).then(function (d) {
                        if (d.status == 200 && d.data.status == 1) {
                            if (_config.callback) $timeout(function () {
                                _config.callback(isEndSelected);
                            }, 100);
                            if (d.data.answers) {
                                angular.element(function () { // assign answerid if necessary
                                    $.each($scope.obj.questions, function (i, o) {
                                        var answer = _.find(d.data.answers, function (x) {
                                            return x.QuestionID == o.Id;
                                        });
                                        var orderNum = o.OrderNum;
                                        var answerIdOption = "[" + (orderNum - 1) + "].AnswerId";
                                        var curId = $(_formSelector + ' input[name="' + answerIdOption + '"]').val();
                                        if (typeof answer !== 'undefined' && (curId == null || curId.length == 0)) $(_formSelector + ' input[name="' + answerIdOption + '"]').val(answer.Id);
                                    });
                                });
                            }
                            if (d.data.id) {
                                $('input[name="AnswerID"]').val(d.data.id);
                            }
                        } else {
                            App.loader.hideLoader();
                            App.notify.Warning(d.data.message);
                        }
                    });
                } else { //#region JumptTo options modifications
                    var isKantarOptions = [129, 130, 131, 132];
                    if (isKantarOptions.indexOf(q.JumptTo) > -1) {
                        var selectedKantarIx = _surveyData.optionValues.indexOf(q.rdoVal);
                        if (q.JumptTo == 129) {
                            $(_formSelector + ' input[id^="chk1_' + index + '_"').each(function (i, o) {
                                $(o).parents('[ng-repeat="o in rdoOpts"]').show();
                                if (i <= selectedKantarIx) {
                                    $(o).parents('[ng-repeat="o in rdoOpts"]').hide();
                                    if ($(o).val() == $scope.obj.questions[index].rdoVal) { // reset answer if answer got hidden
                                        $scope.obj.questions[index].rdoVal = null;
                                    }
                                }
                            });
                            var jumptTo131 = _.find($scope.obj.questions, function (x) {
                                return x.JumptTo == 131;
                            });
                            var dependentKantarQs = jumptTo131.OrderNum;
                            $(_formSelector + ' input[id^="chk1_' + dependentKantarQs + '_"').each(function (i, o) {
                                $(o).parents('[ng-repeat="o in rdoOpts"]').show();
                                if (i > selectedKantarIx) {
                                    $(o).parents('[ng-repeat="o in rdoOpts"]').hide();
                                    if ($(o).val() == jumptTo131.rdoVal) { // reset answer if answer got hidden
                                        jumptTo131.rdoVal = null;
                                    }
                                }
                            });
                        }
                        if (q.JumptTo == 130) {
                            $(_formSelector + ' input[id^="chk1_' + index + '_"').each(function (i, o) {
                                $(o).parents('[ng-repeat="o in rdoOpts"]').show();
                                if (i < selectedKantarIx) {
                                    $(o).parents('[ng-repeat="o in rdoOpts"]').hide();
                                    if ($(o).val() == $scope.obj.questions[index].rdoVal) { // reset answer if answer got hidden
                                        $scope.obj.questions[index].rdoVal = null;
                                    }
                                }
                            });
                        }
                    }
                    if (q.JumptTo == 110) { // apply option filter for next question based on jumptTo = 110 question
                        var qix = $scope.obj.questions[index];
                        var gridFiltering = function gridFiltering(isInclude, jumptToQ) {
                            var groupTable = $('#group_' + jumptToQ.Groups);
                            var answerTexts = _.chain(answers).map(function (x) {
                                var on = x.toLowerCase().charCodeAt(0) - 96;
                                return $scope.obj.getOptionDetail(q, on).text.toLowerCase();
                            }).value();
                            groupTable.find('.group-question-text').each(function (i, o) {
                                var $span = $(o);
                                var text = $.trim($span.html()).toLowerCase();
                                $span.parents('tr').show(); // check if text value is in the previously selection option text
                                if (isInclude && _.filter(answerTexts, function (x) {
                                        return x == text;
                                    }).length === 0) $span.parents('tr').hide();
                                else if (!isInclude && _.filter(answerTexts, function (x) {
                                        return x == text;
                                    }).length > 0) $span.parents('tr').hide();
                            });
                        };
                        if (typeof qix != 'undefined' && qix.JumptTo === 141 && qix.Groups > 0) { // handle exclusion of previously selected options into grid
                            gridFiltering(false, qix);
                        }
                        if (typeof qix != 'undefined' && qix.JumptTo === 111) { // single question filter, default behavior
                            if (qix.Groups > 0) { // grouped filter
                                // filter by question row
                                gridFiltering(true, qix);
                            } else {
                                var selectorGroup = _formSelector + ' input[name="[' + (qix.OrderNum - 1) + '].Answer"]';
                                $(selectorGroup).parent().show(); // reset show all options
                                $(selectorGroup).prop('checked', false);
                                for (var i in answers) selectorGroup += ':not([value="' + answers[i] + '"])';
                                $(selectorGroup).parent().hide(); // hide all unselected options based from 110
                                if ($scope.obj.isCustomOptionSelected(q, 'NOTA')) { // if NOTA is selected, select the next NOTA option
                                    $(_formSelector + ' input[name="[' + (qix.OrderNum - 1) + '].Answer"][value="' + answers[0] + '"]').prop('checked', true);
                                }
                                var $j110OtherElem = $(_formSelector + ' textarea[name="[' + (q.OrderNum - 1) + '].Other"]');
                                var j111OtherSelector = _formSelector + ' textarea[name="[' + (qix.OrderNum - 1) + '].Other"]';
                                $(j111OtherSelector).parent().hide();
                                if ($.trim($j110OtherElem.val()).length > 0 && q.showOtherBox) { // show text option and copy other answer
                                    var textValue = $.trim($(_formSelector + ' textarea[name="[' + (q.OrderNum - 1) + '].Other"]').val());
                                    var $lastOption = $(_formSelector + ' input[name="[' + (qix.OrderNum - 1) + '].Answer"]:last');
                                    $(_formSelector + ' input[name="[' + (q.OrderNum - 1) + '].Answer"]:last').prop('checked', true);
                                    $(j111OtherSelector).val(textValue);
                                    $lastOption.parent().show();
                                    $lastOption.next().find('span').text(textValue);
                                }
                            }
                        }
                    }
                    if ($scope.obj.isPoker(q) && q.JumptTo != 122) { // apply Jumpto.POKER to filter options
                        var jumptTo113 = _.find($scope.obj.questions, function (x) {
                            return x.JumptTo == 113;
                        });
                        if (typeof jumptTo113 != 'undefined') { // reset show all 113 options
                            var selectorGroup = _formSelector + ' input[name="[' + (jumptTo113.OrderNum - 1) + '].Answer"]';
                            $(selectorGroup).parent().show(); // reset show all options
                            var lastOption = String.fromCharCode(q.TotOptions - 1 + 97).toUpperCase();
                            for (var i in groups) {
                                var g = groups[i];
                                var a = _.chain(formJson).filter(function (x) {
                                    return x.name == '[' + (g.OrderNum - 1) + '].Answer';
                                }).pluck('value').value();
                                if (lastOption != a[0] && parseInt(a[0]) > 0) selectorGroup += ':not([value="' + String.fromCharCode(parseInt(i) + 97).toUpperCase() + '"])';
                            }
                            $(selectorGroup).parent().hide(); // hide all unselected options based from 112
                        }
                    } //#endregion
                    if ($scope.obj.questionNumber < lastItem.OrderNum) { // increase question number and hide current question
                        $scope.obj.questionNumber++;
                        q.showCard = false;
                    }
                    var isJumpToNota = q.JumptTo == 110 && $scope.obj.isCustomOptionSelected(q, 'NOTA');
                    if (!isSkipSelected && !isXSkipNotSelected && !isHeroSelected && !isJumpToNota && !kidsAnsweredNone) { // normal next behavior, show next question in sequence
                        $scope.obj.questions[index].showCard = true;
                        var newGroups = $scope.obj.getGroupOptions($scope.obj.questions[index]); // apply this switch for grouped questions
                        if ($scope.obj.questions[index].OrderNum == lastItem.OrderNum || newGroups != null && newGroups.length - 1 + $scope.obj.questions[index].OrderNum == lastItem.OrderNum) // last item
                            $scope.obj.isToSubmit = true;
                    } else if (isHeroSelected) { // for HERO custom option action, this overrides SKIP if selected
                        var heroConfig = $scope.obj.filterOptionCustomSettingByType(q, 'HERO')[0];
                        var lnk = heroConfig.LinkToQOrderNum;
                        index = lnk - 1;
                        $scope.obj.questions[index].showCard = true;
                        $scope.obj.questions[index].prevLinkOrderNum = q.OrderNum;
                    } else if (isXSkipNotSelected) { // for XSKIP custom option action
                        var xSkipConfig = $scope.obj.filterOptionCustomSettingByType(q, 'XSKIP')[0];
                        var lnk = xSkipConfig.LinkToQOrderNum;
                        index = lnk - 1;
                        $scope.obj.questions[index].showCard = true;
                        $scope.obj.questions[index].prevLinkOrderNum = q.OrderNum;
                    } else if (isSkipSelected) { // for SKIP custom option action
                        var lnk = skipSelected.LinkToQOrderNum;
                        index = lnk - 1;
                        $scope.obj.questions[index].showCard = true;
                        $scope.obj.questions[index].prevLinkOrderNum = q.OrderNum;
                    } else if (isJumpToNota) { // skip jumptto-111 if NOTA is selected in jumptto-110
                        var jumptTo111 = _.find($scope.obj.questions, function (x) {
                            return x.JumptTo == 111;
                        });
                        index = jumptTo111.OrderNum;
                        $scope.obj.questions[jumptTo111.OrderNum - 1].showCard = false;
                        $scope.obj.questions[index].showCard = true;
                        $scope.obj.questions[index].prevLinkOrderNum = q.OrderNum;
                    } else if (kidsAnsweredNone) { // for horizontal tot kids option, jump over kids age
                        index = kidsAgeQuestion.OrderNum;
                        $scope.obj.questions[index].showCard = true;
                        $scope.obj.questions[index].prevLinkOrderNum = q.OrderNum;
                    } // for poker linked survey question with parent
                    var isNextQuestionPoker = $scope.obj.isPoker($scope.obj.questions[index]);
                    if (isNextQuestionPoker && $scope.obj.parentPokerAnswers.length > 0) loadPokerParentAnswers($scope.obj.questions[index]); // add timeout wait if group/non poker question
                    var nextQuestion = $scope.obj.questions[index];
                    if (nextQuestion.Groups > 0 && !$scope.obj.isPoker(nextQuestion)) {
                        groupTimeoutPromise = $timeout(function () {
                            $scope.obj.validateGroupedQuestion(nextQuestion);
                        }, groupTimeoutSeconds);
                    } // scroll top question
                    if ($scope.obj.questions[index].showCard) {
                        angular.element(function () {
                            App.scrollTo('#div_' + $scope.obj.questions[index].Id + $scope.obj.set, 50);
                        });
                    } // partial insert
                    if ($scope.obj.currentType !== $scope.obj.questionTypes.userprofile) { // only for surveys, qualfiers and lnw
                        if (_partialHttpCanceler) _partialHttpCanceler.resolve(); // cancel currently running partial answerl event
                        var isOnHold = q.OrderNum == 1 && $scope.obj.surveyTable == 'answers03';
                        if (isOnHold) { // hold next button question
                            $scope.obj.questions[index].isOnPause = true;
                        }
                        _partialHttpCanceler = storePartialAnswer(function () {
                            if (isOnHold) $scope.obj.questions[index].isOnPause = false;
                        });
                    } // AB test progress bar increments
                    if ($('#divProgTestB').length > 0 && _surveyData.regPath == 'B' && _surveyData.action == 'register' && _surveyData.controller == 'account') {
                        $timeout(function () {
                            var currPerc = angular.element('#divProgTestB').scope().obj.progressPerc;
                            currPerc += 5;
                            angular.element('#divProgTestB').scope().$apply(function () {
                                angular.element('#divProgTestB').scope().obj.progressPerc = currPerc;
                            });
                        }, 100);
                    }
                }
                angular.element(function () {
                    adjustInputHeights();
                });
            };
            var _partialHttpCanceler = null;
            var storePartialAnswer = function storePartialAnswer(callback) {
                if (_config.surveyData.partialUri === null || $.trim(_config.surveyData.partialUri).length === 0) return;
                var formData = new FormData(document.getElementById(_formId));
                var partialHttpCanceler = $q.defer();
                $http({
                    url: _config.surveyData.partialUri,
                    method: 'POST',
                    data: formData, //assign content-type as undefined, the browser
                    //will assign the correct boundary for us
                    headers: {
                        'Content-Type': undefined
                    }, //prevents serializing payload.  don't do it.
                    transformRequest: angular.identity,
                    timeout: partialHttpCanceler.promise
                }).then(function (d) {
                    if (d.data.id) {
                        $('#' + _formId).find('input[name="AnswerID"]').val(d.data.id);
                    }
                    if (callback) callback();
                });
                return partialHttpCanceler;
            };
            var loadPokerParentAnswers = function loadPokerParentAnswers(q) {
                if ($scope.obj.parentAnswerLoaded > 0) return;
                $scope.obj.parentAnswerLoaded++;
                var pokerGroups = $scope.obj.getGroupOptions(q);
                var canLimitOptions = _.filter(pokerGroups, function (g) {
                    return g.JumptTo == 112;
                }).length > 0;
                var canShowPrevNotice = _.filter(pokerGroups, function (g) {
                    return g.JumptTo == 122;
                }).length > 0;
                for (var i in pokerGroups) {
                    var g = pokerGroups[i];
                    var s = _formSelector + " select[name='[" + (g.OrderNum - 1) + "].Answer']";
                    if ($scope.obj.parentPokerAnswers[i] == null) continue; // new product, skip
                    var parentAnswer = parseInt($.trim($scope.obj.parentPokerAnswers[i]));
                    $(s).parent().parent().parent().show();
                    if (isNaN(parentAnswer)) parentAnswer = 0;
                    if ($.trim(parentAnswer).length == 0) continue; // new product, skip
                    if (g.JumptTo != 124) { // limit number of options for preselected poker option
                        $(s + ' option').each(function (i, o) {
                            var optValue = $(o).attr('value');
                            if (optValue == null || $.trim(optValue).length == 0) return; // skip default please select option
                            if (canLimitOptions && !isNaN(optValue) && optValue != 0 && optValue > parentAnswer) // hide options greater the the previous selection
                                $(o).hide();
                            else if (optValue == parentAnswer && canShowPrevNotice) // just append flag if option is previously selected
                                $(o).text($(o).text() + ' » ' + _surveyData.previousSelection);
                        });
                    } else if (g.JumptTo == 124) {
                        $(s + ' option').each(function (i, o) {
                            var optValue = $(o).attr('value');
                            if (optValue == null || $.trim(optValue).length == 0) return; // skip default please select option
                            if (isNaN(optValue) || optValue == 0) {
                                $(o).text('0 » ' + _surveyData.noLongerAvailable);
                                $(o).prop('selected', true);
                            } else $(o).hide();
                        });
                    }
                    if (parentAnswer == 0 && canLimitOptions) { // set answer to zero and hide option
                        g.AnswerModel = $scope.obj.parentPokerAnswers[i];
                        $(s).parent().parent().parent().hide();
                    }
                }
            };
            $scope.obj.validateGroupedQuestion = function (q) {
                var validation = $scope.obj.isQuestionValidated(q);
                if (!validation.v) // invalid answer
                    showAlertValidate(validation, q);
            };
            var adjustInputHeights = function adjustInputHeights() {
                var maxHeight = 0;
                $('.radio.radio-primary:visible,.cp-form-style .checkbox.checkbox-remember:visible').each(function (i, o) {
                    if ($(o).find('label').height() > maxHeight) maxHeight = $(o).find('label').height();
                });
                $('.radio.radio-primary:visible,.cp-form-style .checkbox.checkbox-remember:visible').css('height', parseInt(maxHeight) + 30 + 'px');
            };
            var hasVoxInQuestionList = function hasVoxInQuestionList() {
                return _.filter($scope.obj.questions, function (q) {
                    return q.JumptTo === 139;
                }).length > 0;
            };

            var min_recording_time = 15;
            var max_recording_time = 60;
            
            var loadVox = function loadVox() {
                window.vpm_widget_config = {
                    project_id: _surveyData.vox.vProjectId,
                    additional_data: {
                        "Age": _surveyData.vox.vAge,
                        "Gender": _surveyData.vox.vGender,
                        "htcpromo": _surveyData.vox.vPromo,
                        "htcbox": _surveyData.vox.vBox,
                        "htcuserid": _surveyData.vox.userId
                    },
                    settings: {
                        locale: _surveyData.vox.vLang,
                        min_recording_time: min_recording_time,
                        max_recording_time: max_recording_time
                    }
                };
                $(window).on('resize', function () {
                    $('video.vpm-cameraPreview').css({
                        'height': 'auto !important',
                        'width': '100% !important'
                    });
                }); // Vox scripts
                //this code is used to listen for events from the iframe
                var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
                var eventer = window[eventMethod];
                var messageEvent = eventMethod === "attachEvent" ? "onmessage" : "message"; // Listen to message from child window (iframe)
                var onlyStrings = false;
                try {
                    window.postMessage({
                        toString: function toString() {
                            onlyStrings = true;
                        }
                    }, "*");
                } catch (e) {
                    console.log(e);
                }
                eventer(messageEvent, function (e) {
                    if (e.data) {
                        var eventData = {};
                        if (typeof e.data === 'string' && onlyStrings) {
                            eventData = JSON.parse(e.data);
                        } else {
                            eventData = e.data;
                        }
                        console.log({
                            'vox_event': eventData.event,
                            'vox_object': eventData
                        });
                        $('video.vpm-cameraPreview').css({
                            'height': 'auto !important',
                            'width': '100% !important'
                        });
                        if ("initialized" === eventData.event) { // apply custom layout
                            $('style.vpm-parent-styles,style.vpm-styles').remove();
                        } else if (eventData.event === 'readyToRecord' /*'response_complete'*/ ) {
                            console.log('vox-ready-event');
                        } else if (eventData.event === 'processed' /*'response_complete'*/ ) {
                            console.log('vox-processed-event');
                            var q = _.find(_surveyData.questions, function (x) {
                                return x.JumptTo === 139;
                            });
                            $(_formSelector + ' input[name="[' + (q.OrderNum - 1) + '].Answer"]').prop('checked', true);
                            $scope.$apply(function () { $scope.obj.onSingleCheckChange(q, 1, null); });
                            $('.vpm-capture-widget').html('<h2>' + _surveyData.successTxt + '</h2><span>' + _surveyData.successVoxNoticeTxt + '</span>');
                        }
                    }
                }, false); // load Vox script
                !(function (a, b, c, d) {
                    function e() {
                        var a = b.createElement(c);
                        a.type = "text/javascript", a.src = d;
                        var e = b.getElementsByTagName(c)[0];
                        e.parentNode.insertBefore(a, e);
                    }
                    a.attachEvent ? a.attachEvent("onload", e) : a.addEventListener("load", e, !1);
                })(window, document, "script", "https://capture.voxpopme.net/main.js");
            };

            function loadPagedTest() {
                if (!_surveyData.isTest) return;

                if (_surveyData.testPage > 0) { // jump to specific question
                    var ix = _surveyData.testPage - 1;
                    $scope.obj.questions[0].showCard = false; // hide first question
                    $scope.obj.questionNumber = _surveyData.testPage;

                    if ($scope.obj.questions[ix].Groups == null || $scope.obj.questions[ix].Groups == 0) {
                        $scope.obj.questions[ix].showCard = true;
                        return;
                    }

                    // for groups
                    var groups = $scope.obj.getGroupOptions($scope.obj.questions[ix]);
                    $scope.obj.questions[groups[0].OrderNum - 1].showCard = true;
                }
            }

            $(window).resize(function () {
                adjustInputHeights();
                if ($(_formSelector + ' .search-select .selectpicker').length > 0) {
                    $(_formSelector + ' .search-select .selectpicker').selectpicker('refresh');
                }
            });

            angular.element(function () {
                adjustInputHeights();
                if ($(_formSelector + ' .search-select .selectpicker').length > 0) $(_formSelector + ' .search-select .selectpicker').selectpicker(); // render select picker
                if ($scope.obj.answers != null && $scope.obj.answers.length > 0) { // pre fill answers for answered profile questions
                    $.each($scope.obj.questions, function (i, o) {
                        var answer = _.find($scope.obj.answers, function (x) {
                            return x.QuestionID == o.Id;
                        });
                        var orderNum = o.OrderNum;
                        var nameOption = "[" + (orderNum - 1) + "].Answer";
                        var nameOther = "[" + (orderNum - 1) + "].Other";
                        var nameAnswerId = "[" + (orderNum - 1) + "].AnswerId";
                        if (typeof answer !== 'undefined') { // answer implement for user profile select controls
                            if ($scope.obj.currentType == $scope.obj.questionTypes.userprofile && o.MaxOption == 1 && (o.Groups == 0 || o.Groups == null)) {
                                if (answer.Answer != null && answer.Answer.length > 0) $(_formSelector + ' select[name="' + nameOption + '"]').val(answer.Answer[0]);
                            } else { // answer for radio, check boxes
                                for (var ix in answer.Answer) {
                                    var a = answer.Answer[ix];
                                    $(_formSelector + ' input[name="' + nameOption + '"][value="' + a + '"]').prop('checked', true);
                                }
                            }
                            if (answer.Other != null && answer.Other.length > 0) $(_formSelector + ' textarea[name="' + nameOther + '"]').val(answer.Other[0]);
                            if (answer.AnswerId != null) $(_formSelector + ' input[name="' + nameAnswerId + '"]').val(answer.AnswerId);
                        }
                    });
                } // load parent answer if first question is poker
                var isFirstQuestionPoker = $scope.obj.isPoker($scope.obj.questions[0]);
                if (isFirstQuestionPoker && $scope.obj.parentPokerAnswers.length > 0) loadPokerParentAnswers($scope.obj.questions[0]);

                var setKidsOpts = function () { // toggle has kids options
                    var hasAnswers = $scope.obj.answers != null && $scope.obj.answers.length > 0;
                    if (!hasAnswers) return;

                    var totKidsQuestion = _.find($scope.obj.questions, function (x) { return x.RelatedFile == 'totKids' });
                    if (typeof totKidsQuestion != 'undefined') {
                        $scope.obj.setupKidOptions(totKidsQuestion);
                    }
                }

                if ($scope.obj.questions && $scope.obj.questions.length > 0) { // load all premade scripts
                    $.each($scope.obj.questions, function (i, o) {
                        try { // ignore errors of the eval
                            eval(o.Script);
                        }
                        catch (err) { }
                    })
                    setKidsOpts();
                }

                window.checkboxChange = function (e) {
                    setKidsOpts(); // Mark: workaround if nochild selected and need to reselect to trigger script
                    $(e).attr('onchange', null);
                }

                // initialize regular image modal
                $('.venobox-image').venobox({
                    spinColor: 'deeppink',
                    cb_post_open: function cb_post_open(obj, gallIndex, thenext, theprev) {
                        $('.vbox-preloader').hide();
                    }
                }); // initialize image gallery (set data-gall="GalleryName")
                $('.venobox-gallery').venobox({
                    infinigall: true,
                    spinColor: 'deeppink',
                    cb_post_open: function cb_post_open(obj, gallIndex, thenext, theprev) {
                        $('.vbox-preloader').hide();
                    }
                }); // initialize full screen video (vimeo or youtube only)
                $('.venobox-video').venobox({
                    framewidth: '100%', // default: ''
                    frameheight: '100%', // default: ''
                    titleattr: 'data-title', // default: 'title'
                    numeratio: false, // default: false
                    infinigall: false, // default: false
                    spinner: 'cube-grid-none',
                    contentMarginTop: 0,
                    contentMarginBottom: 0,
                    overFlowY: 'inherit',
                    spinColor: 'deeppink',
                    cb_pre_open: function cb_pre_open(obj) {
                        $('.vbox-preloader').hide();
                        App.loader.showLoader();
                    },
                    cb_post_open: function cb_post_open(obj, gallIndex, thenext, theprev) {
                        $('.vbox-preloader').hide();
                        App.loader.hideLoader();
                    }
                });
                $('#modalStopSurvey').on('hidden.bs.modal', function (e) {
                    App.loader.showLoader();
                    window.location = '../../Test';
                }); // load vox
                if (hasVoxInQuestionList()) loadVox(); // init wait
                wait.start();
                $timeout(loadPagedTest, 300)
            });
        }]);
    };
    return {
        init: init
    };
};
App.Shared._Questions = questionsFunction('');
App.Shared._Questions1 = questionsFunction('1');
App.Shared._Questions2 = questionsFunction('2');
App.Shared._ExtendedFiles = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config == 'object') {
            $.extend(true, _config, config);
        }
        var sliderSettings = {
            minSlides: 1,
            maxSlides: 4,
            slideWidth: 255,
            slideMargin: 35,
            prevSelector: '#slider-extendedfiles-prev-big',
            prevText: '<i class="fa fa-angle-left" aria-hidden="true"></i>',
            nextSelector: '#slider-extendedfiles-next-big',
            nextText: '<i class="fa fa-angle-right" aria-hidden="true"></i>',
            onSliderLoad: function onSliderLoad() {
                $('#extended-files-slider .bx-default-pager').hide();
                $('#extended-files-slider .tester-gallery-slider-control').appendTo('#extended-files-slider .bx-wrapper');
            }
        };
        $('#extended-files-slider .bxslider').bxSlider(sliderSettings);
        var autoClosePopup = false;
        $('#extended-files-slider').magnificPopup({
            delegate: 'a.tester-gallery-box-link, a.tester-box-reg-vid-link',
            type: 'image',
            closeOnContentClick: true,
            closeBtnInside: false,
            mainClass: 'mfp-with-zoom mfp-img-mobile',
            image: {
                verticalFit: true,
                titleSrc: function titleSrc(item) {
                    return item.el.attr('data-desc');
                }
            },
            zoom: {
                enabled: true
            },
            callbacks: {
                beforeOpen: function beforeOpen() { // just a hack that adds mfp-anim class to markup 
                    this.st.image.markup = this.st.image.markup.replace('mfp-figure', 'mfp-figure mfp-with-anim');
                    this.st.mainClass = this.st.el.attr('data-effect');
                },
                elementParse: function elementParse(item) {
                    if (item.el[0].className == 'tester-box-reg-vid-link' || item.src.indexOf('youtube.com') > -1) {
                        item.type = 'iframe';
                    } else if (item.src.indexOf('.pdf') > -1 || item.src.indexOf('facebook.com') > -1) { // open FB and PDF in new window
                        var win = window.open(item.src, '_blank');
                        win.focus();
                        autoClosePopup = true;
                    } else {
                        item.type = 'image';
                    }
                },
                open: function open() {
                    if (autoClosePopup) {
                        autoClosePopup = false;
                        this.close();
                    }
                }
            },
            gallery: {
                enabled: false
            }
        });
    };
    return {
        init: init
    };
})();;
'use strict';

if (typeof App == 'undefined') var App = {};

App.Support = (function () {
    return {};
})();

App.Support.Faq = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);

            App.angular.controller('MainController', ['$scope', '$http', function ($scope, $http) {
                $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
                $scope.obj = {};

                angular.element(function () {
                    function toggleIcon(e) {
                        $(e.target).prev('.panel-heading').find(".more-less").toggleClass('glyphicon-plus glyphicon-minus');
                    }

                    $('.panel-group').on('hidden.bs.collapse', toggleIcon);
                    $('.panel-group').on('shown.bs.collapse', toggleIcon);
                });
            }]);
        }
    };

    return {
        init: init
    };
})();

App.Support.ThankYou = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);

            App.angular.controller('MainController', ['$scope', '$http', function ($scope, $http) {
                $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
                $scope.obj = {};

                angular.element(function () {});
            }]);
        }
    };

    return {
        init: init
    };
})();

App.Support.Index = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config == 'object') {
            $.extend(true, _config, config);
        }

        App.angular.controller('MainController', ['$scope', '$http', function ($scope, $http) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};

            $(function () {
                // add scripts here
            });
        }]);

        App.angular.controller('supportController', ['$scope', '$location', '$anchorScroll', '$window', function ($scope, $location, $anchorScroll, $window) {
            $scope.obj = {};
            var support = this;

            support.firstName = _config.firstName;
            support.email = _config.email;
            support.comment = '';
            support.isAgency = false;
            support.displayReceivedMessage = false;
            support.displayFailedMessage = false;
            support.messageTimer = null;

            $(function () {
                support.productId = _config.productId;
                // reset the form on load
                support.reset();
            });

            support.reset = function (form) {
                if (form) {
                    form.$setPristine();
                    form.$setUntouched();
                }
            };

            support.submit = function (form) {
                if (form) {
                    if (form.$valid) {
                        support.submitFeedback();
                    }
                }
            };

            support.submitFeedback = function () {
                // put up the loader
                App.loader.showLoader();

                var data = {
                    firstName: support.firstName,
                    email: support.email,
                    comment: support.comment,
                    isAgency: support.isAgency,
                    productId: support.productId,
                    '__RequestVerificationToken': $('[name="__RequestVerificationToken"]').val()
                };

                $.post(window._submitFeedbackUri, data).done(function (result) {

                    // The result will either be a link to the
                    // success page or false if something went wrong
                    if (result.result == false) {
                        support.displayFailedMessage = true;
                        $location.hash('failed-message');
                        support.startMessageTimer();
                        $scope.$apply();
                        $anchorScroll();
                        // hide the loader
                        App.loader.hideLoader();
                    } else {
                        support.firstName = '';
                        support.email = '';
                        support.isAgency = false;
                        support.comment = '';
                        // take the user to the thank you page
                        $window.location.href = result.result.toString();
                    }
                }).fail(function () {
                    support.displayFailedMessage = true;
                    $location.hash('failed-message');
                    support.startMessageTimer();
                    $scope.$apply();
                    $anchorScroll();
                    // hide the loader
                    App.loader.hideLoader();
                });
            };

            support.startMessageTimer = function () {
                // Set a timer to hide the message panel
                support.messageTimer = setTimeout(function () {
                    support.messageTimer = null;
                    support.displayReceivedMessage = false;
                    support.displayFailedMessage = false;
                    $scope.$apply();
                }, 5000);
            };
        }]);
    };

    return {
        init: init
    };
})();;
if (typeof App == 'undefined') var App = {};

App.Survey = function () { return {} }();
App.Survey.Index = function () {
    var _config = {};
    var init = function (config) {
        if (config && typeof (config) == 'object') {
            $.extend(true, _config, config);
        }

        App.angular.controller('MainController', function ($scope, $http, $sce, dateFilter, unitOfWork) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};

            $(function () {

            })
        });

    };


    return { init: init };
}()

App.Survey.HomeTested = function () {
    var _config = {};
    var init = function (config) {
        if (config && typeof (config) == 'object') {
            $.extend(true, _config, config);
        }

        App.angular.controller('MainController', function ($scope, $http, $sce, dateFilter, unitOfWork) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};

            angular.element(function () {
                App.loadSurveyQuestionTextClone();
            })
        });
    };
    return { init: init };
}()


App.Survey.LearnWin = function () {
    var _config = {};
    var init = function (config) {
        if (config && typeof (config) == 'object') {
            $.extend(true, _config, config);
        }

        App.angular.controller('MainController', function ($scope, $http, $sce, dateFilter, unitOfWork) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};

            angular.element(function () {
                App.loadSurveyQuestionTextClone();
            })
        });
    };
    return { init: init };
}()


App.Survey.Qualifier = function () {
    var _config = {};
    var init = function (config) {
        if (config && typeof (config) == 'object') {
            $.extend(true, _config, config);
        }

        App.angular.controller('MainController', function ($scope, $http, $sce, dateFilter, unitOfWork) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};

            angular.element(function () {
                App.loadSurveyQuestionTextClone();
            })
        });
    };
    return { init: init };
}()

App.Survey.Success = function () {
    var _config = {};
    var init = function (config) {
        if (config && typeof (config) == 'object') {
            $.extend(true, _config, config);
        }

        if (_config.hasFeatItems) { // set bg to white
            $('body').removeClass('secondary-blue');
            $('#secHeader .navbar-wrapper').addClass('secondary-orange');
        }

        App.angular.controller('MainController', function ($scope, $http, $sce, dateFilter, unitOfWork) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};
            $scope.obj.inviteViaFb = function () {
                App.fbInvite(_config.appId, _config.content, _config.url, _config.fbData);
            }
            angular.element(function () {
                $('.js-star-rating').makeStars();
            })
        });
    };

    var onSubmit = function () {

    }


    return { init: init, onSubmit: onSubmit };
}()

App.Survey.ShareWeb = function () {
    var _config = {};
    var init = function (config) {
        if (config && typeof (config) == 'object') {
            $.extend(true, _config, config);
        }

        App.angular.controller('MainController', function ($scope, $http, $sce, dateFilter, unitOfWork) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};
            $scope.obj.insertHtml = function (s) {
                return $sce.trustAsHtml($.trim(s));
            }
            $scope.obj.goNext = function () {
                if (_config.hasTerm && !$scope.obj.isSurveyAccepted) {
                    $('#acceptSurveyPromo').focus();
                    $scope.obj.isSurveyAccepted = false;
                    return;
                }

                window.open(_config.redirect, '_blank');
            }

            $scope.obj.showAcceptError = function () {
                return ($scope.obj.isSurveyAccepted != null && typeof $scope.obj.isSurveyAccepted != 'undefined') && !$scope.obj.isSurveyAccepted;
            }

            $scope.obj.showTerm = function () {
                $scope.obj.showPromoTerms = !$scope.obj.showPromoTerms

                if (!$scope.obj.showPromoTerms) return;

                $('#webshareTermsDialog').modal('show');
            }

            $scope.obj.goSkip = function () {
                window.location = _config.skip;
            }

            angular.element(function () {
                $('#txtWebShare') // highlight text
                    .on("focus keyup", function (e) {
                        var keycode = e.keyCode ? e.keyCode : e.which ? e.which : e.charCode;
                        if (keycode === 9 || !keycode) {
                            // select
                            var $this = $(this);
                            $this.select();

                            // For Chrome's bug
                            $this.on("mouseup", function () {
                                // Unbindl mouseup
                                $this.off("mouseup");
                                return false;
                            });
                        }
                    });
            })
        });
    };

    var onSubmit = function () {

    }


    return { init: init, onSubmit: onSubmit };
}()

App.Survey.Media = function () {
    var _config = {};
    var init = function (config) {
        if (config && typeof (config) == 'object') {
            $.extend(true, _config, config);
        }

        App.angular.controller('MainController', function ($scope, $http, $sce, dateFilter, unitOfWork) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {
                photoArray: _config.photoArray,
                videoArray: _config.videoArray,
                selectedPhoto: _config.selectedPhoto,
                selectedVideo: _config.selectedVideo,
                allowMultiple: _config.allowMultiple,
                successVidUpload: false,
                successImgUpload: false,
                publishStatus: { 'inappropriate': 5, 'new': 33, 'newUpload': 40, 'uploadError': 45, 'profanity': 49, 'removed': 86  },
                removeModal: {
                    cancelAlert: function () { $scope.obj.removeModal.okAlert = null; $('#modalRemove').modal('hide'); }
                }
            };
            
            $scope.obj.choosePhotoUpload = function () {
                if (_config.isChomeMobileIos) {
                    App.notify.Info(_config.T_MobileChromeIosCameraNotice);
                }

                $('#imageInputFile').click();
                return false;
            }

            $scope.obj.youtubeVideoUploader = function () {
                $('#frmYoutubeSubmit input[type="file"]').click();
            }

            $scope.obj.GoNext = function () {
                if (!_config.isQualifier) { // for survey tasks
                    if ($.trim(_config.shareFbUri).length > 0)
                        window.location = _config.shareFbUri;
                    else if ($.trim(_config.shareWebUri).length > 0)
                        window.location = _config.shareWebUri;
                    else
                        window.location = _config.successUri;
                }
                else {
                    if (_config.isForShare) // supposedly if referral is turned on
                        window.location = _config.shareUri;
                    else
                        window.location = _config.successUri;
                }
            }

            $scope.obj.addNewMedia = function (type) {
                var obj = { id: null, file: '', date: '', desc: '' };
                if (type == 'v') {
                    $scope.obj.selectedVideo = obj;
                    $('[name=btnTryAgainVideoUpload]').click();
                }
                else {
                    $scope.obj.selectedPhoto = obj;
                    $('[name=btnTryAgainPhotoUpload]').click();
                }
            }

            $scope.obj.editMedia = function (obj, type) {
                if (type == 'v') {
                    $scope.obj.selectedVideo = obj;
                    App.scrollTo('#divUploadVideo', 200);
                    $scope.obj.successVidUpload = false;
                }
                else {
                    $scope.obj.selectedPhoto = obj;
                    App.scrollTo('#divUploadPhoto', 200);
                    $scope.obj.successImgUpload = false;
                }

                angular.element(function () { rebindModalZoom(); })
            }

            $scope.obj.removeMedia = function (obj, type) {
                $scope.obj.removeModal.okAlert = function () {
                    App.loader.showLoader();
                    $http.post(_config.updateReviewUploadsUrl, $.param({ id: obj.id, status: $scope.obj.publishStatus.removed }))
                        .then(function (res) {
                            if (res.status == 200) {
                                if (res.data.status == 1) {
                                    //App.notify.Success(_config.successTxt);
                                    //App.inlineSuccessAlert('#divTextMessage', _config.successTxt, App.placement.after);
                                    if (type == "v") {
                                        $scope.obj.videoArray = _.reject($scope.obj.videoArray, function (x) { return x.id == obj.id });
                                        $scope.obj.selectedVideo = $scope.obj.videoArray.length > 0 ? $scope.obj.videoArray[0] : null;
                                        $('[name=btnTryAgainVideoUpload]').click();
                                    }
                                    else {
                                        $scope.obj.photoArray = _.reject($scope.obj.photoArray, function (x) { return x.id == obj.id });
                                        $scope.obj.selectedPhoto = $scope.obj.photoArray.length > 0 ? $scope.obj.photoArray[0] : null;
                                        $('[name=btnTryAgainPhotoUpload]').click();
                                    }

                                    // H3NF-427: don't show success message, just remove media
                                    //App.notify.Success(_config.successTxt);
                                }
                                else
                                    App.notify.Warning(res.data.message);

                                App.loader.hideLoader();
                            }
                        })
                }
                $scope.obj.removeModal.body = "Do you want to remove this media?";
                $scope.obj.removeModal.title = "Remove media";

                $('#modalRemove').modal('show');
            }

            $scope.obj.replaceSrc = function (e) {
                console.log(e.currentTarget);
            }

            $scope.obj.insertHtml = function (s) {
                return $sce.trustAsHtml($.trim(s));
            }

            var uploadVideo = function (form, dynamicFieldValid, showUploadProgress, videoDesc) {
                if (form.valid() && $('#AcceptTermsMediaUpload').is(':checked') && dynamicFieldValid) {
                    var fd = new FormData(document.getElementById('frmUploadVideo'));
                    if (showUploadProgress) {
                        $('.upload-progress-box').show();
                    }

                    var videoInput = $('#videoInputFile').get(0);
                    fd.append('filename', $(videoInput).val().split('\\').pop());
                    fd.append('uploadId', $scope.obj.selectedVideo.id);
                    $('#divUploadNotes').removeClass('hide');

                    $.ajax({
                        url: form.attr('action'),
                        type: "POST",
                        data: fd,
                        processData: false,
                        contentType: false
                    })
                        .fail(function (jqXHR, textStatus, errorThrown) {
                            App.loader.hideLoader();
                            App.notify.Warning(textStatus + ': ' + errorThrown);
                        })
                        .done(function (data, textStatus, jqXHR) {
                            App.loader.hideLoader();
                            if (data.status === 1) {
                                // check for youtube vid                                
                                if ($('#videoid').val() !== '' && data.videoId !== '') {                                    
                                    showUploadedVideo(data, data.videoId, videoDesc, 'YouOpen');
                                }
                                else {
                                    var aws4D = data.result;
                                    var fdFile = App.createFormDataAWS4(aws4D);

                                    // Upload the File
                                    //TODO: hide or replace credential method
                                    AWS.config.credentials = new AWS.Credentials(aws4D.Ajax1, aws4D.Ajax2, null);
                                    AWS.config.httpOptions.timeout = 0;
                                    var file = videoInput.files[0];
                                    var opts = { queueSize: queueSize, partSize: 1024 * 1024 * maxChunkSize };
                                    var params = { Key: aws4D.Key, ContentType: file.type, Body: file };
                                    var maxChunkSize = 5; // size in MB
                                    var queueSize = 3;
                                    var bucketParams = { params: { Bucket: aws4D.BucketName } };
                                    var bucket = new AWS.S3(bucketParams)
                                        .upload(params, opts)
                                        .on('httpUploadProgress', function (evt) { // progress
                                            if (showUploadProgress) onVideoUploadProgress(evt.loaded, evt.total);
                                        });
                                    bucket
                                        .send(function (err, d) {
                                            if (err) {
                                                failedUploadHandler(aws4D, "ERR", "FAILED UPLOAD");
                                                return;
                                            }
                                            successUploadHandler(data.uploadId, function () {
                                                App.loader.hideLoader();
                                                showUploadedVideo(data, data.videoId, videoDesc, 'video');
                                            });
                                        });
                                }
                            }
                            else
                                App.notify.Warning(data.message);
                        });
                }
            };

            var successUploadHandler = function (uploadId, callback) {
                // update userupload entry status from 40 (new upload) to 33 (completed)
                $.post(_config.updateReviewUploadsUrl, { id: uploadId, status: $scope.obj.publishStatus.new },
                    function (data) {
                        callback();
                    }
                );
            }

            var failedUploadHandler = function (aws4D, textStatus, errorThrown) {
                App.loader.hideLoader();
                App.notify.Warning(textStatus + ': ' + errorThrown);
                clearVideoInputs();

                // update userupload entry status from 40 (new upload) to 45 (error encountered)
                $.post(_config.updateReviewUploadsUrl,
                    { id: aws4D.UploadId, status: $scope.obj.publishStatus.uploadError }
                );
            }

            var showUploadedVideo = function (data, videoId, videoDesc, type) {
                var obj = { id: data.uploadId, file: videoId, desc: $('#videoDescription').val(), fileType: type };
                $scope.obj.videoArray = _.reject($scope.obj.videoArray, function (x) { return x.id === obj.id; });
                $scope.obj.videoArray.push(obj);
                $scope.obj.selectedVideo = obj;
                $scope.obj.successVidUpload = true;
                $scope.$apply();

                //window.location.replace(_config.uploadUrl); // redirect and replace browser history (not in click back)
                angular.element(function () {
                    clearVideoInputs();

                    var d = new Date(Date.now());
                    var dateTime = d.getHours() + ':' + d.getMinutes() + ', ' + d.getMonth() + 1 + '/' + d.getDate() + '/' + d.getFullYear();

                    // Show user uploaded video                                                                      
                    var thumbnail = "/images/pic_placeholder.jpg";
                    var uploadVidUrl = type.toLowerCase() === 'youopen' ? 'https://www.youtube.com/watch?v=' + videoId : videoId;
                    var videoUrl = _config.frameUri + "?q={0}".format(uploadVidUrl);

                    var $divSuccess = $('#divVideoUploadSuccess');
                    $('#divVideoUploadForm').addClass('hide');
                    $divSuccess.removeClass('hide');
                    setTimeout(function () {
                        // add delay to allow time for youtube to product video and thumbnail
                        $divSuccess.find('.img-video-upload').attr('src', thumbnail);
                        $divSuccess.find('a').attr('href', videoUrl);
                    }, 2000);

                    $('.video-upload-description').html(videoDesc);
                    $('.video-upload-date').html(dateTime);
                    $divSuccess.find('[name=btnTryAgainVideoUpload]').attr('data-mid', data.uploadId);
                    $divSuccess.find('[name=btnTryAgainVideoUpload]').attr('data-vid', uploadVidUrl);
                    $divSuccess.find('[name=btnSharedVideoOnInstagram]').attr('data-mid', data.uploadId);
                    $('#frmUploadVideo').find('#uploadId').val(data.uploadId);

                    rebindModalZoom();
                });
            };

            var clearImageInputs = function () {
                $('#spanPhotoFile').text('');
                $('#cancelPhotoFile').addClass('hide');
                $('#imageInputFile').val('');
                $('.formUploadPic').parent().show();
                $('#imgCropper').cropper('destroy');
                $('#imgCropper').data('filename', '');
                $('#imgCropper').data('ext', '');
                $('#divCropBox').addClass('hide');
                $('span[data-valmsg-for="imageInputFile"]').show();
                $('#divBtnUploadPhoto').addClass('hidden');
            }

            var clearVideoInputs = function () {
                $('#spanVideoFile').text('');
                $('#videoInputFile').val('');
                $('#cancelVideoFile').addClass('hide');
                $('#divUploadNotes').addClass('hide');
                $('#videoDescription').val('');
                $('#youTubeDescription').val('');
                $('#videoid').val('');
                $('#btnUploadVideo').prop('disabled', true);
            };

            var uploadVideoProgress = function () {
                var xhr = new window.XMLHttpRequest();
                xhr.upload.addEventListener("progress", function (evt) {
                    if (evt.lengthComputable) {
                        onVideoUploadProgress(evt.loaded, evt.total);
                    }
                }, false);

                return xhr;
            }
            var onVideoUploadProgress = function (loaded, total) {
                var percentComplete = loaded / total;
                percentComplete = parseInt(percentComplete * 100);
                $('.upload-progress-box').show();
                $('.upload-progress-box .upload-progress').css('width', percentComplete + '%')
                if (percentComplete === 100) {
                    $('.upload-progress-box').hide();
                    $('#divUploadNotes').addClass('hide');
                    $('.upload-progress-box .upload-progress').css('width', '0px');
                    App.loader.showLoader();
                }
            }

            var rebindModalZoom = function () {
                // re-bind modal pop-up
                $('.media-link-popup').magnificPopup({
                    fixedContentPos: false, // prevent scroll top on img click                    
                    mainClass: 'mfp-with-zoom mfp-img-mobile',
                    zoom: {
                        enabled: true
                    },
                    closeMarkup: '<button title="%title%" class="btn-nobg btn-close-media-popup" style="position: absolute; top: 44px; right: 2px; opacity:.7; font-size:24px;"><i class="fa fa-minus-circle dark-grey-color" aria-hidden="true"></i></button>'
                });
            };

            angular.element(function () {

                // Allow validation for hidden fields, checkbox, radios
                if($("#frmUploadPhoto").length > 0) $("#frmUploadPhoto").data("validator").settings.ignore = "";
                if($("#frmUploadVideo").length > 0) $("#frmUploadVideo").data("validator").settings.ignore = "";

                $('#btnRotateLeft, #btnRotateRight').click(function () {
                    var degree = parseInt($(this).data('degree'));
                    $('#imgCropper').cropper("rotate", degree);
                    if (_config.isMobile) {
                        window._cropperData = $('#imgCropper').cropper('getData');
                    }
                });

                $('#imageInputFile').change(function () {
                    var $obj = $(this);
                    if (this.files && this.files[0]) {
                        var reader = new FileReader();

                        $('#imgCropper').cropper('destroy');
                        App.loader.showLoader();

                        reader.onload = function (e) {
                            $('span[data-valmsg-for="imageInputFile"]').hide();
                            $('#spanPhotoFile').text('[' + $obj.val().replace(/.*[\/\\]/, '') + ']');
                            $('#cancelPhotoFile').removeClass('hide');
                            $('#divCropBox').removeClass('hide');
                            // hide choose photo
                            $('.formUploadPic').parent().hide();

                            // initialize cropper image
                            var $imageCrop = $('#imgCropper');
                            $imageCrop.attr('src', e.target.result);

                            //autoCropArea: 1 to get the full image
                            //checkOrientation: true, to fix wrong rotation on mobile pictures
                            var cropperOptions = {
                                aspectRatio: 1/1,
                                preview: '#imgPreview',
                                autoCrop: true,
                                zoomable: false,
                                cropBoxMovable: false,
                                cropBoxResizable: false,
                                dragMode: 'none',
                                autoCropArea: 1,
                                rotatable: true,
                                checkOrientation: true
                            };

                            if (_config.isMobile) {
                                cropperOptions.crop = function (data) {
                                    if (!window._cropperData)
                                        window._cropperData = data;
                                };
                            }

                            $imageCrop.cropper(cropperOptions);
                            $imageCrop.on('built.cropper', function () {
                                App.loader.hideLoader();
                            });

                            $('#divBtnUploadPhoto').removeClass('hidden');
                        }

                        reader.readAsDataURL(this.files[0]);

                        var frag = this.files[0].name.split('.');
                        $('#imgCropper').data('filename', $obj.val().replace(/.*[\/\\]/, ''));
                        $('#imgCropper').data('ext', frag[frag.length - 1]);
                    }
                    else {
                        $('#divBtnUploadPhoto').addClass('hidden');
                        $('#imgCropper').cropper('destroy');
                        $('#imgCropper').data('filename', '');
                        $('#imgCropper').data('ext', '');
                        $('#spanPhotoFile').text('');
                        $('#cancelPhotoFile').addClass('hide');
                        $('#divCropBox').addClass('hide');
                        $('.formUploadPic').show();
                    }
                });

                $('#frmUploadPhoto').submit(function (e) {
                    var form = $(this);
                    var hasImage = false;
                    if (form.valid() && $('#AcceptTermsMediaUpload').is(':checked')) {
                        var input = $('#frmUploadPhoto').find('input[type="file"]').get(0);

                        if (input.files && input.files[0]) {

                            hasImage = true;
                            var fd = new FormData(document.getElementById('frmUploadPhoto'));
                            fd.append('uploadid', $scope.obj.selectedPhoto.id);

                            if ($.trim($('#imgCropper').attr('src')).length > 0) {
                                var data = $('#imgCropper').cropper('getData');
                                fd.append('imagedata[0].QuestionID', 0);
                                fd.append('imagedata[0].Extension', $('#imgCropper').data('ext'));
                                fd.append('imagedata[0].FileName', $(input).val().split('\\').pop());
                                fd.append('imagedata[0].X', data.x);
                                fd.append('imagedata[0].Y', data.y);
                                fd.append('imagedata[0].Width', data.width);
                                fd.append('imagedata[0].Height', data.height);

                                var rotate = data.rotate;
                                fd.append('imagedata[0].Rotate', rotate == 0 ? 0 : (rotate > 0 ? rotate : 360 + rotate));
                            }

                            App.loader.showLoader();
                            $.ajax({
                                url: $(this).attr('action'),
                                type: 'POST',
                                data: fd,
                                contentType: false,
                                processData: false,
                                success: function (data) {
                                    if (data.status == 1) {
                                        // upload to s3
                                        // Uploaded one file only
                                        var aws4D = data.result;
                                        var fdFile = App.editCreateFormDataAWS4(aws4D);
                                        // image upload
                                        var cropperData = App.toScaledImage($('#imgCropper').get(0));
                                        fdFile.append('file', App.dataURItoBlob(cropperData));

                                        $.ajax({
                                            url: aws4D.PostActionUrl,
                                            type: 'POST',
                                            data: fdFile,
                                            contentType: false,
                                            processData: false,
                                            cache: false
                                        })
                                            .done(function (s3Data, textStatus, jqXHR) {
                                                var obj = { id: data.uploadid, file: data.imageUrl, desc: $('#imageDescription').val(), date: '' };
                                                $scope.obj.photoArray = _.reject($scope.obj.photoArray, function (x) { return x.id == obj.id });
                                                $scope.obj.photoArray.push(obj)
                                                $scope.obj.selectedPhoto = obj;
                                                $scope.obj.successImgUpload = true;
                                                $scope.$apply();

                                                clearImageInputs();
                                                var $divSuccess = $('#divPhotoUploadSuccess');
                                                $('#divPhotoUploadForm').addClass('hide');
                                                $divSuccess.removeClass('hide');
                                                //$divSuccess.find('.img-photo-upload').attr('src', data.imageUrl);
                                                //$divSuccess.find('a').attr('href', data.imageUrl);
                                                $divSuccess.find('[name=btnSharedPhotoOnInstagram]').attr('data-mid', data.uploadid);
                                                $('#frmUploadPhoto').find('#uploadid').val(data.uploadid);

                                                angular.element(function () { App.loader.hideLoader(); });
                                            })
                                            .fail(function (jqXHR, textStatus, errorThrown) {
                                                App.loader.hideLoader();
                                                App.notify.Warning(textStatus + ': ' + errorThrown);

                                                // delete data entry for upload
                                                $.post(_config.removeReviewUploadsUrl, { id: aws4D.UploadId });
                                            });
                                    }
                                    else
                                        App.notify.Warning(data.message)

                                    App.loader.hideLoader();
                                },
                                error: function (xhr, ajaxOptions, thrownError) {
                                    App.notify.Danger('ERROR: ' + thrownError);
                                }
                            });
                        }
                        else
                            e.preventDefault();
                    }

                    if ($('#AcceptTermsMediaUpload').is(':checked') === false) {
                        var msg = $('#AcceptTermsMediaUpload').data('val-required');
                        var $alertSpan = $('span[data-valmsg-for="AcceptTermsMediaUpload"]');
                        $alertSpan.addClass('field-validation-error').text(msg).show();
                    }

                    return false;
                });

                $('#btnUploadFromYouTube').click(function () {
                    // toggle youtube link upload
                    var $this = $(this);
                    var videoId = $('#videoid');
                    var form = videoId.closest('form');
                    if (videoId.parent().parent().hasClass('hide')) {
                        // disable local upload, change form action url
                        videoId.parent().parent().removeClass('hide');
                        $('#btnChooseVideo').attr('disabled', 'disabled');
                        $('#videoid').attr('data-val', 'true');
                        $('#videoInputFile').attr('data-val', 'false');
                        
                        form.attr('action', $this.attr('data-upload-youtubelink'));
                        form.attr('data-upload-type', 'youtubelink');
                        $('[data-valmsg-for=videoInputFile]').html('').removeClass('field-validation-error');
                        $('#btnUploadVideo').prop('disabled', false);
                        App.formValidateReset('#frmUploadVideo');
                    }
                    else {
                        videoId.parent().parent().addClass('hide');
                        $('#btnChooseVideo').removeAttr('disabled', 'disabled');                        
                        form.attr('action', $this.attr('data-upload-localvid'));
                        form.attr('data-upload-type', 'localvideo');
                        $('[data-valmsg-for=videoid]').html('').removeClass('field-validation-error');
                        $('#videoid').attr('data-val', 'false');
                        $('#videoInputFile').attr('data-val', 'true');
                        $('#btnUploadVideo').prop('disabled', true);
                        App.formValidateReset('#frmUploadVideo');
                    }
                });

                // manually clear errors
                $('#videoid').keypress(function () {
                    $('[data-valmsg-for=videoid]').html('').removeClass('field-validation-error');
                });
                $('#videoid').change(function () {
                    $('[data-valmsg-for=videoid]').html('').removeClass('field-validation-error');
                });

                $('#videoInputFile').change(function () {
                    var $obj = $(this);
                    $('[data-valmsg-for=videoInputFile]').html('').removeClass('field-validation-error'); // clear errors
                    App.loader.showLoader();
                    if (this.files && this.files[0]) {
                        var reader = new FileReader();

                        reader.onload = function (e) {
                            $('span[data-valmsg-for="videoInputFile"]').hide();
                            $('#spanVideoFile').text('[' + $obj.val().replace(/.*[\/\\]/, '') + ']');
                            $('#cancelVideoFile').removeClass('hide');
                            $('#btnUploadVideo').prop('disabled', false);
                            App.loader.hideLoader();
                        }

                        reader.readAsDataURL(this.files[0]);
                    }
                    else {
                        $('#spanVideoFile').text('');
                        $('#cancelVideoFile').addClass('hide');
                        $('#btnUploadVideo').prop('disabled', true);
                        App.loader.hideLoader();
                    }
                });

                $('#frmUploadVideo').attr("data-upload-type", "localvideo"); // default to localvideo
                $('#frmUploadVideo').submit(function (e) {
                    e.preventDefault();

                    var form = $(this);
                    var input = $('#videoInputFile').get(0);
                    var videoDesc = $('#videoDescription').val();

                    // manually validate dynamic fields
                    var uploadType = form.attr('data-upload-type'); //
                    var dynamicFieldValid = true;
                    var showUploadProgress = false;
                    if (uploadType == 'youtubelink') {
                        // videoInputFile not required, videoid is required
                        var ytUrl = $.trim($('#videoid').val());
                        if (ytUrl == '') {
                            var msg = $('#videoid').data('val-required');
                            var $alertSpan = $('span[data-valmsg-for="videoid"]');
                            $alertSpan.addClass('field-validation-error').text(msg).show();
                            dynamicFieldValid = false;
                        }
                    }
                    else if (uploadType == 'localvideo') {
                        //  videoid not required, videoInputFile is required
                        if ($.trim($('#videoInputFile').val()) == '' || (input.files && input.files.length < 1)) {
                            var msg = $('#videoInputFile').data('val-required');
                            var $alertSpan = $('span[data-valmsg-for="videoInputFile"]');
                            $alertSpan.addClass('field-validation-error').text(msg).show();
                            dynamicFieldValid = false
                        }
                        else {
                            showUploadProgress = true;
                        }
                    }
                    if (uploadType == 'youtubelink' && dynamicFieldValid) {
                        // validate if youtube video exist
                        App.youtubeVideoExists(ytUrl, function (exist) {
                            if (exist) {
                                // continue submit form
                                uploadVideo(form, dynamicFieldValid, showUploadProgress, videoDesc);
                            }
                            else {
                                var $alertSpan = $('span[data-valmsg-for="videoid"]');
                                $alertSpan.addClass('field-validation-error').text(_config.T_InvalidYoutubeLink).show();
                            }
                        });
                    }
                    else {
                        uploadVideo(form, dynamicFieldValid, showUploadProgress, videoDesc);
                    }

                    if ($('#AcceptTermsMediaUpload').is(':checked') === false) {
                        var msg = $('#AcceptTermsMediaUpload').data('val-required');
                        var $alertSpan = $('span[data-valmsg-for="AcceptTermsMediaUpload"]');
                        $alertSpan.addClass('field-validation-error').text(msg).show();
                    }

                    return false;
                });

                $('#btnChooseVideo').on('click', function () {
                    $('#videoInputFile').click();
                });

                $('#cancelPhotoFile').on('click', function () {
                    clearImageInputs();
                });

                $('#cancelVideoFile').on('click', function () {
                    clearVideoInputs();
                });

                $('#AcceptTermsMediaUpload').on('click', function (e) {
                    console.log($(this).is(':checked') && $('#AcceptTermsMediaUpload').is(':checked'))
                    if ($(this).is(':checked')) {
                        if ($('#AcceptTermsMediaUpload').is(':checked')) {
                            termsAccepted();

                            if (_config.isVideoOnly) {
                                openVideoSection();
                                return;
                            }

                            openPhotoSection();
                        }
                    }
                    else {
                        $('#btnOkContinue').attr('disabled', 'disabled').html(_config.T_PleaseAcceptTermsToContinue);
                    }
                });

                function termsAccepted() {
                    $('#divAcceptTerms').addClass('hidden');
                    $('#divContinueButtons').addClass('hidden');
                    $('#divMediaButtons').removeClass('hidden');

                    if (!$('#AcceptTermsMediaUpload').is(':checked')) $('#AcceptTermsMediaUpload').prop('checked', true);
                }

                function openPhotoSection() {
                    $('#lnkUploadPhoto').find('i').addClass('active');
                    $('#lnkUploadVideo').find('i').removeClass('active');
                    $('#lnkUploadInstagram').find('i').removeClass('active');
                    $('#divUploadVideo').addClass('hidden');
                    $('#divUploadInstagram').addClass('hidden');
                    $('#divUploadPhoto').removeClass('hidden');
                    $('.circle_v2.circle-purple-hover').removeClass('active')
                    $('#lnkUploadPhoto').addClass('active');

                    if (_config.isVideoOnly) $('#lnkUploadVideo').click();

                    // scroll to photo div
                    $('html, body').animate({
                        scrollTop: $(_config.isVideoOnly ? "#divUploadVideo" : "#divUploadPhoto").offset().top
                    }, 1000);
                }

                function openVideoSection() {
                    $('#lnkUploadVideo').find('i').addClass('active');
                    $('#lnkUploadInstagram').find('i').removeClass('active');
                    $('#lnkUploadPhoto').find('i').removeClass('active');
                    $('#divUploadPhoto').addClass('hidden');
                    $('#divUploadInstagram').addClass('hidden');
                    $('#divUploadVideo').removeClass('hidden');
                    $('.circle_v2.circle-purple-hover').removeClass('active')
                    $('#lnkUploadVideo').addClass('active');
                    // scroll to video div
                    $('html, body').animate({
                        scrollTop: $("#divUploadVideo").offset().top
                    }, 1000);
                    if ($('.vpm-webrtc').length > 0) {
                        $('#audioSource,#videoSource')
                            .after('<div class="clearfix"></div>')
                            .wrap('<div class="selectdiv margin-l15" style="width: 300px;"></div>')
                            .addClass('form-control')
                            .css({
                                'margin': '',
                                'width': '',
                                'height': '',
                                'font-size': '',
                                'color': '',
                                'background-image': '',
                                'background-position': '',
                                'background-size': '',
                                'background-repeat': '',
                                'padding': ''
                            });
                        $('.vpm-selectAudio.vpm-reset-style,.vpm-selectVideo.vpm-reset-style').css('width', '');
                        $('.vpm-audio-dropdown-label,.vpm-video-dropdown-label').css('float', 'left');
                        $('.vpm-responsive-container,.vpm-mediaSelectPage.vpm-reset-style').css('height', '900px');
                    }
                }

                $('#lnkUploadPhoto').on('click', function (e) {
                    e.preventDefault();
                    openPhotoSection();
                });

                $('#lnkUploadVideo').on('click', function (e) {
                    e.preventDefault();
                    openVideoSection();
                });

                $('[name=btnTryAgainPhotoUpload]').on('click', function () {
                    $('#divPhotoUploadSuccess').addClass('hide');
                    $('#divPhotoUploadForm').removeClass('hide');
                    var uploadid = $(this).data('uploadid');
                    $('#frmUploadPhoto [name="uploadid"]').val(uploadid);
                });

                $('[name=btnTryAgainVideoUpload]').on('click', function () {
                    $('#divVideoUploadSuccess').addClass('hide');
                    $('#divVideoUploadForm').removeClass('hide');
                    var uploadid = $(this).data('uploadid');
                    $('#frmUploadVideo [name="uploadid"]').val(uploadid);

                    var fileType = $(this).data('filetype');
                    if (fileType.toLowerCase() === 'youopen') {
                        $('#btnUploadVideo').prop('disabled', false);
                    }
                });

                rebindModalZoom();

                if (_config.photoArray.length > 0 || _config.videoArray.length > 0) termsAccepted();

                if (_config.photoArray.length > 0)
                    openPhotoSection();
                else if (_config.videoArray.length > 0)
                    openVideoSection();

                $(document).on('click', '.btn-close-media-popup', function () {
                    $.magnificPopup.close();
                });
            })
        });
    };


    return { init: init };
}()

App.Survey.Share = function () {
    var _config = { getSharedFriendsUri: '' };
    var init = function (config) {
        if (config && typeof (config) == 'object') {
            $.extend(true, _config, config);
        }

        App.angular.controller('MainController', function ($scope, $http, $sce, dateFilter, unitOfWork) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = { submitClicked: false };
            $scope.obj.sharedToFriends = _config.sharedToFriends;
            $scope.obj.shareMessage = _config.message;
            $scope.obj.getShareStatus = function (s) {
                if (s.Status == null) s.Status = 0; // New
                if (s.Opened != null && s.Status != 1) return _.find(_config.shareStatus, function (x) { return x.key == 999 }); // Invitation sent

                return _.find(_config.shareStatus, function (x) { return x.key == s.Status });
            }

            $scope.obj.shareFb = function () {
                var uri = _config.shareToFbUri + '&message=' + encodeURIComponent($scope.obj.shareMessage);
                App.loader.showLoader();
                App.fbFeedDialog(_config.linkToShare, function () {
                    $http.post(uri)
                        .then(function (res) {
                            if (res.status == 200) {
                                if (res.data.status == 1) {
                                    //App.notify.Success(_config.successTxt);
                                    App.inlineSuccessAlert('#divTextMessage', _config.successTxt, App.placement.after);
                                    $scope.obj.shareMessage = null;
                                }
                                else
                                    App.notify.Warning(res.data.message);

                                App.loader.hideLoader();
                            }
                        })
                })
            }

            $scope.obj.removeFriend = function (s) {
                var uri = _config.unsubUri + '&id=' + s.Guid;
                App.loader.showLoader();
                $http.post(uri)
                    .then(function (res) {
                        if (res.status == 200) {
                            if (res.data.status == 1) {
                                App.notify.Success(_config.successTxt);
                                $scope.obj.sharedToFriends = _.reject($scope.obj.sharedToFriends, function (x) { return x.Id == s.Id });
                            }
                            else
                                App.notify.Danger(res.data.message);

                            App.loader.hideLoader();
                        }
                    })
            }

            $scope.obj.resendEmail = function (s) {
                var email = prompt('Please enter email');
                if (email == null || email.length == 0)
                    return;

                if (!isStringEmail(email))
                    return;

                App.loader.showLoader();
                var uri = _config.resendEmailUri + "?id=" + s.Id + '&e=' + encodeURIComponent(email);
                $http.post(uri)
                    .then(function (res) {
                        if (res.status == 200) {
                            if (res.data.status == 1)
                                App.notify.Success(_config.successTxt)
                            else
                                App.notify.Danger(res.data.message);

                            App.loader.hideLoader();
                        }
                    })
            }

            $scope.obj.showPreview = function () {
                // cleanup
                $('#contentDiv').remove();
                var $frame = $('#re_contentIframe');
                $frame.on('load', function () {
                    App.loader.hideLoader();
                    // adjust iframe height
                    var height = this.contentWindow.document.body.offsetHeight;
                    console.log(height);
                    document.getElementById('re_contentIframe').style.height = /*height + */'1250px';

                    // show modal
                    $('#modalEmailBody').modal();
                })
                $frame.attr('src', _config.frameUri + "/" + _config.boxId + "?body=" + encodeURIComponent($('#EmailBody').val()));
                App.loader.showLoader();
            }

            function hideEmailErr() {
                $('#err_recipientsList').addClass('hide');
            }

            function isStringEmail(email) {
                var pattern = new RegExp(/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i);
                return pattern.test(email);
            }

            angular.element(function () {
                var form = $("#frmShare");
                form.removeData('validator');
                form.removeData('unobtrusiveValidation');
                $.validator.unobtrusive.adapters.addBool("mandatory", "required");
                $.validator.unobtrusive.adapters.add("checkbox", function (options) {
                    if (options.element.tagName.toUpperCase() === "INPUT" && options.element.type.toUpperCase() === "CHECKBOX") {
                        options.rules["required"] = true;
                        if ($.trim(options.message).length == 0) {
                            options.messages["required"] = _config.plsSpecifyText;//options.message;
                        }
                    }
                });

                $.validator.unobtrusive.parse(form);

                $('#frmShare').submit(function (e) {
                    e.preventDefault();
                    if (!$(this).valid()) return false;

                    var emailList = $("#txtEmails").tagsinput('items');
                    if (_.filter(emailList, function (x) { return x.toLowerCase() == _config.myEmail.toLowerCase() }).length > 0) {
                        App.notify.Warning(_config.notOwnEmailNoticeTxt)
                        return false;
                    }

                    if (_.filter(emailList, function (x) { return !isStringEmail(x) }).length > 0) {
                        App.notify.Warning(_config.onlyValidEmailNoticeTxt)
                        return false;
                    }

                    App.loader.showLoader();
                    $http.post($(this).attr('action'), $(this).serialize())
                        .then(
                            function (r) {
                                if (r.status == 200 && r.data.status == 1) {
                                    $http.post(_config.getSharedFriendsUri)
                                        .then(function (res) {
                                            if (res.status == 200) {
                                                $scope.obj.sharedToFriends = res.data;
                                                $scope.obj.submitClicked = true;
                                                $('#txtEmails').val('');
                                                App.loader.hideLoader();
                                            }
                                        })
                                }
                                else
                                    App.loader.hideLoader();
                            }
                        )

                })

                $('#frmFbShare').submit(function (e) {
                    e.preventDefault();
                })

                $('#txtFbMessage').on("focus keyup", function (e) {
                    var keycode = e.keyCode ? e.keyCode : e.which ? e.which : e.charCode;
                    if (keycode === 9 || !keycode) {
                        // select
                        var $this = $(this);
                        $this.select();

                        // For Chrome's bug
                        $this.on("mouseup", function () {
                            // Unbindl mouseup
                            $this.off("mouseup");
                            return false;
                        });
                    }
                });

                $('#txtEmails')
                    .on('beforeItemAdd', function (event) {
                        $('.bootstrap-tagsinput input:eq(0)').css('width', '100%');
                    }).on('itemAdded', function (event) {
                        if (!isStringEmail(event.item))
                            return;
                        hideEmailErr();
                    }).on('itemRemoved', function (event) {
                        if (!isStringEmail(event.item))
                            return;
                    });

                $('#txtEmails').tagsinput({
                    tagClass: function (item) {
                        return (isStringEmail(item) ? 'label-info' : 'label-danger');
                    },
                    trimValue: true,
                    confirmKeys: [13, 188, 44, 32]
                });

                $('#AcceptTermsMediaUpload').on('click', function () {
                    if ($(this).is(':checked')) {
                        $('#btnOkContinue').removeClass('hidden');
                        $('#btnOkContinue').removeAttr('disabled').html(_config.T_OkContinue);
                    }
                    else {
                        $('#btnOkContinue').attr('disabled', 'disabled').html(_config.T_PleaseAcceptTermsToContinue);
                    }
                });

                $('#btnOkContinue').on('click', function (e) {
                    e.preventDefault();
                    if ($('#AcceptTermsMediaUpload').is(':checked') || !_config.hasTerms) {
                        $('#divAcceptTerms').addClass('hidden');
                        $('#divContinueButtons').addClass('hidden');
                        $('.share-section').removeClass('hidden');
                    }
                });

                if (_config.isFromFbShareFeed) {
                    if (_config.hasTerms) {
                        $('#AcceptTermsMediaUpload').click();
                        setTimeout(function () {
                            $('#btnOkContinue').click();
                            setTimeout(function () {
                                $('#lnkShareFb').click();
                                App.inlineSuccessAlert('#divTextMessage', _config.successFbFeed, App.placement.after);
                            }, 50)
                        }, 50)
                    }
                    else {
                        $('.share-section').removeClass('hidden');
                        $('#divContinueButtons').remove();
                        App.inlineSuccessAlert('#divTextMessage', _config.successFbFeed, App.placement.after);
                    }
                }
                else if (!_config.hasTerms) {
                    $('#divContinueButtons').remove();
                    $('.share-section').removeClass('hidden');
                }
            })
        });
    };
    return { init: init };
}()

App.Survey.AcceptShare = function () {
    var _config = {};
    var init = function (config) {
        if (config && typeof (config) == 'object') {
            $.extend(true, _config, config);
        }

        App.angular.controller('MainController', function ($scope, $http, $sce, dateFilter, unitOfWork) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};
            $scope.obj.unsub = function () {
                App.loader.showLoader();
                $http.post(_config.unsubUri)
                    .then(function (res) {
                        if (res.status == 200) {
                            $('.accept-share').remove();
                            $('#acceptBox').append('<p>' + _config.unsubNoticeTxt + '</p>');
                            App.notify.Success(_config.unsubNoticeTxt)
                            App.loader.hideLoader();
                        }
                    })
            }
            angular.element(function () {
                $('#frmAcceptExist').submit(function (e) {
                    e.preventDefault();
                    App.loader.showLoader();
                    $http.post($(this).attr('action'), $(this).serialize())
                        .then(function (res) {
                            if (res.status == 200) {
                                App.notify.Success(_config.acceptedTxt);

                                if (res.data.redir.length > 0) { // redirect to src page
                                    window.location = res.data.redir;
                                    return false;
                                }

                                $('#btnAcceptExist').prop('disabled', true);
                                App.loader.hideLoader();
                            }
                        })
                })

                $('#frmAccept').submit(function (e) {
                    e.preventDefault();
                    App.loader.showLoader();
                    $http.post($(this).attr('action'), $(this).serialize())
                        .then(function (res) {
                            if (res.status == 200) {
                                App.notify.Success(_config.acceptedTxt);
                                $(this).find('input[name][type="text"]').val('');

                                if (res.data.redir.length > 0) { // redirect to src page
                                    window.location = res.data.redir;
                                    return false;
                                }

                                App.loader.hideLoader();
                            }
                        })
                })
            })
        });
    };

    return { init: init };
}()

App.Survey.Confirm = function () {
    var _config = {};
    var init = function (config) {
        if (config && typeof (config) == 'object') {
            $.extend(true, _config, config);
        }
        App.angular.controller('MainController', function ($scope, $http) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};
            $scope.obj.suburbList = _config.indoDistrictList;
            $scope.obj.address2List = _config.indoSubDistrictList;

            $scope.obj.goToTab = function (tab) {
                $('[href="#' + tab + '"]').click()
            }

            $scope.obj.confirmAddress = _config.confirmAddress;
            $scope.obj.requireProfile = _config.requireProfile;
            $scope.obj.userState = _config.indoState;
            $scope.obj.userSuburb = _config.indoDistrict;
            $scope.obj.userAddress2 = _config.indoSubDistrict;
            $scope.obj.postcodeAreaListing = [];
            $scope.obj.marketSelected = _config.market;
            $scope.obj.stateList = _config.stateList;

            $scope.obj.dynamicPostCode = function () {
                if (!!!$scope.obj.userPostCode || $.trim($scope.obj.userPostCode).length < 4) return;

                App.loader.showLoader();
                $http.post(_config.getDynamicPcListUri, $.param({ code: $scope.obj.userPostCode, market: $scope.obj.marketSelected }))
                    .then(function (d) {
                        if (d.status == 200) { //success
                            $scope.obj.postcodeAreaListing = d.data;
                        }

                        App.loader.hideLoader();
                    }, function () { App.loader.hideLoader(); })
            }

            $scope.obj.setLocationByPostCode = function (_data) {
                App.loader.showLoader();
                $scope.obj.userState = _.find($scope.obj.stateList, function (x) { return $.trim(x.Name).toLowerCase() == $.trim(_data.Province).toLowerCase() }).State; // assign state
                $scope.obj.setIdState(function () { // load district list
                    $scope.obj.userSuburb = _data.District; // assign district
                    $scope.obj.setIdSuburb(function () { // load subdistrict
                        $scope.obj.userAddress2 = _data.SubDistrict; // assign subdistrict
                        $scope.obj.userAddress3 = _data.Area; // assign area
                        $scope.obj.userPostCode = _data.PostCode; // assign postcode
                        $scope.obj.postcodeAreaListing = [];
                        App.loader.hideLoader();
                    })
                })
            }

            $scope.obj.setIdState = function (callback) {
                if (!!!$scope.obj.userState || $scope.obj.userState.length == 0) return;

                if (!callback) App.loader.showLoader();
                $http.post(_config.getSuburbListUri, $.param({ state: $scope.obj.userState }))
                    .then(function (d) {
                        if (d.status == 200 && d.data.status == 1) { //success
                            $scope.obj.suburbList = d.data.list;
                            if (callback) callback();
                        }
                        if (!callback) App.loader.hideLoader();
                    }, function () { App.loader.hideLoader(); })
            }

            $scope.obj.setIdSuburb = function (callback) {
                if (!!!$scope.obj.userSuburb || $scope.obj.userSuburb.length == 0) return;

                if (!callback) App.loader.showLoader();
                $http.post(_config.getAddress2ListUri, $.param({ suburb: $scope.obj.userSuburb }))
                    .then(function (d) {
                        if (d.status == 200 && d.data.status == 1) { //success
                            $scope.obj.address2List = d.data.list;
                            if (callback) callback();
                        }
                        if (!callback) App.loader.hideLoader();
                    }, function () { App.loader.hideLoader(); })
            }

            angular.element(function () {
                // add asterisk on required label fields
                $('[data-val-required]').parents('.form-group').find('label[for]:eq(0)').addClass('required')

                $('#frmDelivery').submit(function (e) {
                    if (!$(this).valid()) return false;
                    App.loader.showLoader();
                    $.post($(this).attr('action'), $(this).serialize(), function (d) {
                        if (d.status == 1) {
                            if (_config.requireProfile) { $('a[href="#about"]').attr('data-toggle', 'tab'); $scope.obj.goToTab('about'); App.loader.hideLoader(); }
                            else window.location = _config.qualifierUri;
                        }
                        else {
                            App.notify.Danger(d.message);
                            App.loader.hideLoader();
                        }
                    })
                    return false;
                })
            })
        });
    };


    return { init: init };
}()

App.Survey.Tasks = function () {
    var _config = {};
    var init = function (config) {
        if (config && typeof (config) == 'object') {
            $.extend(true, _config, config);
        }

        App.angular.controller('MainController', function ($scope, $http, $sce, dateFilter, unitOfWork) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};

            $(function () {
                // add scripts here
            })
        });
    };

    return { init: init };
}()

App.Survey.ShareFb = function () {
    var _config = {};
    var init = function (config) {
        if (config && typeof (config) == 'object') {
            $.extend(true, _config, config);
        }

        App.angular.controller('MainController', function ($scope, $http, $sce, dateFilter, unitOfWork) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};
            $scope.obj.Message = _config.Message;
            $scope.obj.Link = _config.Link;
            $scope.obj.IsSurveyClosed = _config.isSurveyClosed;
            $scope.obj.IsReviewedByUser = _config.isReviewedByUser;

            $scope.obj.skip = function () {
                if ($.trim(_config.ShareWebLink).length > 0) {
                    window.location = _config.ShareWebLink;
                    return;
                }
                window.location = _config.SuccessLink;
            }

            angular.element(function () {
                $('#message') // highlight text
                    .on("focus keyup", function (e) {
                        var keycode = e.keyCode ? e.keyCode : e.which ? e.which : e.charCode;
                        if (keycode === 9 || !keycode) {
                            // select
                            var $this = $(this);
                            $this.select();

                            // For Chrome's bug
                            $this.on("mouseup", function () {
                                // Unbindl mouseup
                                $this.off("mouseup");
                                return false;
                            });
                        }
                    });

                // add scripts here                
                $('#AcceptTermsShareFb').on('click', function () {
                    if ($(this).is(':checked')) {
                        $('#divContinueButtons').removeClass('hidden');
                        $('#btnOkContinue').removeAttr('disabled').html(_config.T_OkContinue);
                    }
                    else {
                        $('#btnOkContinue').attr('disabled', 'disabled').html(_config.T_PleaseAcceptTermsToContinue);
                    }
                });

                $('#btnOkContinue').on('click', function (e) {
                    e.preventDefault();
                    if ($('#AcceptTermsShareFb').is(':checked')) {
                        $('#divAcceptTerms').addClass('hidden');
                        $('#divContinueButtons').addClass('hidden');
                        $('#divShareFbForm').removeClass('hidden');
                    }
                });

                $('#frmShareToFb').submit(function (e) {
                    e.preventDefault();

                    var $this = $(this);
                    if ($this.valid() && $('#AcceptTermsShareFb').is(':checked')) {
                        App.loader.showLoader();
                        var message = $('#message').val();
                        var lnkToShare = message.indexOf('#use_test_uri#') > -1 ? _config.currentTestPage : _config.currentPage;

                        // allow using product test page for hidden items
                        $this.find('[name="uri"]').val(lnkToShare);
                        App.fbFeedDialog(lnkToShare, function () {
                            $http.post($this.attr('action'), $this.serialize())
                                .then(function (response) {
                                    // success                                 
                                    if (response.data.status == 1) {
                                        window.location = _config.SuccessLink;
                                    }
                                    else {
                                        App.notify.Danger(response.data.message);
                                        App.loader.hideLoader();
                                    }

                                }, function (response) {
                                    // error                                                
                                });
                        })

                    }

                    if ($('#AcceptTermsShareFb').is(':checked') === false) {
                        var msg = $('#AcceptTermsShareFb').data('val-required');
                        var $alertSpan = $('span[data-valmsg-for="AcceptTermsShareFb"]');
                        $alertSpan.addClass('field-validation-error').text(msg).show();
                    }

                    // go immediately to webshare if available
                    if (_config.isFromFbRequest && $.trim(_config.ShareWebLink).length > 0) {
                        App.loader.showLoader();
                        setTimeout(function () { window.location = _config.ShareWebLink; }, 200);
                    }
                })
            })
        });
    };

    return { init: init };
}();
'use strict';

if (typeof App === 'undefined') var App = {};

App.Test = (function () {
    return {};
})();

App.Test.Index = (function () {
    var _config = {
        'usersUploads': []
    };

    var init = function init(config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);
        }

        App.angular.controller('MainController', ['$scope', '$http', '$sce', function ($scope, $http, $sce) {
            $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
            $scope.obj = {};

            $scope.trustSrc = function (src) {
                return $sce.trustAsResourceUrl(src);
            };

            $scope.insertHtml = function (s) {
                return $sce.trustAsHtml($.trim(s));
            };

            $scope.getProductImage = function (img) {
                if (img === '') return "data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=";

                return img;
            };

            $scope.slickConfig = {
                dots: false,
                infinite: false,
                speed: 300,
                slidesToShow: 3,
                slidesToScroll: 3,
                responsive: [{
                    breakpoint: 920,
                    settings: {
                        slidesToShow: 2,
                        slidesToScroll: 2
                    }
                }, {
                    breakpoint: 700,
                    settings: {
                        slidesToShow: 1,
                        slidesToScroll: 1
                    }
                }]
            };

            $scope.getLastestReviews = function (url, callback) {
                $('.hero-review-products').loadingOverlay();
                $http.get(url).then(function (response) {
                    // success
                    $scope.obj.LastestReviews = response.data.LastestReviews;

                    setTimeout(function () {
                        // colorize stars based on product ratings
                        $('.js-star-rating').makeStars();

                        // slick carousel
                        $('.responsive-slider').slick($scope.slickConfig);
                    }, 300);

                    if (typeof callback !== 'undefined') callback();
                }, function (response) {
                    // error                                               
                })['finally'](function () {
                    $('.hero-review-products').loadingOverlay('remove');
                });
            };

            angular.element(function () {

                // add event handler here
                $scope.getLastestReviews(_config.lastestReviewsUrl);

                $(".boxCellPic-container .boxCellPic-overlay").each(function (i, o) {
                    if ($(o).find('a.href-link2').length == 0) {
                        $(o).css('cursor', 'initial');
                        $(o).find('.href-link2').css('cursor', 'initial');
                    }
                });
                $(".boxCellPic-container .boxCellPic-overlay").click(function () {
                    if ($(this).find("a").length == 0) return false;

                    window.location = $(this).find("a").attr("href");
                    return false;
                });

                var hash = window.location.hash ? window.location.hash.replace(/[^a-z0-9A-Z\-\_]*/gi, '') : null;
                if (!!hash && hash.length > 0) {
                    hash === 'register' && App.scrollTo('#secBoxSuggestions', 500);
                    hash === 'task' && App.scrollTo('#secYourProductTasks', 500);
                }
            });
        }]);
    };

    return {
        init: init
    };
})();;
'use strict';

if (typeof App === 'undefined') var App = {};

App.Widget = (function () {
    return {};
})();

App.Widget._NotInCountry = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);

            $(function () {
                // footer change country popover
                $("#change-country-select").popover({
                    html: true,
                    content: function content() {
                        var $div = $('<div/>');
                        $div.html($("#country-popover-content").html());
                        var path = (location.pathname + location.search + location.hash).substr(7);
                        $div.find('a').each(function (i, o) {
                            $(o).attr('href', $(o).attr('href') + path);
                        });
                        return $div.html();
                    },
                    title: _config.T_ChangeCountry,
                    placement: 'bottom',
                    trigger: 'click' // when using 'focus', clicking links inside the popover doesn't work
                });
            });
        }
    };

    return {
        init: init
    };
})();

App.Widget._BoxSuggestion = (function () {
    var _config = {};
    var init = function init(config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);

            $(function () {
                $('#lnkHeroBoxViewAll').length > 0 && $('#lnkHeroBoxViewAll').click(function () {
                    $('.toggle-box-slide').slideToggle();
                    $(this).off('click').text(_config.testText).attr('href', _config.testLink);
                });

                if (_config.action === 'index' && _config.controller === 'test' && $('[data-register]').length > 0) {
                    // only applied for /test page
                    var _box = $('[data-register]').eq(0).data('register');
                    var _link = _config.boxReg + '/' + _box;

                    $('.test-icons .body-padding-l').each(function (i, o) {
                        $(o).wrap('<a href="' + _link + '"></a>');
                    });
                }
            });
        }
    };

    return {
        init: init
    };
})();

App.Widget._LatestProductReviews = (function () {
    var _config = {
        'markets': '',
        'mobileSize': 400
    };

    var init = function init(config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);
        }

        $(function () {

            // HTCNEW-418:
            // Making the "View All" button the same width as the "Tried It!" button.
            // Since the content of the "Tried It!" but will be language specific we
            // have to set the "View All" button width dynamically on the client at runtime.
            var triedItButton = $('.tried-it-btn');
            var triedItWidth = $(triedItButton[0]).width();
            $('.view-all-btn').width(triedItWidth);

            //custom carousel
            $('.responsive-slider').slick({
                dots: false,
                infinite: false,
                speed: 300,
                slidesToShow: 3,
                slidesToScroll: 3,
                responsive: [
                    //{
                    //    breakpoint: 1080,
                    //    settings: {
                    //        slidesToShow: 3,
                    //        slidesToScroll: 3,
                    //        infinite: true,
                    //        dots: true
                    //    }
                    //},
                    {
                        breakpoint: 920,
                        settings: {
                            slidesToShow: 2,
                            slidesToScroll: 2
                        }
                    }, {
                        breakpoint: 700,
                        settings: {
                            slidesToShow: 1,
                            slidesToScroll: 1
                        }
                    }
                    // You can unslick at a given breakpoint now by adding:
                    // settings: "unslick"
                    // instead of a settings object
                ]
            });
        });

        // colorize stars based on product ratings
        $('.js-star-rating').makeStars();
    };

    return {
        init: init
    };
})();

App.Widget._YourProductTests = (function () {
    var _config = {};

    var init = function init(config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);
        }

        $('.product-test-box-head-link, .product-test-box-body a, a.product-box-text-link').hover(function () {
            var $box = $(this).parent().parent();
            if (!$box.hasClass('product-rounded-box')) $box = $box.find('.product-rounded-box');
            var $boxHead = $box.find('.product-test-box-head');
            $box.removeClass('product-test-box-border').addClass('product-test-box-hover');
            $boxHead.removeClass('product-test-box-head-normal').addClass('product-test-box-head-hover');
            $box.find('a').addClass('product-test-box-head-link-hover');
            $box.next().find('a').addClass('product-box-link-hover');
        }, function () {
            var $box = $(this).parent().parent();
            if (!$box.hasClass('product-rounded-box')) $box = $box.find('.product-rounded-box');
            var $boxHead = $box.find('.product-test-box-head');
            $box.addClass('product-test-box-border').removeClass('product-test-box-hover');
            $boxHead.addClass('product-test-box-head-normal').removeClass('product-test-box-head-hover');
            $box.find('a').removeClass('product-test-box-head-link-hover');
            $box.next().find('a').removeClass('product-box-link-hover');
        });

        var sliderSettings = {
            minSlides: 1,
            maxSlides: 4,
            slideWidth: 270,
            slideMargin: 30,
            prevSelector: '#slider-yourproduct-test-prev-big',
            prevText: '<i class="fa fa-angle-left" aria-hidden="true"></i>',
            nextSelector: '#slider-yourproduct-test-next-big',
            nextText: '<i class="fa fa-angle-right" aria-hidden="true"></i>',
            onSliderLoad: function onSliderLoad() {
                $('.yourproduct-test-slider .bx-default-pager').hide();
                $('.yourproduct-test-slider-control').appendTo('.yourproduct-test-slider .bx-wrapper');
            }
        };

        $('.yourproduct-test-slider .bxslider').bxSlider(sliderSettings);
    };

    return {
        init: init
    };
})();

App.Widget._TestersGallery = (function () {
    var _config = {};
    var galleryId = '';
    var galleryDataPage = 0;

    var init = function init(config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);
        }

        var usersUploads = [];
        var userUploadPagesize = 15;
        var userUploadPage = 1;
        var showMoreUploads = true;

        var getUsersUploads = function getUsersUploads(page, orderBy, randomSalt, callback) {
            var url = _config.testersGalleryDataUrl + '?page=' + page + '&pageSize=' + userUploadPagesize + '&orderBy=' + orderBy + '&salt=' + randomSalt;
            $.getJSON(url, function (data) {
                if (data.UsersUploads.length < userUploadPagesize) {
                    showMoreUploads = false;
                } else {
                    showMoreUploads = true;
                }

                // call callback if provided
                if (typeof callback !== 'undefined') callback(data);
            }).fail(function () {
                //error
            }).always(function () {
                //finished
            });
        };

        //custom carousel
        $('.responsive-slider-gallery').slick({
            dots: false,
            infinite: false,
            speed: 300,
            slidesToShow: 3,
            slidesToScroll: 3,
            responsive: [{
                breakpoint: 920,
                settings: {
                    slidesToShow: 2,
                    slidesToScroll: 2
                }
            }, {
                breakpoint: 700,
                settings: {
                    slidesToShow: 1,
                    slidesToScroll: 1
                }
            }]
        });

        var escapeQuote = function escapeQuote(str) {
            return str.replace(/'/g, "\\'");
        };

        $('.responsive-slider-gallery').on('afterChange', function (event, slick, currentSlide) {
            if (slick.$slides.length === currentSlide + slick.options.slidesToScroll) {
                // end of current slides, add more slide via ajax
                if (showMoreUploads) {
                    userUploadPage += 1;
                    getUsersUploads(userUploadPage, _config.defaultOrderBy, _config.galleryRandomText, function (data) {
                        var width = $(document).width();
                        var cssMobile = ''; // on mobile slick seems to remove the outer 2 div, hence got 3 outer div here
                        if (width <= 900) {
                            cssMobile = 'col-md-4 col-sm-6 col-xs-12';
                        }
                        var imageType = ["img"];
                        var youtubeType = ["you", "youopen", "youtube"];
                        var videoType = ["video"];
                        for (var i = 0; i < data.UsersUploads.length; i++) {
                            var up = data.UsersUploads[i];
                            var slHtml = '<div><div class="col-md-4 col-sm-6 col-xs-12" style="width:100%"><div class="' + cssMobile + '">';
                            if (imageType.indexOf(up.FileType.toLowerCase()) > -1) {
                                slHtml += '<a href="' + up.ProductUrl + '" alt="' + up.AltLabel + '">';
                                slHtml += '<div aria-label="' + up.AltLabel + '" style="background: url(' + up.Thumbnail + ') no-repeat center center; height: 396px; width: 100%; background-size: cover;"></div>';
                                slHtml += '</a>';
                            } else if (youtubeType.indexOf(up.FileType.toLowerCase()) > -1) {
                                slHtml += '<div style="height: 396px;" class="embed-responsive embed-responsive-16by9">';
                                slHtml += '<iframe class="embed-responsive-item" src="' + up.UploadUrl + '" height="234" frameborder="0" allowfullscreen></iframe>';
                                slHtml += '</div>';
                            } else if (videoType.indexOf(up.FileType.toLowerCase()) > -1) {
                                slHtml += '<div style="background-color:#000; text-align:center; height: 396px;" class="embed-responsive embed-responsive-16by9 ng-scope vid-wrapper">';
                                slHtml += '<video width="300" height="300" controls crossorigin="anonymous" title="" preload="auto">';
                                slHtml += '<source src="https://d13isgnnvtd7yz.cloudfront.net/' + up.FileName + '" type="video/mp4">';
                                slHtml += '<source src="https://d13isgnnvtd7yz.cloudfront.net/' + up.FileName + '" type="mpg">';
                                slHtml += '</video>';
                                slHtml += '</div>';
                            }
                            slHtml += '<div class="tester_image_desc text-capitalize padding-t20">' + escapeQuote(up.Firstname) + (up.SubUrb === '' || up.SubUrb === null ? "" : " (" + escapeQuote(up.SubUrb) + ")") + '</div>';
                            slHtml += '</div></div></div>';

                            $('.responsive-slider-gallery').slick('slickAdd', slHtml);
                        }
                    });
                }
            }
        });

        // media pop-up for image and video link and media pop-up for uploader name link
        $('#tester-gallery-slider .tester-gallery-box-link, #tester-gallery-slider .tester-box-reg-play-link, #tester-gallery-slider .tester-gallery-link').magnificPopup({
            tClose: _config.T_CloseEsc,
            tLoading: _config.T_Loading,
            type: 'ajax',
            gallery: {
                enabled: true
            },
            mainClass: 'my-mfp-zoom-in',
            removalDelay: 300,
            callbacks: {
                ajaxContentAdded: function ajaxContentAdded() {
                    // Ajax content is loaded and appended to DOM
                    setTimeout(function () {
                        App.fixCommentsUserImage('.media-responses');
                    }, 300);

                    $(".tooltips").tooltip({
                        trigger: "hover"
                    });
                    galleryId = $(this.st.el).data('gid');
                    history.pushState(null, null, _config.baseUrl + '?gallery=' + galleryId); // Update browser URL
                },
                close: function close() {
                    history.pushState(null, null, _config.baseUrl);
                }
            }
        });

        // Auto popup image/video if gallery ID is not empty
        if (typeof _config.galleryId !== 'undefined' && _config.galleryId !== '') {
            $.magnificPopup.open({
                tClose: _config.T_CloseEsc,
                tLoading: _config.T_Loading,
                items: {
                    src: '/au/en/Widget/_ShowUploadedMedia/' + _config.galleryId
                },
                type: 'ajax',
                gallery: {
                    enabled: true
                },
                mainClass: 'my-mfp-zoom-in',
                removalDelay: 300,
                callbacks: {
                    ajaxContentAdded: function ajaxContentAdded() {
                        // Ajax content is loaded and appended to DOM                   
                        setTimeout(function () {
                            App.fixCommentsUserImage('.media-responses');
                        }, 300);

                        $(".tooltips").tooltip({
                            trigger: "hover"
                        });

                        // open comment box if it was click before login
                        if (typeof _config.clickAction !== 'undefined') {
                            if (_config.clickAction === 'comment') {
                                // show comment box
                                $('.media-comment-box').toggle("slow", function () {
                                    $(this).find('textarea').focus();
                                });
                            }
                        }
                    },
                    close: function close() {
                        history.pushState(null, null, _config.baseUrl);
                    }
                }
            }, 0);
        }

        $(document).on('click', '.lnkAddMediaComment, .lnkMediaCommentCancel', function (e) {
            e.preventDefault();
            var $this = $(this);
            var uid = $this.data('uid');
            if (uid === 0) {
                return window.location = _config.loginUrl + '?returnurl=' + encodeURIComponent(_config.baseUrl + '?gallery=' + galleryId + '&act=comment' + '#testers-gallery');
            }

            $('.media-comment-box').toggle("slow", function () {
                console.log('focus');
                $(this).find('textarea').focus();
            });
        });

        $(document).on('click', '.lnkMediaCommentSubmit', function (e) {
            e.preventDefault();
            var $this = $(this);
            var commentBox = $this.closest('.media-comment-box');
            var textBox = commentBox.find('textarea[name=yourMediaComment]');
            var comment = textBox.val();
            var productId = $this.data('pid');
            var productId_sha1 = $this.data('pid-sha1');
            var uploadId = $this.data('uid');
            var uploadId_sha1 = $this.data('uid-sha1');

            if (comment === '') {
                // show error
                return;
            }

            App.loader.showLoader();
            var postData = {
                ProductId: productId,
                ProductId_sha1: productId_sha1,
                UploadId: uploadId,
                UploadId_sha1: uploadId_sha1,
                Comment: comment
            };
            var jqxhr = $.post(_config.addMediaCommentUrl, postData, function (data) {
                // success, hide edit form
                commentBox.hide();
                if (data.result > 0) {
                    // display response
                    var template = $('#templateMediaResponse');
                    template.find('.right > button').data('cid', data.result);
                    template.find('.right').append(comment);
                    commentBox.parent().next('.media-responses').prepend(template.html());
                    setTimeout(function () {
                        App.fixCommentsUserImage('.media-responses');
                    }, 300);
                } else if (data.error !== '') {
                    // show error
                    alert(data.error);
                }
            }).fail(function () {
                alert(_config.T_ErrorProcessingRequest);
            }).always(function () {
                App.loader.hideLoader();
            });
        });

        $(document).on('click', '.like-button-media', function (e) {
            var $this = $(this);
            var id = $this.data('id');
            var type = $this.data('type');
            var emo = $this.data('emo');
            var totalEmoji = $this.data('count');

            if (id === 0) return;

            var uid = $this.data('uid');
            if (uid === 0) {
                return window.location = _config.loginUrl + '?returnurl=' + encodeURIComponent(_config.baseUrl + '?gallery=' + galleryId + '#testers-gallery');
            }

            App.loader.showLoader();
            var postData = {
                id: id,
                theTable: _config.tableToVote,
                type: type
            };
            var jqxhr = $.post(_config.addEmojiCommentUrl, postData, function (data) {
                // success, remove response box         
                if (!data.hasError) {
                    totalEmoji = parseInt(totalEmoji || 0);
                    var $parent = $this.parents('.sharing:eq(0)');
                    if ($parent.find('.badge.total:not(.aggregate-reaction)').length === 0) $parent.find('.aggregate-reaction').append('<span class="badge total"></span>');

                    var newCount = parseInt($parent.find('.li-' + emo).data('count')) + 1;
                    $parent.find('.aggregate-reaction').removeClass('hide');
                    $parent.find('.li-' + emo).removeClass('hide').data('count', newCount);
                    $parent.find('.badge.total:not(.aggregate-reaction)').text(parseInt(totalEmoji) + 1);
                    $parent.find('.like-button-media > i').attr('data-original-title', data);
                    $parent.find('.like-button-media').off('click').removeClass('like-button-media');
                } else {
                    App.notify.Warning(data.message);
                }
            }).fail(function () {
                App.notify.Danger(_config.errorOnRequest);
            }).always(function () {
                App.loader.hideLoader();
            });
        });
    };

    var beforeReportMediaUpload = function beforeReportMediaUpload(el) {
        var uid = el.data('uid');
        if (uid === 0) {
            window.location = _config.loginUrl + '?returnurl=' + encodeURIComponent(_config.baseUrl + '?gallery=' + galleryId + '#testers-gallery');
            return false;
        }

        return true;
    };

    var reportMediaUpload = function reportMediaUpload(el) {
        // report upload       
        var id = el.data('id');
        if (id === 0) return;

        var uid = el.data('uid');
        if (uid === 0) {
            return window.location = _config.loginUrl + '?returnurl=' + encodeURIComponent(_config.baseUrl + '?gallery=' + galleryId + '#testers-gallery');
        }

        App.loader.showLoader();
        var jqxhr = $.post(_config.reportMediaUploadUrl + '/' + id, function (data) {
            // success, remove response box         
            if (data.result > 0) {
                App.notify.Success(_config.T_InAppropriateUploadReported);
            } else if (data.message !== '') {
                App.notify.Warning(data.message);
            }
        }).fail(function () {
            App.notify.Warning(_config.T_ErrorProcessingRequest);
        }).always(function () {
            App.loader.hideLoader();
            $.magnificPopup.close();
        });
    };

    var deleteMediaComment = function deleteMediaComment(el) {
        var cid = el.data('cid');
        if (cid === 0) return;

        App.loader.showLoader();
        var jqxhr = $.post(_config.removeMediaCommentUrl + '/' + cid, function (data) {
            // success, remove response box         
            if (data.result > 0) {
                var closeBtn = $('button[data-cid=' + cid + '][class=close]');
                var commentBox = closeBtn.closest('.media-child-comment-box');
                commentBox.animate({
                    height: 0
                }, 1000, function () {
                    commentBox.parent().parent().empty();
                });
            }
        }).fail(function () {
            alert(_config.T_ErrorProcessingRequest);
        }).always(function () {
            App.loader.hideLoader();
        });
    };

    return {
        init: init,
        reportMediaUpload: reportMediaUpload,
        beforeReportMediaUpload: beforeReportMediaUpload,
        deleteMediaComment: deleteMediaComment
    };
})();

App.Widget._DashProductTest = (function () {
    var _config = {};

    var init = function init(config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);
        }

        var sliderSettings = {
            minSlides: 1,
            maxSlides: 4,
            slideWidth: 270,
            slideMargin: 30,
            prevSelector: '#slider-tester-prev-big',
            prevText: '<i class="fa fa-angle-left" aria-hidden="true"></i>',
            nextSelector: '#slider-tester-next-big',
            nextText: '<i class="fa fa-angle-right" aria-hidden="true"></i>',
            onSliderLoad: function onSliderLoad() {
                $('.tester-gallery .bx-default-pager').hide();
                $('.tester-gallery-slider-control').appendTo('.tester-gallery .bx-wrapper');
            }
        };

        $('.tester-gallery .bxslider').bxSlider(sliderSettings);

        $('.tester-gallery').magnificPopup({
            delegate: 'a.tester-gallery-box-link, a.tester-box-reg-vid-link',
            type: 'image',
            closeOnContentClick: true,
            closeBtnInside: false,
            mainClass: 'mfp-with-zoom mfp-img-mobile',
            image: {
                verticalFit: true,
                titleSrc: function titleSrc(item) {
                    return item.el.attr('data-desc');
                }
            },
            zoom: {
                enabled: true
            },
            callbacks: {
                beforeOpen: function beforeOpen() {
                    // just a hack that adds mfp-anim class to markup
                    this.st.image.markup = this.st.image.markup.replace('mfp-figure', 'mfp-figure mfp-with-anim');
                    this.st.mainClass = this.st.el.attr('data-effect');
                },
                elementParse: function elementParse(item) {
                    if (item.el[0].className === 'tester-box-reg-vid-link' || item.src.indexOf('youtube.com') > -1) {
                        item.type = 'iframe';
                    } else {
                        item.type = 'image';
                    }
                }
            },
            gallery: {
                enabled: false
            }
        });
    };

    return {
        init: init
    };
})();

App.Widget._SimilarProducts = (function () {
    var _config = {
        'markets': '',
        'mobileSize': 400
    };

    var init = function init(config) {
        if (config && typeof config === 'object') {
            $.extend(true, _config, config);
        }

        // colorize stars based on product ratings
        $('.js-star-rating').makeStars();

        var bigSliderSetttings = {
            minSlides: 1,
            maxSlides: 4,
            slideWidth: 270,
            slideMargin: 30,
            nextSelector: '#similar-product-slider-next-big',
            nextText: '<i class="fa fa-angle-right" aria-hidden="true"></i>',
            onSliderLoad: function onSliderLoad() {
                $('.similar-product-mobile-next').hide();
                var $next = $('.similar-product-box-next');
                $next.appendTo('.similar-product-slider .bx-wrapper');
                $('.similar-product-slider .bx-default-pager').hide();
                if (this.getSlideCount() > 1) {
                    $next.show();
                } else {
                    $next.hide();
                }
            }
        };

        var mobileSliderSetttings = {
            minSlides: 1,
            maxSlides: 4,
            slideWidth: 270,
            slideMargin: 30,
            nextSelector: '#similar-product-slider-next-mobile',
            nextText: '<i class="fa fa-angle-right circle-blue" aria-hidden="true"></i>',
            infiniteLoop: false,
            onSliderLoad: function onSliderLoad() {
                var $pager = $('.similar-product-slider .bx-default-pager');
                var $nextMobile = $('.similar-product-mobile-next');
                $('.similar-product-box-next').hide();
                $nextMobile.appendTo('.similar-product-slider .bx-wrapper');
                if (this.getSlideCount() > 1) {
                    $pager.show();
                    $nextMobile.show();
                } else {
                    $pager.hide();
                    $nextMobile.hide();
                }
            }
        };

        $('.similar-box-hide-right-circle').show();
        $('.next-similar-product-box').show();
        var $nextProductReview = $('.similar-product-box-next');
        var $defaultPager = $('.similar-product-slider .bx-default-pager');
        var isSmallSlider = false;
        var isBigSlider = false;
        var loadWidth = $(window).width();
        var slider = null;
        if (loadWidth <= _config.mobileSize) {
            slider = $('.similar-product-bxslider').bxSlider(mobileSliderSetttings);
            isSmallSlider = true;
        } else {
            slider = $('.similar-product-bxslider').bxSlider(bigSliderSetttings);
            isBigSlider = true;
        }

        $('.similar-product-link-span').hover(function () {
            var $li = $(this).closest('li');
            if ($li.length === 0) $li = $(this).parent().parent();

            $li.find('.similar-product-box-upper').addClass('similar-product-box-upper-selected');
            $li.find('.product-box-circle').addClass('product-box-circle-selected');
        }, function () {
            var $li = $(this).closest('li');
            if ($li.length === 0) $li = $(this).parent().parent();

            $li.find('.similar-product-box-upper').removeClass('similar-product-box-upper-selected');
            $li.find('.product-box-circle').removeClass('product-box-circle-selected');
        });

        $(window).resize(function () {
            if (typeof slider.reloadSlider === 'undefined') return;

            var width = $(window).width();
            if (width <= _config.mobileSize) {
                if (!isSmallSlider) {
                    slider.reloadSlider(mobileSliderSetttings);
                    isSmallSlider = true;
                    isBigSlider = false;
                }
            } else {
                if (!isBigSlider) {
                    slider.reloadSlider(bigSliderSetttings);
                    isBigSlider = true;
                    isSmallSlider = false;
                }
            }
        });
    };

    return {
        init: init
    };
})();;
'use strict';

App.angular.service('activityService', ['$q', '$http', function ($q, $http) {
    var keys;
    var client;

    this.getActivities = function (userId, offset, limit) {

        // just concerned with get stream at the moment.
        if (this.keys["GetStream"]) {
            if (!client) {
                this.connect();
            }
            var feed = this.client.feed('timeline', userId);

            return feed.get({ limit: limit, offset: offset });
        }

        return {
            error: "no keys for GetStream provier"
        };
    };

    this.followUser = function (userId, followUserUri) {
        var deferred = $q.defer();
        $http.post(followUserUri, $.param({
            followedId: userId
        })).then(function (response) {
            deferred.resolve(response.data);
        })['catch'](function (response) {
            deferred.reject(response.data);
        });
        return deferred.promise;
    };

    this.unFollowUser = function (followedId, unFollowUserUri) {
        var deferred = $q.defer();
        $http.post(unFollowUserUri, $.param({
            followedId: followedId
        })).then(function (response) {
            deferred.resolve(response.data);
        })['catch'](function (response) {
            deferred.reject(response.data);
        });
        return deferred.promise;
    };

    this.blockUser = function (userId, blockUserUri) {
        var deferred = $q.defer();
        $http.post(blockUserUri, $.param({
            followerId: userId
        })).then(function (response) {
            deferred.resolve(response.data);
        })['catch'](function (response) {
            deferred.reject(response.data);
        });
        return deferred.promise;
    };

    this.unBlockUser = function (followerId, unBlockUserUri) {
        var deferred = $q.defer();
        $http.post(unBlockUserUri, $.param({
            followerId: followerId
        })).then(function (response) {
            deferred.resolve(response.data);
        })['catch'](function (response) {
            deferred.reject(response.data);
        });
        return deferred.promise;
    };

    this.markActivities = function (userId, groupid, isSeen, isRead) {

        var options = {};

        // just concerned with get stream at the moment.
        if (this.keys["GetStream"]) {
            if (!client) {
                this.connect();
            }
            var feed = this.client.feed('timeline', userId);

            if (isSeen) {
                options['mark_seen'] = [groupid];
            }

            if (isRead) {
                options['mark_read'] = [groupid];
            }

            var deferred = $q.defer();
            feed.get(options).then(function (data) {
                deferred.resolve(true);
            })['catch'](function (error) {
                console.log('Error trying to mark activities');
                console.log(error);
                deferred.reject(false);
            });

            return deferred.promise;
        }

        return {
            error: "no keys for GetStream provier"
        };
    };

    this.connect = function () {
        this.client = window.stream.connect(this.keys["GetStream"]["api.key"], this.keys["GetStream"]["user.token"], this.keys["GetStream"]["app.id"], { location: 'us-east' });
    };

    this.setProviderKeys = function (keys) {
        this.keys = keys;
    };
}]);

;
"use strict";

App.angular.service('searchService', ["$rootScope", "$anchorScroll", function ($rootScope, $anchorScroll) {
    var searchService = this;

    searchService.sortByEnum = {
        Latest: '0',
        MostReviewed: '1',
        HighestRated: '2',
        Trending: '3',
        Default: '4'
    };

    var AllFlag = 1;
    var FeaturedFlag = 2;
    var HomeTestedFlag = 4;

    // private fields
    var _searchString = '';
    var _brandString = '';
    var _filterTimer = null;
    var _all = true;
    var _featured = true;
    var _homeTested = true;
    var _sortBy = searchService.sortByEnum.Default;
    var _showCount = false;
    var _productsGrid = null;
    var _loadMoreProductsButton = null;
    var _page = 0;
    var _categories = null;
    var _crumbs = null;
    var _selectedFilter = null;
    var _selectedCategory = null;
    var _brandId = 0;
    var _productCount = 0;
    var _totalCount = 0;
    var _pageSize = 21;
    var _showResultText = false;
    var _reviewsRoot = window.location;
    var _isLoadingMore = false;
    var _isAllDataLoaded = true;

    $(function () {
        window.addEventListener('popstate', function (event) {
            restoreContentCallback(event.state);
        });
    });

    // public properties
    searchService.isAllDataLoaded = function (newIsAllDataLoaded) {
        return arguments.length > 0 ? _isAllDataLoaded = newIsAllDataLoaded : _isAllDataLoaded;
    };

    searchService.showResultText = function (newShowResultText) {
        return arguments.length > 0 ? _showResultText = newShowResultText : _showResultText;
    };

    searchService.selectedFilter = function (newSelectedFilter) {
        return arguments.length > 0 ? _selectedFilter = newSelectedFilter : _selectedFilter;
    };

    searchService.selectedCategory = function (newSelectedCategory) {
        return arguments.length > 0 ? _selectedCategory = newSelectedCategory : _selectedCategory;
    };

    searchService.crumbs = function (newCrumbs) {
        return arguments.length > 0 ? _crumbs = newCrumbs : _crumbs;
    };

    searchService.all = function (newAll) {
        return arguments.length > 0 ? _all = newAll : _all;
    };

    searchService.featured = function (newFeatured) {
        return arguments.length > 0 ? _featured = newFeatured : _featured;
    };

    searchService.homeTested = function (newHomeTested) {
        return arguments.length > 0 ? _homeTested = newHomeTested : _homeTested;
    };

    searchService.sortBy = function (newSortBy) {
        return arguments.length > 0 && newSortBy.toString().length > 0 ? _sortBy = newSortBy : _sortBy;
    };

    searchService.searchString = function (newSearchSting) {
        return arguments.length > 0 ? _searchString = newSearchSting : _searchString;
    };

    searchService.brandString = function (newBrandSting) {
        return arguments.length > 0 ? _brandString = newBrandSting : _brandString;
    };

    searchService.productsGrid = function (newProductsGrid) {
        return arguments.length > 0 ? _productsGrid = newProductsGrid : _productsGrid;
    };

    searchService.page = function (newPage) {
        return arguments.length > 0 ? _page = newPage : _page;
    };

    searchService.categories = function (newCategories) {
        return arguments.length > 0 ? _categories = newCategories : _categories;
    };

    searchService.parentCategories = function (newCategories) {
        var allCategories = searchService.categories();
        return _.filter(allCategories, function (x) {
            return x.parentId == 0;
        });
    };

    searchService.childCategories = function () {
        var selected = _.filter(searchService.parentCategories(), function (x) {
            return x.selected;
        });
        if (selected.length == 1 && selected[0].parentId == 0) return _.filter(searchService.categories(), function (x) {
            return x.parentId == selected[0].id;
        });

        return null;
    };

    searchService.grandChildCategories = function () {
        var parent = _.filter(searchService.categories(), function (x) {
            return x.selected;
        });
        if (parent && parent.length == 1 && parent[0].parentId > 0) {
            var pid = searchService.isLastChild() ? parent[0].parentId : parent[0].id;

            return _.filter(searchService.categories(), function (x) {
                return x.parentId == pid;
            });
        }

        return null;
    };

    searchService.isLastChild = function () {
        var parent = _.filter(searchService.categories(), function (x) {
            return x.selected;
        });
        if (parent && parent.length == 1 && parent[0].parentId > 0) return _.filter(searchService.categories(), function (x) {
            return x.parentId == parent[0].id;
        }).length == 0;

        return false;
    };

    searchService.loadMoreProductsButton = function (newLoadMoreProductsButton) {
        return arguments.length > 0 ? _loadMoreProductsButton = newLoadMoreProductsButton : _loadMoreProductsButton;
    };

    searchService.showCount = function (newShowCount) {
        return arguments.length > 0 ? _showCount = newShowCount : _showCount;
    };

    searchService.brandId = function (newBrandId) {
        return arguments.length > 0 ? _brandId = newBrandId : _brandId;
    };

    searchService.productCount = function (newProductCount) {
        return arguments.length > 0 ? _productCount = newProductCount : _productCount;
    };

    searchService.totalCount = function (newTotalCount) {
        return arguments.length > 0 ? _totalCount = newTotalCount : _totalCount;
    };

    searchService.pageSize = function (newPageSize) {
        return arguments.length > 0 ? _pageSize = newPageSize : _pageSize;
    };

    searchService.reviewRoot = function (reviewRoot) {
        return arguments.length > 0 ? _reviewsRoot = reviewRoot : _reviewsRoot;
    };

    // public methods
    searchService.resetSearchString = function () {
        searchService.searchString('');
    };

    searchService.hasSearchString = function () {
        return searchService.searchString() !== null && searchService.searchString().toString().length > 0;
    };

    searchService.startFilterTimer = function () {
        // Set a refresh timer
        setFilterTimer(setTimeout(function () {
            clearFilterTimer();
            refreshProductsGrid(true);
        }, 1250));
    };

    searchService.loadMoreProducts = function (storeHistory, clearGrid) {
        showSpinner(!!clearGrid ? clearGrid : false);
        var uri = '',
            hasCategoryGrid = false;
        var isBrandPage = searchService.brandString().length > 0;
        if (searchService.brandId() > 0) {
            uri = window._productgridajaxuri + '?page=' + _page + '&brandId=' + searchService.brandId() + '&sortby=' + searchService.sortBy();
        } else {
            var paramNoCat = '?page=' + _page + '&show=' + searchFilter() + '&sortby=' + searchService.sortBy();
            var queryParams = paramNoCat + '&cat=' + getSelectedCategories();

            var catIds = getSelectedCategories().split(',');
            var childList = _selectedCategory == null ? [] : _.filter(_categories, function (x) {
                return _selectedCategory.id == x.parentId;
            });

            ///au/en/reviews/index
            var pathName = _reviewsRoot;
            if (_selectedCategory != null && _selectedCategory.id != 0) {
                var actionIndex = _reviewsRoot.lastIndexOf("/");
                pathName = _reviewsRoot.substring(0, actionIndex) + '/' + _selectedCategory.urlName;
            }

            hasCategoryGrid = catIds.length > 1 && childList != null && childList.length > 0;
            uri = /*hasCategoryGrid ? window._productGridCategoryUri : */window._productgridajaxuri + queryParams;

            if (searchService.selectedCategory() != null) uri += '&lvl=' + searchService.selectedCategory().level;
        }

        _isLoadingMore = true;
        _isAllDataLoaded = false;
        $.get(uri, function (data) {
            appendProducts(data);
            _isAllDataLoaded = true;
            var cout = getProductCount(data);
            if (cout === 0) _loadMoreProductsButton.hide();
        }).always(function () {
            _isLoadingMore = false;
            hideSpinner();
            if (storeHistory === true && !isBrandPage) {
                history.pushState(createHistoryData(), 'Reviews', location.protocol + '//' + location.host + pathName);
            }
        });
    };

    searchService.isLoadingMore = function () {
        return _isLoadingMore;
    };

    searchService.resetLoadingMore = function () {
        _isLoadingMore = false;
        _isAllDataLoaded = false;
    };

    searchService.onFilterChanged = function () {
        searchService.all(searchService.selectedFilter() === '0' ? true : false);
        searchService.feature(searchService.selectedFilter() === '1' ? true : false);
        searchService.homeTested(searchService.selectedFilter() === '2' ? true : false);

        switch (searchService.selectedFilter()) {
            case '0':
                {
                    searchService.sortBy(searchService.sortByEnum.Latest);
                    searchService.all(true);
                    searchService.featured(false);
                    searchService.homeTested(false);
                    break;
                }
            case '1':
                {
                    searchService.sortBy(searchService.sortByEnum.Latest);
                    searchService.all(false);
                    searchService.featured(true);
                    searchService.homeTested(false);
                    break;
                }
            case '2':
                {
                    searchService.sortBy(searchService.sortByEnum.Latest);
                    searchService.all(false);
                    searchService.featured(false);
                    searchService.homeTested(true);
                    break;
                }
            case '3':
                {
                    searchService.sortBy(searchService.sortByEnum.Latest);
                    searchService.all(true);
                    searchService.feature(true);
                    searchService.homeTested(true);
                    break;
                }
            case '4':
                {
                    searchService.sortBy(searchService.sortByEnum.MostReviewed);
                    searchService.all(true);
                    searchService.feature(true);
                    searchService.homeTested(true);
                    break;
                }
            case '5':
                {
                    searchService.sortBy(searchService.sortByEnum.HighestRated);
                    searchService.all(true);
                    searchService.feature(true);
                    searchService.homeTested(true);
                    break;
                }
            case '6':
                {
                    searchService.sortBy(searchService.sortByEnum.Trending);
                    searchService.all(true);
                    searchService.feature(true);
                    searchService.homeTested(true);
                    break;
                }
        }
        searchService.recentlyAdded(searchService.selectedFilter() === '2' ? true : false);
        searchService.mostReviewed(searchService.selectedFilter() === '3' ? true : false);
        searchService.highestRated(searchService.selectedFilter() === '4' ? true : false);
        searchService.trending(searchService.selectedFilter() === '5' ? true : false);

        refreshProductsGrid(true);
    };

    searchService.searchForProducts = function (resetCategoriesAndTypes, storeHistory) {
        _showCount = false;
        if (searchService.hasSearchString()) {
            _isAllDataLoaded = false;
            showSpinner(resetCategoriesAndTypes);

            // HTCNEW-923
            if (resetCategoriesAndTypes === true) {
                // when the user types a search string and presses the enter key or "search" button
                // we need to reset the filters and categories to their default state
                searchService.selectAllCategoriesAndTypes();

                // set the sort order back to Latest (default)
                searchService.sortBy(searchService.sortByEnum.Latest);
            }

            var uri = '';
            if (searchService.brandId() > 0) {
                var queryParams = '?product=' + encodeURI(searchService.searchString()) + '&brandId=' + searchService.brandId() + '&sortby=' + searchService.sortBy();
                uri = window._searchuri + queryParams;
            } else {
                queryParams = '?product=' + encodeURI(searchService.searchString()) + '&page=' + _page + '&show=' + searchFilter() + '&sortby=' + searchService.sortBy() + '&cat=' + getSelectedCategories();
                uri = window._searchuri + queryParams;
            }

            $.get(uri, function (result) {
                _isAllDataLoaded = true;
                var currentItems = _page * 21;
                searchService.productCount(getProductCount(result) + currentItems);
                searchService.totalCount(getTotalCount(result));
                appendProducts(result);

                $(function () {
                    _showCount = true;
                    $rootScope.$apply();
                });
                $anchorScroll('product-reviews');
            }).always(function () {
                hideSpinner();
                if (storeHistory === true) {
                    history.pushState(createHistoryData(), 'Reviews', location.protocol + '//' + location.host + location.pathname + (!location.pathname.endsWith('/') ? '/' : '') + (location.pathname.toLowerCase().indexOf('/search') == -1 ? 'search' : '') + queryParams);
                }
            }).fail(function () {
                searchService.productCount(0);
            });

            //_loadMoreProductsButton.hide();
        } else {
                // if no search string is entered then just refresh the default products page
                searchService.resetProductsGrid();
            }
    };

    // resets the products grid to the original state when the page is
    // loaded which is all filters selected and no search string
    searchService.resetProductsGrid = function () {
        // even if we were drilled into a brand, this method take us back out
        // to the main reviews page
        searchService.brandId(0);
        searchService.resetSearchString();
        searchService.selectAllCategoriesAndTypes();
        searchService.sortBy(searchService.sortByEnum.Latest);
        searchService.showCount(false);
        _loadMoreProductsButton.show();
        refreshProductsGrid(true);
    };

    searchService.onCategoryChanged = function () {
        refreshProductsGrid(true);
    };

    searchService.setSelectedOnLoad = function () {
        var parentSelected = _.filter(searchService.parentCategories(), function (x) {
            return x.selected == true;
        });
        if (parentSelected.length > 0) return parentSelected;else if (_.filter(searchService.categories(), function (x) {
            return x.selected == true;
        }).length == 1) {
            return _.filter(searchService.categories(), function (x) {
                return x.selected == true;
            });
        } else {
            parentSelected = _.filter(searchService.categories(), function (x) {
                return x.selected == true;
            });
            var subParents = _.filter(parentSelected, function (x) {
                return _.filter(parentSelected, function (y) {
                    return y.id == x.parentId;
                }).length == 0;
            });
            if (subParents.length > 0) return subParents;
        }
        return [];
    };

    searchService.setSelected = function (item) {
        var categories = searchService.categories();
        categories.every(function (category) {
            category.selected = category.id == item.id;
            return true;
        });
    };

    searchService.selectAllCategoriesAndTypes = function () {

        // select all categories
        var categories = searchService.categories();
        categories.every(function (category) {
            category.selected = false;
            return true;
        });

        searchService.selectedCategory(null);
        searchService.crumbs([]);
        // select all of the product types
        searchService.all(true);
        searchService.featured(true);
        searchService.homeTested(true);
        searchService.page(0);
        searchService.loadMoreProductsButton().show();
    };

    // Private functions

    var clearFilterTimer = function () {
        // Clear any existing timers and start over
        if (_filterTimer !== null) {
            clearTimeout(_filterTimer);
        }
    };

    var setFilterTimer = function (newFilterTimer) {
        clearFilterTimer();
        _filterTimer = newFilterTimer;
    };

    // refreshes the products grid using both the checked filter
    // options and the search string if entered.
    var refreshProductsGrid = function (storeHistory) {
        // Close the mobile dropdown
        var dropDown = angular.element(".dropdown");
        if (undefined !== dropDown) {
            dropDown.toggleClass("open", false);
        }

        _showCount = false;
        searchService.productCount(0);
        searchService.page(0);
        _loadMoreProductsButton.show();

        if (searchService.hasSearchString()) {
            // we're refreshing our list based on an existing search string
            // do not reset the filters and catetories
            _productsGrid.empty();
            searchService.searchForProducts(false, storeHistory);
        } else {
            searchService.loadMoreProducts(storeHistory, true);
        }
    };

    function searchFilter() {
        var result = 0;

        if (_all) {
            // include all flag
            result |= AllFlag;
        }

        if (_homeTested) {
            // include home tested products
            result |= HomeTestedFlag;
        }

        if (_featured) {
            // include brand power spotlight
            result |= FeaturedFlag;
        }

        return result;
    }

    var showSpinner = function (clearProducts) {
        var isClearProducts = clearProducts === true;
        if (isClearProducts) _productsGrid.empty();

        $('.review-listing-container').append('<div class="inline-loader" style="min-height:' + (isClearProducts ? '500px' : '100%') + '"><div class="loaderD"></div></div>');
    };

    var hideSpinner = function () {
        if ($('.review-listing-container .inline-loader').length > 0) $('.review-listing-container .inline-loader').remove();
    };

    var getSelectedCategories = function () {
        // return if all is selected
        if (_categories.filter(function (c) {
            return c.selected === false;
        }).length == 0) return '';

        var selected = _categories.filter(function (c) {
            return c.selected === true;
        });
        if (selected == null || typeof selected[0] == 'undefined') return '';
        var ids = [];

        ids.push(selected[0].id);
        var children = _categories.filter(function (c) {
            return c.parentId == selected[0].id;
        });

        // if not last child
        if (children.length > 0) {
            ids = _.union(ids, children.map(function (x) {
                return x.id;
            }));
            for (var i in children) {
                var p = children[i];
                var grandChildren = _categories.filter(function (c) {
                    return c.parentId == p.id;
                });
                if (grandChildren.length > 0) ids = _.union(ids, grandChildren.map(function (x) {
                    return x.id;
                }));
            }
        }

        return ids.join(',');
    };

    var getProductCount = function (html) {
        var result = 0;
        if (html !== null && html.toString() !== '' && html.toString().length > 0) {
            var match = html.toString().match(/<div\sclass=([',"])prd-slider-item/g);
            if (match !== null && match.length > 0) {
                result = match.length;
            }
        }

        return result;
    };

    var getTotalCount = function (html) {
        var $div = $(html);
        var result = $div.find('#hdnTotalSearchCount').length > 0 ? parseInt($div.find('#hdnTotalSearchCount').val()) : 0;
        console.log('total', result);
        return result;
    };

    var appendProducts = function (data) {
        searchService.page(searchService.page() + 1);
        searchService.productsGrid().append($(data).html());

        // colorize stars based on product ratings
        $('.js-star-rating').makeStars();
    };

    var createHistoryData = function () {
        return {
            searchString: _searchString,
            all: _all,
            featured: _featured,
            homeTested: _homeTested,
            sortBy: _sortBy,
            showCount: _showCount,
            page: _page,
            categories: _categories,
            selectedFilter: _selectedFilter
        };
    };

    var restoreContentCallback = function (data) {
        searchService.searchString(data.searchString);
        searchService.all(data.all);
        searchService.featured(data.featured);
        searchService.homeTested(data.homeTested);
        searchService.sortBy(data.sortBy);
        searchService.showCount(data.showCount);
        searchService.page(data.page);
        searchService.categories(data.categories);
        searchService.selectedFilter(data.selectedFilter);

        refreshProductsGrid(false);
    };
}]);

;
