﻿/// <reference path="jquery-1.4.4.js" />

/* WebShop API */
var WebShopAPI = (function () {
    /// <summary>WebShop API</summary>

    /* Private */
    function _Init() {

        //set events - registration, set billing adress
        $("#RegisterUser").find(".BillingInfo .toggle input[type='checkbox'").click(function (event) {
            WebShopAPI.Registration.Toggle(event.target, "#RegisterUser .BillingInfo .toggleContainer", false);
        });
        //set events - registration, change password
        $("#RegisterUser").find(".UserInfo .toggle input[type='checkbox'").click(function (event) {
            WebShopAPI.Registration.Toggle(event.target, "#RegisterUser .UserInfo .toggleContainer", true);
        });

        //gogogo
        WebShopAPI.Status.Ready = true;

        //Init custom code
        WebShopAPI.SandnesGarn.Init();
        WebShopAPI.SandnesGarn.Forum.Init();
        WebShopAPI.SandnesGarn.Newsletter.Init();
        WebShopAPI.SandnesGarn.Search.Init();
    }

    /* Public */
    return {
        Status: null,
        Basket: null,
        Debug: null,
        Template: null,
        Registration: null,
        SandnesGarn: null,
        Init: function () {
            _Init();
        }
    }
})();

/*** STATUS    */
WebShopAPI.Status = {Ready:false};

/*** TEMPLATE    */
/// <summary>
/// Template functionality
/// </summary>
WebShopAPI.Template = (function() {

    /* Private */

    /// <summary>Builds HTML by using a modified John Resig's Microtemplating engine, then calls the callback function</summary>
    /// <param name="TemplatePath">Required Json property. Root relative path to template file.</param>
    /// <param name="TemplateData">Required Json property. son.</param>    
    /// <param name="SuccessHandler">Required Json property. Callback for success.</param>
    /// <param name="ErrorHandler">Required Json property. Callback for errors.</param>
    /// <returns>Template HTML</returns>
    function _GetMicroTemplate(Json) {

        // Validate input
        var Validation = WebShopAPI.Debug.TestProperties({ TestObject: Json, TestProperties: ["TemplatePath", "TemplateData", "SuccessHandler", "SuccessHandler", "ErrorHandler"] });

        if (Validation.Status == false) {
            WebShopAPI.Debug.DisplayError({ ErrorMessage: Validation.ErrorMessage, Caller: "_GetMicroTemplate" });
            return false;
        }
        
        //Gogo
        $.ajax({
            url: Json.TemplatePath,
            dataType: 'text',
            data: '',
            success: function(templateText) {
                var result = $(templateText).parseTemplate(data = Json.TemplateData);
                Json.SuccessHandler(result);
            },
            error: function(XMLHttpRequest, textStatus, errorThrown) {
                Json.ErrorHandler(XMLHttpRequest, textStatus, errorThrown);
            }
        });
    }

    /* Public */
    return {
        /// <summary>Builds a DOM node based on a template, then calls the callback function</summary>
        /// <param name="TemplatePath">Required Json property. Root relative path to template file.</param>
        /// <param name="TemplateData">JRequired Json property. son.</param>    
        /// <param name="SuccessHandler">Required Json property. Callback for success.</param>
        /// <param name="ErrorHandler">Required Json property. Callback for errrors.</param>
        /// <returns>Template HTML</returns>
        GetMicroTemplate: function(Json) {
            // Validate input
            var Validation = WebShopAPI.Debug.TestProperties({ TestObject: Json, TestProperties: ["TemplatePath", "TemplateData", "SuccessHandler", "SuccessHandler", "ErrorHandler"] });

            if (Validation.Status == false) {
                WebShopAPI.Debug.DisplayError({ ErrorMessage: Validation.ErrorMessage, Caller: "GetMicroTemplate" });
                return false;
            }

            //Gogo
            _GetMicroTemplate(Json);

        }
    }

})();

