var $j = jQuery.noConflict();
var Configurator = function () {
	return {
        //= Init function
		init: function(debug) {
			var instance = this;

            if($j.browser.msie && $j.browser.version=="6.0") {

                $j('.configurator').prepend('<p class="option-deactivated-msg option-deactivated-msg-full">Skjortkonfiguratorn &auml;r tyv&auml;rr en av de sektioner p&aring; sidan som inte fungerar med Internet Explorer 6.</p>');

                return false;
            };

            // Don't continue if there is no configurator present
            if ($j('.configurator').length == 0){
                return false;
            }

            instance.prepare.setConstants();
            instance.dom.configuratorInfo.show();
            instance.dom.wizard.show();

            $j(instance.dom.wizard).mask(instance.msg.loadingConfigurator);

            if(debug) {
            } else {
                // Run some functions
                instance.prepare.mapOptions();
                instance.prepare.setMeta();
                instance.prepare.restructure();
                instance.measure.createPresetsStandard();
                instance.measure.createPresetsUser();
                instance.measure.createMeasureGuideLinks();
                instance.prepare.setDefaults();
                instance.prepare.populate();
                instance.prepare.replaceSelects();
                instance.core.launch();
                instance.core.reloadPrice();
            }

            $j(instance.dom.wizard).unmask();
        },

        //= Core functions
        core: {

            ajax: function(type, serializedData, url, callbackServerSuccess, callbackServerFailure) {

                var instance = Configurator;

                $j.ajax({
                    type: type,
                    url: url,
                    data: serializedData,
                    success: function(response){
                        var instance = Configurator;

                        var responseJSON = JSON.parse(response);

                        /*
                        if(html.match('actionFailure')) {
                            instance.ajaxresponse.currentError = html;
                            callbackServerFailure(html);
                        } else {
                            instance.ajaxresponse.currentSuccess = html;
                            callbackServerSuccess(html);
                        }
                        */
                        if(responseJSON.success) {
                            instance.ajaxresponse.currentError = responseJSON.msg;
                            callbackServerSuccess(responseJSON.msg);
                        } else {
                            instance.ajaxresponse.currentSuccess = responseJSON.msg;
                            callbackServerFailure(responseJSON.msg);
                        }

                    },
                    failure: function() {
                        alert('Ajax call failed');
                    }
                });
            },

            launch: function() {

                var instance = Configurator;

                // enable tabs that are contained within the wizard
                $j("ul.w-tabs", instance.dom.wizard).tabs("div.w-panes > div", {

                    onBeforeClick: function(event, index) {

                        switch(index) {
                            case 0:
                                //execute code block 0
                                break;
                            case 1:
                                //execute code block 1
                                break;
                            case 2:
                                //execute code block 2
                                break;
                            case 3:
                                function showPaneErrors(paneValidator, msg) {
                                    $j(paneValidator)
                                        .html('')
                                        .append(msg)
                                        .fadeIn();

                                    // Scroll to top
                                    $j('html, body').animate({scrollTop:0}, 'fast');
                                }

                                var paneValidator = $j('#w-pane-3 .pane-validator');
                                var selectedType = $j('ul.measure-type-list li.selected');
                                var selectedFieldset = "";
                                var measureField = $j('#measure-type-fieldset textarea');

                                var measureValidator = {};
                                measureValidator.errorMessage = "";
                                measureValidator.errorFields = [];
                                measureValidator.hasType = true;
                                measureValidator.hasRequired = true;
                                measureValidator.hasValidData = true;

                                // Clean measureField
                                $j(measureField).attr('value', '');

                                if(selectedType.length == 0) {
                                    measureValidator.hasType = false;
                                    measureValidator.errorMessage = '<p>Innan du kan g&aring; vidare m&aring;ste du l&auml;gga till dina m&aring;tt. B&ouml;rja med att v&auml;lja vilken typ av m&aring;tt du vill anv&auml;nda och f&ouml;lj sedan guiden f&ouml;r att m&auml;ta.</p>';
                                } else {
                                    var selType = selectedType.get(0);
                                    var selTypeLinkArr = $j(selType).find('a:first');
                                    var selTypeLink = selTypeLinkArr.get(0);
                                    var selFieldsetId = $j(selTypeLink).attr('rel');

                                    selectedFieldset = $j('#' + selFieldsetId);

                                    $j('input', selectedFieldset).each(function(i, domEl) {

                                        var curValue = $j(domEl).attr('value');

                                        // Check if value exists
                                        if(curValue == "") {
                                            measureValidator.hasRequired = false;
                                            measureValidator.errorFields.push(domEl);
                                        }

                                        // Check if value is a number
                                        if(!instance.util.isNumber(curValue)) {
                                            measureValidator.hasValidData = false;
                                            measureValidator.errorFields.push(domEl);
                                        }

                                    });

                                    if(!measureValidator.hasRequired) {
                                        measureValidator.errorMessage += '<p>Du m&aring;ste fylla i alla obligatoriska f&auml;lt.</p>';
                                    }
                                    if(!measureValidator.hasValidData) {
                                        measureValidator.errorMessage += '<p>M&aring;tten skall anges med siffror (och eventuella kommatecken).</p>';
                                    }

                                }

                                if(!measureValidator.hasType || !measureValidator.hasRequired || !measureValidator.hasValidData) {
                                    showPaneErrors(paneValidator, measureValidator.errorMessage);
                                    $j(measureValidator.errorFields).addClass('input-error');

                                    // If you have multiple callbacks of the same type this prevents  the rest of the callbacks from being executed.
                                    event.stopImmediatePropagation();

                                    return false;
                                } else {

                                    // Logic to populate hidden measureField
                                    var measureJson = instance.util.getMeasureJson(selectedFieldset);

                                    // Populate measure field
                                    $j(measureField).attr('value', measureJson);

                                    // Hide validator
                                    $j(paneValidator).hide();

                                    //event.stopImmediatePropagation();
                                    //return false;
                                }

                                break;

                            case 4:
                                //execute code block 4
                                break;

                            default:
                                //code to be executed if n is different from case 1 and 2
                        }
                    },
                    onClick: function(event, index) {

                        $j('html, body').animate({scrollTop:0}, 'fast');

                        var clickedPane = this.getPanes().eq(index);
                        var clickedTab = this.getTabs().eq(index);

                        if($j(clickedTab).parent().hasClass('step-final')) {
                            $j(instance.dom.wizard).addClass('wizard-step-final');
                        } else {
                            $j(instance.dom.wizard).removeClass('wizard-step-final');
                        }
                    }
                }).history();

                instance.toolsapi.wizardTabs = $j("ul.w-tabs", instance.dom.wizard).tabs(0);

                // Show wizard
                instance.dom.configuratorInfo.fadeIn();
                instance.dom.wizard.fadeIn();

                $j("a.next", instance.dom.wizard).click(function() {

                    // Trigger click on tab component
                    instance.toolsapi.wizardTabs.getCurrentTab().parent().next().children('a').trigger('click');
                    return false;
                });

                $j("a.next", instance.dom.wizard).bind('onBeforeClick', function() {
                    // Trigger onBeforeClick on tab component
                    instance.toolsapi.wizardTabs.getCurrentTab().parent().next().children('a').trigger('onBeforeClick');
                });

                // Trigger click on next control for additional next button
                $j(".measure-block-presets-wrap .order-wrap a", instance.dom.wizard).click(function() {
                    var curPane = $j(this).parents(".w-pane");
                    $j(curPane).find(".pane-controls a.next").trigger('click');
                    return false;
                });


                // "previous tab" button
                $j("a.prev", instance.dom.wizard).click(function() {
                    // possibility to cancel click action
                    $j(this).trigger('onBeforeClick');

                    // Trigger click on tab component

                    instance.toolsapi.wizardTabs.getCurrentTab().parent().prev().children('a').trigger('click');
                    return false;
                });
                $j("a.prev", instance.dom.wizard).bind('onBeforeClick', function() {
                    // Trigger onBeforeClick on tab component
                    instance.toolsapi.wizardTabs.getCurrentTab().parent().prev().children('a').trigger('onBeforeClick');
                });

                // Bind meta-info click to Show meta info overlay
                $j(".option-more-info a.option-more-info-link", instance.dom.wizard).click(function(e) {

                    var instance = Configurator;

                    var curSelect = $j(this).parents(".ctrl-holder:first").find("select").get(0);
                    var curSelectId = $j(curSelect).attr('id');

                    instance.ids.overlayOptionMetaSelect = curSelectId;

                    instance.design.showMetaOverlay();

                    return false;
                });

                /* FLAG */
                $j("ul.measure-type-list li a", instance.dom.wizard).click(function() {

                    var instance = Configurator;

                    //var elementId = $j(this).parent().attr('id');
                    //instance.measure.showMeasureFieldset(elementId);

                    var domElement = $j(this).parent();
                    var element = $j(domElement);
                    instance.measure.showMeasureFieldset(element);

                    return false;
                });


                /*
                $j(".measure-fieldset input", instance.dom.wizard).focus(function() {

                    var holderArr = $j('#' + this.id).parents().filter('.ctrl-holder');
                    var holder = $j(holderArr[0]);
                    var sku = $j(holder).attr('rel');
                    var metaWrapInnerArr = holder.parents('fieldset').find('.measure-meta-inner');
                    var metaWrapInner = $j(metaWrapInnerArr.get(0));

                    instance.measure.showMeta(metaWrapInner, sku);
                });
                */

                $j(".measure-fieldset .meta-btn", instance.dom.wizard).click(function() {

                    var instance = Configurator;
                    var $this = $j(this);

                    var holderArr = $this.parents().filter('.ctrl-holder');
                    var holder = $j(holderArr[0]);
                    var sku = $j(holder).attr('rel');
                    var metaWrapInnerArr = holder.parents('fieldset').find('.measure-meta-inner');
                    var metaWrapInner = $j(metaWrapInnerArr.get(0));

                    instance.measure.showMeta(metaWrapInner, sku);
                });

                $j(".measure-fieldset .measure-block-label", instance.dom.wizard).click(function() {

                    var curLabel = $j(this);
                    var sku = $j(curLabel).attr('rel');

                    if(sku != '') {
                        var metaWrapInnerArr = $j(this).parents('fieldset').find('.measure-meta-inner');
                        var metaWrapInner = $j(metaWrapInnerArr.get(0));

                        instance.measure.showMeta(metaWrapInner, sku);
                    }
                });

                // Bind signin button to signin overlay
                $j('.' + instance.classes.signinWrap + ' button', instance.dom.wizard)
                .add($j('.' + instance.classes.signinWrap + ' a', instance.dom.wizard))
                .click(function() {

                    var instance = Configurator;

                    // If at measures pane
                    if(instance.toolsapi.wizardTabs.getIndex() == 2) {

                        var measureField = $j('#measure-type-fieldset textarea');
                        var selectedFieldset = instance.util.getSelectedMeasureFieldset();
                        var measureJson = instance.util.getMeasureJson(selectedFieldset);

                        // Populate measure field
                        $j(measureField).attr('value', measureJson);
                    }

                    instance.user.showSigninOverlay();
                    return false;
                });

                // Bind save measures button to save measures overlay
                $j('.' + instance.classes.saveMeasuresWrap + ' button', instance.dom.wizard).click(function() {

                    var instance = Configurator;

                    instance.measure.showSaveProfileOverlay();
                    return false;
                });

                // Bind save design button to save design overlay
                $j('.' + instance.classes.saveShirtdesignWrap + ' button', instance.dom.wizard).click(function() {

                    var instance = Configurator;

                    instance.design.showSaveDesignOverlay();
                    return false;
                });

                // Bind add-to-cart button to Add to cart
                $j('.add-to-cart button', instance.dom.wizard).click(function() {

                    //productAddToCartForm defined by Magento
                    productAddToCartForm.submit();
                });


                // Trigger the correct start page
                var loadListItemArr = instance.toolsapi.wizardTabs.getCurrentTab().parent().parent().find('li.step-' + instance.data.startPage);
                if(loadListItemArr.length == 1) {
                    var loadListItem = $j(loadListItemArr.get(0));
                    loadListItem.children('a').trigger('click');
                }
            },

            reloadPrice: function() {
                // opConfig is defined by Magento
                if(typeof(opConfig) != "undefined") {
                    opConfig.reloadPrice();
                }
            }

        },

        //= Stuff related to the shirt design
        design: {

            activateOption: function(selectId) {

                var instance = Configurator;

                var msddId = selectId + '_msdd';
                var selectDD = $j('#' + msddId, instance.dom.wizard).parent();

                $j(selectDD).removeClass('dd-deactivated');
                $j(selectDD).find('.option-deactivated-msg').remove();
                $j(selectDD).find('.dd').show();
                $j(selectDD).parent().find('.option-more-info').show();
            },

            createSaveDesignOverlay: function(load) {

                var instance = Configurator;

                var overlayId = instance.ids.overlaySaveDesign;
                var formId = 'configuratorSaveDesignForm';
                var formUrl = instance.url.SAVE_DESIGN;

                var templateOverlay = $j.template(
                    '<div id="${overlayId}" class="simple_overlay overlay-save-design">'+
                        '<div class="overlay-content-wrap">'+
                            '<div class="form-msg"></div>'+
                            '<form id="${formId}" action="${formUrl}" method="post">'+
                                '<fieldset>'+
                                    '<div class="ctrl-holder clearfix"><label>Skjortdesignens namn:</label> <input name="designName" class="input-text" /></div>'+
                                    '<div class="ctrl-holder clearfix">'+
                                        '<input type="submit" value="Spara skjortdesign" />'+
                                        '<button class="button btn-cancel" type="button"><span>Avbryt</span></button>'+
                                    '</div>'+
                                '</fieldset>'+
                            '</form>'+
                            '<div class="btn-wrap">'+
                                '<button class="button btn-close" type="button"><span>St&auml;ng</span></button>'+
                            '</div>'+
                        '</div>'+
                    '</div>'
                );

                $j('body').append(templateOverlay, {
                    overlayId: overlayId,
                    formId: formId,
                    formUrl: formUrl
                });

                // select the overlay element - and "make it an overlay"
                instance.toolsapi.overlaySaveDesign = $j('#' + overlayId).overlay({
                    api: true,
                    expose: {
                        color: '#333',
                        opacity: 0.3
                    },
                    closeOnClick: true,
                    onBeforeLoad: function() {
                        // Hide close button
                        $j('.btn-close', this.getContent()).hide();
                        // Show form
                        $j('form', this.getContent()).show();
                        // Remove form messages
                        $j('.form-msg', this.getContent()).html('');
                    },
                    onLoad: function() {},
                    onBeforeClose: function() {},
                    onClose: function() {}
                });

                $j('.btn-cancel,.btn-close', instance.toolsapi.overlaySaveDesign.getContent()).click(function() {
                    var instance = Configurator;
                    instance.toolsapi.overlaySaveDesign.close();
                    return false;
                });

                var form = instance.toolsapi.overlaySaveDesign.getContent().find("form");
                var formSubmitBtn = form.find('input[type="submit"]');

                // Bind form submit button
                formSubmitBtn.click(function() {

                    var form = $j(this).parents('.overlay-content-wrap').find('form');
                    var formInputs = form.find('input.input-text');

                    var rawSetupJSON = instance.util.getSetupJson();
                    var cleanedSetupJSON = instance.util.cleanMeasures(rawSetupJSON);

                    var data = form.serialize() + '&json_setup=' + cleanedSetupJSON;

                    var url = form.attr('action');

                    instance.design.saveDesign(data, url);
                    return false;
                });

                if(load) {
                    instance.toolsapi.overlaySaveDesign.load();
                }
            },

            createMetaOverlay: function () {

                var instance = Configurator;

                var overlayId = instance.ids.overlayOptionMeta;

                var templateOptionMetaOverlay = $j.template(
                    '<div id="${overlayId}" class="simple_overlay overlay-option-meta">'+
                        '<div id="${overlayIdContent}" rel="" class="overlay-content-wrap">'+
                            '<div id="${overlayIdLeft}" class="overlay-content-left">'+
                                '<div class="overlay-content-left-inner overlay-content-inner">'+
                                '</div>'+
                            '</div>'+
                            '<div id="${overlayIdRight}" class="overlay-content-right">'+
                                '<div class="overlay-content-right-inner overlay-content-inner">'+
                                '</div>'+
                            '</div>'+
                            '<div id="${overlayIdFooter}" class="overlay-content-footer clearfix">'+
                                '<div class="footer-btn-wrap clearfix">'+
                                    '<button class="button btn-footer-choose" type="button"><span>V&auml;lj</span></button>'+
                                    '<button class="button btn-footer-cancel" type="button"><span>Avbryt</span></button>'+
                                '</div>'+
                            '</div>'+
                        '</div>'+
                    '</div>'
                );

                $j('body').append(templateOptionMetaOverlay, {
                    overlayId: overlayId,
                    overlayIdContent: instance.ids.overlayOptionMetaContent,
                    overlayIdFooter: instance.ids.overlayOptionMetaFooter,
                    overlayIdLeft: instance.ids.overlayOptionMetaLeft,
                    overlayIdRight: instance.ids.overlayOptionMetaRight
                });

                // select the overlay element - and "make it an overlay"
                instance.toolsapi.overlayOptionMeta = $j('#' + overlayId).overlay({

                    api: true,
                    expose: {
                        color: '#333',
                        opacity: 0.3,
                        zIndex: 9996
                    },
                    closeOnClick: true,
                    onBeforeLoad: function() {

                        var instance = Configurator;

                        var wrap = $j('#' + instance.ids.overlayOptionMetaContent, this.getContent());
                        var wrapLeft = $j('#' + instance.ids.overlayOptionMetaLeft, wrap);
                        var wrapFooter = $j('#' + instance.ids.overlayOptionMetaFooter, wrap);

                        var curSelectId = instance.ids.overlayOptionMetaSelect;
                        var curSelect = $j('#' + curSelectId);
                        var curOptionSelected = $j('option:selected', curSelect).get(0);
                        var curOptionIdSelected = $j(curOptionSelected).attr('id');

                        // Get current content block id (left)
                        var curContentBlockLeftId = instance.ids.overlayOptionMetaLeft + '-' + curSelectId;

                        // Hide all content blocks (left and right)
                        $j('.overlay-content-left-block', wrap).hide();
                        $j('.overlay-content-right-block', wrap).hide();

                        // Get left content block
                        var curContentBlockLeft = $j('#' + curContentBlockLeftId, wrap);

                        // Create left content block if doesnt exist
                        if(curContentBlockLeft.length <= 0) {
                            var templateLeft = $j.template(
                                '<div id="${contentBlockId}" class="overlay-content-left-block">'+
                                    '<ul class="options-list clearfix">'+
                                    '</ul>'+
                                '</div'
                            );

                            $j('.overlay-content-inner', wrapLeft).append(templateLeft , {
                                contentBlockId: curContentBlockLeftId
                            });

                            curContentBlockLeft = $j('#' + curContentBlockLeftId, wrap);

                            var templateLeftItems = $j.template(
                                '<li id="item-${optionId}" rel="${optionId}">'+
                                    '<div class="option-wrap">'+
                                        '<img src="${imgThumbUrl}" alt="${imgThumbAlt}" />'+
                                        '<div class="option-title">${name}</div>'+
                                    '</div>'+
                                '</li>'
                            );

                            // Populate left items
                            /* Flagging now */
                            $j('option', curSelect).each(function(i, domEl) {
                            	
                            	var isSaleable = $j(this).data("isSaleable");
                            	
                            	if(isSaleable != 0) {
                                    $j('ul.options-list', curContentBlockLeft).append(templateLeftItems , {
                                        optionId: this.id,
                                        name: $j(this).data('name'),
                                        imgThumbUrl: $j(this).data('imgThumbUrl'),
                                        imgThumbAlt: $j(this).data('name')
                                    });
                            	}
                            });

                            // Attach listener to hover event on each option item
                            $j('ul.options-list li .option-wrap', curContentBlockLeft).hover(
                                function() {
                                    $j(this).addClass('option-wrap-over');
                                },
                                function () {
                                    $j(this).removeClass('option-wrap-over');
                                }
                            );

                            // Attach listener to click event on each option item
                            $j('ul.options-list li .option-wrap', curContentBlockLeft).click(function() {

                                var instance = Configurator;

                                // Remove active class from all option items
                                $j('ul.options-list li .option-wrap', curContentBlockLeft).removeClass('option-wrap-active');

                                // Set clicked item to selected
                                $j(this).addClass('option-wrap-active');

                                var curOptionId = $j(this).parent().attr('rel');
                                instance.ids.overlayOptionMetaOptionActive = curOptionId;
                                var curOption = $j('#' + curOptionId);

                                // Get current content block id (right)
                                var curContentBlockRightId = instance.ids.overlayOptionMetaRight + '-' + curSelectId + '-' + curOptionId;

                                // Hide all right content blocks
                                $j('.overlay-content-right-block', wrap).hide();

                                // Get current right block
                                var curContentBlockRight = $j('#' + curContentBlockRightId, wrap);

                                // Create current right block if doesnt exist
                                if(curContentBlockRight.length <= 0) {
                                    var curSerializedData = 'sku=' + curOption.data('sku');
                                    instance.design.getMeta(curSerializedData, instance.url.GET_OPTION_META);
                                } else {
                                    curContentBlockRight.fadeIn();
                                }
                            });
                        }
                        curContentBlockLeft.show();
                    },
                    onLoad: function() {

                        var instance = Configurator;

                        var wrap = $j('#' + instance.ids.overlayOptionMetaContent, this.getContent());

                        var curSelectId = instance.ids.overlayOptionMetaSelect;
                        var curSelect = $j('#' + curSelectId);
                        var curOptionSelected = $j('option:selected', curSelect).get(0);
                        var curOptionIdSelected = $j(curOptionSelected).attr('id');

                        // Set selected item
                        $j('#item-' + curOptionIdSelected + ' .option-wrap', wrap).trigger('click');
                    },
                    onBeforeClose: function() {},
                    onClose: function() {}
                    // load it immediately after the construction
                });

                var wrap = $j('#' + instance.ids.overlayOptionMetaContent, instance.toolsapi.overlayOptionMeta.getContent());
                var wrapLeft = $j('#' + instance.ids.overlayOptionMetaLeft, wrap);
                var wrapFooter = $j('#' + instance.ids.overlayOptionMetaFooter, wrap);

                // Attach listeners to footer buttons
                $j('.btn-footer-choose', wrapFooter).click(function() {
                    var instance = Configurator;

                    var curSelectId = instance.ids.overlayOptionMetaSelect;
                    var curSelect = $j('#' + curSelectId);
                    var curContentBlockLeftId = instance.ids.overlayOptionMetaLeft + '-' + curSelectId;
                    var curOptionSelected = $j('option:selected', curSelect).get(0);
                    var curOptionIdSelected = $j(curOptionSelected).attr('id');

                    var overlayItemSelected = $j('#' + curContentBlockLeftId + ' .option-wrap-active').get(0);
                    var overlayOptionIdSelected = $j(overlayItemSelected).parent().attr("rel");

                    if(curOptionIdSelected != overlayOptionIdSelected) {

                        //var curSelectId = $j(curSelect).attr("id");
                        var curReplacedSelect = $j("#" + curSelectId + "_msdd");

                        var replacedOptionId = overlayOptionIdSelected.replace("_option_", "_msa_");

                        // Make the new selection
                        $j("#" + replacedOptionId, curReplacedSelect).trigger('click');
                        $j("#" + curSelectId).trigger("change");
                    }

                    instance.toolsapi.overlayOptionMeta.close();
                    return false;
                });

                $j('.btn-footer-cancel', wrapFooter).click(function() {
                    var instance = Configurator;

                    instance.toolsapi.overlayOptionMeta.close();
                    return false;
                });

                instance.toolsapi.overlayOptionMeta.load();
            },

            deactivateOption: function(selectId) {

                var instance = Configurator;

                var msddId = selectId + '_msdd';
                var selectDD = $j('#' + msddId, instance.dom.wizard).parent();

                // If not already deactivated
                if(!selectDD.hasClass('dd-deactivated')) {
                    $j(selectDD).addClass('dd-deactivated');
                    $j(selectDD).find('.dd').hide();
                    $j(selectDD).parent().find('.option-more-info').hide();
                    $j(selectDD).append('<div class="option-deactivated-msg">' + instance.msg.selectDeactivated + '</div>');
                }
            },

            getMeta: function(serializedData, url) {

                var instance = Configurator;

                var callbackSuccess = function(response) {
                    var instance = Configurator;
                    instance.design.metaSuccess(response);
                };
                var callbackFailure = function(response) {
                    var instance = Configurator;
                    instance.design.metaFailure(response);
                };

                var wrap = $j('#' + instance.ids.overlayOptionMetaContent);
                $j(wrap).mask(instance.msg.optionMetaLoadProgress);

                instance.core.ajax('GET', serializedData, url, callbackSuccess, callbackFailure);
            },

            metaFailure: function(responseTxt) {

                var instance = Configurator;

                var wrap = $j('#' + instance.ids.overlayOptionMetaContent, instance.toolsapi.overlayOptionMeta.getContent());
                var wrapRight = $j('#' + instance.ids.overlayOptionMetaRight, wrap);

                instance.util.createErrorMsg(wrapRight, instance.msg.optionMetaLoadError);
            },

            metaSuccess: function(responseTxt) {

                var instance = Configurator;

                var ajaxResponse = JSON.parse(responseTxt);
                var wrap = $j('#' + instance.ids.overlayOptionMetaContent, instance.toolsapi.overlayOptionMeta.getContent());
                var wrapRight = $j('#' + instance.ids.overlayOptionMetaRight, wrap);

                $j(wrap).unmask();

                var curSelectId = instance.ids.overlayOptionMetaSelect;
                var curOptionId = instance.ids.overlayOptionMetaOptionActive;
                var isFabric = (instance.data.configuratorFieldMap.fieldmap.fabric.domId == curSelectId);

                var curOption = $j('#' + curOptionId);

                // Get current content block id (right)
                var curContentBlockRightId = instance.ids.overlayOptionMetaRight + '-' + curSelectId + '-' + curOptionId;

                var templateRight = $j.template(
                    '<div id="${contentBlockId}" class="overlay-content-right-block">'+
                    '</div'
                );

                // Run template right
                $j('.overlay-content-inner', wrapRight).append(templateRight , {
                    contentBlockId: curContentBlockRightId
                });

                var curContentBlockRight = $j('#' + curContentBlockRightId, wrap);

                if(isFabric) {

                    var fabricAttributes = [
                        {id: 'fabricComposition',label: 'Komposition',value: ajaxResponse.attributes.fabricComposition},
                        {id: 'fabricYarn',label: 'Garn',value: ajaxResponse.attributes.fabricYarn},
                        {id: 'fabricColor',label: 'F&auml;rg',value: ajaxResponse.attributes.fabricColor},
                        {id: 'fabricWeavingTechnique',label: 'V&auml;vteknik',value: ajaxResponse.attributes.fabricWeavingTechnique},
                        {id: 'fabricTreatment',label: 'Behandling',value: ajaxResponse.attributes.fabricTreatment},
                        {id: 'fabricWeight',label: 'Vikt (g/m2)',value: ajaxResponse.attributes.fabricWeight},
                        {id: 'fabricLaundryTemperature',label: 'Tv&auml;ttemperatur',value: ajaxResponse.attributes.fabricLaundryTemperature},
                        {id: 'fabricDryCleaning',label: 'Kemtv&auml;tt',value: ajaxResponse.attributes.fabricDryCleaning},
                        {id: 'fabricChlorineBleaching',label: 'Klorblekning',value: ajaxResponse.attributes.fabricChlorineBleaching},
                        {id: 'fabricTumbling',label: 'Torktumling',value: ajaxResponse.attributes.fabricTumbling},
                        {id: 'fabricIroning',label: 'Strykning',value: ajaxResponse.attributes.fabricIroning}
                    ];

                    var templateRightInnerFabric = $j.template(
                        '<div class="option-details-wrap">'+
                            '<img src="${imgUrl}" alt="${imgAlt}" />'+
                            '<h3>${name}</h3>'+
                            '<ul class="attributes-list"></ul>'+
                        '</div>'
                    );

                    var templateRightInnerFabricAttributes = $j.template(
                        '<li><span class="attribute-label">${label}:</span><span class="attribute-value">${content}</span></li>'
                    );

                    // Run template right inner fabric
                    $j(curContentBlockRight).append(templateRightInnerFabric, {
                        optionId: curOptionId,
                        name: ajaxResponse.name,
                        imgUrl: ajaxResponse.imgSmallUrl,
                        imgAlt: ajaxResponse.name
                    });

                    $j.each(fabricAttributes, function(index, attribute){

                        $j('ul.attributes-list', curContentBlockRight).append(templateRightInnerFabricAttributes, {
                            label: Encoder.htmlDecode(attribute.label),
                            content: Encoder.htmlDecode(attribute.value)
                        });
                    });

                } else {

                    var templateRightInner = $j.template(
                        '<div class="option-details-wrap">'+
                            '<img src="${imgUrl}" alt="${imgAlt}" />'+
                            '<h3>${name}</h3>'+
                            '<p class="option-short-desc">${shortDesc}</p>'+
                            '<p class="option-long-desc">${desc}</p>'+
                        '</div>'
                    );

                    // Run template right inner
                    $j(curContentBlockRight).append(templateRightInner, {
                        optionId: curOptionId,
                        name: ajaxResponse.name,
                        imgUrl: ajaxResponse.imgSmallUrl,
                        imgAlt: ajaxResponse.name,
                        shortDesc: Encoder.htmlDecode(ajaxResponse.shortDesc),
                        desc: Encoder.htmlDecode(ajaxResponse.desc)
                    });
                }

                curContentBlockRight.fadeIn();
            },

            saveDesign: function(serializedData, url) {

                var instance = Configurator;

                var callbackSuccess = function(response) {
                    var instance = Configurator;

                    var container = $j('#' + instance.ids.overlaySaveDesign + ' .overlay-content-wrap');
                    var formMsg = $j('#' + instance.ids.overlaySaveDesign + ' .overlay-content-wrap .form-msg');

                    formMsg.html('');
                    instance.util.createSuccessMsg(formMsg, instance.msg.saveDesignSuccess);

                    // Show close button
                    $j('.btn-close', container).show();
                    // Hide form
                    $j('form', container).hide();

                    $j(container).unmask();
                };
                var callbackFailure = function(response) {
                    var instance = Configurator;

                    var container = $j('#' + instance.ids.overlaySaveDesign + ' .overlay-content-wrap');
                    var formMsg = $j('#' + instance.ids.overlaySaveDesign + ' .overlay-content-wrap .form-msg');

                    formMsg.html('');
                    instance.util.createErrorMsg(formMsg, instance.msg.saveDesignFailure);

                    $j(container).unmask();
                };

                var container = $j('#' + instance.ids.overlaySaveDesign + ' .overlay-content-wrap');
                $j(container).mask(instance.msg.saveDesignProgress);

                instance.core.ajax('POST', serializedData, url, callbackSuccess, callbackFailure);
            },

            showMetaOverlay: function () {
                var instance = Configurator;

                if(instance.toolsapi.overlayOptionMeta) {
                    instance.toolsapi.overlayOptionMeta.load();
                } else {
                    instance.design.createMetaOverlay();
                }
            },

            showSaveDesignOverlay: function() {

                var instance = Configurator;

                if(instance.toolsapi.overlaySaveDesign) {
                    instance.toolsapi.overlaySaveDesign.load();
                } else {
                    instance.design.createSaveDesignOverlay(true);
                }
            }

        },

        //= Stuff related to measures
        measure: {

            activatePresets: function(){

                var instance = Configurator;

                $j('.' + instance.classes.measurePresetsWrap + ' .dd .ddChild a').click(function(e) {

                    var instance = Configurator;

                    var targetId = e.currentTarget.id;

                    var targetIdArr = targetId.split('_msa_');
                    var curSelectId = targetIdArr[0];
                    var curOptionIndex = targetIdArr[1];

                    var curSelect = $j('#' + curSelectId);
                    var curFieldsetId = $j(curSelect.parents().filter('.' + instance.classes.measurePresetsItem).get(0)).attr('rel');
                    var curInputPrefix = curFieldsetId.replace('fieldset', '');

                    var curOptionsArr = $j('option', curSelect);
                    var curOption = curOptionsArr.get(curOptionIndex);

                    var curMeasureJson = $j(curOption).data("measureJson");

                    if(typeof(curMeasureJson) == "undefined") {
                        return;
                    }

                    var curMeasureObj = JSON.parse(curMeasureJson);

                    for (var measureName in curMeasureObj) {
                        var measureVal =  curMeasureObj[measureName];
                        $j('#' + curInputPrefix + measureName).attr('value', measureVal);
                    }
                })
            },

            createMeasureGuideLinks: function() {

                var instance = Configurator;

                var measureGuides = instance.data.measureGuides.measureGuides;

                var templateMeasureGuideLinks = $j.template(
                    '<p>'+
                        '<a class="guide-link" href="${url}" target="_BLANK">${label} &raquo;</a>'+
                    '</p>'
                );

                for (var category in measureGuides) {
                    for(var gender in measureGuides[category]) {

                        var curFieldsetId = 'measure-' + category + '-' + gender + '-fieldset';
                        var curFieldset = $j('#' + curFieldsetId);

                        var curLabel = measureGuides[category][gender]['label'];
                        var curUrl = instance.url.MEASURE_GUIDES + measureGuides[category][gender]['filename'];
                        var curEmbedUrl = measureGuides[category][gender]['embedUrl'];

                        var curMeasureGuideWrap = $j('.measure-guides-wrap', curFieldset);
                        
                        $j(curMeasureGuideWrap).append(templateMeasureGuideLinks , {
                            downloadMsg: instance.msg.download,
                            url: curUrl,
                            label: curLabel
                        });

                        /* Set embed code as data on link */
                        $j('a.guide-link', curMeasureGuideWrap).data('embedUrl', curEmbedUrl);

                    }
                }

                // Attach click function to each measure guide link (opens overlay)
                $j('.measure-guides-wrap a').click(function(e) {

                    var curLink = $j(this);

                    instance.measure.showMeasureGuideOverlay(curLink);

                    return false;
                });
            },

            createPresets: function(settings) {

                var instance = Configurator;

                var curMeasures = settings.measures;
                var selectIdPrefix = settings.selectIdPrefix;
                var selectWrapClass = settings.selectWrapClass;
                var firstLabel = settings.firstLabel;

                var wrapClass = instance.classes.measurePresetsWrap;

                var templateMeasureSelect = $j.template(
                    '<select id="${selectId}"></select>'
                );

                var templateOption = $j.template(
                    '<option value="${optionValue}">${optionLabel}</option>'
                );

                for (var category in curMeasures) {
                    for(var gender in curMeasures[category]) {

                        // TODO - only insert if there are measures

                        var curFieldsetId = 'measure-' + category + '-' + gender + '-fieldset';
                        var curFieldset = $j('#' + curFieldsetId);
                        var curSelectId = 'measure-' + category + '-' + gender + selectIdPrefix;

                        var curSelectWrapArr = $j('.' + selectWrapClass, curFieldset);

                        // There is no select wrap
                        if(curSelectWrapArr.length == 0) {
                            // Do nothing
                        } else {

                            var curSelectWrap = $j(curSelectWrapArr.get(0));
                            curSelectWrap.attr('rel', curFieldsetId);

                            // Append block with select
                            $j(curSelectWrap, curFieldset).append(templateMeasureSelect, {
                                selectId: curSelectId
                            });

                            // Get selectDomItem
                            var select = $j('#' + curSelectId, curFieldset);

                            // Append first option
                            $j(select).append(templateOption , {
                                optionValue: "",
                                optionLabel: firstLabel
                            });

                            $j.each(curMeasures[category][gender], function(index, profileObj){

                                var curId = profileObj.id;
                                var curLabel = profileObj.label;
                                var curMeasures = profileObj.measures;
                                var curMeasuresJSON = JSON.stringify(curMeasures);

                                $j(select).append(templateOption , {
                                    optionValue: curId,
                                    optionLabel: curLabel
                                });

                                $j('option:last', select).data("measureJson", curMeasuresJSON);
                            });
                        }
                    }
                }
            },

            createPresetsStandard: function() {

                var instance = Configurator;

                var settings = {
                    measures: instance.data.standardMeasures.standardMeasures,
                    selectIdPrefix: 'standard',
                    selectWrapClass: 'measure-presets-standard',
                    firstLabel: instance.msg.useStandardMeasure
                };

                instance.measure.createPresets(settings);
            },

            createPresetsUser: function() {

                var instance = Configurator;

                var settings = {
                    measures: instance.data.userMeasures.userMeasures,
                    selectIdPrefix: 'user',
                    selectWrapClass: 'measure-presets-user',
                    firstLabel: instance.msg.useUserMeasure
                };

                instance.measure.createPresets(settings);
            },

            createSaveProfileOverlay: function(load) {

                var instance = Configurator;

                var overlayId = instance.ids.overlaySaveMeasures;
                var formId = 'configuratorSaveMeasuresForm';
                var formUrl = instance.url.SAVE_MEASURES;

                var templateOverlay = $j.template(
                    '<div id="${overlayId}" class="simple_overlay overlay-save-measures">'+
                        '<div class="overlay-content-wrap">'+
                            '<div class="form-msg"></div>'+
                            '<form id="${formId}" action="${formUrl}" method="post">'+
                                '<fieldset>'+
                                    '<div class="ctrl-holder clearfix"><label>M&aring;ttprofilens namn:</label> <input name="measureProfileName" class="input-text" /></div>'+
                                    '<div class="ctrl-holder clearfix">'+
                                        '<input type="submit" value="Spara m&aring;ttprofil" />'+
                                        '<button class="button btn-cancel" type="button"><span>Avbryt</span></button>'+
                                    '</div>'+
                                '</fieldset>'+
                            '</form>'+
                            '<div class="btn-wrap">'+
                                '<button class="button btn-close" type="button"><span>St&auml;ng</span></button>'+
                            '</div>'+
                        '</div>'+
                    '</div>'
                );

                $j('body').append(templateOverlay, {
                    overlayId: overlayId,
                    formId: formId,
                    formUrl: formUrl
                });

                // select the overlay element - and "make it an overlay"
                instance.toolsapi.overlaySaveMeasures = $j('#' + overlayId).overlay({
                    api: true,
                    expose: {
                        color: '#333',
                        opacity: 0.3
                    },
                    closeOnClick: true,
                    onBeforeLoad: function() {

                        // Hide close button
                        $j('.btn-close', this.getContent()).hide();
                        // Show form
                        $j('form', this.getContent()).show();
                        // Remove form messages
                        $j('.form-msg', this.getContent()).html('');
                    },
                    onLoad: function() {},
                    onBeforeClose: function() {},
                    onClose: function() {}
                });

                $j('.btn-cancel,.btn-close', instance.toolsapi.overlaySaveMeasures.getContent()).click(function() {
                    var instance = Configurator;
                    instance.toolsapi.overlaySaveMeasures.close();
                    return false;
                });

                var form = instance.toolsapi.overlaySaveMeasures.getContent().find("form");
                var formSubmitBtn = form.find('input[type="submit"]');

                // Bind form submit button
                formSubmitBtn.click(function() {
                    var measureField = $j('#measure-type-fieldset textarea', instance.dom.wizard);
                    var measureJSON = $j(measureField).attr('value');

                    var form = $j(this).parents('.overlay-content-wrap').find('form');
                    var formInputs = form.find('input.input-text');

                    var data = form.serialize() + '&measure_json=' + measureJSON;
                    var url = form.attr('action');

                    instance.measure.saveProfile(data, url);
                    return false;
                });

                if(load) {
                    instance.toolsapi.overlaySaveMeasures.load();
                }
            },

            getMeta: function(sku) {

                var instance = Configurator;

                var serializedData = 'sku=' + sku;
                var url = instance.url.GET_MEASURE_META;

                var callbackSuccess = function(response) {
                    var instance = Configurator;
                    instance.measure.metaSuccess(response);
                };
                var callbackFailure = function(response) {
                    var instance = Configurator;
                    instance.measure.metaFailure(response);
                };

                instance.core.ajax('GET', serializedData, url, callbackSuccess, callbackFailure);
            },

            metaFailure: function(response) {

                var instance = Configurator;

                // Unmask all metaWraps in wizard
                $j('.measure-meta-inner', instance.dom.wizard).unmask();

            },

            metaSuccess: function(responseTxt) {

                var instance = Configurator;

                var response = JSON.parse(responseTxt);

                var curRelItemArr = $j('.measure-inputs-block [rel="' + response.sku + '"]', instance.dom.wizard);
                var curRelItem = $j(curRelItemArr.get(0));

                var curLabelArr = $j('label:first', curRelItem);
                var curLabel = $j(curLabelArr.get(0));

                //If curRelItem is label > set label to curRelItem
                if(curRelItem.hasClass('measure-block-label')) {
                    curLabel = curRelItem;
                }

                var curMetaWrapInnerArr = curRelItem.parents().filter('.measure-fieldset').find('.measure-meta-inner');
                var curMetaWrapInner = $j(curMetaWrapInnerArr.get(0));

                // Get current meta list (create if doesnt exist)
                var curMetaListArr = $j('ul.meta-list', curMetaWrapInner);
                if(curMetaListArr.length == 0) {
                    $j(curMetaWrapInner).append('<ul class="meta-list"></ul>');
                    curMetaListArr = $j('ul.meta-list', curMetaWrapInner);
                }
                var curMetaList = $j(curMetaListArr.get(0));

                var templateMetaListItem = $j.template(
                    '<li id="${metaId}" class="${metaClass}">'+
                        '<h3 class="meta-label">${metaLabel}</h3>'+
                        '<div class="meta-text">'+
                            '${metaText}'+
                        '</div>'+
                        '<div class="meta-media">'+
                            '${metaShortDesc}'+
                        '</div>'+
                    '</li>'
                );

                var metaId = 'meta-' + response.sku;

                // Check that item does not already exist
                var curMetaItem = $j('#' + metaId);

                if(curMetaItem.length > 0) {
                    // Do nothing
                } else {

                    var metaClass = '';
                    var metaLabel = curLabel.text();
                    var metaText = '';
                    var metaShortDesc = '';

                    if(response.items == 'noSuchItem') {
                        metaClass = 'no-data'
                    } else {
                        metaText = response.items.desc;
                        metaShortDesc = response.items.shortDesc;
                    }

                    curMetaList.append(templateMetaListItem, {
                        metaId: metaId,
                        metaLabel: metaLabel,
                        metaClass: metaClass,
                        metaText: Encoder.htmlDecode(metaText),
                        metaShortDesc: Encoder.htmlDecode(metaShortDesc)
                    });
                    curMetaItem = $j('#' + metaId);

                    // Fix image urls
                    curMetaItem.find('.meta-media img').each(function(i, domEl) {

                        var imgUrl = $j(domEl).attr('src');
                        if(imgUrl.match('http:')) {
                            // Do nothing
                        } else {
                            var newImgUrl = instance.url.DEFAULT_SKIN_URL + imgUrl;
                            $j(domEl).attr('src', newImgUrl);
                        }

                        // Fix width and height
                        $j(domEl).attr('width', '80');
                        $j(domEl).attr('height', '80');
                    });

                    // Add hover pulse behaviour to images
                    $j('.meta-media img', curMetaItem).hoverpulse({
                        size: 140,
                        speed: 400
                    });
                    curMetaItem.find('.meta-media ul').addClass('clearfix');

                    // Fix video urls
                    curMetaItem.find('.meta-media .meta-video a').each(function(i, domEl) {

                        var url = $j(domEl).attr('href');
                        if(url.match('http:')) {
                            // Do nothing
                        } else {
                            var newUrl = instance.url.DEFAULT_SKIN_URL + url;
                            $j(domEl).attr('href', newUrl);
                            $j(domEl).attr('id', 'metavideo-' + response.sku);
                        }
                    });


                    if($j('.meta-video', curMetaItem).length > 0) {
                        var curPlayers = $f('metavideo-' + response.sku, {
                            debug: true,
                            src: instance.url.DEFAULT_SKIN_URL + '/swf/flowplayer-3.1.5.swf',
                            wmode: 'opaque'
                        });

                        // this function is called when splash image is clicked or player's load() method is called
                        curPlayers.onBeforeLoad(function()  {

                            // this is the place to start scripting with Flowplayer
                            //alert("onBefore player load");

                            // this- variable points to the player's API
                            //this.getScreen().animate({width:300, height:200});
                        });
                        curPlayers.onLoad(function()  {

                            // this is the place to start scripting with Flowplayer
                            //alert("player loaded");

                            // this- variable points to the player's API
                            //this.getScreen().animate({width:300, height:200});
                        });

                        //console.log(curPlayers);
                        //curPlayers.load();


                    }
                }

                $j('ul.meta-list>li', instance.dom.wizard).hide();
                $j(curMetaWrapInner).unmask();
                curMetaItem.fadeIn();
            },

            saveProfile: function(serializedData, url) {

                var instance = Configurator;

                var callbackSuccess = function(response) {
                    var instance = Configurator;
                    instance.measure.saveProfileSuccess(response);

                };
                var callbackFailure = function(response) {
                    var instance = Configurator;
                    instance.measure.saveProfileFailure(response);
                };

                var container = $j('#' + instance.ids.overlaySaveMeasures + ' .overlay-content-wrap');
                $j(container).mask(instance.msg.saveMeasuresProgress);

                instance.core.ajax('POST', serializedData, url, callbackSuccess, callbackFailure);
            },

            saveProfileFailure: function(response) {

                    var instance = Configurator;

                    var container = $j('#' + instance.ids.overlaySaveMeasures + ' .overlay-content-wrap');
                    var formMsg = $j('#' + instance.ids.overlaySaveMeasures + ' .overlay-content-wrap .form-msg');

                    formMsg.html('');
                    instance.util.createErrorMsg(formMsg, instance.msg.saveMeasuresFailure);

                    $j(container).unmask();
            },

            saveProfileSuccess: function(response) {

                    var instance = Configurator;

                    var container = $j('#' + instance.ids.overlaySaveMeasures + ' .overlay-content-wrap');
                    var formMsg = $j('#' + instance.ids.overlaySaveMeasures + ' .overlay-content-wrap .form-msg');

                    formMsg.html('');
                    instance.util.createSuccessMsg(formMsg, instance.msg.saveMeasuresSuccess);

                    // Show close button
                    $j('.btn-close', container).show();
                    // Hide form
                    $j('form', container).hide();

                    $j(container).unmask();
            },

            /* FLAG */

            showMeasureFieldsetByTypeId: function(typeId) {

                var instance = Configurator;

                var element = $j('#' + typeId);

                instance.measure.showMeasureFieldset(element);
            },

            showMeasureFieldset: function(element) {

                var instance = Configurator;

                //var element = $j('#' + elementId);

                // Set active item to selected
                $j("ul.measure-type-list li", instance.dom.wizard).removeClass('selected');
                element.addClass('selected');

                // Hide pane validator
                element.parents().filter('.w-pane').find('.pane-validator').hide();

                var elementLinkArr = $j('a', element);
                var elementLink = $j(elementLinkArr.get(0));

                // Hide all measure fieldsets
                $j('.measure-fieldset').hide();

                // Get which measure fieldset to display
                var curMeasureId = $j(elementLink).attr('rel');

                // Show measure fieldset (and show first label info)
                $j('#' + curMeasureId)
                    .fadeIn()
                    .find('.measure-inputs-block:first .measure-block-label').trigger('click');
            },

            showMeasureGuideOverlay: function(curLink) {

                var instance = Configurator;

                var overlayId = instance.ids.overlayMeasureGuide;

                var templateMeasureGuideOverlay = $j.template(
                    '<div id="${overlayId}" class="simple_overlay overlay-measure-guide">'+
                        '<div class="overlay-content-wrap">'+
                            '<div class="doc-wrap">'+
                                '<div class="download-wrap">'+
                                    '${downloadlabel}: <a class="pdf" href="${downloadUrl}" target="_BLANK">${downloadMsg}</a>'+
                                '</div>'+
                                '<object codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" id="doc_331481590850358" name="doc_331481590850358" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" align="middle" height="500" width="700" >'+
                                        '<param name="movie" value="${embedUrl}">'+
                                        '<param name="quality" value="high">'+
                                        '<param name="play" value="true">'+
                                        '<param name="loop" value="true">'+
                                        '<param name="scale" value="showall">'+
                                        '<param name="wmode" value="opaque">'+
                                        '<param name="devicefont" value="false">'+
                                        '<param name="bgcolor" value="#ffffff">'+
                                        '<param name="menu" value="true">'+
                                        '<param name="allowFullScreen" value="true">'+
                                        '<param name="allowScriptAccess" value="always">'+
                                        '<param name="salign" value="">'+
                                        '<param name="mode" value="list">'+
                                        '<embed src="${embedUrl}" menu="true" allowfullscreen="true" allowscriptaccess="always" salign="" type="application/x-shockwave-flash" align="middle" mode="list" height="500" width="700"></embed>'+
                                '</object>'+
                            '</div>'+
                        '</div>'+
                    '</div>'
                );

                var curDownloadUrl = $j(curLink).attr("href");
                var curDownloadMsg = $j(curLink).html();
                var curEmbedUrl = $j(curLink).data("embedUrl");

                $j('body').append(templateMeasureGuideOverlay, {
                    overlayId: overlayId,
                    downloadlabel: instance.msg.download,
                    downloadMsg: curDownloadMsg,
                    downloadUrl: curDownloadUrl,
                    embedUrl: curEmbedUrl
                });

                // select the overlay element - and "make it an overlay"
                $j('#' + overlayId).overlay({

                    api: true,
                    expose: {
                        color: '#333',
                        opacity: 0.3
                    },
                    closeOnClick: true,
                    onLoad: function() {

                    },
                    onClose: function() {
                        // Remove from dom on close
                        $j('#' + overlayId).remove();
                    }

                // load it immediately after the construction
                }).load();
            },

            showMeta: function(metaWrapInner, sku) {

                var instance = Configurator;

                // Unload flowplayers if exists
                if(flowplayer()) {
                    flowplayer("*").each(function() {
                        this.unload();
                    });

                }

                var curMetaId = 'meta-' + sku;
                var curMetaItem = $j('#' + curMetaId);

                if(curMetaItem.length > 0) {
                    // Item already exists > hide all other items and show this item
                    $j('ul.meta-list>li', instance.dom.wizard).hide();
                    curMetaItem.fadeIn();
                } else {
                    metaWrapInner.mask(instance.msg.optionMetaLoadProgress);
                    instance.measure.getMeta(sku);
                }
            },

            showSaveProfileOverlay: function () {

                var instance = Configurator;

                if(instance.toolsapi.overlaySaveMeasures) {
                    instance.toolsapi.overlaySaveMeasures.load();
                } else {
                    instance.measure.createSaveProfileOverlay(true);
                }
            }

        },

        //= Stuff done to prepare configurator for launch
        prepare: {

            mapOptions: function() {

                var instance = Configurator;
                var fieldmapJSON = instance.data.configuratorFieldMap.fieldmap;

                for (var optionName in fieldmapJSON) {

                    var curField = fieldmapJSON[optionName];
                    var curDomId = curField.domId;
                    var curActive = curField.active;
                    var curEl = $j('#' + curDomId);

                    curEl.data('optionName', optionName);

                    if(!curActive) {
                        var holderArr = curEl.parents('.ctrl-holder');
                        var holder = $j(holderArr.get(0));
                        holder.addClass(instance.classes.holderDeactive);
                    }

                }
            },

            populate: function() {

                var instance = Configurator;

                var setupJSON = instance.data.initialSetup.configuratorSetup;
                var fieldmapJSON = instance.data.configuratorFieldMap.fieldmap;

                for (var fieldName in setupJSON) {

                    var curField = fieldmapJSON[fieldName];
                    var curFieldId = curField.domId;
                    var curFieldEl = $j('#' + curFieldId);

                    var fieldVal =  setupJSON[fieldName];
                    var curFieldVal = fieldVal;
                    var curOption = $j('#' + curFieldId);

                    // Fabric
                    if(fieldName == 'fabric') {

                        var curFieldOptionArr = $j('option[value=' + curFieldVal + ']', curFieldEl);
                        var curFieldOption = $j(curFieldOptionArr.get(0));

                        var isSaleable = $j(curFieldOption).data("isSaleable");

                        if(isSaleable == 0) {
                            var curFieldset = $j('#w-pane-1 .pane-content>fieldset:first');
                            curFieldset.prepend('<div class="option-deactivated-msg option-deactivated-msg-full">' + instance.msg.fabricOutOfStock + '</div>');
                        } else {
                            curOption.attr('value', curFieldVal);
                        }
                    }

                    //Measures (cMeasureJson)
                    else if(fieldName == 'measureJson' && curFieldVal != '') {
                        var measureObj = JSON.parse(curFieldVal);

                        var measureCategory = measureObj.category;
                        var measureGender = measureObj.gender;
                        var measures = measureObj.measures;

                        var typeId = 'measure-type-' + measureCategory + '-' + measureGender;
                        instance.measure.showMeasureFieldsetByTypeId(typeId);

                        var inputPrefix = 'measure-' + measureCategory + '-' + measureGender + '-';

                        for (var measureName in measures) {

                            var curMeasureId = inputPrefix + measureName;
                            var curMeasureVal = measures[measureName];

                            $j('#' + curMeasureId).attr('value', curMeasureVal);
                        }
                    }

                    else if(curFieldVal != '') {
                        curOption.attr('value', curFieldVal);
                    }


                }
            },

            replaceSelects: function() {

                var instance = Configurator;

                // Fancy select boxes
                // Filter out those with deactivated holders
                $j('select', instance.dom.wizard)
                    .filter(function(index) {
                        var deactiveHolders = $j(this).parents('.' + instance.classes.holderDeactive);
                        return (deactiveHolders.length == 0);
                    })
                    .msDropDown({
                        showIcon: false
                });

                // Fix width bug
                $j('.dd', instance.dom.wizard)
                    .filter(function(index) {
                        var presetsWrap = $j(this).parents('.' + instance.classes.measurePresetsWrap);
                        return (presetsWrap.length == 0);
                    })
                    .css('width','240px');
                $j('.ddChild', instance.dom.wizard)
                    .filter(function(index) {
                        var presetsWrap = $j(this).parents('.' + instance.classes.measurePresetsWrap);
                        return (presetsWrap.length == 0);
                    })
                    .css('width','236px');

                $j('.' + instance.classes.measurePresetsWrap + ' .dd', instance.dom.wizard).css('width','220px');
                $j('.' + instance.classes.measurePresetsWrap + ' .ddChild', instance.dom.wizard).css('width','216px');

                // Turn on validation for replaced selects
                instance.util.activateValidation();
                instance.measure.activatePresets();
            },

            restructure: function () {

                var instance = Configurator;

                var orgSetup = {};
                orgSetup.addToCart = $j('.add-to-cart:first', instance.dom.wizard);
                orgSetup.addToCartButtonSpan = $j('.add-to-cart:first button:first span:first', instance.dom.wizard);
                orgSetup.priceBox = $j('.price-box:first', instance.dom.wizard);
                orgSetup.holderStep1 = $j('.holder-step-1', instance.dom.wizard);
                orgSetup.holderStep2 = $j('.holder-step-2', instance.dom.wizard);
                orgSetup.holderMeasureType = $j('.holder-measure-type', instance.dom.wizard);
                orgSetup.holderMeasureBody = $j('.holder-measure-body', instance.dom.wizard);
                orgSetup.holderMeasureShirt = $j('.holder-measure-shirt', instance.dom.wizard);

                var wizardSetup = {};
                wizardSetup.addToCart = $j('#w-pane-4 .add-to-cart-wrap:first', instance.dom.wizard);
                wizardSetup.price = $j('.w-price-wrap:first', instance.dom.wizard);
                wizardSetup.contentStep1 = $j('#w-pane-1 .pane-content:first fieldset:first', instance.dom.wizard);
                wizardSetup.contentStep2 = $j('#w-pane-2 .pane-content:first fieldset:first', instance.dom.wizard);
                wizardSetup.contentMeasureType = $j('#w-pane-3 .pane-content:first #measure-type-fieldset', instance.dom.wizard);

                // Move add to cart
                $j(wizardSetup.addToCart).append(orgSetup.addToCart);
                $j(wizardSetup.addToCart).find("fieldset:first")
                    .empty()
                    .append('<button class="btn-styled btn-styled-1" type="button"><span>' + orgSetup.addToCartButtonSpan.text() + '</span></button>');

                // Move price
                var priceWrapEl = $j(wizardSetup.price).append(orgSetup.priceBox);
                // Fix price id
                var priceEl = $j(".price-box span:first", priceWrapEl);
                var priceElId = $j(".price-box span:first", priceWrapEl).attr("id");
                if(priceElId) {
                    var priceElNewId = priceElId.replace("_clone", "");
                    priceEl.attr("id", priceElNewId);
                }

                // Move step holders
                $j(wizardSetup.contentStep1).append(orgSetup.holderStep1);
                $j(wizardSetup.contentStep2).append(orgSetup.holderStep2);
                $j(wizardSetup.contentMeasureType).append(orgSetup.holderMeasureType);
                //$j(wizardSetup.contentMeasureBody).append(orgSetup.holderMeasureBody);
                //$j(wizardSetup.contentMeasureShirt).append(orgSetup.holderMeasureShirt);
            },

            setConstants: function() {

                var instance = Configurator;

                // Define some variables
                instance.ajaxresponse = {};
                instance.classes = {};
                instance.data = {};
                instance.dom = {};
                instance.ids = {};
                instance.msg = {};
                instance.toolsapi = {};
                instance.url = {};

                // Some default urls
                instance.url.DEFAULT_SKIN_URL = BASE_URL + 'skin/frontend/default/thefairtailor/';
                instance.url.AJAX_BASE = BASE_URL + 'tft-ext';
                instance.url.GET_MEASURE_META = instance.url.AJAX_BASE + '/get_measure_meta/';
                instance.url.GET_OPTION_META = instance.url.AJAX_BASE + '/get_option_meta/';
                instance.url.SAVE_DESIGN = instance.url.AJAX_BASE + '/save_design/';
                instance.url.SIGNIN = instance.url.AJAX_BASE + '/signin/';
                instance.url.SAVE_MEASURES = instance.url.AJAX_BASE + '/save_measures/';
                instance.url.MEASURE_GUIDES = instance.url.DEFAULT_SKIN_URL + 'documents/measurement_guides/';

                // Define ajax messages
                instance.ajaxresponse.currentSuccess = '';
                instance.ajaxresponse.currentError = '';

                // Define messages
                instance.msg.loadingConfigurator = 'Laddar skjortkonfiguratorn...';
                instance.msg.optionMetaLoadProgress = 'Laddar information...';
                instance.msg.optionMetaLoadError = 'N&aring;got blev galet n&auml;r informationen laddas. V&auml;lj n&aring;got annat val och testa sen med detta val igen.';

                instance.msg.fabricOutOfStock = 'Din laddade design inneh&aring;ller ett tyg som just nu inte finns i lager. Tyget har ersatts med ett annat.';

                instance.msg.download = 'Ladda ner';
                instance.msg.saveDesignProgress = 'Sparar skjortdesign...';
                instance.msg.saveDesignFailure = 'N&aring;got gick fel n&auml;r skjortdesignen skulle sparas.';
                instance.msg.saveDesignSuccess = 'Skjortdesignen har sparats';
                instance.msg.saveMeasuresProgress = 'Sparar m&aring;ttprofil...';
                instance.msg.saveMeasuresFailure = 'N&aring;got gick fel n&auml;r m&aring;ttprofilen skulle sparas.';
                instance.msg.saveMeasuresSuccess = 'M&aring;ttprofilen har sparats';
                instance.msg.selectDeactivated = 'Kan bara v&auml;ljas med &auml;rmtyp "L&aring;ng &auml;rm"';
                instance.msg.signInFailure = 'Inloggningen misslyckades. Kontrollera din epost och ditt l&ouml;senord.';
                instance.msg.signInProgress = 'Loggar in...';
                instance.msg.signInSuccess = 'Du har loggats in.';
                instance.msg.reloadingConfigurator = 'Skjortkonfiguratorn laddas om...';
                instance.msg.useStandardMeasure = 'Utg&aring; fr&aring;n standardm&aring;tt';
                instance.msg.useUserMeasure = 'Utg&aring; fr&aring;n egen sparad profil';

                // Define domElements for configurator
                instance.dom.configurator = $j(".configurator");
                instance.dom.configuratorInfo = $j(".configuration-info", instance.dom.configurator);
                instance.dom.wizard = $j(".wizard", instance.dom.configurator);

                // Define some classes
                instance.classes.holderDeactive = 'ctrl-holder-deactive';
                instance.classes.measurePresetsWrap = 'measure-block-presets-wrap';
                instance.classes.measurePresetsItem = 'measure-presets-item';
                instance.classes.signinWrap = 'signin-wrap';
                instance.classes.saveMeasuresWrap = 'save-measures-wrap';
                instance.classes.saveShirtdesignWrap = 'save-shirtdesign-wrap';

                // Define some ids
                instance.ids.overlayMeasureGuide = 'configuratorOverlayMeasureGuide';
                instance.ids.overlayOptionMetaSelect = '';
                instance.ids.overlayOptionMetaOptionActive = '';
                instance.ids.overlayOptionMeta = 'configuratorOverlayOptionMeta';
                instance.ids.overlayOptionMetaContent = 'configuratorOverlayOptionMetaContent';
                instance.ids.overlayOptionMetaFooter = 'configuratorOverlayOptionMetaFooter';
                instance.ids.overlayOptionMetaLeft = 'configuratorOverlayOptionMetaLeft';
                instance.ids.overlayOptionMetaRight = 'configuratorOverlayOptionMetaRight';
                instance.ids.overlaySaveDesign = 'configuratorOverlaySaveDesign';
                instance.ids.overlaySaveMeasures = 'configuratorOverlaySaveMeasures';
                instance.ids.overlaySignin = 'configuratorOverlaySignin';
                instance.ids.overlayWrapVideo = 'configuratorOverlayWrapVideo';

                // Define tools api
                instance.toolsapi.overlayOptionMeta = false;
                instance.toolsapi.overlayOptionMetaRightExpose = false;
                instance.toolsapi.overlaySignin = false;
                instance.toolsapi.overlaySaveMeasures = false;
                instance.toolsapi.overlaySaveDesign = false;
                instance.toolsapi.wizardTabs = false;

                instance.data.configuratorFieldMap = "";
                if(typeof(CONFIGURATOR_FIELDMAP_JSON) != "undefined") {
                    instance.data.configuratorFieldMap = JSON.parse(CONFIGURATOR_FIELDMAP_JSON);
                }

                instance.data.measureGuides = "";
                if(typeof(CONFIGURATOR_MEASURE_GUIDES_JSON) != "undefined") {
                    instance.data.measureGuides = JSON.parse(CONFIGURATOR_MEASURE_GUIDES_JSON);
                }

                instance.data.standardMeasures = "";
                if(typeof(CONFIGURATOR_STANDARD_MEASURES_JSON) != "undefined") {
                    instance.data.standardMeasures = JSON.parse(CONFIGURATOR_STANDARD_MEASURES_JSON);
                }

                instance.data.userMeasures = "";
                if(typeof(CONFIGURATOR_USER_MEASURES_JSON) != "undefined") {
                    instance.data.userMeasures = JSON.parse(CONFIGURATOR_USER_MEASURES_JSON);
                }

                instance.data.optionsMeta = "";
                if(typeof(CONFIGURATOR_OPTIONS_JSON) != "undefined") {
                    instance.data.optionsMeta = JSON.parse(CONFIGURATOR_OPTIONS_JSON);
                }

                instance.data.initialSetup = "";
                if(typeof(CONFIGURATOR_SETUP_JSON) != "undefined") {
                    instance.data.initialSetup = JSON.parse(CONFIGURATOR_SETUP_JSON);
                }

                /* START PAGE FLAG */
                instance.data.startPage = "";
                if(typeof(CONFIGURATOR_STARTPAGE) != "undefined") {
                    instance.data.startPage = CONFIGURATOR_STARTPAGE;
                }
            },

            setDefaults: function() {

                var instance = Configurator;

                $j("select", instance.dom.wizard).each(function(i, domEl) {

                    var holderArr = $j(domEl).parents('.ctrl-holder');
                    var holder = $j(holderArr.get(0));
                    var deactive = holder.hasClass(instance.classes.holderDeactive);

                    // If dective - add a new first option with a blank value
                    if(deactive) {
                        $j(domEl).prepend('<option value="">Option Deactive</option>');
                    }

                    // Set select value to the first option
                    var curOption = $j("option", domEl).get(0);
                    var curOptionVal = $j(curOption).attr('value');
                    $j(domEl).attr('value', curOptionVal);
                });
            },

            setMeta: function() {

                var instance = Configurator;

                // Only continue if optionsMeta is set
                if(instance.data.optionsMeta == "") {
                    return;
                }

                // Component Meta
                $j("select", instance.dom.wizard).each(function(i, domElSel) {

                    var domElSelId = $j(domElSel).attr("id");

                    var curMetaObject = instance.data.optionsMeta[i];
                    var curMetaOptions = curMetaObject.options;

                    $j("option", this).each(function(j, domElOpt) {

                        // Attach an id to each option that can be used as a reference to retrive data attached to the dom element
                        if(!this.id) {
                            $j(this).attr("id", domElSelId + "_option_" + j);
                        }

                        // Attach meta data to each option element
                        var curMetaOption = curMetaOptions[j];
                        if(typeof(curMetaOption) != "undefined") {

							// Attach imgThumbUrl to title attribute
							if(curMetaOption.imgThumbUrl != '') {
								$j(this).attr('title', curMetaOption.imgThumbUrl);
							}

							// Set data
                            $j(this).data("sku", curMetaOption.sku);
                            $j(this).data("name", curMetaOption.name);
                            $j(this).data("imgThumbUrl", curMetaOption.imgThumbUrl);
							$j(this).data("isSaleable", curMetaOption.isSaleable);

                            // Disable fabrics that are not saleable
                            if(domElSelId == instance.data.configuratorFieldMap.fieldmap.fabric.domId) {
                                if(curMetaOption.isSaleable == "0") {
                                    // Disabled attribute does not work in ie (doesnt matter because selects are replaced)
                                    $j(this).attr('disabled', 'disabled');
                                }
                            }

                        }
                    });

                });
            }
        },

        user: {

            showSigninOverlay: function () {

                var instance = Configurator;

                var overlayId = instance.ids.overlaySignin;
                var formId = 'configuratorSigninForm';
                var formUrl = instance.url.SIGNIN;

                var templateSigninOverlay = $j.template(
                    '<div id="${overlayId}" class="simple_overlay overlay-signin">'+
                        '<div class="overlay-content-wrap">'+
                            '<form id="${formId}" action="${formUrl}" method="post">'+
                                '<div class="form-msg"></div>'+
                                '<fieldset>'+
                                    '<div class="ctrl-holder clearfix"><label>Epost:</label> <input name="email" class="input-text" /></div>'+
                                    '<div class="ctrl-holder clearfix"><label>L&ouml;senord:</label> <input type="password" name="password" class="input-text" /></div>'+
                                    '<div class="ctrl-holder clearfix"><input type="submit" value="Logga in" /></div>'+
                                '</fieldset>'+
                            '</form>'+
                        '</div>'+
                    '</div>'
                );

                $j('body').append(templateSigninOverlay, {
                    overlayId: overlayId,
                    formId: formId,
                    formUrl: formUrl
                });

                // select the overlay element - and "make it an overlay"
                $j('#' + overlayId).overlay({

                    api: true,
                    expose: {
                        color: '#333',
                        opacity: 0.3
                    },
                    closeOnClick: true,
                    onLoad: function() {

                        var form = this.getContent().find("form");

                        form.find('input[type="submit"]').click(function() {

                            var form = $j(this).parents('.overlay-content-wrap').find('form');
                            var data = form.serialize() + '&json_setup=' + instance.util.getSetupJson();
                            var url = form.attr('action');

                            instance.user.signin(data, url);

                            return false;
                        });
                    },
                    onBeforeClose: function() {

                        // Unbind click event on form
                        var form = this.getContent().find("form");
                        form.find('input[type="submit"]').unbind('click');

                    },
                    onClose: function() {
                        // Remove from dom on close
                        $j('#' + overlayId).remove();
                    }

                // load it immediately after the construction
                }).load();
            },

            signin: function(serializedData, url) {

                var instance = Configurator;

                var callbackSuccess = function(response) {
                    var instance = Configurator;
                    instance.user.signinSuccess(response);
                };
                var callbackFailure = function(response) {
                    var instance = Configurator;
                    instance.user.signinFailure(response);
                };

                var container = $j('#' + instance.ids.overlaySignin + ' .overlay-content-wrap');
                $j(container).mask(instance.msg.signInProgress);

                instance.core.ajax('POST', serializedData, url, callbackSuccess, callbackFailure);
            },

            signinFailure: function(responseTxt) {

                var instance = Configurator;

                var container = $j('#' + instance.ids.overlaySignin + ' .overlay-content-wrap')
                var formMsg = $j('#' + instance.ids.overlaySignin + ' .overlay-content-wrap .form-msg')

                $j(container).unmask(instance.msg.signInProgress);
                $j(formMsg).html('');
                instance.util.createErrorMsg(formMsg, instance.msg.signInFailure);
            },

            signinSuccess: function(responseTxt) {

                var instance = Configurator;

                var container = $j('#' + instance.ids.overlaySignin + ' .overlay-content-wrap')
                var formMsg = $j('#' + instance.ids.overlaySignin + ' .overlay-content-wrap .form-msg')

                $j(container).unmask(instance.msg.signInProgress);
                $j(container).mask(instance.msg.signInSuccess + '' +  instance.msg.reloadingConfigurator);

                location.reload();
            }

        },

        //= Misc util functions
        util: {

            activateValidation: function() {

                $j('.dd .ddChild a').click(function(e) {

                    var instance = Configurator;

                    var targetId = e.currentTarget.id;

                    var targetIdArr = targetId.split('_msa_');
                    var curSelectId = targetIdArr[0];
                    var curOptionIndex = targetIdArr[1];

                    var curSelectOptionArr = $j('#' + curSelectId + ' option');
                    var curSelectOption = $j(curSelectOptionArr.get(curOptionIndex));
                    var curSelectValue = curSelectOption.attr('value');

                    // If change occurred to sleeve
                    if(curSelectId == instance.data.configuratorFieldMap.fieldmap.sleeve.domId) {
                        // If long sleeve was choosen
                        if(curSelectValue == instance.data.configuratorFieldMap.fieldmap.sleeve.optionValues.longSleeve) {
                            instance.design.activateOption(instance.data.configuratorFieldMap.fieldmap.cuff.domId);
                            instance.design.activateOption(instance.data.configuratorFieldMap.fieldmap.cuffColor.domId);
                            instance.design.activateOption(instance.data.configuratorFieldMap.fieldmap.sleavePlacketButton.domId);
                        } else {
                            instance.design.deactivateOption(instance.data.configuratorFieldMap.fieldmap.cuff.domId);
                            instance.design.deactivateOption(instance.data.configuratorFieldMap.fieldmap.cuffColor.domId);
                            instance.design.deactivateOption(instance.data.configuratorFieldMap.fieldmap.sleavePlacketButton.domId);
                        }
                    }
                });
            },

            cleanMeasures: function(setupJSON) {

                var rawSetup = JSON.parse(setupJSON);

                rawSetup.configuratorSetup.measureJson = '';

                var cleanedSetupJSON = JSON.stringify(rawSetup);

                return cleanedSetupJSON;
            },

            createErrorMsg: function(container, msg) {

                var templateAjaxProgress = $j.template(
                    '<div class="error-msg">${msg}</div>'
                );
                $j(container).append(templateAjaxProgress , {
                    msg: msg
                });
            },

            createSuccessMsg: function(container, msg) {

                var templateAjaxProgress = $j.template(
                    '<div class="success-msg">${msg}</div>'
                );
                $j(container).append(templateAjaxProgress , {
                    msg: msg
                });
            },

            getMeasureJson: function(activeFieldset) {

                var measurePrefix = $j(activeFieldset).attr('id').replace('fieldset', '');

                var selType = $j('ul.measure-type-list li.selected').get(0);
                var selTypeId = $j(selType).attr('id');
                var selTypeIdSplit = selTypeId.split('-');
                var selTypeCategory = selTypeIdSplit[2];
                var selTypeGender = selTypeIdSplit[3];

                var measureObj = {
                    'category' :selTypeCategory,
                    'gender': selTypeGender,
                    'measures': {}
                };

                var measures = measureObj.measures;

                $j(activeFieldset).find('input').each(function() {
                    var curId = $j(this).attr('id');
                    var curValue = $j(this).attr('value');
                    var curKey = curId.replace(measurePrefix, '');

                    measures[curKey] = curValue;
                });

                return JSON.stringify(measureObj);
            },

            getSelectedMeasureFieldset: function() {

                var instance = Configurator;
                var selectedFieldset = false;

                var panes = instance.toolsapi.wizardTabs.getPanes();
                var measurePane = $j(panes[2]);

                var selTypeLinkArr = $j('ul.measure-type-list li.selected a', measurePane);
                if(selTypeLinkArr.length == 0) {
                    return selectedFieldset;
                } else {

                    var selTypeLink = $j(selTypeLinkArr);
                    var fieldsetId = selTypeLink.attr('rel');
                    selectedFieldset = $j('#' + fieldsetId);

                    return selectedFieldset;
                }
            },

            getSetupJson: function() {

                var instance = Configurator;

                var currentSetup = {'configuratorSetup' : {}};

                $j('.product-custom-option', instance.dom.wizard).each(function(i, element){

                    var curId = $j(element).attr('id');
                    var curOptionName = $j(element).data('optionName');
                    var curValue = $j(element).attr('value');

                    currentSetup.configuratorSetup[curOptionName] = curValue;
                });

                var currentSetupJSON = JSON.stringify(currentSetup);

                return currentSetupJSON;
            },
            
            isNumber: function (value) {
                var numberRegex = /^([0-9])*([.,][0-9]+)?$/;
                return numberRegex.test(value);
            },

            removeErrorMsg: function(container) {
                $j('.error-msg', container).remove();
            },

            removeSuccessMsg: function(container) {
                $j('.success-msg', container).remove();
            }

        }
    };
}();

$j(document).ready(function(){
    var doDebug = false;
    Configurator.init(doDebug);
});