twitter-bootstrap Twitter Bootstrap / jQuery - 如何暂时防止模态被关闭?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13421750/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 15:44:32  来源:igfitidea点击:

Twitter Bootstrap / jQuery - How to temporarily prevent the modal from being closed?

javascriptjquerytwitter-bootstrapmodal-dialogtwitter-bootstrap-2

提问by BadHorsie

I am using Twitter Bootstrap modals, with the default options where you can click the backdrop or press [Esc] to close the modal.

我正在使用 Twitter Bootstrap 模态,默认选项是您可以单击背景或按 [Esc] 关闭模态。

However, when I initiate an ajax operation in the modal I want to disable the modal from being closed in any way. So I disable buttons and hide the modal's close button but I can't figure out how to disable the backdrop and the [Esc] key.

但是,当我在模态中启动 ajax 操作时,我想禁止以任何方式关闭模态。所以我禁用了按钮并隐藏了模态的关闭按钮,但我不知道如何禁用背景和 [Esc] 键。

I tried:

我试过:

$('#myModal').modal({
    backdrop: 'static',
    keyboard: false
});

But this doesn't seem to work on the fly.

但这似乎并不能即时生效。

I will also need to re-enable the backdrop and keyboard once the ajax operation is finished.

ajax 操作完成后,我还需要重新启用背景和键盘。

采纳答案by davidkonrad

Note: This solution is targeting twitter bootstrap 2.x! See this answer(just below) for differences according to bootstrap 3.

注意:此解决方案针对twitter bootstrap 2.x!根据引导程序 3,请参阅此答案(就在下面)以了解差异。



Extending bootstrap modal functionality withoutmodifying original source.

修改原始源的情况下扩展引导模式功能。

Thanks to @David and his suggestion at How to Extend Twitter Bootstrap PluginI finally got it to work. It is a slightly modified version of his solution with modal "lock" added. I post it as a additional answer since I think it may could be a starting point for others that like me have struggled hard with this issue.

感谢 @David 和他在How to Extend Twitter Bootstrap Plugin 上的建议,我终于让它工作了。这是他的解决方案的略微修改版本,添加了模态“锁定”。我将其作为附加答案发布,因为我认为这可能是像我一样在这个问题上苦苦挣扎的其他人的起点。

// save the original function object
var _superModal = $.fn.modal;

// add locked as a new option
$.extend( _superModal.defaults, {
    locked: false
});

// create a new constructor
var Modal = function(element, options) {
    _superModal.Constructor.apply( this, arguments )
}

// extend prototype and add a super function
Modal.prototype = $.extend({}, _superModal.Constructor.prototype, {
    constructor: Modal

    , _super: function() {
        var args = $.makeArray(arguments)
        // call bootstrap core
        _superModal.Constructor.prototype[args.shift()].apply(this, args)
    }

    , lock : function() {
        this.options.locked = true
    }

    , unlock : function() {
        this.options.locked = false
    }

    , hide: function() {
        if (this.options.locked) return
        this._super('hide')
    }
});

// override the old initialization with the new constructor
$.fn.modal = $.extend(function(option) {
    var args = $.makeArray(arguments),
    option = args.shift()

    // this is executed everytime element.modal() is called
    return this.each(function() {
        var $this = $(this)
        var data = $this.data('modal'),
            options = $.extend({}, _superModal.defaults, $this.data(), typeof option == 'object' && option)

        if (!data) {
            $this.data('modal', (data = new Modal(this, options)))
        }
        if (typeof option == 'string') {
            data[option].apply( data, args )
        }
    });
}, $.fn.modal);

With this technique it should not be nessecary to alter bootstrap.js, and the same functionality can more easily be shared among bootstrap projects. This method should be applicable to all the other bootstrap plugins. Have so far only tried with button though, but I cant se why it shouldnt.

使用这种技术不需要更改 bootstrap.js,并且可以更轻松地在 bootstrap 项目之间共享相同的功能。这种方法应该适用于所有其他引导插件。到目前为止只尝试过按钮,但我不知道为什么不应该。

