/*

 * SmartWizard 3.3.1 plugin

 * jQuery Wizard control Plugin

 * by Dipu

 *

 * Refactored and extended:

 * https://github.com/mstratman/jQuery-Smart-Wizard

 *

 * Original URLs:

 * http://www.techlaboratory.net

 * http://tech-laboratory.blogspot.com

 */



function SmartWizard(target, options) {

    this.target       = target;

    this.options      = options;

    this.curStepIdx   = options.selected;

    this.steps        = $(target).children("ul").children("li").children("a"); // Get all anchors

    this.contentWidth = 0;

    this.msgBox = $('<div class="msgBox"><div class="content"></div><a href="#" class="close">X</a></div>');

    this.elmStepContainer = $('<div></div>').addClass("stepContainer");

    this.loader = $('<div>Loading</div>').addClass("loader");

    this.buttons = {

        next : $('<a>'+options.labelNext+'</a>').attr("href","#").addClass("buttonNext"),

        previous : $('<a>'+options.labelPrevious+'</a>').attr("href","#").addClass("buttonPrevious"),

        finish  : $('<a>'+options.labelFinish+'</a>').attr("href","#").addClass("buttonFinish")

    };



    /*

     * Private functions

     */



    var _init = function($this) {

        var elmActionBar = $('<div></div>').addClass("actionBar");

        elmActionBar.append($this.msgBox);

        $('.close',$this.msgBox).click(function() {

            $this.msgBox.fadeOut("normal");

            return false;

        });



        var allDivs = $this.target.children('div');

        // CHeck if ul with steps has been added by user, if not add them

        if($this.target.children('ul').length == 0 ){

            var ul = $("<ul/>");

            target.prepend(ul)



            // for each div create a li

            allDivs.each(function(i,e){

                var title = $(e).first().children(".StepTitle").text();

                var s = $(e).attr("id")

                // if referenced div has no id, add one.

                if (s==undefined){

                    s = "step-"+(i+1)

                    $(e).attr("id",s);

                }

                var span = $("<span/>").addClass("stepDesc").text(title);

                var li = $("<li></li>").append($("<a></a>").attr("href", "#" + s).append($("<label></label>").addClass("stepNumber").text(i + 1)).append(span));

                ul.append(li);

            });

            // (re)initialise the steps property

            $this.steps = $(target).children("ul").children("li").children("a"); // Get all anchors

        }

        $this.target.children('ul').addClass("anchor");

        allDivs.addClass("content");



        // highlight steps with errors

        if($this.options.errorSteps && $this.options.errorSteps.length>0){

            $.each($this.options.errorSteps, function(i, n){

                $this.setError({ stepnum: n, iserror:true });

            });

        }



        $this.elmStepContainer.append(allDivs);

        elmActionBar.append($this.loader);

        $this.target.append($this.elmStepContainer);



        if ($this.options.includeFinishButton){

            elmActionBar.append($this.buttons.finish)

        }



        elmActionBar.append($this.buttons.next)

            .append($this.buttons.previous);

        $this.target.append(elmActionBar);

        this.contentWidth = $this.elmStepContainer.width();



        $($this.buttons.next).click(function() {

            $this.goForward();

            return false;

        });

        $($this.buttons.previous).click(function() {

            $this.goBackward();

            return false;

        });

        $($this.buttons.finish).click(function() {

            if(!$(this).hasClass('buttonDisabled')){

                if($.isFunction($this.options.onFinish)) {

                    var context = { fromStep: $this.curStepIdx + 1 };

                    if(!$this.options.onFinish.call(this,$($this.steps), context)){

                        return false;

                    }

                }else{

                    var frm = $this.target.parents('form');

                    if(frm && frm.length){

                        frm.submit();

                    }

                }

            }

            return false;

        });



        $($this.steps).bind("click", function(e){

            if($this.steps.index(this) == $this.curStepIdx){

                return false;

            }

            var nextStepIdx = $this.steps.index(this);

            var isDone = $this.steps.eq(nextStepIdx).attr("isDone") - 0;

            if(isDone == 1){

                _loadContent($this, nextStepIdx);

            }

            return false;

        });



        // Enable keyboard navigation

        if($this.options.keyNavigation){

            $(document).keyup(function(e){

                if(e.which==39){ // Right Arrow

                    $this.goForward();

                }else if(e.which==37){ // Left Arrow

                    $this.goBackward();

                }

            });

        }

        //  Prepare the steps

        _prepareSteps($this);

        // Show the first slected step

        _loadContent($this, $this.curStepIdx);

    };



    var _prepareSteps = function($this) {

        if(! $this.options.enableAllSteps){

            $($this.steps, $this.target).removeClass("selected").removeClass("done").addClass("disabled");

            $($this.steps, $this.target).attr("isDone",0);

        }else{

            $($this.steps, $this.target).removeClass("selected").removeClass("disabled").addClass("done");

            $($this.steps, $this.target).attr("isDone",1);

        }



        $($this.steps, $this.target).each(function(i){

            $($(this).attr("href").replace(/^.+#/, '#'), $this.target).hide();

            $(this).attr("rel",i+1);

        });

    };



    var _step = function ($this, selStep) {

        return $(

            $(selStep, $this.target).attr("href").replace(/^.+#/, '#'),

            $this.target

        );

    };



    var _loadContent = function($this, stepIdx) {

        var selStep = $this.steps.eq(stepIdx);

        var ajaxurl = $this.options.contentURL;

        var ajaxurl_data = $this.options.contentURLData;

        var hasContent = selStep.data('hasContent');

        var stepNum = stepIdx+1;

        if (ajaxurl && ajaxurl.length>0) {

            if ($this.options.contentCache && hasContent) {

                _showStep($this, stepIdx);

            } else {

                var ajax_args = {

                    url: ajaxurl,

                    type: $this.options.ajaxType,

                    data: ({step_number : stepNum}),

                    dataType: "text",

                    beforeSend: function(){

                        $this.loader.show();

                    },

                    error: function(){

                        $this.loader.hide();

                    },

                    success: function(res){

                        $this.loader.hide();

                        if(res && res.length>0){

                            selStep.data('hasContent',true);

                            _step($this, selStep).html(res);

                            _showStep($this, stepIdx);

                        }

                    }

                };

                if (ajaxurl_data) {

                    ajax_args = $.extend(ajax_args, ajaxurl_data(stepNum));

                }

                $.ajax(ajax_args);

            }

        }else{

            _showStep($this,stepIdx);

        }

    };



    var _showStep = function($this, stepIdx) {

        var selStep = $this.steps.eq(stepIdx);

        var curStep = $this.steps.eq($this.curStepIdx);

        if(stepIdx != $this.curStepIdx){

            if($.isFunction($this.options.onLeaveStep)) {

                var context = { fromStep: $this.curStepIdx+1, toStep: stepIdx+1 };

                if (! $this.options.onLeaveStep.call($this,$(curStep), context)){

                    return false;

                }

            }

        }

        $this.elmStepContainer.height(_step($this, selStep).outerHeight());

        var prevCurStepIdx = $this.curStepIdx;

        $this.curStepIdx =  stepIdx;

        if ($this.options.transitionEffect == 'slide'){

            _step($this, curStep).slideUp("fast",function(e){

                _step($this, selStep).slideDown("fast");

                _setupStep($this,curStep,selStep);

            });

        } else if ($this.options.transitionEffect == 'fade'){

            _step($this, curStep).fadeOut("fast",function(e){

                _step($this, selStep).fadeIn("fast");

                _setupStep($this,curStep,selStep);

            });

        } else if ($this.options.transitionEffect == 'slideleft'){

            var nextElmLeft = 0;

            var nextElmLeft1 = null;

            var nextElmLeft = null;

            var curElementLeft = 0;

            if(stepIdx > prevCurStepIdx){

                nextElmLeft1 = $this.elmStepContainer.width() + 10;

                nextElmLeft2 = 0;

                curElementLeft = 0 - _step($this, curStep).outerWidth();

            } else {

                nextElmLeft1 = 0 - _step($this, selStep).outerWidth() + 20;

                nextElmLeft2 = 0;

                curElementLeft = 10 + _step($this, curStep).outerWidth();

            }

            if (stepIdx == prevCurStepIdx) {

                nextElmLeft1 = $($(selStep, $this.target).attr("href"), $this.target).outerWidth() + 20;

                nextElmLeft2 = 0;

                curElementLeft = 0 - $($(curStep, $this.target).attr("href"), $this.target).outerWidth();

            } else {

                $($(curStep, $this.target).attr("href"), $this.target).animate({left:curElementLeft},"fast",function(e){

                    $($(curStep, $this.target).attr("href"), $this.target).hide();

                });

            }



            _step($this, selStep).css("left",nextElmLeft1).show().animate({left:nextElmLeft2},"fast",function(e){

                _setupStep($this,curStep,selStep);

            });

        } else {

            _step($this, curStep).hide();

            _step($this, selStep).show();

            _setupStep($this,curStep,selStep);

        }

        return true;

    };



    var _setupStep = function($this, curStep, selStep) {

        $(curStep, $this.target).removeClass("selected");

        $(curStep, $this.target).addClass("done");



        $(selStep, $this.target).removeClass("disabled");

        $(selStep, $this.target).removeClass("done");

        $(selStep, $this.target).addClass("selected");



        $(selStep, $this.target).attr("isDone",1);



        _adjustButton($this);



        if($.isFunction($this.options.onShowStep)) {

            var context = { fromStep: parseInt($(curStep).attr('rel')), toStep: parseInt($(selStep).attr('rel')) };

            if(! $this.options.onShowStep.call(this,$(selStep),context)){

                return false;

            }

        }

        if ($this.options.noForwardJumping) {

            // +2 == +1 (for index to step num) +1 (for next step)

            for (var i = $this.curStepIdx + 2; i <= $this.steps.length; i++) {

                $this.disableStep(i);

            }

        }

    };



    var _adjustButton = function($this) {

        if (! $this.options.cycleSteps){

            if (0 >= $this.curStepIdx) {

                $($this.buttons.previous).addClass("buttonDisabled");

                if ($this.options.hideButtonsOnDisabled) {

                    $($this.buttons.previous).hide();

                }

            }else{

                $($this.buttons.previous).removeClass("buttonDisabled");

                if ($this.options.hideButtonsOnDisabled) {

                    $($this.buttons.previous).show();

                }

            }

            if (($this.steps.length-1) <= $this.curStepIdx){

                $($this.buttons.next).addClass("buttonDisabled");

                if ($this.options.hideButtonsOnDisabled) {

                    $($this.buttons.next).hide();

                }

            }else{

                $($this.buttons.next).removeClass("buttonDisabled");

                if ($this.options.hideButtonsOnDisabled) {

                    $($this.buttons.next).show();

                }

            }

        }

        // Finish Button

        $this.enableFinish($this.options.enableFinishButton);

    };



    /*

     * Public methods

     */



    SmartWizard.prototype.goForward = function(){

        var nextStepIdx = this.curStepIdx + 1;

        if (this.steps.length <= nextStepIdx){

            if (! this.options.cycleSteps){

                return false;

            }

            nextStepIdx = 0;

        }

        _loadContent(this, nextStepIdx);

    };



    SmartWizard.prototype.goBackward = function(){

        var nextStepIdx = this.curStepIdx-1;

        if (0 > nextStepIdx){

            if (! this.options.cycleSteps){

                return false;

            }

            nextStepIdx = this.steps.length - 1;

        }

        _loadContent(this, nextStepIdx);

    };



    SmartWizard.prototype.goToStep = function(stepNum){

        var stepIdx = stepNum - 1;

        if (stepIdx >= 0 && stepIdx < this.steps.length) {

            _loadContent(this, stepIdx);

        }

    };

    SmartWizard.prototype.enableStep = function(stepNum) {

        var stepIdx = stepNum - 1;

        if (stepIdx == this.curStepIdx || stepIdx < 0 || stepIdx >= this.steps.length) {

            return false;

        }

        var step = this.steps.eq(stepIdx);

        $(step, this.target).attr("isDone",1);

        $(step, this.target).removeClass("disabled").removeClass("selected").addClass("done");

    }

    SmartWizard.prototype.disableStep = function(stepNum) {

        var stepIdx = stepNum - 1;

        if (stepIdx == this.curStepIdx || stepIdx < 0 || stepIdx >= this.steps.length) {

            return false;

        }

        var step = this.steps.eq(stepIdx);

        $(step, this.target).attr("isDone",0);

        $(step, this.target).removeClass("done").removeClass("selected").addClass("disabled");

    }

    SmartWizard.prototype.currentStep = function() {

        return this.curStepIdx + 1;

    }



    SmartWizard.prototype.showMessage = function (msg) {

        $('.content', this.msgBox).html(msg);

        this.msgBox.show();

    }



    SmartWizard.prototype.enableFinish = function (enable) {

        // Controll status of finish button dynamically

        // just call this with status you want

        this.options.enableFinishButton = enable;

        if (this.options.includeFinishButton){

            if (!this.steps.hasClass('disabled') || this.options.enableFinishButton){

                $(this.buttons.finish).removeClass("buttonDisabled");

                if (this.options.hideButtonsOnDisabled) {

                    $(this.buttons.finish).show();

                }

            }else{

                $(this.buttons.finish).addClass("buttonDisabled");

                if (this.options.hideButtonsOnDisabled) {

                    $(this.buttons.finish).hide();

                }

            }

        }

        return this.options.enableFinishButton;

    }



    SmartWizard.prototype.hideMessage = function () {

        this.msgBox.fadeOut("normal");

    }

    SmartWizard.prototype.showError = function(stepnum) {

        this.setError(stepnum, true);

    }

    SmartWizard.prototype.hideError = function(stepnum) {

        this.setError(stepnum, false);

    }

    SmartWizard.prototype.setError = function(stepnum,iserror) {

        if (typeof stepnum == "object") {

            iserror = stepnum.iserror;

            stepnum = stepnum.stepnum;

        }



        if (iserror){

            $(this.steps.eq(stepnum-1), this.target).addClass('error')

        }else{

            $(this.steps.eq(stepnum-1), this.target).removeClass("error");

        }

    }



    SmartWizard.prototype.fixHeight = function(){

        var height = 0;



        var selStep = this.steps.eq(this.curStepIdx);

        var stepContainer = _step(this, selStep);

        stepContainer.children().each(function() {

            if($(this).is(':visible')) {

                 height += $(this).outerHeight(true);

            }

        });



        // These values (5 and 20) are experimentally chosen.

        stepContainer.height(height + 5);

        this.elmStepContainer.height(height + 20);

    }



    _init(this);

};







(function($){



    $.fn.smartWizard = function(method) {

        var args = arguments;

        var rv = undefined;

        var allObjs = this.each(function() {

            var wiz = $(this).data('smartWizard');

            if (typeof method == 'object' || ! method || ! wiz) {

                var options = $.extend({}, $.fn.smartWizard.defaults, method || {});

                if (! wiz) {

                    wiz = new SmartWizard($(this), options);

                    $(this).data('smartWizard', wiz);

                }

            } else {

                if (typeof SmartWizard.prototype[method] == "function") {

                    rv = SmartWizard.prototype[method].apply(wiz, Array.prototype.slice.call(args, 1));

                    return rv;

                } else {

                    $.error('Method ' + method + ' does not exist on jQuery.smartWizard');

                }

            }

        });

        if (rv === undefined) {

            return allObjs;

        } else {

            return rv;

        }

    };



// Default Properties and Events

    $.fn.smartWizard.defaults = {

        selected: 0,  // Selected Step, 0 = first step

        keyNavigation: true, // Enable/Disable key navigation(left and right keys are used if enabled)

        enableAllSteps: false,

        transitionEffect: 'fade', // Effect on navigation, none/fade/slide/slideleft

        contentURL:null, // content url, Enables Ajax content loading

        contentCache:true, // cache step contents, if false content is fetched always from ajax url

        cycleSteps: false, // cycle step navigation

        enableFinishButton: false, // make finish button enabled always

        hideButtonsOnDisabled: false, // when the previous/next/finish buttons are disabled, hide them instead?

        errorSteps:[],    // Array Steps with errors

        labelNext:'Next',

        labelPrevious:'Previous',

        labelFinish:'Finish',

        noForwardJumping: false,

        ajaxType: "POST",

        onLeaveStep: null, // triggers when leaving a step

        onShowStep: null,  // triggers when showing a step

        onFinish: null,  // triggers when Finish button is clicked

        includeFinishButton : true   // Add the finish button

    };



})(jQuery);

