jquery - 引导向导 - 转到特定步骤

标签 jquery

我正在使用这个插件来创建一个类似向导的界面。

https://github.com/jeffreypolk/bootstrap-wizard

有没有办法添加一个支持转到任何步骤的方法?例如:如果我在第 2 步,然后单击“下一步”,我想转到第 4 步。同样,如果我在第 4 步,但单击“上一步”,我想转到第 4 步2、因为我就是这样来到这里的。

我正在为此编写一种方法,但正在寻找一些想法。

最佳答案

不幸的是,无法移动到特定步骤,也无法添加此类功能。

你有两种可能性:

  1. 从 github 克隆并添加此类功能(即:moveToStep()....)
  2. 复制函数中的 js 步骤。

使用第二个选择:

$('#wizard').wizard({
    autoOpen: true,
    onOpen: function() {
        moveTo(3);
    }
});


//
//  move to step......
//
function moveTo(idx) {
    var settings = $('#wizard').data('wizardsettings')
    settings.stepIndex = idx;
    $('#wizard').find('.wizard-step').hide();
    settings.titleElement.html($('#wizard').find('.wizard-step').eq(idx - 1).data('title'));
    $('#wizard').find('.wizard-step').eq(idx - 1).show();
    $('#wizard').find('.alert').html('').hide();

    var percent = parseInt(idx / settings.stepCount * 100);
    settings.progress.css('width', percent + '%');
    settings.progress.html('Step ' + idx + ' of ' + settings.stepCount);
    settings.progress.parent().show();
    if (idx === 1) {
        settings.prevButton.prop('disabled', true);
        settings.nextButton.html(settings.nextText);
    } else if (idx === settings.stepCount) {
        settings.nextButton.html(settings.submitText);
        settings.prevButton.prop('disabled', false);
    } else {
        settings.prevButton.prop('disabled', false);
        settings.nextButton.html(settings.nextText);
    }
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

<link rel="stylesheet" href="https://rawgit.com/jeffreypolk/bootstrap-wizard/master/wizard.css">
<script src="https://rawgit.com/jeffreypolk/bootstrap-wizard/master/wizard.js"></script>


<!-- Begin wizard -->
<div class="wizard" id="wizard">

    <-- Step One -->
    <div class="wizard-step" data-title="Step One">
        This is step one
    </div>

    <-- Step Two -->
    <div class="wizard-step" data-title="Step Two">
        This is step two
    </div>

    <-- Step Three -->
    <div class="wizard-step" data-title="Step Three">
        This is step three
    </div>

    <-- Step Four -->
    <div class="wizard-step" data-title="Step Four">
        This is step four
    </div>

</div>
<!-- End wizard -->

为了添加 moveTo 方法和 leaveStep 事件,需要对源代码进行一些更改,以便以下代码可以工作:

$("#wizard").on("leaveStep", function (e, currentStepNumber, gotoStep, stepDirection) {
    if (currentStepNumber == 2 && stepDirection == "forward") {
        e.preventDefault();
        $(this).wizard('moveTo', 4);
    }
    if (currentStepNumber == 4 && stepDirection == "backward") {
        e.preventDefault();
        $(this).wizard('moveTo', 2);
    }

});

(function ($) {

    var _dataKey = 'wizardsettings';

    var _reset = function (wiz) {
        var settings = wiz.data(_dataKey);

        // hide all the steps except the first
        wiz.find('.wizard-step').hide().first().show();
        // show all buttons
        wiz.find('button').show();
        // disable the previous button
        settings.prevButton.prop('disabled', true);

        // special handle with 1 step
        if (settings.stepCount === 1) {
            //there's only one step, switch to submit text
            settings.nextButton.html(settings.submitText);
            // hide the previous button
            settings.prevButton.hide();
        } else {
            // reset the next button text
            settings.nextButton.html(settings.nextText);
        }
        // hide the ok button
        settings.okButton.hide();
        // reset index
        settings.stepIndex = 1;
        // hide the message
        _hideMessages(wiz);
        // reset progress
        _setProgress(settings.progress, 1, settings.stepCount);
        // reset title
        settings.titleElement.html(_getTitle(wiz, settings));
    }

    var _validate = function (wiz, settings) {

        // see if this step has a form, call valid if that is a function
        var step = $(wiz.find('.wizard-step')[settings.stepIndex - 1]);
        var form = step.find('form');
        if (form.length) {
            if ($.isFunction(form.valid)) {
                if (form.valid() === false) {
                    return false;
                }
            }
            if ($.isFunction(form.validate)) {
                if (form.validate() === false) {
                    return false;
                }
            }
        }

        // iterate the validators looking for matches
        if (settings.validators) {
            for (var i = 0; i < settings.validators.length; i++) {
                var v = settings.validators[i];
                // if step index matches or 0 (all steps)
                if (v.step === 0 || v.step === settings.stepIndex) {
                    if ($.isFunction(v.validate)) {
                        if (v.validate.call(wiz) === false) {
                            //if (v.validate() === false) {
                            // no bueno
                            return false;
                        }
                    }
                }
            }
        }
        // if here, it passes
        return true;
    }


    // changed: added last param
    var _move = function (wiz, next, stepNumber) {
        //debugger;

        var settings = wiz.data(_dataKey);

        // special handing on next
        if (next === true) {

            // validate the current step
            if (_validate(wiz, settings) === false) {
                return;
            }

            // if final step, submit
            if (settings.stepIndex === settings.stepCount) {
                if ($.isFunction(settings.onSubmit)) {
                    settings.onSubmit.call(wiz);
                } else {
                    // no submit method, just close
                    _close(wiz);
                }
                return;
            }
        }

        // calculate current index and next index
        var currIndex = settings.stepIndex;
        var nextIndex = next ? settings.stepIndex + 1 : settings.stepIndex - 1;
        if (stepNumber != undefined) {
            nextIndex = stepNumber;
        }


        // store the new index for later
        settings.stepIndex = nextIndex;

        if (nextIndex > settings.stepCount || nextIndex < 1) {
            //this should never happen
        } else {

            var allSteps = wiz.find('.wizard-step');


            // hide the current step
            $(allSteps[currIndex - 1]).hide();

            // set the title
            settings.titleElement.html(_getTitle(wiz, settings));

            // show the next step
            $(allSteps[nextIndex - 1]).show();

            // hide the message
            _hideMessages(wiz);

            // set the progress bar
            _setProgress(settings.progress, settings.stepIndex, settings.stepCount);

            if (nextIndex === 1) {
                //we're at the beginning
                settings.prevButton.prop('disabled', true);
                //set next to standard text
                settings.nextButton.html(settings.nextText);
            } else if (nextIndex === settings.stepCount) {
                //we're on the last step, switch to submit text
                settings.nextButton.html(settings.submitText);
                //enable previous
                settings.prevButton.prop('disabled', false);
            } else {
                settings.prevButton.prop('disabled', false);
                settings.nextButton.html(settings.nextText);
            }
        }

    }

    var _close = function (wiz) {
        var settings = wiz.data(_dataKey);
        if (settings.isModal === true) {
            wiz.modal('hide');
        }
        _reset(wiz);
        if ($.isFunction(settings.onReset)) {
            settings.onReset.call(wiz);
        }
        if ($.isFunction(settings.onClose)) {
            settings.onClose.call(wiz);
        }
        if (settings.isModal === false) {
            wiz.hide();
        }
    }

    var _submit = function (wiz) {
        var settings = wiz.data(_dataKey);
        if ($.isFunction(settings.onSubmit)) {
            settings.onSubmit.call(wiz);
        } else {
            // no submit method, just close
            _close(wiz);
        }
    }

    var _cancel = function (wiz) {
        var settings = wiz.data(_dataKey);
        var close = true;
        if ($.isFunction(settings.onCancel)) {
            if (settings.onCancel.call(wiz) === false) {
                close = false;
            }
        }
        if (close) {
            _close(wiz);
        }
    }

    var _open = function (wiz) {
        var settings = wiz.data(_dataKey);
        if (settings.isModal) {
            wiz.modal({
                backdrop: 'static',
                keyboard: settings.showCancel
            });
        } else {
            wiz.show();
        }
        if ($.isFunction(settings.onOpen)) {
            settings.onOpen.call(wiz);
        }
    }

    var _initMarkup = function (wiz, settings) {
        var html = [];

        if (settings.isModal) {
            html.push('<div class="modal-dialog">');
        }

        html.push(' <div class="modal-content', settings.isModal ? '' : ' wizard-nomodal', '">');
        html.push('     <div class="modal-header">');
        if (settings.isModal && settings.showCancel === true) {
            html.push('     <button type="button" class="close wizard-cancel-header">');
            html.push('         <span aria-hidden="true">&times;</span>');
            html.push('         <span class="sr-only">Close</span>');
            html.push('     </button>');
        }
        html.push('         <h4 class="modal-title wizard-title">', _getTitle(wiz, settings), '</h4>');
        html.push('     </div>');
        html.push('     <div class="modal-body wizard-body">');

        if (settings.showProgress) {
            html.push(_initMarkupProgress(settings));
        }

        html.push('         <div class="wizard-info alert alert-info" style="display:none"></div>');
        html.push('         <div class="wizard-success alert alert-success" style="display:none"></div>');
        html.push('         <div class="wizard-warning alert alert-warning" style="display:none"></div>');
        html.push('         <div class="wizard-error alert alert-danger" style="display:none"></div>');
        html.push('     </div>');
        html.push('     <div class="modal-footer wizard-footer">');
        html.push(_initMarkupButtons(settings));
        html.push('     </div>');
        html.push(' </div>');

        if (settings.isModal) {
            html.push('</div>');
        }

        return html.join('');
    }

    var _initMarkupButtons = function (settings) {
        var html = [];

        if (settings.showPrevious === true) {
            html.push('<button type="button" class="btn btn-default wizard-prev">', settings.previousText, '</button>');
        }
        html.push('<button type="button" class="btn btn-primary wizard-next">', settings.nextText, '</button>');
        if (settings.showCancel === true) {
            html.push('<button type="button" class="btn btn-default wizard-cancel">' + settings.cancelText + '</button>');
        }
        html.push('<button type="button" class="btn btn-primary wizard-ok">OK</button>');

        return html.join('');
    }

    var _initMarkupProgress = function (settings) {
        var html = [];

        html.push('<div class="progress">');
        html.push(' <div class="progress-bar progress-bar-info" role="progressbar" aria-valuenow="1" aria-valuemin="1" aria-valuemax="10" style="width: 0%;">Progress</div>');
        html.push('</div>');

        return html.join('');
    }

    var _getTitle = function (wiz, settings) {
        var stepIndex = settings.stepIndex ? settings.stepIndex : 1;

        var curStep = $(wiz.find('.wizard-step')[stepIndex - 1]);

        if (curStep.data('title')) {
            // use the step title
            return curStep.data('title');
        } else {
            // use the default title
            return settings.title;
        }
    }

    var _showMessage = function (wiz, type, text) {
        wiz.find('div.wizard-' + type).html(text).show();
    }

    var _hideMessages = function (wiz) {
        wiz.find('.alert').html('').hide();
    }

    var _end = function (wiz, settings, options) {
        // hide steps
        wiz.find('.wizard-step').hide();

        // hide progress
        wiz.find('.progress').hide();

        // hide messagges
        _hideMessages(wiz);

        // show messages
        if (options.info) _showMessage(wiz, 'info', options.info);
        if (options.warning) _showMessage(wiz, 'warning', options.warning);
        if (options.success) _showMessage(wiz, 'success', options.success);
        if (options.error) _showMessage(wiz, 'error', options.error);

        // reset title
        settings.titleElement.html(settings.title);

        // set buttons
        settings.prevButton.hide();
        settings.nextButton.hide();
        settings.cancelButton.hide();
        settings.okButton.show();

        // auto close?
        var delay = 0;
        if (options.autoClose === true) {
            delay = 2000;
        } else if (options.autoClose > 0) {
            delay = options.autoClose;
        }
        if (delay > 0) {
            window.setTimeout(function () {
                _close(wiz);
            }, delay);
        }
    }

    var _setProgress = function (progress, stepIndex, stepCount) {
        var percent = parseInt(stepIndex / stepCount * 100);
        progress.css('width', percent + '%');
        progress.html('Step ' + stepIndex + ' of ' + stepCount);
        progress.parent().show();
    }

    var methods = {

        init: function (options) {
            // Establish our default settings
            var settings = $.extend({
                title: '',
                validators: null,
                onSubmit: null,
                onReset: null,
                onCancel: null,
                onClose: null,
                onOpen: null,
                previousText: '<< Back',
                nextText: 'Next >>',
                submitText: 'Submit',
                cancelText: 'Cancel',
                showCancel: true,
                showPrevious: true,
                showProgress: false,
                isModal: true,
                autoOpen: false
            }, options);

            return this.each(function () {

                var $this = $(this);

                // commit html to document
                $(_initMarkup($this, settings)).appendTo($this);

                // move the dialog to the body if it is not already there
                // dialogs have issues if they aren't a child of the body
                if (!$this.parent().is('body')) {
                    $this.appendTo($('body'))
                }

                if (settings.isModal) {
                    // clean up the modal
                    $this.addClass('modal');
                    $this.attr('tabindex', '-1');
                }

                // don't show
                $this.hide();

                // set refs for later
                settings.prevButton = $this.find('.wizard-prev');
                settings.nextButton = $this.find('.wizard-next');
                settings.cancelButton = $this.find('.wizard-cancel');
                settings.okButton = $this.find('.wizard-ok');
                settings.progress = $this.find('.progress-bar');
                settings.titleElement = $this.find('.wizard-title');

                // set uniform height
                if (settings.bodyHeight) {
                    $(this).find('.wizard-body').height(settings.bodyHeight);
                }
                //set the step count
                settings.stepCount = $this.find('.wizard-step').length;

                //set the progress width
                _setProgress(settings.progress, 1, settings.stepCount);

                // add handlers
                settings.prevButton.click(function () {
                    // added event ....
                    var e = $.Event('leaveStep');
                    $(this).closest('.wizard').trigger(e, [settings.stepIndex, settings.stepIndex - 1 , 'backward']);
                    if (e.isDefaultPrevented()) {
                        return false;
                    }
                    _move($(this).parents('.wizard').first(), false);
                });
                settings.nextButton.click(function () {
                    // added event ....
                    var e = $.Event('leaveStep');
                    $(this).closest('.wizard').trigger(e, [settings.stepIndex, settings.stepIndex + 1 , 'forward']);
                    if (e.isDefaultPrevented()) {
                        return false;
                    }
                    _move($(this).parents('.wizard').first(), true);
                });
                settings.cancelButton.click(function () {
                    _cancel($(this).parents('.wizard').first(), true);
                });
                settings.okButton.click(function () {
                    _close($(this).parents('.wizard').first(), true);
                });
                $this.find('.wizard-cancel-header').click(function () {
                    _cancel($(this).parents('.wizard').first());
                });

                if (settings.stepCount === 1) {
                    //there's only one step, switch to submit text
                    settings.nextButton.html(settings.submitText);
                    // hide previous
                    settings.prevButton.hide();
                }

                // move the steps into the new modal body
                $this.find('.wizard-step').appendTo($this.find('.wizard-body'));

                //store the settings
                $this.data(_dataKey, settings);

                // reset everything
                _reset($this);

                // auto open?
                if (settings.autoOpen === true) {
                    _open($this);
                }

            });

        },

        // added..............
        moveTo: function (stepNumber) {
            _move($(this), false, stepNumber);
        },

        open: function () {
            return this.each(function () {
                _open($(this));
            });
        },

        close: function () {
            return this.each(function () {
                _close($(this));
            });
        },

        submit: function () {
            return this.each(function () {
                _submit($(this));
            });
        },

        info: function (text) {
            return this.each(function () {
                _showMessage($(this), 'info', text);
            });
        },

        warning: function (text) {
            return this.each(function () {
                _showMessage($(this), 'warning', text);
            });
        },

        success: function (text) {
            return this.each(function () {
                _showMessage($(this), 'success', text);
            });
        },

        error: function (text) {
            return this.each(function () {
                _showMessage($(this), 'error', text);
            });
        },

        end: function (options) {

            // Establish our default settings
            var options2 = $.extend({
                info: null,
                warning: null,
                success: null,
                error: null,
                autoClose: false
            }, options);

            return this.each(function () {
                _end($(this), $(this).data(_dataKey), options2);
            });
        }
    };

    $.fn.wizard = function (methodOrOptions) {

        if (methods[methodOrOptions]) {
            return methods[methodOrOptions].apply(this, Array.prototype.slice.call(arguments, 1));
        } else if (typeof methodOrOptions === 'object' || !methodOrOptions) {
            // Default to "init"
            return methods.init.apply(this, arguments);
        } else {
            $.error('Method ' + methodOrOptions + ' does not exist on jQuery.tooltip');
        }
    };
}(jQuery));



$('#wizard').wizard({
    autoOpen: true
});

$("#wizard").on("leaveStep", function (e, currentStepNumber, gotoStep, stepDirection) {
    if (currentStepNumber == 2 && stepDirection == "forward") {
        e.preventDefault();
        $(this).wizard('moveTo', 4);
    }
    if (currentStepNumber == 4 && stepDirection == "backward") {
        e.preventDefault();
        $(this).wizard('moveTo', 2);
    }
});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://rawgit.com/jeffreypolk/bootstrap-wizard/master/wizard.css">


<!-- Begin wizard -->
<div class="wizard" id="wizard">

    <-- Step One -->
    <div class="wizard-step" data-title="Step One">
        This is step one
    </div>

    <-- Step Two -->
    <div class="wizard-step" data-title="Step Two">
        This is step two
    </div>

    <-- Step Three -->
    <div class="wizard-step" data-title="Step Three">
        This is step three
    </div>

    <-- Step Four -->
    <div class="wizard-step" data-title="Step Four">
        This is step four
    </div>

    <-- Step Five -->
    <div class="wizard-step" data-title="Step Five">
        This is step four
    </div>

</div>
<!-- End wizard -->

关于jquery - 引导向导 - 转到特定步骤,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52387682/

相关文章:

javascript - setInterval 无法按预期使用 javascript oops

javascript - HTML/HTA 文档中鼠标位置的实时更新

javascript - 如何在 javascript 中使用 setTimeout 考虑延迟

jquery - 使用 jQuery 更改边框底部颜色?

javascript - jQuery 表单 : Ajax response is displayed, 但未显示在源代码中

javascript - 检查 jQuery 数据表中预选的行

javascript - JQuery Mobile 和 Phonegap - 垂直滚动断断续续/更难

javascript - 在解析中检索信息

javascript - 如何将 Javascript 对象中相同的值元素分组?

javascript - 如何获取动态表行值