see working fiddle -> http://jsfiddle.net/Sz7ZS/

见工作小提琴 - > http://jsfiddle.net/Sz7ZS/

回答by qingu

There is an easier way to do it. Thisbootstrap pull request explains a little more. The solution disables all methods for closing the modal (keyboard, mouse click, close button).

有一种更简单的方法可以做到。这个引导拉取请求解释了更多。该解决方案禁用关闭模态的所有方法(键盘、鼠标单击、关闭按钮)。

All you have to do to disable closing the modal is:

禁用关闭模式所需要做的就是:

$('#myModal').data('bs.modal').isShown = false;

To enable closing again:

要再次启用关闭:

$('#myModal').data('bs.modal').isShown = true;

Example

例子

Here is some sample code that works in conjunction with a jQuery get:

下面是一些与 jQuery get 结合使用的示例代码:

// disable closing the modal
$('#myModal').data('bs.modal').isShown = false;

// Send an HTTP GET request to the server - replace this with getJSON, post or ajax as needed
$.get( "ajax/test.html", function( data ) {
  // enable closing the modal
  $('#myModal').data('bs.modal').isShown = true;

  // Do something with the data
  $( ".result" ).html( data );
});

回答by davidkonrad

You are not the only one who are missing that feature. I think bootstrap sometimes is too "minimalistic", the people behind has the idea a lot should be done in the "implementation layer", but it is to no use when the bootstrap jQuery plugins themselves makes it impossible!

您不是唯一缺少该功能的人。我觉得 bootstrap 有时候太“简约”了,背后的人有很多想法应该在“实现层”做,但是当 bootstrap jQuery 插件本身使它不可能时,它就没有用了!

You have to implement the functionality yourself, like this:

您必须自己实现该功能,如下所示

in bootstrap.jsv2.1.1 modal begins at line 61.

bootstrap.jsv2.1.1 中,modal 从第 61 行开始。

in Modal.prototype, add two functions, lockand unlock, so it looks like this (I show here only the beginning of modal.prototype, becuase it is too much code)

