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

时间:2012-11-16 17:44:41

标签: javascript jquery twitter-bootstrap modal-dialog twitter-bootstrap-2

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

然而,当我在模态中启动ajax操作时,我想禁用模态以任何方式关闭。所以我禁用按钮并隐藏模态的关闭按钮,但我无法弄清楚如何禁用背景和[Esc]键。

我试过了:

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

但这似乎没有动态。

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

6 个答案:

答案 0 :(得分:17)

注意:此解决方案的目标是twitter bootstrap 2.x!有关根据bootstrap 3的差异,请参阅this answer(仅在下方)。


扩展引导模式功能,无需修改原始源。

感谢@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);

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

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

答案 1 :(得分:10)

有一种更简单的方法。 This bootstrap pull请求解释了一点。该解决方案禁用关闭模式的所有方法(键盘,鼠标单击,关闭按钮)。

要禁用关闭模式,您只需:

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

要再次启用关闭:

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

示例

以下是一些与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 );
});

答案 2 :(得分:9)

您不是唯一缺少该功能的人。我认为bootstrap有时太“简约”了,后面的人有很多想法应该在“实现层”中完成,但是当引导jQuery插件本身使它变得不可能时它是没有用的!

您必须自己实施这项功能,例如

bootstrap.js v2.1.1模式中的

从第61行开始。

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 () {
    ... 
    ...

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

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

    var that = this

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

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

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

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

现在,您在自举模式中具有即时锁定/解锁功能,可防止用户在关键时刻关闭模态。

示例

这是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">

我已插入两个按钮,“锁定”和“解锁” - 点击后,他们将模态设置为锁定或正常模式(初始化设置)

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

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

答案 3 :(得分:8)

你可以创建一个变量isBlocked,你可以在AJAX调用为true时设置,然后你可以用这种方式在bootsrap模态隐藏事件上检查它:

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

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

答案 4 :(得分:6)

感谢@davidkonrad对此的工作。我也试图实现这一点,似乎事情已经改变了bootstrap 3.现在而不是:

_superModal.defaults

它现在已附加到构造函数,因此您必须执行

_superModal.Constructor.DEFAULTS

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

// 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);
    }
});

所以为了锁定模态:

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

并解锁:

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

耶!

答案 5 :(得分:0)

我更新了这个很棒的脚本以与Bootstrap 4和Bootstrap 3一起使用。 我保留这两种情况,因为我在项目中使用了一个全局脚本,其中一些脚本同时使用了两个版本的Boostrap(不用担心,每个项目一个引导程序)。如果有人有更好的主意,请与我们分享。

// save the original function object
var _superModal = $.fn.modal;
// Bootstrap 3: Constructor.DEFAULTS
// Bootstrap 4: Constructor.Default
var _superModalDefault = (typeof _superModal.Constructor.DEFAULTS === 'undefined') ? _superModal.Constructor.Default : _superModal.Constructor.DEFAULTS;

// add locked as a new option
$.extend(_superModalDefault, {
    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
    // Bootstrap 3: this.options
    // Bootstrap 4: this._config
    lock: function() {
        // console.log('lock called');
        if (this.options)
            this.options.locked = true;  // Bootstrap 3
        else
            this._config.locked = true;  // Bootstrap 4
    }
    // 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');
        if (this.options)
            this.options.locked = false;  // Bootstrap 3
        else
            this._config.locked = false;  // Bootstrap 4
    }
    // 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)
            if (this.options.locked) return;  // Bootstrap 3
        else
            if (this._config.locked) return;  // Bootstrap 4

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