/*** DEBUG    */
WebShopAPI.Debug = (function() {
    /// <summary>
    /// Debug functionality
    /// </summary>

    /* Private */
    var _EnableDebug = true;

    /// <summary>Show error message from caller</summary>
    /// <param name="Json">Data transfer object.</param>
    /// <param name="ErrorMessage">Required Json property. Error message string.</param>
    /// <param name="Caller">Required Json property. Method or function that caused the error.</param>    
    function _DisplayError(Json) {    
        // Enabled?
        if (!_EnableDebug && !("ErrorMessage" in Json)) {
            return false;
        }

        var text = "Caller: " + Json.Caller + "\n" + "ErrorMessage: " + Json.ErrorMessage;

        //Gogo display
        alert(text);
    }
    
    /// <summary>Test if given property is inside given object.</summary>
    /// <param name="Json">Data transfer object.</param>
    /// <param name="TestObject">Required Json property. Error message string.</param>
    /// <param name="TestProperties">Required Json property. Array of strings (each one is the name of the property you want to test)..</param>
    /// <returns>{status:"True if all TestProperties are found, false if any are missing" , ErrorMessage:""}</returns>  
    function _TestProperties(Json) {  
        // Enabled?
        if (!_EnableDebug) {
            return false;
        }

        var Validation = {};
        var ErrorMessage = "";

        for (var i = 0, Arraylength = Json.TestProperties.length; Property = Json.TestProperties[i], i < Arraylength; i++) {
            if (!(Property in Json.TestObject)) {
                ErrorMessage += "Missing: " + Property + "\n";
            }
        }

        if (ErrorMessage.length > 0) {
            Validation.Status = false;
            Validation.ErrorMessage = ErrorMessage;
            return Validation;
        }
        else {
            Validation.Status = true;
            return Validation;
        }
    }

    /* Public */
    return {
        /// <summary>Show error message from caller</summary>
        /// <param name="Json">Data transfer object.</param>
        /// <param name="ErrorMessage">Required Json property. Error message string.</param>
        /// <param name="Caller">Required Json property. Method or function that caused the error.</param>
        /// <returns>Visible error message</returns>
        DisplayError: function(Json) {
            _DisplayError(Json);
        },
        /// <summary>Test if given property is inside given object.</summary>
        /// <param name="Json">Data transfer object.</param>
        /// <param name="TestObject">Required Json property. Error message string.</param>
        /// <param name="TestProperties">Required Json property. Array of strings (each one is the name of the property you want to test)..</param>
        /// <returns>{status:True if all TestProperties are found, false if any are missing , ErrorMessage: string}</returns>
        TestProperties: function(Json) {
            var Validation = _TestProperties(Json);
            return Validation;
        }
    }
})();


/*** Basket    */
/// <summary>
/// Basket methods and handeling.
/// </summary>
WebShopAPI.Basket = (function() {
    /* Private */
    var _BasketLink = { NodeId: "BasketLink", Quantity: ".quantity span", Total: ".sum .total" };

    /* Public */
    return {
        /// <summary>
        /// Post Basket
        /// </summary>
        Post: function() {
        },
        /// <summary>
        /// Collection of methods for adding to the Basket
        /// </summary>
        Put: (function() {
            /* Private */
            function _OnError(XMLHttpRequest, textstatus, errorThrown) {
                alert("WebShopAPI.Basket.OnError: " + textstatus);
            }

            function _OnSuccess(data, textstatus, XMLHttpRequest) {
                //alert("WebShopAPI.Basket.OnSuccess: " + textstatus);
                _UpdateBasketLink(data);
            }

            /// <summary>Update the quantity and total sum inside the basketlink.</summary>
            /// <param name="Json">Data transfer object. Basically the same json you get returned from calling </param>
            function _UpdateBasketLink(Json) {
                if (document.getElementById(_BasketLink.NodeId)) {
                    WebShopAPI.Basket.Get.Data(_UpdateHTML);
                }

                function _UpdateHTML(Json) {
                    var Quantity = $("#" + _BasketLink.NodeId).find(_BasketLink.Quantity).get(0);
                    var Total = $("#" + _BasketLink.NodeId).find(_BasketLink.Total).get(0);
                    $(Quantity).empty();
                    $(Quantity).text(Json.Items.length);
                    $(Total).empty();
                    $(Total).text(Json.TotalWithTax.DisplayValue);
                }
            }

            /* Public */

            return {
                /// <summary>Method for adding the given sku to the Basket.</summary>
                /// <param name="Json">Data transfer object.</param>
                /// <param name="SkuId">Required Json property</param>
                /// <param name="Quantity">Required Json property.</param>
                ThisSku: function(Json) {
                    //Validate input
                    var Validation = WebShopAPI.Debug.TestProperties({ TestObject: Json, TestProperties: ["SkuId", "Quantity"] });

                    if (Validation.Status == false) {
                        WebShopAPI.Debug.DisplayError({ ErrorMessage: Validation.ErrorMessage, Caller: "ThisSku" });
                        return false;
                    }

                    //Gogo
                    $.ajax({
                        type: "POST",
                        url: "/API/Cart/Sku/" + Json.SkuId + "/" + Json.Quantity + ".ashx",
                        dataType: "json",
                        data: "",
                        success: function(data, textstatus, XMLHttpRequest) {
                            _OnSuccess(data, textstatus, XMLHttpRequest);
                            if (Json.Callback) {
                                Json.Callback();
                            }
                        },
                        error: _OnError
                    });
                },
                /// <summary>Method for adding the first sku of the given product to the Basket.</summary>
                /// <param name="Json">Data transfer object.</param>
                /// <param name="ProductId">Required Json property.</param>
                /// <param name="Quantity">Required Json property.</param>
                FirstSku: function(Json) {
                    //Validate input
                    var Validation = WebShopAPI.Debug.TestProperties({ TestObject: Json, TestProperties: ["ProductId", "Quantity"] });

                    if (Validation.Status == false) {
                        WebShopAPI.Debug.DisplayError({ ErrorMessage: Validation.ErrorMessage, Caller: "FirstSku" });
                        return false;
                    }

                    //Gogo
                    $.ajax({
                        type: "POST",
                        url: "/API/Cart/AddProduct/" + Json.ProductId + "/" + Json.Quantity + ".ashx",
                        dataType: "json",
                        data: "",
                        success: _OnSuccess,
                        error: _OnError
                    });
                }
            }
        })(),
        Delete: null, /* Delete from the Basket */
        /// <summary>Collection of methods for getting stuff from the Basket.</summary>
        Get: (function() {
            /* Private */
            function _Data(callback) {
                $.ajax({
                    type: "GET",
                    url: "/API/Cart/Current.ashx",
                    dataType: "json",
                    success: callback,
                    error: function(XMLHttpRequest, textStatus, errorThrown) { WebShopAPI.Debug.DisplayError({ ErrorMessage: (textStatus + "\n" + errorThrown), Caller: "WebShopAPI.Basket.Get.Data" }) }
                });
            }

            /* Public */

            /// <summary>Gets current basket data and returns it to the callback function.</summary>
            /// <param name="callback">Function to callback the data.</param>
            return {
                Data: function(callback) {
                    _Data(callback);
                },
                BasketLink: function() {
                    return _BasketLink;
                }
            }
        })()
    }
})();



