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

时间:2017-02-01 00:10:49

标签: javascript twitter-bootstrap interact.js

我使用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);
    });
});
&#13;
.modal-content {
  overflow: auto;
  max-height: 200px;
}
.modal-dialog {
  max-height: 200px;
}
&#13;
<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>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:0)

问题在于,当鼠标指针移动到模态的内容之外时,鼠标释放将在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的未记录部分的替代解决方案感到好奇。

以下是说明此解决方案的代码段。 &#34;制作一个错误的模式&#34;复制问题中的问题。 &#34;做一个好的模式&#34;按钮显示修复。

&#13;
&#13;
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);
    });
});
&#13;
.modal-content {
  overflow: auto;
  max-height: 200px;
}
.modal-dialog {
  max-height: 200px;
}
&#13;
<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>
&#13;
&#13;
&#13;