﻿var commerce = commerce || {};
(function() {
    // ..create the product functionality base prototypes..
    commerce.product = commerce.product || {};
    commerce.product._data = commerce.product._data || {};

    commerce.ui = commerce.ui || {};

    var VariantClicked;

    // File location constants
    var IconsDirectory = '/assets/en/site/icons/';
    var MissingColourSwatch = IconsDirectory + 'missing-colour.gif';
    var MissingSelColourSwatch = IconsDirectory + 'missing-colour-S.gif';
    var SwatchColourImageFormat = IconsDirectory + '{0}.gif';


    function HtmlDecode(text) {
        return $('<div/>').html(text).text();
    };


    // reset the mouse cursor from progress/waiting
    function resetMouse(){
        $("*").css("cursor", "auto");
        $('a').css('cursor','pointer');
        $('button').css('cursor','pointer');
        $('img').css('cursor','pointer');
        $('#FabricSwatchImg').css("cursor", "auto");
        $('#AddedImg').css("cursor", "auto");
        //$('.jqzoom img').css('cursor', 'crosshair');
        if ($('.product-details-img a.jqzoom img').attr('src').search(/no_image/) != -1) {
            $('.jqzoom img').css('cursor', 'auto');
        }
        if ($('.product-details-img a.jqzoom').attr('href') == '') {
            $('.jqzoom img').css('cursor', 'auto');
        }
    };

    /*
    ** e-commerce product comparison functionality.
    **
    ** Calls .asmx web services to interact with the
    ** current context, basket and comparison lists.
    */
    if (typeof commerce._callws !== 'function') {
        commerce._callws = function(options) {
            var fn_wsok = function(data, status) {
                // ..convert from Microsoft.NET json format,
                // which serializes into a "d" field to
                // prevent cross-site scripting..
                if (typeof data == 'object' && data != null && typeof data.d != 'undefined')
                {
                try{
                    data = eval(data.d);
                    }
                    catch (err)
                    {
                    //alert(err);
                    }
                    }
                if (typeof options.success == 'function' && data.status == 200)
                    options.success(data, status);
                else if (typeof options.error == 'function')
                    options.error(data, status);
                return false;
            };
            var fn_wserr = function(data, status) {
                if (typeof data == 'object' && data != null && typeof data.d != 'undefined')
                    data = eval(data.d);
                if (typeof options.error == 'function')
                    options.error(data, status);
                return false;
            };
            var data = $.extend({ success: fn_wsok, error: fn_wserr }, options);
            if (data.success != fn_wsok) data.success = fn_wsok;
            if (data.error != fn_wserr) data.error = fn_wserr;
            $.ajax(data);
        };
    }

    if (typeof commerce.product._fetch !== 'function') {
        commerce.product._fetch = function(id, options) {
            var item = null;
            options = $.extend({ async: true, success: function(data, status) { commerce.product._data['$' + data.id] = (item = data); } }, options);
            commerce._callws($.extend({ url: '/SiteWebServices/products.asmx/Get', type: 'POST', contentType: 'application/json; charset=utf-8', dataType: 'json', data: JSON.stringify({ key: id }) }, options));
            return false;
        };
    }

    if (typeof commerce.product.consider !== 'function') {
        commerce.product.consider = function(id, options) {
            commerce._callws($.extend({ url: '/SiteWebServices/products.asmx/Consider', type: 'POST', contentType: 'application/json; charset=utf-8', dataType: 'json', data: JSON.stringify({ key: id }) }, options));
            return false;
        };
    }

    if (typeof commerce.product.disregard !== 'function') {
        commerce.product.disregard = function(id, options) {
            var k = JSON.stringify((id = id || '') === '' ? {} : { key: id });
            commerce._callws($.extend({ url: id === '' ? '/SiteWebServices/products.asmx/DisregardAll' : '/services/products.asmx/Disregard', type: 'POST', contentType: 'application/json; charset=utf-8', dataType: 'json', data: k }, options));
            return false;
        };
    }

    if (typeof commerce.ui.new_comparison_line !== 'function') {
        commerce.ui.new_comparison_line = function(result) {
            if (typeof result == "undefined")
                return '';

            var li = $(document.createElement('li')).addClass('product').css('display', 'none');
            var a_name = $(document.createElement('a')).html('<span class="title">' + result.name + '</span>').attr({ href: result.url, title: result.name });
            var thumbn = $(document.createElement('img')).attr({ src: '/assets/en/catalogue/XSmall/' + result.id + '.jpg', title: result.name }).css('vertical-align', 'middle');

            var a_butn = $(document.createElement('a')).html('<img src="/assets/en/site/buttons/comparison-remove.png" />').addClass('remove').attr({ href: '#?disregard=' + result.id }).css({ cursor: 'pointer' }).click(function() {
                commerce.product.disregard(result.id, { success: function() { li.slideUp('fast'); } });
            });
            li.append(a_name).append(a_butn);
            a_name.prepend(thumbn);
            li.fadeIn('slow');
            return li;
        };
    }

    if (typeof commerce.ui.new_comparison_list !== 'function') {
        commerce.ui.new_comparison_list = function(results, status) {
            $('#product-comparison .product-list').empty();
            switch (results.status) {
                case 200: // OK
                    if (results.data.length === 0) {
                        var span = $(document.createElement('span')).addClass('message');
                        $('#product-comparison .product-list').append(span);
                        span.text('You currently have no products for comparison');
                        return;
                    }

                    for (var index = 0; index < results.data.length; index++) {
                        var element = commerce.ui.new_comparison_line(results.data[index]);
                        $('#product-comparison ul.product-list').append(element);
                    }
                    break;

                case 404: // Product not found
                    var span = $(document.createElement('span')).addClass('message');
                    $('#product-comparison .product-list').append(span);
                    span.text('The product you requested could not be found!');
                    break;

                case 409: // Product definition not apporopriate
                    var span = $(document.createElement('span')).addClass('message');
                    $('#product-comparison .product-list').append(span);
                    span.text('The product you requested is not of type "' + results.message + '"; only products of the same type can be compared.');
                    break;

                default: // General error
                    var span = $(document.createElement('span')).addClass('message');
                    $('#product-comparison .product-list').append(span);
                    span.text("We don't seem to be able to to add the product for comparison; sorry about that.");
                    break;
            }
        };
    }


    /*
    ** e-commerce product variant styles functionality.
    **
    ** Calls .asmx web services to interact with the
    ** current context, basket and comparison lists.
    */
    if (typeof commerce.product.find !== 'function') {
        commerce.product.find = function(id, attrs) {
            var item = commerce.product._data['$' + id] || commerce.product._fetch(id);
            if (item == null) return null;
            if (arguments.length == 1)
                return item;
            if (attrs == null || attrs.length === 0)
                return null;
            for (var v = 0, m = 0; v < item.variants.length; v++, m = 0) {
                for (var n = 0; n < attrs.length; n++) {
                    if (typeof item.variants[v][attrs[n].key] === 'undefined')
                        continue;
                    var a = (attrs[n].value || '').toLowerCase();
                    var b = (item.variants[v][attrs[n].key].id || '').toLowerCase();
                    if (a == b) m++;
                }
                if (m === attrs.length) return item.variants[v];
            }
            return null;
        };
    }

    if (typeof commerce.product.place !== 'function') {
        commerce.product.place = function(p, v, c, options, bcnt) {
            var fn = function(data, status) {
                
                $('.BackInStock').html('');  // clear back in stock overlay error

                var msg = 'Unable to add product to basket; system failure.';

                if (status == 'success') {
                    var json = eval('(' + data + ')');

                    // get the cid and vid passed back
                    if (typeof json.products != 'undefined' && json.products.length != 0) {
                        if (c == null || c== 'undefined' || c == '') {
                            c = json.products[0].cid;
                        }
                        variant_id = json.products[0].vid;
                    }

                    if (typeof json.products != 'undefined' && json.products.length != 0) {
                        
                        msg = (json.products[0].addToBasket ? 'Item successfully added to basket' : (json.products[0].reason || 'unknown error'));
                        // added to basket ok - rebuild minibasket and update omniture
                        if (json.products[0].addToBasket == "true" || json.products[0].addToBasket == true) {

                            // update the added basket section and show it
                            $('#AddedQty').text(json.products[0].qty);
                            $('#AddedPrice').text('');
                            if (json.products[0].Price != null && json.products[0].Price != 'undefined' && json.products[0].Price != '') {
                                $('#AddedPrice').text(HtmlDecode(json.products[0].Price));
                            }
                            $('#AddedImg').attr('src','');
                            if (json.products[0].ImageUrl != null && json.products[0].ImageUrl != 'undefined' && json.products[0].ImageUrl != '') {
                                $('#AddedImg').attr('src', HtmlDecode(json.products[0].ImageUrl));
                            }
                            $('#AddedVariantSection').css('display','none');
                            if (json.products[0].AddedVariant != null && json.products[0].AddedVariant != 'undefined' && json.products[0].AddedVariant != '' && (json.products[0].AddedVariant == true || json.products[0].AddedVariant == "true")) {
                                $('#AddedVariantSection').css('display','block');
                            }
                            $('#AddedSwatchImg').attr('src', MissingColourSwatch);
                            if (json.products[0].SwatchImg != null && json.products[0].SwatchImg != 'undefined' && json.products[0].SwatchImg != '') {
                                var imgsrc = HtmlDecode(json.products[0].SwatchImg);
                                // check the colour icon exists
                                $.ajax({
                                    url: imgsrc,
                                    type: 'HEAD',
                                    error:
                                    function () {
                                        $('#AddedSwatchImg').attr('src', MissingColourSwatch);
                                    },
                                    success:
                                    function () {
                                        $('#AddedSwatchImg').attr('src', imgsrc);
                                    }
                                });
                            }
                            var colourCaption = $('#hdnColourCaption').val();
                            $('#AddedSwatchText').text('');
                            if (json.products[0].SwatchText != null && json.products[0].SwatchText != 'undefined' && json.products[0].SwatchText != '') {
                                $('#AddedSwatchText').text(colourCaption + HtmlDecode(json.products[0].SwatchText));
                            }
                            // show it
                            $('#item-added-basket').fadeIn('fast');

                            // update mini basket
                            if (json.products[0].minibaskethtml != null && json.products[0].minibaskethtml != 'undefined' && json.products[0].minibaskethtml != '') {
                                $("#mini-basket-main").html(HtmlDecode(json.products[0].minibaskethtml));
                            }
                            var arrow = $('a.basket-nav-summary-link');
                            arrow.attr('title', arrow.attr('tooltipExpand'));
                            
                            if (typeof Omniture != 'undefined') {
                                if (v != null && v != '') {
                                    Omniture.SubmitAddToBasketSingle(p, v, c, options.quantity, bcnt);
                                }
                                else {
                                    Omniture.SubmitAddToBasketSingle(p, p, c, options.quantity, bcnt);
                                }
                            }

                            // show the checkout link in the summary header
                            $('#basket-nav-checkout-li').html($('#hidden-basket-nav-checkout-li').html());
                            $('#basket-nav-basket-li').attr('class','');
                            //update the basket summary in header
                            var basketTitle = $('.hdnBasketTitleCaption').val();
                            // strip out items and total
                            var itemsText = "";
                            var totalText = "";
                            if (json !== null && json.message != null && json.message != '' && json.message != 'undefined') {
                                var splitIndex = json.message.indexOf(",");
                                if (splitIndex > 0) {
                                    itemsText = json.message.substring(0, splitIndex);
                                }
                                else {
                                    itemsText = json.message;
                                }
                                totalText = HtmlDecode(json.total);
                            }

                            $('a#basket-nav-summary').html('<span>' + basketTitle + '</span> ' + itemsText);
                            var totalSection = $('[id$="basket-nav-summary2"]');
                            if (totalSection != null && totalSection != 'undefined' && totalSection != '' && totalSection.html() != null && totalSection.html() != 'undefined' && totalSection.html() != '') {
                                $('[id$="basket-nav-summary2"]').html(totalText);
                            }
                            else {
                                $('[id$="basket-nav-summary2"]').html(totalText);
                            }

                            rebindBasketNavClicks();

                            // show backordered overlay?
                            if (json.products[0].backordered != null && json.products[0].backordered != 'undefined' && json.products[0].backordered != '' && json.products[0].backordered == "true") {
                                $('.tool-tip-wrap.backordered-stock-info').fadeIn(300);
                                // set the positioning correctly
                                $('.tool-tip-wrap.backordered-stock-info').css('top',$('.prodaddtobasket').position().top - ($('.backordered-stock-info').height() / 2) + ($('.prodaddtobasket').height() / 2));
                                $('.tool-tip-wrap.backordered-stock-info').css('width',301);
                                $('.tool-tip-wrap.backordered-stock-info').css('left', 20 - $('.prodaddtobasket').position().left);
                            }

                            // reset mouse cursor
                            resetMouse();
                            return false;
                        }
                    } else if (typeof json.message != 'undefined') {
                        msg = json.message;
                    }

                }


                // handle error/out of stock
                if (msg == 'out of stock')
                {
                    $('.tool-tip-wrap.outof-stock-info').fadeIn(300);
                    // set the positioning correctly
                    $('.tool-tip-wrap.outof-stock-info').css('top',$('.prodaddtobasket').position().top - $('.prodaddtobasket').height());
                    $('.tool-tip-wrap.outof-stock-info').css('width',301);
                    $('.tool-tip-wrap.outof-stock-info').css('left', 20 - $('.prodaddtobasket').position().left);
                }
                else if (msg == 'insufficient stock')
                {
                    $('.tool-tip-wrap.insufficient-stock-info').fadeIn(300);
                    // set the positioning correctly
                    $('.tool-tip-wrap.insufficient-stock-info').css('top',$('.prodaddtobasket').position().top - ($('.insufficient-stock-info').height() / 2) + ($('.prodaddtobasket').height() / 2));
                    $('.tool-tip-wrap.insufficient-stock-info').css('width',301);
                    $('.tool-tip-wrap.insufficient-stock-info').css('left', 20 - $('.prodaddtobasket').position().left);
                }
                else
                {
                    $('.tool-tip-wrap.error-stock-info').fadeIn(300);
                    // set the positioning correctly
                    $('.tool-tip-wrap.error-stock-info').css('top',$('.prodaddtobasket').position().top - ($('.error-stock-info').height() / 2) + ($('.prodaddtobasket').height() / 2));
                    $('.tool-tip-wrap.error-stock-info').css('width',301);
                    $('.tool-tip-wrap.error-stock-info').css('left', 20 - $('.prodaddtobasket').position().left);
                }

                // reset mouse cursor
                resetMouse();
                return false;
            };
            if (p !== null && typeof p != 'string') p = p.id; // ..extract the product id..
            if (v !== null && typeof v != 'string' && typeof v != 'undefined') v = v.id; // ..extract the variant id..
            //If the variant is undefined, it implies that the variant doesnt exist for the choosen product, therefore
            //set it to null
            if (typeof v == 'undefined') v = '';
            var o = $.extend({ command: 'AddToBasket', ajax: true, pid: p, vid: v, swatchImageFormat: SwatchColourImageFormat }, options);
            var h = $.ajax({ url: '/handler.aspx', data: o, success: fn, error: fn, dataType: 'text', cache: false });

        };
    }


    // add to wishlist function
    if (typeof commerce.product.addtowishlist !== 'function') {
        commerce.product.addtowishlist = function(p, v, c, options) {
            var fn = function(data, status) {
                var msg = 'Unable to add product to wishlist; system failure.';
                if (status == 'success') {
                    var json = eval('(' + data + ')');

                    if (typeof json.products != 'undefined' && json.products.length != 0) {
                        // added ok - show the overlay
                        if (json.products[0].addToBasket == "true" || json.products[0].addToBasket == true) {
                            $('.tool-tip-wrap.wishlist-info').fadeIn(300);
                            // correctly position the overlay
                            $('.tool-tip-wrap.wishlist-info').css('top',$('#wishlist-link').position().top-($('.wishlist-info').height()/2)+($('#wishlist-link').height()/2));
                        }
                    }
                }

                // reset mouse cursor
                resetMouse();
                return false;
            };

            if (p !== null && typeof p != 'string') p = p.id; // ..extract the product id..
            if (v !== null && typeof v != 'string' && typeof v != 'undefined') v = v.id; // ..extract the variant id..
            //If the variant is undefined, it implies that the variant doesnt exist for the choosen product, therefore
            //set it to null
            if (typeof v == 'undefined') v = '';
            var o = $.extend({ command: 'AddToWishList', ajax: true, pid: p, vid: v, cid: c }, options);
            var h = $.ajax({ url: '/handler.aspx', data: o, success: fn, error: fn, dataType: 'text', cache: false });
        };
    }

    // add to giftlist function
    if (typeof commerce.product.addtogiftlist !== 'function') {
        commerce.product.addtogiftlist = function(p, v, c, options) {
            var fn = function(data, status) {
                var msg = 'Unable to add product to giftlist; system failure.';
                if (status == 'success') {
                    var json = eval('(' + data + ')');

                    if (typeof json.products != 'undefined' && json.products.length != 0) {
                        // added ok - show the overlay
                        if (json.products[0].addToBasket == "true" || json.products[0].addToBasket == true) {
                            $('.tool-tip-wrap.giftlist-info').fadeIn(300);
                            // correctly position the overlay
                            $('.tool-tip-wrap.giftlist-info').css('top',$('#giftlist-link').position().top-($('.giftlist-info').height()/2)+($('#giftlist-link').height()/2));
                        }
                    }
                    else
                    {
                        if (json.UrlRedirect != null && json.UrlRedirect != 'undefined' && json.UrlRedirect != '') {
                            window.location = json.UrlRedirect;
                        }
                    }
                }

                // reset mouse cursor
                resetMouse();
                return false;
            };

            if (p !== null && typeof p != 'string') p = p.id; // ..extract the product id..
            if (v !== null && typeof v != 'string' && typeof v != 'undefined') v = v.id; // ..extract the variant id..
            //If the variant is undefined, it implies that the variant doesnt exist for the choosen product, therefore
            //set it to null
            if (typeof v == 'undefined') v = '';
            var o = $.extend({ command: 'AddToGiftList', ajax: true, pid: p, vid: v, cid: c }, options);
            var h = $.ajax({ url: '/handler.aspx', data: o, success: fn, error: fn, dataType: 'text', cache: false });
        };
    }

    // stock email request function
    if (typeof commerce.product.stockemail !== 'function') {
        commerce.product.stockemail = function(p, v, emailaddress, options) {
            var fn = function(data, status) {
                if (status == 'success') {
                    var json = eval('(' + data + ')');

                    if (json != null && json != '' && json.success != null && json.success == true)
                    {
                        // success...
                        var msgText = $('#hdnStockEmailRequestSuccess').val();
                        $('.BackInStock').html(msgText);
                        return false;
                    }

                }
                // failure...
                var msgText = $('#hdnStockEmailRequestFailure').val();
                $('.BackInStock').html(msgText);
                return false;
            };

            if (p !== null && typeof p != 'string') p = p.id; // ..extract the product id..
            if (v !== null && typeof v != 'string' && typeof v != 'undefined') v = v.id; // ..extract the variant id..
            //If the variant is undefined, it implies that the variant doesnt exist for the choosen product, therefore
            //set it to null
            if (typeof v == 'undefined') v = '';
            var o = $.extend({ command: 'RequestStockEmail', ajax: true, pid: p, vid: v, emailid: emailaddress }, options);
            var h = $.ajax({ url: '/handler.aspx', data: o, success: fn, error: fn, dataType: 'text', cache: false });
        };
    }

    if (typeof commerce.product.stockmsgemail !== 'function') {
        commerce.product.stockmsgemail = function(p, v, emailaddress, options) {
            var fn = function(data, status) {
                if (status == 'success') {
                    var json = eval('(' + data + ')');

                    if (json != null && json != '' && json.success != null && json.success == true)
                    {
                        // success...
                        var msgText = $('#hdnStockEmailRequestSuccess').val();
                        $('.OOSMsgBackInStock').html(msgText);
                        return false;
                    }

                }
                // failure...
                var msgText = $('#hdnStockEmailRequestFailure').val();
                $('.OOSMsgBackInStock').html(msgText);
                return false;
            };

            if (p !== null && typeof p != 'string') p = p.id; // ..extract the product id..
            if (v !== null && typeof v != 'string' && typeof v != 'undefined') v = v.id; // ..extract the variant id..
            //If the variant is undefined, it implies that the variant doesnt exist for the choosen product, therefore
            //set it to null
            if (typeof v == 'undefined') v = '';
            var o = $.extend({ command: 'RequestStockEmail', ajax: true, pid: p, vid: v, emailid: emailaddress }, options);
            var h = $.ajax({ url: '/handler.aspx', data: o, success: fn, error: fn, dataType: 'text', cache: false });
        };
    }


    /*
    ** e-commerce product variant styles functionality.
    **
    ** Calls .asmx web services to interact with the
    ** current context, basket and comparison lists.
    */
    if (typeof commerce.product.find !== 'function') {
        commerce.product.find = function(id, attrs) {
            var item = commerce.product._data['$' + id] || commerce.product._fetch(id);
            if (item == null) return null;
            if (arguments.length === 1)
                return item;
            if (attrs == null || attrs.length === 0)
                return null;
            for (var v = 0, m = 0; v < item.variants.length; v++, m = 0) {
                for (var n = 0; n < attrs.length; n++) {
                    if (typeof item.variants[v][attrs[n].key] === 'undefined')
                        continue;
                    var a = (attrs[n].value || '').toLowerCase();
                    var b = (item.variants[v][attrs[n].key].id || '').toLowerCase();
                    if (a === b) m++;
                }
                if (m == attrs.length) return item.variants[v];
            }
            return null;
        };
    }


    /*
    ** e-commerce product user interface functionality.
    **
    ** Utility functions for making swatches from drop-down lists
    ** and intercepting the product variant controls range selector.
    */
    if (typeof commerce.ui.swatchify !== 'function') {
        commerce.ui.swatchify_resolve = function(container) {
            var options = [];
            container.find("select.property").each(function(index, select) {
                var id = select.id.match(/[a-zA-Z0-9]+$/) || [];
                if (id.length === 0) return;

                options.push({ key: id[0].toLowerCase(), value: $(select).val() || '' });
            });

            var id = container.find("input[type='hidden'].product-key").val();
            //return the product id if the choosen options is null
            //If the choosen option is null, it implies that the selected item is a Product without any variant
            if (commerce.product.find(id, options) == null) {
                return id;
            }
            else {
                return commerce.product.find(id, options);
            }
        };

        commerce.ui.swatchify_range = function(container, options) {
            if (container === null) return;
            var lists = container.find('select.colour');

            commerce.ui.swatchify(lists, options);
            lists.change(function(eventObject) {
                var id = container.find("input[type='hidden'].product-key").val();
                var pr = commerce.product.find(id);
                if (pr === null) return true;

                // ..find the 'size' selector and restructure the values
                // based on the keys found in the variant collection of
                // the product..                
                var selector = container.find('select.property.size');
                if (selector !== null && selector.size() !== 0) {
                    var prev = selector.val();
                    selector.empty();

                    for (var index = 0; index < pr.variants.length; index++) {
                        var variant = pr.variants[index];
                        if (typeof variant.colour !== 'undefined' && typeof variant.size !== 'undefined' && variant.colour.id === $(this).val()) {
                            if (prev == null) {
                                // if prev is null, it means there is no pre-selected value, so we should
                                // go ahead and assign the first item in the list as the selected value
                                prev = variant.size.id;
                            }
                            selector.append('<option value="' + variant.size.id + '">' + variant.size.descr + '</option>');
                        }
                    }

                    // ..reset the previously selected value (if present)
                    // and issue any custom change event handler specified
                    // in the options given..
                    selector.val(prev);
                }
                if (typeof options.change === 'function') {
                    eventObject = $.extend(eventObject, { data: commerce.ui.swatchify_resolve(container) });
                    options.change(eventObject);
                }
            });

            // ..map all other drop downs tagged as being variant properties
            // with the custom callback handler; resolve the selected product
            // and pass through as a secondary parameter..
            container.find("select.property").filter(":not(.colour)").change(function(eventObject) {
                if (typeof options.change === 'function') {
                    eventObject = $.extend(eventObject, { data: commerce.ui.swatchify_resolve(container) });
                    options.change(eventObject);
                }
            });

            // Trigger select of default variant - if any
            lists.change();

        };

        commerce.ui.swatchify = function(lists, options) {
            if (lists === null || lists.size() == 0)
                return;

            VariantClicked = false;

            options = $.extend({}, options);
            lists.each(function(index, select) {
                var choice = $(select).children(':selected').val();
                var div = $(document.createElement('div')).addClass('swatches').width('160');
                var ul = $(document.createElement('ul'));
                $(select).css('display', 'none').children('option').each(function(index, option) {
                    var li = $(document.createElement('li'));
                    var a = $(document.createElement('a'));
                    var i = $(document.createElement('img'));
                    a.attr({ alt: option.text, href: '#' }).addClass('swatch').append(i).addClass($(option).val() == choice ? 'selected' : '').click(function() {
                        
                        if (VariantClicked == true){
                            return false;  // disable varaint mouse clicks until this variant details have been loaded
                        }
                        VariantClicked = true;

                        $(this).parent().children('a.swatch').removeClass('selected');
                        $(this).addClass('selected');
                        $(select).val(option.value).change();

                        // use ajax request as a way of determining that the varaints details have finsihed loading
                        $.ajax({
                            url: MissingColourSwatch,
                            type: 'HEAD',
                            error:
                            function () {
                                VariantClicked = false;  // re-enable variant clicks
                            },
                            success:
                            function () {
                                VariantClicked = false;  // re-enable variant clicks
                            }
                        });
                        return false;
                    });

                    // hide the icons until fully loaded
                    $('.option-list').attr('style','display:none;');

                    var imgsrc = IconsDirectory + $(option).val() + '.gif';
                    i.attr('id', $(option).val());
                    i.attr('alt', $(option).text());
                    i.attr('title', $(option).text());
                    i.attr('src', imgsrc);
                    i.attr('style', 'display:none;');
                    // check the colour icon exists
                    $.ajax({
                        url: imgsrc,
                        type: 'HEAD',
                        error:
                        function () {
                            $('.option-list').attr('style','display:block;');  // show the icons
                            i.attr('src', MissingColourSwatch);
                            i.attr('class','missing-swatch');
                            i.attr('style', 'display:inline;');
                        },
                        success:
                        function () {
                            $('.option-list').attr('style','display:block;');  // show the icons
                            i.attr('style', 'display:inline;');
                        }
                    });
                    li.append(a);
                    ul.append(li);
                    // add a space after each list item except the items on the end of the div (multiples of 8)
                    if (index != 7 && index != 15 && index != 23 && index != 31 && index != 39 && index != 47 && index != 55 && index != 63 && index != 71 && index != 79)
                    {
                        ul.append('&nbsp;');
                    }
                });
                div.append(ul);
                $(select).before(div);
            });
        };
    }

    if (typeof commerce.ui.intercept !== 'function') {
        commerce.ui.intercept = function(button) {
            if (button === null || button.size() == 0)
                return;

            $(button).click(function() {
                $('.tool-tip-wrap').hide();  // hide overlays

                var options = {};
                var item = commerce.ui.swatchify_resolve($("#product-config"));
                if (item == null)
                {
                    // ..submit the form; we can't find the product!..
                    $('.addtobasket_failover').click();
                    return;
                }

                $("#product-config").find(".product-options select.non-property").each(function(index, select) {
                    var id = select.id.match(/[a-zA-Z0-9]+$/) || [];
                    if (id.length === 0)
                    {
                        // ..submit the form; we can't find the product!..
                        $('.addtobasket_failover').click();
                        return;
                    }
                    options[id[0].toLowerCase()] = $(select).val() || '';
                });
                // ..the quantity is a special case; select it directly..
                var id = $("#product-config").find("input[type='hidden'].product-key").val();
                var quantity = $('.QtyDropDown');
                options.quantity = quantity.size() == 0 ? '1' : quantity.val();
                var bcnt = $('#basket-count').val();
                if (bcnt == "True")
                { $('#basket-count').val('False'); }
                var cid = $('#product-cat').val();

                // show progress mouse cursor
                $("*").css("cursor", "progress");
                commerce.product.place(id, item.id, cid, options, bcnt);
                return false;
            });
        };
    };

    // handle add to wishlist click
    if (typeof commerce.ui.interceptWishLink !== 'function') {
        commerce.ui.interceptWishLink = function(anchor) {
            if (anchor === null || anchor.size() == 0)
                return;

            $(anchor).click(function() {
                $('.tool-tip-wrap').hide();  // hide overlays

                var options = {};
                var item = commerce.ui.swatchify_resolve($("#product-config"));
                if (item == null) { return true; } // ..submit the form; we can't find the product!..

                $("#product-config").find(".product-options select.non-property").each(function(index, select) {
                    var id = select.id.match(/[a-zA-Z0-9]+$/) || [];
                    if (id.length === 0) return;

                    options[id[0].toLowerCase()] = $(select).val() || '';
                });
                
                var id = $("#product-config").find("input[type='hidden'].product-key").val();
                var quantity = '1';

                var cid = $('#product-cat').val();
                // show progress mouse cursor
                $("*").css("cursor", "progress");
                commerce.product.addtowishlist(id, item.id, cid, options);
                return false;
            });
        };
    };

    // handle add to giftlist click
    if (typeof commerce.ui.interceptGiftLink !== 'function') {
        commerce.ui.interceptGiftLink = function(anchor) {
            if (anchor === null || anchor.size() == 0)
                return;

            $(anchor).click(function() {
                $('.tool-tip-wrap').hide();  // hide overlays

                var options = {};
                var item = commerce.ui.swatchify_resolve($("#product-config"));
                if (item == null) { return true; } // ..submit the form; we can't find the product!..

                $("#product-config").find(".product-options select.non-property").each(function(index, select) {
                    var id = select.id.match(/[a-zA-Z0-9]+$/) || [];
                    if (id.length === 0) return;

                    options[id[0].toLowerCase()] = $(select).val() || '';
                });
                
                var id = $("#product-config").find("input[type='hidden'].product-key").val();
                var quantity = '1';

                var cid = $('#product-cat').val();
                // show progress mouse cursor
                $("*").css("cursor", "progress");
                commerce.product.addtogiftlist(id, item.id, cid, options);
                return false;
            });
        };
    };

    // handle email when back in stock submit click
    if (typeof commerce.ui.interceptStockEmail !== 'function') {
        commerce.ui.interceptStockEmail = function(btn) {
            if (btn === null || btn.size() == 0)
                return;

            $(btn).click(function() {
                var options = {};
                var item = commerce.ui.swatchify_resolve($("#product-config"));
                if (item == null) { return true; } // ..submit the form; we can't find the product!..

                $("#product-config").find(".product-options select.non-property").each(function(index, select) {
                    var id = select.id.match(/[a-zA-Z0-9]+$/) || [];
                    if (id.length === 0) return;

                    options[id[0].toLowerCase()] = $(select).val() || '';
                });
                
                var id = $("#product-config").find("input[type='hidden'].product-key").val();
                
                var email = '';
                email = $('.txtEmailAddress').val();
                if (email == null || email == '')
                {
                    var errorText = $('#hdnStockEmailNotEnteredFailure').val();
                    $('.BackInStock').html(errorText);
                    return false;
                }
                if (!validateEmail(email)) {
                    var errorText = $('#hdnStockEmailInvalidAddress').val();
                    $('.BackInStock').html(errorText);
                    return false;
                }

                commerce.product.stockemail(id, item.id, email, options);
                return false;
            });
        };
    };

    if (typeof commerce.ui.interceptStockMsgEmail !== 'function') {
        commerce.ui.interceptStockMsgEmail = function(btn) {
            if (btn === null || btn.size() == 0)
                return;

            $(btn).click(function() {
                var options = {};
                var item = commerce.ui.swatchify_resolve($("#product-config"));
                if (item == null) { return true; } // ..submit the form; we can't find the product!..

                $("#product-config").find(".product-options select.non-property").each(function(index, select) {
                    var id = select.id.match(/[a-zA-Z0-9]+$/) || [];
                    if (id.length === 0) return;

                    options[id[0].toLowerCase()] = $(select).val() || '';
                });
                
                var id = $("#product-config").find("input[type='hidden'].product-key").val();
                
                var email = '';
                email = $('.txtOOSMsgEmailAddress').val();
                if (email == null || email == '')
                {
                    var errorText = $('#hdnStockEmailNotEnteredFailure').val();
                    $('.OOSMsgBackInStock').html(errorText);
                    return false;
                }
                if (!validateEmail(email)) {
                    var errorText = $('#hdnStockEmailInvalidAddress').val();
                    $('.OOSMsgBackInStock').html(errorText);
                    return false;
                }

                commerce.product.stockmsgemail(id, item.id, email, options);
                return false;
            });
        };
    };

    function validateEmail(src) {
        var regex = /^[a-zA-Z0-9._-]+@([a-zA-Z0-9.-]+\.)+[a-zA-Z0-9.-]{2,4}$/;
        return regex.test(src);
    };

}());

