当我调整超过其最大大小时,如何防止 Bootstrap 模态对话框关闭?

How can I prevent the closure of my Bootstrap modal dialog when I resize past its maximum size?

我正在使用 interact.js 来允许用户调整我使用 Bootstrap 3.3.7 生成的模态对话框的大小。存在一个问题,当用户启动调整大小并移动鼠标指针以使对话框的大小调整到超过其最大尺寸时,一旦用户释放鼠标按钮,模式就会关闭。如果用户正在缩小模式,则不会发生这种情况。以下代码片段显示了该问题。

var makeModalButton = document.getElementById("makeModal");
var modalTemplate =
  '\
<div class="modal" style="position: absolute" tabindex="1">\
  <div class="modal-dialog">\
    <div class="modal-content">\
      <div class="modal-header">\
        <button type="button" class="close" data-dismiss="modal" \
         aria-hidden="true">&times;</button>\
        <h3 class="modal-title">Foo</h3>\
      </div>\
      <div class="modal-body">\
        <p>Foo foo.</p>\
      </div>\
      <div class="modal-footer">\
      </div>\
    </div>\
  </div>\
</div>';

function updateRect(el, dx, dy) {
  var rect = el.getBoundingClientRect();
  var width = rect.width + dx;
  var height = rect.height + dy;
  el.style.width = width + 'px';
  el.style.height = height + 'px';
}

$(makeModalButton).on("click", function() {
  var $modal = $(modalTemplate);
  document.body.appendChild($modal[0]);
  var body = $modal[0].getElementsByClassName("modal-body")[0];
  var content = $modal[0].getElementsByClassName("modal-content")[0];
  $modal.modal();
  interact(content)
    .resizable({})
    .on('resizemove', function(event) {
      var target = event.target;

      updateRect(target, event.dx, event.dy);
      updateRect(body, event.dx, event.dy);
    });
});
.modal-content {
  overflow: auto;
  max-height: 200px;
}
.modal-dialog {
  max-height: 200px;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/interact.js/1.2.6/interact.min.js"></script>
<p>
  Click the button "Make a modal". Click on the bottom footer of the modal to resize it, and move the pointer down until the modal stop resizing. Release the mouse button. The modal will close.
</p>
<button id="makeModal">Make a modal</button>

问题是当鼠标指针移动到模态内容之外时,鼠标释放记录在 Bootstrap 创建的背景上以捕捉模态之外的点击.这样的点击关闭模式。

以下是概念验证。关键是添加了这两个事件监听器:

    .on('resizestart', function() {
      var modal = $modal.data('bs.modal');
      modal.ignoreBackdropClick = true;
    })
    .on('resizeend', function() {
      setTimeout(function() {
        var modal = $modal.data('bs.modal');
        modal.ignoreBackdropClick = false;
      }, 0);
    })

我们使用 var modal = $modal.data('bs.modal') 获取 Bootstrap 创建的 JavaScript 对象来存储模态的状态。在 resizestart 处理程序中,我们设置了 .ignoreBackdropClick 属性,它告诉 Bootstrap 忽略背景上的下一次点击。在 resizeend 处理程序中,我们要重置 属性。然而,由于事件发生的方式,我们无法立即重置它。相反,我们为事件循环的下一次迭代安排重置,这允许 Bootstrap 首先执行其内务处理。 (如果我们过早清除 属性 就好像我们一开始就没有设置它一样。)

该原则有效,但我对依赖 Bootstrap 中未记录的部分并不是特别满意。我肯定会对不需要依赖 Bootstrap.

的未记录部分的替代解决方案感到好奇

说明此解决方案的代码片段如下。 "Make a faulty modal" 复制了问题中的问题。 "Make a good modal" 按钮显示修复。

var makeFaultyModalButton = document.getElementById("makeFaultyModal");
var makeGoodModalButton = document.getElementById("makeGoodModal");
var modalTemplate = '\
<div class="modal" style="position: absolute" tabindex="1">\
  <div class="modal-dialog">\
    <div class="modal-content">\
      <div class="modal-header">\
        <button type="button" class="close" data-dismiss="modal" \
         aria-hidden="true">&times;</button>\
        <h3 class="modal-title">Foo</h3>\
      </div>\
      <div class="modal-body"><p>Foo foo.</p></div>\
      <div class="modal-footer"></div>\
    </div>\
  </div>\
</div>';

function updateRect(el, dx, dy) {
  var rect = el.getBoundingClientRect();
  var width = rect.width + dx;
  var height = rect.height + dy;
  el.style.width = width + 'px';
  el.style.height = height + 'px';
}

$(makeFaultyModalButton).on("click", function() {
  var $modal = $(modalTemplate);
  document.body.appendChild($modal[0]);
  var body = $modal[0].getElementsByClassName("modal-body")[0];
  var content = $modal[0].getElementsByClassName("modal-content")[0];
  $modal.modal();
  interact(content)
    .resizable({})
    .on('resizemove', function(event) {
      var target = event.target;

      updateRect(target, event.dx, event.dy);
      updateRect(body, event.dx, event.dy);
    });
});

$(makeGoodModalButton).on("click", function() {
  var $modal = $(modalTemplate);
  document.body.appendChild($modal[0]);
  var body = $modal[0].getElementsByClassName("modal-body")[0];
  var content = $modal[0].getElementsByClassName("modal-content")[0];
  $modal.modal();
  interact(content)
    .resizable({})
    .on('resizestart', function() {
      var modal = $modal.data('bs.modal');
      modal.ignoreBackdropClick = true;
    })
    .on('resizeend', function() {
      setTimeout(function() {
        var modal = $modal.data('bs.modal');
        modal.ignoreBackdropClick = false;
      }, 0);
    })
    .on('resizemove', function(event) {
      var target = event.target;

      updateRect(target, event.dx, event.dy);
      updateRect(body, event.dx, event.dy);
    });
});
.modal-content {
  overflow: auto;
  max-height: 200px;
}
.modal-dialog {
  max-height: 200px;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/interact.js/1.2.6/interact.min.js"></script>
<button id="makeFaultyModal">Make a faulty modal</button>
<button id="makeGoodModal">Make a good modal</button>