模态背景剩余

我显示了一个 Bootstrap 模态窗口加载时执行 AJAX 调用。当加载模式应该显示时,我广播了一个“ Progress. init”事件; 当我想隐藏模式时,我广播了一个“ Progress. Finish”事件。在某些情况下,模态显示后会很快隐藏,导致模态背景保留在屏幕上。后续隐藏元素的调用不会移除背景。我也不能简单地删除所有的背景,因为其他模态窗口可能显示在加载窗口。我已经把一个 Jsfiddle放在一起,通过简单地调用模态函数(而不是触发事件)来演示这个问题。

var loadingModal = $("#loadingModal");


$("#btnShow").click(function () {
loadingModal.modal("show");
//hide after 3 seconds
setTimeout(function () {
loadingModal.modal("hide");
}, 3000);
});


$("#btnProblem").click(function () {
//simulate a loading screen finishing fast, followed by another loading screen
loadingModal.modal("show");
loadingModal.modal("hide");
loadingModal.modal("show");


//Again simulate 3 seconds
setTimeout(function () {
loadingModal.modal("hide");
}, 3000);
});

还有 HTML:

<div id="loadingModal" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<p>Loading...</p>
</div>
</div>
</div>
</div>
<button id="btnShow">Show Loading</button>
<button id="btnProblem">Cause show/hide problem</button>

理想情况下,我希望在调用 mode (“ hide”)之前不用等待指定的时间就能解决这个问题。换句话说,我想尽量避免这样的事情:

elem.on("progress.finish", function () {
window.setTimeout(loadingModal.modal("hide");
}, 750);

我也试过从 bootstrap 订阅 hidden.bs.mode 和 shown.bs.mode 事件,试图在需要的时候显示/隐藏元素,但是可能会出错... ... 有什么办法可以让这个模式显示/隐藏吗?

178099 次浏览

只是为了防止其他人遇到类似的问题: 我发现把类“淡出”模态将防止这个背景贴在屏幕上,即使在模态被隐藏之后。它似乎是 modal 的 bootstrap.js 中的一个 bug。

另一种方法(同时保留淡出效果)是用自定义的 javascript 替换对 jQueryElement.mode 的调用,后者添加“ in”类,设置 display: block,并在显示时添加背景,然后在想要隐藏模式时执行相反的操作。

对于我的项目来说,简单地删除淡出就足够了。

只需从模态中删除类“淡出”即可

如果你不需要这样的背景,可以把背景完全隐藏起来: 数据背景 = “”

<div class="modal fade preview-modal" data-backdrop="" id="preview-modal"  role="dialog" aria-labelledby="preview-modal" aria-hidden="true">

以防其他人遇到类似的问题: 我保持淡出,但只是添加 data-dismiss="modal"到保存按钮。我没问题。

在检查元素之后,在我点击浏览器的返回按钮之后,带有 modal-backdrop类的 div仍然保留着,所以我只需要删除它:

$(window).on('popstate', function() {
$(".modal-backdrop").remove();
});

如果在模式隐藏之后,褪色的背景仍然存在,并且不允许您单击任何可以通过使用下面的代码强制删除这些背景的位置。

首先隐藏(所有)模态 div 元素。

$('.modal').modal('hide');

其次,从主体中删除“模态-开放”类,并在页面末尾删除“ . 模态-背景”。

$('body').removeClass('modal-open');
$('.modal-backdrop').remove();

问题是引导程序异步删除背景。因此,当你调用 hideshow之后很快对方,背景是不会被删除。

解决方案(如前所述)是等待模态完全隐藏,使用 'hidden.bs.modal'事件。使用 jQuery只执行一次回调。我已经分叉你的 Jsfiddle,以显示这将如何工作。

// wait for the backdrop to be removed nicely.
loadingModal.one('hidden.bs.modal', function()
{
loadingModal.modal("show");


//Again simulate 3 seconds
setTimeout(function () {
loadingModal.modal("hide");
}, 3000);
});
// hide for the first time, after binding to the hidden event.
loadingModal.modal("hide");

查看 Bootstrap 中的代码:

这就是为什么要隐藏模式异步 :

$.support.transition && this.$element.hasClass('fade') ?
this.$element
.one('bsTransitionEnd', $.proxy(this.hideModal, this))
.emulateTransitionEnd(Modal.TRANSITION_DURATION) :
this.hideModal()

这将检查是否支持转换,以及模式中是否包含 fade类。当两者都是 true时,它等待淡出效果完成,然后隐藏模态。这个等待 又发生了之前 移除背景

这就是为什么删除淡出类将使隐藏模式同步(不再等待 CSS 淡出效果完成) ,以及为什么解决方案 rezonic 的工作。

此检查 确定是否添加或删除背景。同步执行 isShown = true.当你紧接着调用 hideshow时,isShown会变成 true,检查会添加一个背景,而不是移除前一个背景,从而造成你所遇到的问题。

小心添加 { data-release = “ mode”} 正如第二个答案中提到的。当使用控制器作用域定义的函数处理 Angulars n- 提交时,将首先执行数据解散,而控制器作用域定义的函数永远不会被调用。我花了一个小时才想明白。

另一个可能的情况(我的)-您正在动态添加模态 html 到 DOM,它包含更多的1根节点。明白了吧,注释节点也算,所以,如果你从引导网站复制模板-你有他们。

这对我很有效

当触发 hidden.bs.modal事件时,jQuery.remove()函数可以删除具有 .modal-backdrop类的元素。因此,每次模态是关闭的,模式背景将是 被移除了

//setting callback function for 'hidden.bs.modal' event
$('#modal').on('hidden.bs.modal', function(){
//remove the backdrop
$('.modal-backdrop').remove();
})

祝你好运。

我遇到的一个问题(可能对某人有帮助)很简单,那就是我使用了一个片段来加载 Modal。

<li data-toggle="modal" data-target="#priceInfoModal">
<label>Listing Price</label>
<i class="fa fa-money"></i>
@Html.Partial("EditPartials/PriceInfo_Edit")
</li>

我将部分调用放在了同一列表项中 因此 data-target = “ # priceInfoModal”和 div id = “ priceInfoModal” 在同一个集装箱导致我不能关闭我的模式

将这个:
(模式背景) < br > 添加到控制器中的 ng-click 函数,以防止淡入背景停留。

因此,如果你不想删除淡入淡出或修补 Dom 对象,所有你要做的就是确保你等到节目结束:

$('#load-modal').on('shown.bs.modal', function () {
console.log('Shown Modal Backdrop');
$('#load-modal').addClass('shown');
});


function HideLoader() {
var loadmodalhidetimer = setInterval(function () {
if ($('#load-modal').is('.shown')) {
$('#load-modal').removeClass('shown').modal('hide');
clearInterval(loadmodalhidetimer);
console.log('HideLoader');
}
else { //this is just for show.
console.log('Waiting to Hide');
}
}, 200);
}

IMO Bootstrap 应该已经在这么做了。好吧,也许还要多一点,如果你有机会在没有完成 show 的情况下调用 hide,你可能想要在 show.bs.mode 上添加一些内容,添加类‘ show’,并确保定时器在进入循环之前检查所要显示的内容。确保你清楚的“显示”在它的显示点。

最好和最简单的方法是使用 data-dismiss属性。基本上 data-dismiss属性将解散的模式,你不会看到背景剩余。

如何使用数据解散属性

所有你需要做的就是添加下面的地方,你想关闭您的模式:

data-dismiss="modal"

例如,我有一个按钮,当有人点击该按钮时,它将关闭模态。

<button class="btn btn-info float-right" onclick="foo()" data-dismiss="modal">Save changes</button>

您还可以在 onClick上处理 JavaScript 函数,它将关闭模态并运行 JavaScript 函数。

这是使用 data-dismiss属性的最佳方法。

对于引导程序4,这应该对你有用

 $('.modal').remove();
$('.modal-backdrop').remove();

我得到了同样的问题,解决方案是添加属性 data-dismiss="modal" 到你要点击的按钮。

data-backdrop="false"选项作为属性添加到打开模态的按钮。

参见 如何删除自举模式覆盖?

使用下面的代码,每次打开和关闭一个模态时,都会在 body 元素上连续添加7px 的空白。

$('modalId').modal('hide');
$('body').removeClass('modal-open');
$('.modal-backdrop').remove();`

对于那些仍在使用 Bootstrap 3的用户,这里有一个黑客式的解决方案。

$('#modalid').modal('hide');
$('.modal-backdrop').hide();
document.body.style.paddingRight = '0'
document.getElementsByTagName("body")[0].style.overflowY = "auto";

只要创建一个事件调用风箱。在我的情况下,使用 Angular,只要放入 NgOnInit。

let body = document.querySelector('.modal-open');
body.classList.remove('modal-open');
body.removeAttribute('style');
let divFromHell = document.querySelector('.modal-backdrop');
body.removeChild(divFromHell);

执行操作后,只需触发关闭按钮。

例子

$('.close').click();

试试这个

$('.modal').on('hide.bs.modal', function () {
if ($(this).is(':visible')) {
console.log("show modal")
$('.modal-backdrop').show();
}else{
console.log("hidden modal");
$('.modal-backdrop').remove();
}
})

如果关闭解雇按钮是工作,但问题发生时,使用动态代码,如模态(“隐藏”) ,你可以使用这个代码。迫使背景完全移除。

引导程序3

$modal.on('hidden.bs.modal', function(){
//remove the backdrop
jQuery('[data-dismiss="modal"]').click();
});


yourbutton.click(function() {
$modal.modal('hide');
});

在模式中使用关闭按钮,这种方法工作良好:

<input type="button" class="btn btn-default" data-dismiss="modal" value="Cancel" id="close_model">

成功使用后:

$('#model_form').trigger("reset"); // for cleaning a modal form
$('#close_model').click(); // for closing a modal with backdrop

这是为有些人谁不能得到修复后,尝试几乎所有上面列出的。请去做一些基本的检查,如脚本的顺序,引用他们和东西。 就我个人而言,我使用了一个来自 bootstrap 的捆绑包,但由于某些原因它无法正常工作。切换到不同的脚本让我的生活轻松了很多。 所以是的,以防万一。

对于任何还在纠结这个问题的人,我找到了一个解决办法

首先在关闭按钮上添加一个 id (如果你不需要或者没有的话,你可以让它不可见)

<button id="buttonDismiss" type="button" class="close" data-dismiss="modal" aria-label="Close">

在 Ajax 调用中,使用 Javascript 而不是 Jquery 触发单击(失去对 Modal 的引用)

document.getElementById("buttonDismiss").click();

为了绕过在 boostrap.js modal.hide ()之后徘徊的背景,我在模式中给关闭按钮一个 id,并以编程方式发送一个 click 事件。

<div class="modal-header">
<h5 class="modal-title">\{\{title}}</h5>
<button
type="button"
class="btn-close"
data-bs-dismiss="modal"
aria-label="Close"
:id="`${id}-btn-close`" ></button>
</div>




...


hideModal (modalElementId = 'modal') {
// Workaround issue with modal.hide() leaving the overlay behind.
var modalCloseButton = document.getElementById(`${modalElementId}-btn-close`);
if (modalCloseButton !== null) {
modalCloseButton.click();
}
}

不使用 AJAX,但也张贴在这里的任何人谁是使用 引导程序5的现场演示模式。在将 onClick 事件分配给 Save Changes 按钮之后,您可以单击它,模式将关闭,但是背景将保持不变。

添加 data-bs-dismiss="modal"到保存更改按钮将导致在模态解除时正确删除背景。

来自 Bootstrap 网站的原始代码:

<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>

正常工作的版本:

<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" onClick={(e) => { doSomething(e) }}>Save changes</button>
</div>

在@user2443343和@Rory McCrossan 的 回答上进行扩展,同时在@gal007的 关心上解决在将 data-dismiss="modal"添加到按钮元素时无法验证表单的问题: 我们的方向是正确的,让我们把它们放在一起。

$('#myButton').on('click', function(e) {    // using variable name "e" for the event
var isValid = true;   // starting value is true, but set to false if any field is invalidated
  

// (perform validation in script to ultimately get boolean value of "isValid"...)
  

if (isValid === false) {
  

// visually labeling the invalidated field (just an example)...
$('#txtField1').removeClass('is-invalid').addClass('is-invalid');
// (whatever other css/visual warnings you want to give, and then...)
    

isValid = true;   // reset value back to default
e.preventDefault; // <------- TADA! This is the ticket, right here
return false;     // Then you prematurely end the function here
    

} else {
    

// (perform script for when form is validated)
    

}
  

});
<form>
<!--fields/inputs go here...-->
<button type="button" id="myButton" class="btn btn-secondary" data-dismiss="modal">Submit Request</button>
</form>

总结一下:

  1. 是的,请在按钮的属性中包含 data-dismiss="modal"
  2. 在按钮的单击处理程序中传递 事件参数。
  3. 如果表单在脚本中验证失败,请调用 event.preventDefault,然后调用 return false,这将有效地阻止 data-dismiss被处理并退出函数。

这对我来说效果很好。

即使是 Bootstrap 5也有同样的问题。

我发现,在模态关闭后,车身仍然保留着一种风格:

overflow: hidden;
padding-right: 15px;

所以我决定了 $(‘ body’) . RemoveAttr (‘ style’) ; 然后又反弹回来了。 所以这对我来说很有用: mode 是由 新鞋带 Modal Id 是模态的 id:

// Don't add data-bs-dismiss="modal" to the Cancel button.
//
modal.hide();


// Hack to remove any lingering backdrop.https://stackoverflow.com/questions/22056147/bootstrap-modal-backdrop-remaining
// Asked 8 years, 3 months ago ...
//
$('body').removeClass('modal-open');
$('.modal-backdrop').remove();


// My own observations - these are left as body styles after the modal is closed, removing the
// vertical scroll and offsetting the page.
//
// overflow: hidden;
// padding-right: 15px;
//
// Just setting removeAttr ('style') didn't work as it bounced back again, so
// wait for modal to fire a hidden event.
//
$(id).on('hidden.bs.modal', function (e) {
$('body').removeAttr ('style');
});

希望能帮上忙。 ~ C ~

对于任何在 NextJS 中使用 Bootstrap 5的人来说,

const myBackdrop = document.getElementsByClassName("modal-backdrop");
myBackdrop[0].style.width = 0;
myBackdrop[0].style.height = 0;

在按钮的 onClick 事件中调用这个函数。