/*** REGISTRATION    */
/// <summary>
/// Collection of methods for handeling registration.
/// </summary>
WebShopAPI.Registration = (function() {
    /* Private */
function _Toggle(checkboxNode, cssTargetPath, showWhenStateIs) {
        if ($(checkboxNode).attr("checked") == showWhenStateIs) {
            $(cssTargetPath).show("fast");
        }
        else {
            $(cssTargetPath).hide("fast");
        }
    }


    /* Public */
    return {
        /// <summary>
        /// Toggles the display of password inputs based on the "change password" checkbox state.
        /// </summary>
        Toggle: function(checkboxNode, cssTargetPath, showWhenStateIs) {
            _Toggle(checkboxNode, cssTargetPath, showWhenStateIs);
        }
    }
})();




/*** SANDNES GARN    */
/// <summary>
/// All functions specific for Sandnes Garn.
/// </summary>
WebShopAPI.SandnesGarn = (function () {

    /* Private */
    var _cssFocusSku = "FocusSku"; //Css class used on the sku focus container
    var _busy = false;


    /// <summary>Method getting data from a "data" DOM node. Each "property" in this node is a <div></div> where the title attribute on each element acts as the property name, and the content is of the element is the data.</summary>
    /// <param name="Json">Data transfer object.</param>
    /// <param name="DataNode">Required Json property. The node containing data.</param>
    /// <returns>Json.</returns>
    function _getHTMLData(Json) {
        var NewJson = {};

        /* Validate input */
        var Validation = WebShopAPI.Debug.TestProperties({ TestObject: Json, TestProperties: ["DataNode"] });
        if (Validation.Status == false) {
            WebShopAPI.Debug.DisplayError({ ErrorMessage: Validation.ErrorMessage, Caller: "_getData" });
            return false;
        }

        //Validation ok, gogo
        $(Json.DataNode).find("div").each(function () {
            var currentNode = this;
            NewJson[$(currentNode).attr("title")] = $(currentNode).text();
        });

        return NewJson;
    }

    /// <summary>Purchase in Sandnes Garn. Keyword usage not implemented yet.</summary>  
    /// <param name="Json">Data transfer object.</param>
    /// <param name="EventNode">Required Json property. The DOM node where the event that called this method was fired.</param>
    /// <param name="KeyWord">Optional Json property. Keyword for action wanted.</param>  
    function _Purchase(Json) {
        var SkuFocusNode;
        var DataNode;
        var NewJson;

        //find the sku focus node
        SkuFocusNode = $(Json.EventNode).closest("." + _cssFocusSku).get(0);
        //find the data container
        DataNode = $(SkuFocusNode).find(".data").get(0);
        //Build new Json for Basket
        NewJson = _getHTMLData({ DataNode: DataNode });
        //Add quantity
        NewJson["Quantity"] = $(SkuFocusNode).find("input[name='Quantity']").val();
        //Add callback
        NewJson["Callback"] = WebShopAPI.SandnesGarn.DisplayMiniBasket;

        //Validate quantity, default it to 1 if none or 0.
        if (!parseInt(NewJson.Quantity) || String(NewJson.Quantity).length == 0) {
            NewJson.Quantity = 1;
        }


        //gogo to the basketmobile!
        WebShopAPI.Basket.Put.ThisSku(NewJson);
    }

    /// <summary>Generate or remove the minibasket. Basket will be shown for a set time before being removed.</summary>  
    //First check if we are busy getting data.
    //Then check if the miniBasket DOM node exist. If it does then remove it and exit. If it does not then generate a new one,
    //Callback chain: first get Basket data, pass the data to the template engine, and finally pass the complete Basket html to the display function.
    function _DisplayMiniBasket() {
        var _miniBasketId = "miniBasket";
        var _time = 3000; //ms

        if (_busy == false) {
            if (document.getElementById(_miniBasketId)) {
                _Remove();
            }
            else {
                _CreateBasket();
                _busy = true;
            }
        }

        //start of callback chain
        function _CreateBasket() {
            var ParentNode = $(".fwContent").get(0);
            var BasketNode = document.createElement("div");
            var LoaderNode = document.createElement("div");

            $(LoaderNode).addClass("loader");
            $(BasketNode).attr("id", _miniBasketId);
            $(BasketNode).append(LoaderNode);
            ParentNode.appendChild(BasketNode);

            WebShopAPI.Basket.Get.Data(_GetBasketTemplate);
        }

        function _GetBasketTemplate(data) {
            var TemplateInputs = {}; //Json input to the template engine
            var WrappedData = { Basket: data }; //Basket template really wants it like this..

            TemplateInputs.TemplatePath = "/ClientTemplates/miniBasket.aspx";
            TemplateInputs.TemplateData = WrappedData; //
            TemplateInputs.SuccessHandler = _Show;
            TemplateInputs.ErrorHandler = function (XMLHttpRequest, textStatus, errorThrown) { WebShopAPI.Debug.DisplayError({ ErrorMessage: (textStatus + "\n" + errorThrown), Caller: "_GetBasketTemplate" }) };

            WebShopAPI.Template.GetMicroTemplate(TemplateInputs);
        }

        function _Show(BasketHTML) {
            $("#" + _miniBasketId).find("*").remove();
            $("#" + _miniBasketId).html(BasketHTML);
            //add timer
            setTimeout(_DisplayMiniBasket, _time);

            _busy = false;
        }
        //end of callback chain

        function _Remove() {
            $("#" + _miniBasketId).remove();
        }
    }

    function _HookupMiniBasket() {
        var BasketLink = WebShopAPI.Basket.Get.BasketLink();
        $("#" + BasketLink.NodeId).mouseover(WebShopAPI.SandnesGarn.DisplayMiniBasket);
        $("#" + BasketLink.NodeId).mouseout(WebShopAPI.SandnesGarn.DisplayMiniBasket);
    }

    /// <summary>Method for setting a sku as focus.</summary>
    /// <param name="Json">Data transfer object.</param>
    /// <param name="EventNode">Required Json property. The DOM node where the event that called this method was fired.</param>
    function _SetSkuFocus(Json) {
        var cssSelected = "selected";
        var Sku = { Node: null, DataNode: null };
        var FocusSku = { Node: null, DataNode: null };

        //Validate input
        var Validation = WebShopAPI.Debug.TestProperties({ TestObject: Json, TestProperties: ["EventNode"] });
        if (Validation.Status == false) {
            WebShopAPI.Debug.DisplayError({ ErrorMessage: Validation.ErrorMessage, Caller: "_SetSkuFocus" });
            return false;
        }

        //find nodes
        Sku.Node = $(Json.EventNode).get(0);
        Sku.DataNode = $(Sku.Node).find(".data").get(0);
        FocusSku.Node = $(".ShopTemplates .FocusSku").get(0);
        FocusSku.DataNode = $(FocusSku.Node).find(".data").get(0);

        //set sku as selected, clear previous
        $(Sku.Node).siblings("." + cssSelected).removeClass(cssSelected);
        $(Sku.Node).addClass(cssSelected);

        //Start replacing values in skuFocus
        _CopySkuToFocus(FocusSku, Sku);
    }

    /// <summary>Method copying sku data into the focus container.</summary>
    /// <param name="Sku">{Node: sku DOM node, DataNode: DOM node inside sku node}.</param>
    /// <param name="FocusSku">{Node: focus DOM node, DataNode: DOM node inside focus node}.</param>
    function _CopySkuToFocus(FocusSku, Sku) {
        //Name field got quite a few extra info nuggets
        var nameText = $(Sku.Node).find(".name").text();
        if ($(Sku.DataNode).find("[title='color']").text().length > 0) {
            nameText += " " + $(Sku.DataNode).find("[title='color']").text();
        }
        if ($(Sku.DataNode).find("[title='ExtraInteger1']").text().length > 0) {
            nameText += " | " + $(Sku.DataNode).find("[title='ExtraInteger1']").text();
        }


        $(FocusSku.Node).find(".gfx img").attr("src", $(Sku.DataNode).find("[title='ImageMediumUrl']").text());
        $(FocusSku.Node).find(".gfx img").attr("alt", $(Sku.Node).find(".name").text());
        $(FocusSku.Node).find(".name").text(nameText);
        $(FocusSku.Node).find(".priceTag .price").text($(Sku.DataNode).find("[title='price']").text());
        $(FocusSku.Node).find(".priceTag .size").text($(Sku.DataNode).find("[title='size']").text());
        $(FocusSku.Node).find(".purchase input[name='Quantity']").val("1");
        $(FocusSku.DataNode).find("[title='ProductId']").text($(Sku.DataNode).find("[title='ProductId']").text());
        $(FocusSku.DataNode).find("[title='SkuId']").text($(Sku.DataNode).find("[title='SkuId']").text());
    }

    function _SkuSelector(Json) {
        var Sku = { Node: null, DataNode: null };
        var FocusSku = { Node: null, DataNode: null };
        var SkuId = $(Json.EventNode).find("option:selected").val();
        //Validate input
        var Validation = WebShopAPI.Debug.TestProperties({ TestObject: Json, TestProperties: ["EventNode"] });
        if (Validation.Status == false) {
            WebShopAPI.Debug.DisplayError({ ErrorMessage: Validation.ErrorMessage, Caller: "_SkuSelector" });
            return false;
        }

        //find nodes
        Sku.Node = $("#sku" + $(Json.EventNode).find("option:selected").val()).get(0);
        Sku.DataNode = $(Sku.Node).find(".data").get(0);
        FocusSku.Node = $(".ShopTemplates .FocusSku").get(0);
        FocusSku.DataNode = $(FocusSku.Node).find(".data").get(0);

        //Start replacing values in skuFocus
        _CopySkuToFocus(FocusSku, Sku);
    }

    function _PopImage(Json) {
        var PopNode = document.createElement("div");
        var BodyNode = document.createElement("div");
        var btnClose = document.createElement("div");
        var noHigherYPosThanThis; //The popup has to appear below this value.

        $(PopNode).addClass("PopImage");
        $(BodyNode).addClass("body");
        $(btnClose).addClass("btnClose");

        //Validate input
        var Validation = WebShopAPI.Debug.TestProperties({ TestObject: Json, TestProperties: ["ImageNode"] });
        if (Validation.Status == false) {
            WebShopAPI.Debug.DisplayError({ ErrorMessage: Validation.ErrorMessage, Caller: "_PopImage" });
            return false;
        }

        //Set y limit to match "ListTaggedSkus" container in right column
        noHigherYPosThanThis = $(".columnRight .ListTaggedSkus").offset().top;

        //remove any previous image pop, then append new
        $(".PopImage").remove();
        $(PopNode).append($(Json.ImageNode).clone());
        //change layout
        $(PopNode).find(".gfx img").attr("src", $(PopNode).find(".data [title='MediumUrl']").text());
        $(BodyNode).html($(PopNode).find(".data [title='Body']").html());
        $(PopNode).find(".content").append(BodyNode);
        $(PopNode).find(".image").append(btnClose);

        //show it, then calculate current y-offset and set position to absolute so that user can scroll image along with the page
        $("body").append(PopNode);
        var offset = $(PopNode).offset();
        if (offset.top < noHigherYPosThanThis) {
            offset.top = noHigherYPosThanThis;
        }
        $(PopNode).css("top", offset.top);
        $(PopNode).css("position", "absolute");
    }

    /// <summary>Takes a container node and expect to find an image element and a "data" node. Sorts then out instance id from this data node and change title image src.</summary>    
    function _SwapTitleImage(imgContainerNode) {
        var titleImageContainer = $(".columnCenter .TitleImage");
        var titleImage = $(titleImageContainer).find("img").get(0);
        var sourceImage = $(imgContainerNode).find("img").get(0);
        var dataNode = $(imgContainerNode).find(".data");
        var instanceId = $(dataNode).find("[title='MediumImageFileInstanceId']").text();
        var path = "/ShowFile.ashx?FileInstanceId=";

        //No title image, no instance id, no dollah
        if ($(titleImage).length < 1 && instanceId.length < 1) {
            return false;
        }

        //change image and alt text
        path += instanceId;
        $(titleImage).attr("alt", $(sourceImage).attr("alt"));
        $(titleImage).attr("src", path);
        //change caption
        $(titleImageContainer).find(".caption").text($(dataNode).find("[title='ImageCaption']").text());


    }

    function _PopInfo(linkNode) {
        var template = document.createElement("div");
        var infoUrl = $(linkNode).attr("href");
        var infoSelection = infoUrl + " p";

        $(template).load("/clienttemplates/templates.aspx .PopInfo", loadInfo);

        function loadInfo() {
            template = $(template).find(".PopInfo").get(0);
            $(template).find(".content").load(infoSelection, showInfo);
            $(template).find(".btnClose").click(function () {
                $(this).closest(".PopInfo").remove();
            });
        }

        function showInfo() {
            $("body").append(template);
        }
    }
    
    function _GoToImageArchiveItem(itemNode) {
        //find url to main image from link residing inside the item, and redirect to it
        document.location.href = $(itemNode).find("a").attr("href");
    }
    
    /* Public */
    return {
        /// <summary>Method for setting a sku as focus.</summary>
        /// <param name="Json">Data transfer object.</param>
        /// <param name="EventNode">Required Json property. The DOM node where the event that called this method was fired.</param>
        SkuSelector: function (Json) {
            if (!WebShopAPI.Status.Ready) {
                return false;
            }
            _SkuSelector(Json);

        },
        /// <summary>Method for setting a sku as focus.</summary>
        /// <param name="Json">Data transfer object.</param>
        /// <param name="EventNode">Required Json property. The DOM node where the event that called this method was fired.</param>
        SetSkuFocus: function (Json) {
            if (!WebShopAPI.Status.Ready) {
                return false;
            }
            _SetSkuFocus(Json);
        },
        /// <summary>Method for all purchase.</summary>
        /// <param name="Json">Data transfer object.</param>
        /// <param name="EventNode">Required Json property. The DOM node where the event that called this method was fired.</param>
        /// <param name="KeyWord">Optional Json property. Keyword for action wanted.</param>
        Purchase: function (Json) {
            if (!WebShopAPI.Status.Ready) {
                return false;
            }
            /* Validate input */
            var Validation = WebShopAPI.Debug.TestProperties({ TestObject: Json, TestProperties: ["EventNode"] });
            if (Validation.Status == false) {
                WebShopAPI.Debug.DisplayError({ ErrorMessage: Validation.ErrorMessage, Caller: "Purchase" });
                return false;
            }

            // Gogo
            _Purchase(Json)
        },
        /// <summary>Toggles the display of the minibasket. If no minibasket is present then one will be generated. If a minibasket is present then the DOM node will be deleted.</summary>
        DisplayMiniBasket: function () {
            if (!WebShopAPI.Status.Ready) {
                return false;
            }
            _DisplayMiniBasket();
        },
        /// <summary>Show large image based on data found in a product image container.</summary>
        /// <param name="Json">Data transfer object.</param>
        /// <param name="ImageNode">Required Json property. The container where data for the large image display can be found.</param>
        PopImage: function (Json) {
            _PopImage(Json);
        },

        PopInfo: function (linkNode) {
            _PopInfo(linkNode);
        },

        /// <summary>Init SG specific code and events.</summary>
        Init: function () {
            //set event - purchase from FocusSku
            $(".FocusSku .purchaseBtn").live("click", function () {
                var sku = this;
                WebShopAPI.SandnesGarn.Purchase({ EventNode: sku });
            });
            //set event - set sku to focus sku in center colum
            $(".columnCenter").find(".ListSkusWithImages .sku").live("click", function () {
                var sku = this;
                WebShopAPI.SandnesGarn.SetSkuFocus({ EventNode: sku });
            });
            //set event - tagged skus
            $(".columnRight").find(".ListTaggedSkus .sku").live("click", function () {
                var sku = this;
                var url = "/ProductPage.aspx?ProductId=" + $(sku).find(".data").find("[title='ProductId']").text();
                document.location.href = url;
            });
            //set event - click on related images
            $(".RelatedContent").find(".images li").live("click", function () {
                var imgContainerNode = this;
                _SwapTitleImage(imgContainerNode);
            });
            //set event - click on product images
            $(".ListProductImages").find(".image").live("click", function () {
                var imgContainerNode = this;
                WebShopAPI.SandnesGarn.PopImage({ ImageNode: imgContainerNode })
            });
            //set event - click on popInfo links
            $(".popInfo").live("click", function (event) {
                var link = this;
                event.preventDefault();
                WebShopAPI.SandnesGarn.PopInfo(link);
            });
            //set event - skuselector onChange
            $(".SkuSelector select").live("change", function () {
                var eventNode = this;
                WebShopAPI.SandnesGarn.SkuSelector({ EventNode: eventNode });
            });
            //set event - click on image archive item
            $("#ImageArchive .ListImages .image").live("click", function () {
                var itemNode = this;
                _GoToImageArchiveItem(itemNode);
            });
            //set event - click on image archive item
            $(".PopImage .image").live("click", function () {
                $(this).closest(".PopImage").remove();
            });
            //Clear frontpage login on focus
            $("#frontpage_login [type='text'], #frontpage_login [type='password']").live("focus", function () {
                var input = this;
                input.value = "";
            });
            //set event - find stuff in webshop search result
            //Unfortunately to slow to be of any use yet...
            /*
            $("#SearchWebShop .fwSearchInput .input input").live("keyup", function (event) {
            var text = $(this).val();
            _SearchWebShop(text);
            return false;
            });
            */
        }
    }
})();
/*** SANDNES GARN: Forum    */
/// <summary>
/// All functions specific for Sandnes Garn forum.
/// </summary>
WebShopAPI.SandnesGarn.Forum = (function () {
    //*** PRIVATE
    var config = {};
    config.ForumId = "Forum";
    config.ShowPostsclass = "showPosts";
    config.NewPostClass = "NewPost";
    config.NewPostInputsClass = "input";
    config.ListPostsClass = "ListPosts";
    config.TemplatesClass = "templates";
    config.TemplatePostClass = "Post";
    config.ButtonsClass = "btn";
    config.ButtonHighlightClass = "btnHigh";
    config.ButtonAddPostClass = "btnAddPost";
    config.ButtonAddThreadClass = "btnAddThread";

    function InsertPost(postData) {
        var newPost = GetPostTemplate();
        var showPosts = $("." + config.ShowPostsclass);

        if ($(newPost).lenght == 0) {
            return;
        }
        //hide inputs
        HideInputs();

        //insert data
        $(newPost).find(".postName").text($(postData).find("[title='postName']").text());
        $(newPost).find(".postUsername").text($(postData).find("[title='postUsername']").text());
        $(newPost).find(".postDate").text($(postData).find("[title='postDate']").text());
        $(newPost).find(".postTime").text($(postData).find("[title='postTime']").text());
        $(newPost).find(".postText").text($(postData).find("[title='postText']").text());

        //clear out old content, show new post
        $(showPosts).empty();
        $(showPosts).append(newPost);

    }

    function GetPostTemplate() {
        return $("#" + config.ForumId + " ." + config.TemplatesClass + " ." + config.TemplatePostClass).clone(false).get(0);
    }

    function ResetInputs() {
        $("#" + config.ForumId + " ." + config.NewPostInputsClass).find(':input').not(':button, :submit, :reset').val('');
    }

    function ShowInputs() {
        $("#" + config.ForumId + " ." + config.NewPostInputsClass).show();
    }

    function HideInputs() {
        ResetButtons();
        $("#" + config.ForumId + " ." + config.NewPostInputsClass).hide();
    }

    function ResetButtons() {
        $("#" + config.ForumId + " ." + config.ButtonsClass).removeClass(config.ButtonHighlightClass);
    }

    function SetOriginalThreadId() {
        $("#" + config.ForumId + " ." + config.NewPostInputsClass + " input[name='threadId']").val($("#" + config.ForumId + " ." + config.NewPostInputsClass + " .data").find("[title='threadId']").text());
    }

    function GoNewPost() {
        var buttonNewPost = $("#" + config.ForumId + " ." + config.ButtonAddPostClass);

        //If this button allready was active then do a toggle and exit function
        if ($(buttonNewPost).hasClass(config.ButtonHighlightClass)) {
            ResetButtons();
            HideInputs();
            return;
        }

        ResetButtons();
        SetOriginalThreadId();

        //set current button
        $(buttonNewPost).addClass(config.ButtonHighlightClass);
        ShowInputs();
    }

    function GoNewThread() {
        var buttonNewThread = $("#" + config.ForumId + " ." + config.ButtonAddThreadClass);

        //If this button allready was active then do a toggle and exit function
        if ($(buttonNewThread).hasClass(config.ButtonHighlightClass)) {
            ResetButtons(); 
            SetOriginalThreadId();
            HideInputs();
            return;
        }

        //clear active buttons and inputs
        ResetButtons();
        ResetInputs();
        //set current button
        $(buttonNewThread).addClass(config.ButtonHighlightClass);
        ShowInputs();
    }

    function ShowFirstPost() {
        var postData = $("#" + config.ForumId + " ." + config.ListPostsClass + " li:first").find(".data").get(0);
        InsertPost(postData);
    }

    //Events
    function SetAllEvents() {
        //Click - ListPosts item
        $("#" + config.ForumId + " ." + config.ListPostsClass + " li").live("click", function () {
            var itemNode = this;
            WebShopAPI.SandnesGarn.Forum.ShowPost(itemNode);
        });
        //Click - Add post
        $("#" + config.ForumId + " ." + config.ButtonAddPostClass).live("click", function () {
            WebShopAPI.SandnesGarn.Forum.AddPost();
        });
        //Click - Add thread
        $("#" + config.ForumId + " ." + config.ButtonAddThreadClass).live("click", function () {
            WebShopAPI.SandnesGarn.Forum.AddThread();
        });
    }


    //*** PUBLIC
    return {
        Init: function () {
            SetAllEvents();
            ShowFirstPost()
        },
        ShowPost: function (postItemNode) {
            var dataNode = $(postItemNode).find(".data").get(0);
            InsertPost(dataNode);
        },
        AddPost: function () {
            GoNewPost();
        },
        AddThread: function () {
            GoNewThread();
        }
    }
})();
/*** SANDNES GARN: newsletter    */
/// <summary>
/// Newsletter functionality.
/// </summary>
WebShopAPI.SandnesGarn.Newsletter = (function () {
    //*** PRIVATE
    var config = {};
    config.domId = "NewsletterPop";
    config.btnClose = "btnClose";
    config.btnToggle = "btnNewsletter";
    config.Timer = 5000; //milliseconds

    function SetAllEvents() {
        //popup close button - click
        $("#" + config.domId + " [name='" + config.btnClose + "']").live("click", function (event) {
            Close();
            event.preventDefault();
        });
        //toggle button - click
        $("#" + config.btnToggle).live("click", function () {
            Open();
        });

    }

    function Open() {
        $("#" + config.domId).show();
    }

    function Close() {
        $("#" + config.domId).hide();
    }

    function CloseByTimeout() {
        setTimeout(Close, config.Timer);
    }

    function CloseOrShow() {
        var $Pop = $("#" + config.domId);
        var $UserInput = $Pop.find(".userInput");
        var $btnSubmit = $Pop.find(".toolbar [type='submit']");
        var status = $Pop.find(".data > [title='status']").text();

        switch (status) {
            case "inprogress":
                Open();
                break;

            case "complete":
                Open();
                $UserInput.hide();
                $btnSubmit.hide();
                CloseByTimeout();
                break;

            default:
                Close();
                break;
        }
    }

    //*** PUBLIC
    return {
        Open: function () {
            Open();
        },
        Close: function () {
            Close();
        },
        Init: function () {
            SetAllEvents();
            CloseOrShow();
        }
    }
})();
/*** SANDNES GARN: search    */
/// <summary>
/// All search functionality.
/// </summary>
WebShopAPI.SandnesGarn.Search = (function () {
    //*** PUBLIC
    function SetAllEvents() {
        //Find stuff in org table
        $("#SearchOrg .fwSearchInput .input input").live("keyup", function (event) {
            var text = $(this).val();
            SearchOrg(text);
            return false;
        });

        //Clear input on focus
        $(".fwSearchInput [type='text']").live("focus", function () {
            var input = this;
            ClearSearchInput(input);
        });
    }

    function ClearSearchInput(input) {
        input.value = "";
    }

    function SearchWebShop(text) {
        ///<summary>Unfortunately to slow to be aof any use yet. Custom func for searching a resultset from the SearchWebShop page.</summary> 
        var jqResults = $("#SearchWebShop .results ul");
        var searchTextCache;

        if (text.length < 1) {
            //show all rows
            jqResults.find("li").show();
            HitSpam();
            return;
        }

        if (text.length < 2) {
            return;
        }


        //cache all searchable text and tranform it to uppercase for easier comparison
        var searchInput = text.toUpperCase();

        var cache = [];
        jqResults.find("li").each(function () {
            var node = this;
            var text = $(node).hide().find(".description").text().toUpperCase();
            cache.push({ text: text, node: node });
        });

        for (var i = 0; i < cache.length; i++) {
            if (cache[i].text.indexOf(searchInput) !== -1) {
                $(cache[i].node).show();
            }
        }

        //finally update hit counter
        HitSpam();

        function HitSpam() {
            //Hit spam
            $("#SearchWebShop .totalNrOfHits").text(jqResults.find("li:visible").length);
            $("#SearchWebShop .query").text(text);
        }
    }

    function SearchOrg(text) {
        ///<summary>Custom func for searching a resultset from the SearchOrg page</summary> 
        var table = $("#SearchOrgResults").get(0);

        if (text.length < 1) {
            //show all rows
            $(table).find("tr").show();
            HitSpam();
            return;
        }

        if (text.length < 2) {
            return;
        }

        //hide all rows
        $(table).find("tr").hide();

        //cache all searchable text
        var searchInput = text.toUpperCase();
        var rows = {};
        $(table).find("tr").each(function (i) {
            rows[$(this).text().toUpperCase()] = i;
        });

        //search and show rows with hits
        for (var row in rows) {
            if (row.indexOf(searchInput) !== -1) {
                $(table).find("tr:eq(" + rows[row] + ")").show();
            }
        }

        //finally update hit counter
        HitSpam();

        function HitSpam() {
            //Hit spam
            $("#SearchOrg .totalNrOfHits").text($(table).find("tr:visible").length);
            $("#SearchOrg .query").text(text);
        }
    }


    //*** PRIVATE
    return {
        Init: function () {
            SetAllEvents();
        }
    }
})();