Modal.prototype,添加两个函数,lockunlock,所以看起来是这样的(我这里只展示了开头modal.prototype,因为代码太多)

  Modal.prototype = {

      constructor: Modal

      //add this function
    , lock: function () {
        this.options.locked = true
      }

      //add this function
    , unlock: function () {
        this.options.locked = false
      }

    , toggle: function () {
    ... 
    ...

Then, also in Modal.prototype, find the function hide, and add a line so it looks like this (again, only top of hide is showed)

然后,同样在 Modal.prototype 中,找到函数hide,并添加一行使其看起来像这样(同样,只显示隐藏的顶部)

, hide: function (e) {
    e && e.preventDefault()

    var that = this

    //add this line
    if (that.options.locked) return

    e = $.Event('hide')
    ...
    ...

And finally, alter $.fn.modal.defaultsto :

最后,更改$.fn.modal.defaults为:

  $.fn.modal.defaults = {
      backdrop: true
    , keyboard: true
    , show: true
    , locked: false //this line is added
  }

Now you have on-the-fly lock/unlock functionality in your bootstrap modal, preventing the user from closing the modal at critical moments.

现在,您的引导程序模态中具有动态锁定/解锁功能,可防止用户在关键时刻关闭模态。

Example:

示例

This is an altered version of "Live Demo" from http://twitter.github.com/bootstrap/javascript.html#modals

这是来自http://twitter.github.com/bootstrap/javascript.html#modals的“实时演示”的更改版本

<!-- Button to trigger modal -->
<a href="#myModal" role="button" class="btn" data-toggle="modal">Launch demo modal</a>

<!-- Modal -->
<div id="myModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
  <div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
    <h3 id="myModalLabel">Modal header</h3>
  </div>
  <div class="modal-body">
    <p>One fine body…</p>
  </div>
  <div class="modal-footer">
    <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
    <button class="btn btn-primary" onclick="$('#myModal').modal('lock');">lock</button>
    <button class="btn btn-primary" onclick="$('#myModal').modal('unlock');">unLock</button>
  </div>
</div>
<script type="text/javascript">

I have inserted two buttons, "lock" and "unlock" - when clicked, they set the modal in either locked or normal mode (the settings it is initialised with)

我插入了两个按钮,“锁定”和“解锁” - 单击时,它们将模态设置为锁定或正常模式(初始化的设置)

Edit, in your case, you just have to call lock/onlock when doing ajax :

编辑,在您的情况下,您只需要在执行 ajax 时调用 lock/onlock :

$("myModal").modal('lock');
$.ajax({
    url: url,
    ...
    ...
    , success(html) {
       ...
       ...
       $("#myModal").modal('unlock');
    }
});

回答by alez

You can create a variable isBlocked that you can set while doing AJAX calls to true, then you can check it on bootsrap modal hide event this way:

您可以创建一个变量 isBlocked,您可以在执行 AJAX 调用时将其设置为 true,然后您可以通过以下方式在 bootsrap 模式隐藏事件中检查它:

$('#myModal').on('hide.bs.modal', function (e) {
      //Prevent modal from closing is isBlocked is true
      if(isBlocked) return e.preventDefault();
})

I think this way is easier than extending Bootsrap, hope it helps someone :D

我认为这种方式比扩展 Bootsrap 更容易,希望它可以帮助某人:D

回答by ragamufin

Thanks @davidkonrad for your work on this. I was trying to implement this as well and it seems that things have changed with bootstrap 3. Now instead of:

感谢@davidkonrad 在这方面所做的工作。我也试图实现这一点,似乎引导程序 3 发生了变化。现在而不是:

_superModal.defaults

_superModal.defaults

it is now attached to the constructor so you have to do

它现在附加到构造函数,所以你必须做

_superModal.Constructor.DEFAULTS

_superModal.Constructor.DEFAULTS

Also the constructor has changed which meant that I had to copy it and modify it which is less than ideal. Instead I've come up with the following code that works and does not copy the constructor and should be more fool-proof if bootstrap changes going forward. Have a go:

构造函数也发生了变化,这意味着我必须复制它并修改它,这不太理想。相反,我想出了以下代码,该代码可以工作并且不会复制构造函数,并且如果引导程序在未来发生变化,应该会更加万无一失。试试吧:

// save the original function object
var _superModal = $.fn.modal;

// add locked as a new option
$.extend( _superModal.Constructor.DEFAULTS, {
    locked: false
});

// capture the original hide
var _hide = _superModal.Constructor.prototype.hide;
// console.log('HIDE:', _hide);

// add the lock, unlock and override the hide of modal
$.extend(_superModal.Constructor.prototype, {
    // locks the dialog so that it cannot be hidden
    lock: function() {
        // console.log('lock called');
        // console.log('OPTIONS',this.options);
        this.options.locked = true;
    }
    // unlocks the dialog so that it can be hidden by 'esc' or clicking on the backdrop (if not static)
    ,unlock: function() {
        // console.log('unlock called');
        this.options.locked = false;
    }
    // override the original hide so that the original is only called if the modal is unlocked
    ,hide: function() {
        // console.log('hide called');
        if (this.options.locked) return;

        _hide.apply(this, arguments);
    }
});

So in order to lock the modal:

所以为了锁定模态:

$('#dlg').modal('lock');

$('#dlg').modal('lock');

and to unlock:

并解锁:

$('#dlg').modal('unlock');

$('#dlg').modal('unlock');

Yay!

耶!

回答by Ezequiel Villarreal

I updated this awesome script to work with Bootstrap 4.

我更新了这个很棒的脚本以使用 Bootstrap 4。

var _superModal = $.fn.modal;

    $.extend(_superModal.Constructor.Default, {
        locked: false
    });

    var _hide = _superModal.Constructor.prototype.hide;

    $.extend(_superModal.Constructor.prototype, {
        lock: function () {
            this._config.locked = true;
        },
        unlock: function () {
            this._config.locked = false;
        },
        hide: function () {
            if (this._config.locked) return;

            _hide.apply(this, arguments);
        }
    });