35

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

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

我试过:

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

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

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

4

6 回答 6

17

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


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

感谢@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,并且可以更轻松地在 bootstrap 项目之间共享相同的功能。此方法应适用于所有其他引导插件。到目前为止只尝试过按钮,但我不知道为什么不应该这样做。

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

于 2012-11-19T19:05:54.943 回答
10

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

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

$('#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 );
});
于 2014-02-24T21:10:37.953 回答
9

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

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

bootstrap.jsv2.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 中,找到 function hide,并添加一行,使其看起来像这样(同样,只显示了 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…&lt;/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');
    }
});
于 2012-11-17T16:54:10.403 回答
8

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

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

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

于 2014-09-16T11:01:32.257 回答
5

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

耶!

于 2013-11-25T02:43:42.680 回答
1

我更新了这个很棒的脚本以使用 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);
        }
    });
于 2018-12-16T07:33:29.993 回答