如何在 Twitter Bootstrap 中同时打开两个模态对话框

Posted

技术标签:

【中文标题】如何在 Twitter Bootstrap 中同时打开两个模态对话框【英文标题】:How to open two modal dialogs in Twitter Bootstrap at the same time 【发布时间】:2014-05-07 22:19:01 【问题描述】:

我已经在我的项目中实现了引导对话框。我在该对话框中有一些删除功能,删除确认消息会打开另一个引导对话框。但是当第二个确认对话框打开时,第一个对话框并没有被禁用并且所有的事件都正常工作。

当另一个对话框打开时,是否有任何解决方案可以禁用原始对话框?

这是我的代码:

function OpenDialogForSelectionAdmItem(title, content, callback) 
    var dlg = new BootstrapDialog(
        title: title,
        content: content,
        buttons: [
            label: 'Save',
            cssClass: 'btn-primary',
            id: 'btnSave',
            onclick: function (dialog) 

            
        ,
        
            label: 'Close',
            cssClass: 'btn',
            id: 'btnClose',
            onclick: function (dialog) 
                if (callback != "") 
                    callback(true);
                
                dialog.close();
            
        ]
    );

    dlg.open();`

截图:

当删除确认对话框打开时,我想禁用第一个对话框。

【问题讨论】:

"不支持重叠模式。确保在另一个模式仍然可见时不要打开模式。一次显示多个模式需要自定义代码。" getbootstrap.com/javascript/#modals 您可以尝试在第二个对话框后面放置一个页面掩码,并在第二个对话框关闭时将其删除。 @isherwood,页面掩码绝对是正确的方向。创建新模态时,它带有自己的modal-backdrop。当显示第二个模态时,您可以通过相对于第一个模态增加其z-index 使其出现在原始模态之上。查看我的答案以获取完整的详细信息。 @Abhijit,我猜你正在使用bootstrap3-dialog。将来,如果您使用的是相对不常见的第三方库,那么直接链接到它而不是让人们猜测会很有帮助。同样,一个工作小提琴会在这里真正节省一些时间,而不必重复你的努力。提供minimal reproducible example 以便有人可以运行他们自己的代码版本并重现它,使故障排除变得容易大约十倍。 【参考方案1】:

问题:

为了了解 Web 开发中模式对话框的复杂性,您需要了解更多关于 z-index property and stacking contexts 的信息。

简而言之,对话框通过向 DOM 添加两个主要组件来工作:一个占据整个屏幕的背景,以及一个构成对话框的 div。它们中的每一个都从页面的其余部分中脱颖而出,因为它们被放置在 DOM 的根级别,并为其z-index 属性赋予了很高的价值。 多高?好吧,尝试将空白模式添加到空白页面,您将看到以下 DOM 元素:

 
 
     

modal-backdrop 给人一种真正的模态过程的错觉,因为它呈现在所有其他内容之上,从而防止点击在下面的任何地方触发。 modal-dialog 被允许接收点击的唯一原因是因为它通过提供更高的 z-index 堆叠在背景顶部

就是这样!这就是全部的技巧。所以当引导cautions against use multiple dialogs 时,他们这样做是因为堆叠变得棘手。如果添加另一个元素,它会以完全相同的z-index 呈现,这意味着它将位于常规页面内容之上,但与原始对话框位于同一平面上。如果它没有完全覆盖原件,那么原件仍然可以点击,因为它上面没有背景。

解决方案:

为了解决这个问题,您需要想出自己的方法来禁用对背景模式的点击。此问题似乎已(部分)解决。请参阅以下示例:

Demo in jsFiddle

Bootstrap Dialog 做到了,点击对话框关闭 DOM 中的最后一个对话框并将事件标记为已处理,因此它不会触发任何其他事件。如果第二个模态已启动并且您单击它,则唯一会发生的事情是第二个模态将关闭。


更高级的处理:

如果您希望第二个模态 看起来 像第一个模态,您必须手动完成。

当新模态创建时,它带有它自己的modal-backdrop。当显示第二个模态时,您可以通过相对于第一个模态增加其 z-index 来使其显示在原始模态之上。在onshown 事件中,我们只需要获取当前模态,它的覆盖并使用.CSS 方法修改z-index。我们希望它出现在任何现有的模态框上方,因此首先我们将计算 DOM 中的模态框数量 ($('.bootstrap-dialog').length),然后增加 z-index 使其高于下一个最高对话框。

这样调用:

function OpenDialogForSelectionAdmItem(title, content, callback) 
    var dlg = new BootstrapDialog(
        title: title,
        message: content,
        onshown: function(dialog) 
            var tier = $('.bootstrap-dialog').length - 1;
            dialog.$modal.prev(".modal-backdrop")
                .css("z-index", 1030 + tier * 30);
            dialog.$modal
                .css("z-index", 1040 + tier * 30);
         
        // More Settings
    ).open();

Working Demo in jsFiddle

截图:


作为概念证明,这里有一个 Demo,可让您在其他对话框之上不断添加对话框

Infinite Dialogs Fiddle


用户体验警告:

虽然这在技术上是可以实现的,modals within modals can create a confusing UX,但如果您遇到问题,正确的答案可能是尝试通过采用原始工作流程并将其提升为带有 url 和状态的完整页面设计来完全避免它.

【讨论】:

是的,付出了巨大的努力。咳咳咳 @AlanB,您是否正在推广一个与问题无关的大型第三方库,因为它可以节省 7 行代码?真的没有意义。 将整个应用程序转换为基于画布的库需要付出巨大的努力。在解释这个问题和答案时付出了很多努力,但是一旦你知道了答案,实施起来就相当简单了。 我没有宣传任何东西。我指出,试图在一个并非设计用于执行此操作的工具包中执行此操作需要付出努力。 Zebkit 被缩小了 85KB,所以几乎没有。 @AlanB,Bootstrap modal 怎么不是为显示模态而设计的?我认为您严重高估了添加十几行代码的难度。但是由于在 Zebkit 中很容易做到,请随时在 jsFiddle 中附加一个工作演示作为评论,我会检查一下! 我不得不使用 50000 而不是 1040 的 z-index。小提琴也对我不起作用。此外,我将对话框的可见性设置为 hidden onshow 和 visible onshown 以防止对话框从我当前对话框的顶部进入动画,然后弹出到前面。 YMMV。
【参考方案2】:

首先将类添加到主模态所以:<div class="modal-content kk"> 我只是使用:

$('#myModal1').on('shown.bs.modal', function () 
  $('.kk').addClass('magla');
  $('#myModal').modal('hide');
 );
$('#myModal1').on('hidden.bs.modal', function () 
  $('.kk').removeClass('magla');
  $('#myModal').modal('show');


);

.magla css 在哪里:

.magla 
     -webkit-filter: blur(5px);
  -moz-filter: blur(5px);
  -o-filter: blur(5px);
  -ms-filter: blur(5px);
  filter: blur(5px);


尝试对我来说看起来不错。

【讨论】:

【参考方案3】:

只需使用 onclick 方法隐藏实际的模态

<button data-toggle="modal" data-target="#modal-to-show-id" onclick="$('#actual-modal-id').modal('hide');">
    Text Button
</button>

【讨论】:

【参考方案4】:

我的简单解决方案:为每个新模式生成一个新 ID。然后只需通过一个变量管理所有内容。 顺便说一句,它符合我的目的。

var _MODAL_LAST;
$( document ).on( 'show.bs.modal' , '.modal' , function()
    _MODAL_LAST = $(this);
);
$( document ).on( 'hide.bs.modal' , '.modal' , function()
    if( _MODAL_LAST.attr('id') !== $(this).attr('id') )
        return false;
    else
        _MODAL_LAST = $(this).prevAll('.modal:first');
    
);

【讨论】:

以上是关于如何在 Twitter Bootstrap 中同时打开两个模态对话框的主要内容,如果未能解决你的问题,请参考以下文章

如何在 IE 中覆盖 Twitter Bootstrap 下拉悬停

如何在 twitter-bootstrap-3 模态框中使用复选框

如何在 twitter-bootstrap 模式窗口中插入 django 表单?

如何在 Twitter Bootstrap 模式中启用转义键关闭功能?

在 MVC4 Twitter Bootstrap C# 中格式化文本框

如何在有效的 Twitter Bootstrap 中垂直居中内容?