jQuery - 对模态窗口的打开和关闭事件的不期望的递归操作

时间:2021-07-13 10:19:58

I am working on a project that has a jQuery (version 2.2.0) modal window with the following code: Fiddle: https://jsfiddle.net/8f9fh9p0/1/

我正在开发一个具有jQuery(版本2.2.0)模式窗口的项目,其中包含以下代码:Fiddle:https://jsfiddle.net/8f9fh9p0/1/

function buildModalWindow(values) {

  jQuery(document).on('click', '#openWindow', function(e) {

    e.preventDefault();

    // mask effect
    $('#mask').fadeIn(150);
    $('#mask').fadeTo("slow", 0.4);

    // frame effect
    $('#frameModal').fadeIn(500);

    // display the mask and the frame
    $('#mask').css("display", "block");
    $('#frameModal').css("display", "block");

    // HTML content in the frame
    $('#frameModal').html('<form id="formContent" name="formContent" method="post"><div class="myClass"><div class="linha fontmodalbold fontsize14"><label><span class="span-15">Some Form Title</span><span>Form Id</span></label></div><div class="linha"><label class="fontModalBold fontsize12">Atendant Type:</label><label class="fontModalBold fontsize12"><input type="radio" name="atendantType" id="correctiveAction" value="1"/>Corrective Action</label><label class="fontModalBold fontsize12"><input type="radio" name="atendantType" id="preventiveAction" value="2"/>Preventive Action</label><label class="fontModalBold fontsize12"><input type="radio" name="atendantType" id="project" value="3"/>Project</label><label class="fontModalBold fontsize12"><input type="radio" name="atendantType" id="contract" value="4"/>Contract</label></div><div class="direita"><input id="close" type="button" class="button" value="Close" /><input type="button" class="button" id="saveButton" value="Save" onclick="javascript: saveTheInformation();" /></div></div></form>');

  });

  // if close button is clicked
  jQuery(document).on('click', '#close', function(e) {

    e.preventDefault();

    $('#formContent').empty();
    $('#formContent').remove();

    $('#frameModal').css("display", "none");
    $('#mask').css("display", "none");

    $('#frameModal').empty();

  });

  // if div #mask is clicked
  jQuery(document).on('click', '#mask', function(e) {

    e.preventDefault();

    $('#formContent').empty();
    $('#formContent').remove();

    $('#frameModal').css("display", "none");
    $('#mask').css("display", "none");

    $('#frameModal').empty();

  });
}
#mask {
  position: absolute;
  left: 0;
  top: 0;
  background-color: #000;
  display: none;
  width: 500px;
  height: 300px;
}

#modalContent .window {
  position: absolute;
  left: 0;
  top: 0;
  width: 440px;
  height: 200px;
  display: none;
  z-index: 9999;
  padding: 20px;
}

#modalContent #frameModal {
  width: 385px;
  height: 300px;
  padding: 5px;
  background-color: #ffffff;
  overflow: auto;
  left: 200;
  top: 150;
}

.close {
  display: block;
  text-align: right;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div>
  <input type="button" value="Open Modal Window" id="openWindow" onclick="javascript: buildModalWindow(3);">
</div>
<div id="modalContent">
  <div id="frameModal" class="window"></div>
  <div id="mask"></div>
</div>

The strange thing is, if you click to open the modal window and close it many times, you will face some undesired recursive situation.

奇怪的是,如果你点击打开模态窗口并多次关闭它,你将面临一些不希望的递归情况。

If I call a get Ajax method to do something in the database, it behaves as a geometric progression. When I want to register a new report, for example: - First button click following by close or mask click: one record; - Second button click following by close or mask click: 3 records; - Third button click following by close or mask click: 6 records; - And so on.

如果我调用get Ajax方法在数据库中执行某些操作,它就会表现为几何级数。当我想要注册一个新报告时,例如: - 第一个按钮点击后面的关闭或掩码点击:一个记录; - 第二个按钮点击后面的关闭或掩码点击:3条记录; - 第三个按钮点击关闭或掩码点击:6条记录; - 等等。

Crazy, isn't it?

疯了,不是吗?

Anybody knows what is goin on and what I have to change in the JavaScript, CSS or HTML to solve that problem?

任何人都知道什么是goin on以及我必须在JavaScript,CSS或HTML中改变什么来解决这个问题?

Thank you in advance.

先感谢您。

The shorter, clearer and improved code (with the resolution provided) is shown below. https://jsfiddle.net/r5aff042/

更短,更清晰和改进的代码(提供分辨率)如下所示。 https://jsfiddle.net/r5aff042/

3 个解决方案

#1


2  

It's not that crazy. Every time the buildModalWindow function runs, you add another "click" handler to the openWindow element. Bizarrely, this is also the element on which you run the buildModalWindow function in the first place, which is confusing logic.You never remove the previously added handlers,so if you've run that function 3 times, then it'll have added those handlers repeatedly. When you click the button it both runs all the existing handlers (hence the multiple records, you'll see multiple ajax requests in the browser tools, too) and adds yet another click handler to run next time.

这不是那么疯狂。每次运行buildModalWindow函数时,都会向openWindow元素添加另一个“click”处理程序。奇怪的是,这也是你首先运行buildModalWindow函数的元素,这是令人困惑的逻辑。你永远不会删除以前添加的处理程序,所以如果你运行该函数3次,那么它将添加那些处理程序反复。单击按钮时,它都会运行所有现有的处理程序(因此多个记录,您也会在浏览器工具中看到多个ajax请求),并添加另一个单击处理程序以便下次运行。

This is a fixed version. I moved the other event handlers out of your function too, because they also will be getting duplicated, although the effects are not as problematic.

这是一个固定版本。我也将其他事件处理程序移出了你的函数,因为它们也会被复制,尽管效果不是那么有问题。

function buildModalWindow(values) {

  // mask effect
  $('#mask').fadeIn(150);
  $('#mask').fadeTo("slow", 0.4);

  // frame effect
  $('#frameModal').fadeIn(500);

  // display the mask and the frame
  $('#mask').css("display", "block");
  $('#frameModal').css("display", "block");

  // HTML content in the frame
  $('#frameModal').html('<form id="formContent" name="formContent" method="post"><div class="myClass"><div class="linha fontmodalbold fontsize14"><label><span class="span-15">Some Form Title</span><span>Form Id</span></label></div><div class="linha"><label class="fontModalBold fontsize12">Atendant Type:</label><label class="fontModalBold fontsize12"><input type="radio" name="atendantType" id="correctiveAction" value="1"/>Corrective Action</label><label class="fontModalBold fontsize12"><input type="radio" name="atendantType" id="preventiveAction" value="2"/>Preventive Action</label><label class="fontModalBold fontsize12"><input type="radio" name="atendantType" id="project" value="3"/>Project</label><label class="fontModalBold fontsize12"><input type="radio" name="atendantType" id="contract" value="4"/>Contract</label></div><div class="direita"><input id="close" type="button" class="button" value="Close" /><input type="button" class="button" id="saveButton" value="Save" onclick="javascript: saveTheInformation();" /></div></div></form>');

}

jQuery(document.ready(function() {

      // if close button is clicked
      jQuery(document).on('click', '#close', function(e) {

        e.preventDefault();

        $('#formContent').empty();
        $('#formContent').remove();

        $('#frameModal').css("display", "none");
        $('#mask').css("display", "none");

        $('#frameModal').empty();

      });

      // if div #mask is clicked
      jQuery(document).on('click', '#mask', function(e) {

        e.preventDefault();

        $('#formContent').empty();
        $('#formContent').remove();

        $('#frameModal').css("display", "none");
        $('#mask').css("display", "none");

        $('#frameModal').empty();

      });
    });
#mask {
  position: absolute;
  left: 0;
  top: 0;
  background-color: #000;
  display: none;
  width: 500px;
  height: 300px;
}

#modalContent .window {
  position: absolute;
  left: 0;
  top: 0;
  width: 440px;
  height: 200px;
  display: none;
  z-index: 9999;
  padding: 20px;
}

#modalContent #frameModal {
  width: 385px;
  height: 300px;
  padding: 5px;
  background-color: #ffffff;
  overflow: auto;
  left: 200;
  top: 150;
}

.close {
  display: block;
  text-align: right;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div>
  <input type="button" value="Open Modal Window" id="openWindow" onclick="javascript: buildModalWindow(3);">
</div>
<div id="modalContent">
  <div id="frameModal" class="window"></div>
  <div id="mask"></div>
</div>

#2


0  

You can try this:

你可以试试这个:

function buildModalWindow(values){
    jQuery(document).off('click', '#openWindow');
    jQuery(document).off('click', '#close');
    jQuery(document).off('click', '#mask');

    // the rest of your code here...

}

#3


0  

Try this: My example

试试这个:我的例子

Your button:

 <div>
     <input type="button" value="Open Modal Window" id="openWindow" data-values="3">
  </div>

OnClick event:

$(document).ready(function() {
    $("#openWindow").click(function(e) {
      e.preventDefault();
      // other way to manage the "values"
      // You also can add the values in hidden inputs 
      buildModalWindow($(this).attr("data-values"));
    });
});

Building the modal: Note that I deleted the additional event within this function, it was "duplicating" each time the button was clicked

构建模态:请注意,我删除了此函数中的附加事件,每次单击按钮时都会“复制”

function buildModalWindow(values){
   // modal content... 
   // mask effect
    $('#mask').fadeIn(150);
    $('#mask').fadeTo("slow",0.4);

// frame effect
    $('#frameModal').fadeIn(500);

// display the mask and the frame
    $('#mask').css("display","block");
    $('#frameModal').css("display","block");

// HTML content in the frame
$('#frameModal').html('<form id="formContent" name="formContent" method="post"><div class="myClass"><div class="linha fontmodalbold fontsize14"><label><span class="span-15">Some Form Title</span><span>Form Id</span></label></div><div class="linha"><label class="fontModalBold fontsize12">Atendant Type:</label><label class="fontModalBold fontsize12"><input type="radio" name="atendantType" id="correctiveAction" value="1"/>Corrective Action</label><label class="fontModalBold fontsize12"><input type="radio" name="atendantType" id="preventiveAction" value="2"/>Preventive Action</label><label class="fontModalBold fontsize12"><input type="radio" name="atendantType" id="project" value="3"/>Project</label><label class="fontModalBold fontsize12"><input type="radio" name="atendantType" id="contract" value="4"/>Contract</label></div><div class="direita"><input id="close" type="button" class="button" value="Close" /><input type="button" class="button" id="saveButton" value="Save" onclick="javascript: saveTheInformation();" /></div></div></form>');
   // Modal Buttons Events
   jQuery(document).on('click', '#close', function (e) {
      hideAll(); // reuse code
   });
   jQuery(document).on('click', '#mask', function(e) {
      hideAll(); // reuse code
   });
 }

HideAll function:

function hideAll(){
    $('#formContent').empty();
    $('#formContent').remove();
    $('#frameModal').hide();
    $('#mask').hide(); // Hide the mask
    $('#frameModal').empty();
   $('#frameModal').hide(); // also hide the frameModal
}

#1


2  

It's not that crazy. Every time the buildModalWindow function runs, you add another "click" handler to the openWindow element. Bizarrely, this is also the element on which you run the buildModalWindow function in the first place, which is confusing logic.You never remove the previously added handlers,so if you've run that function 3 times, then it'll have added those handlers repeatedly. When you click the button it both runs all the existing handlers (hence the multiple records, you'll see multiple ajax requests in the browser tools, too) and adds yet another click handler to run next time.

这不是那么疯狂。每次运行buildModalWindow函数时,都会向openWindow元素添加另一个“click”处理程序。奇怪的是,这也是你首先运行buildModalWindow函数的元素,这是令人困惑的逻辑。你永远不会删除以前添加的处理程序,所以如果你运行该函数3次,那么它将添加那些处理程序反复。单击按钮时,它都会运行所有现有的处理程序(因此多个记录,您也会在浏览器工具中看到多个ajax请求),并添加另一个单击处理程序以便下次运行。

This is a fixed version. I moved the other event handlers out of your function too, because they also will be getting duplicated, although the effects are not as problematic.

这是一个固定版本。我也将其他事件处理程序移出了你的函数,因为它们也会被复制,尽管效果不是那么有问题。

function buildModalWindow(values) {

  // mask effect
  $('#mask').fadeIn(150);
  $('#mask').fadeTo("slow", 0.4);

  // frame effect
  $('#frameModal').fadeIn(500);

  // display the mask and the frame
  $('#mask').css("display", "block");
  $('#frameModal').css("display", "block");

  // HTML content in the frame
  $('#frameModal').html('<form id="formContent" name="formContent" method="post"><div class="myClass"><div class="linha fontmodalbold fontsize14"><label><span class="span-15">Some Form Title</span><span>Form Id</span></label></div><div class="linha"><label class="fontModalBold fontsize12">Atendant Type:</label><label class="fontModalBold fontsize12"><input type="radio" name="atendantType" id="correctiveAction" value="1"/>Corrective Action</label><label class="fontModalBold fontsize12"><input type="radio" name="atendantType" id="preventiveAction" value="2"/>Preventive Action</label><label class="fontModalBold fontsize12"><input type="radio" name="atendantType" id="project" value="3"/>Project</label><label class="fontModalBold fontsize12"><input type="radio" name="atendantType" id="contract" value="4"/>Contract</label></div><div class="direita"><input id="close" type="button" class="button" value="Close" /><input type="button" class="button" id="saveButton" value="Save" onclick="javascript: saveTheInformation();" /></div></div></form>');

}

jQuery(document.ready(function() {

      // if close button is clicked
      jQuery(document).on('click', '#close', function(e) {

        e.preventDefault();

        $('#formContent').empty();
        $('#formContent').remove();

        $('#frameModal').css("display", "none");
        $('#mask').css("display", "none");

        $('#frameModal').empty();

      });

      // if div #mask is clicked
      jQuery(document).on('click', '#mask', function(e) {

        e.preventDefault();

        $('#formContent').empty();
        $('#formContent').remove();

        $('#frameModal').css("display", "none");
        $('#mask').css("display", "none");

        $('#frameModal').empty();

      });
    });
#mask {
  position: absolute;
  left: 0;
  top: 0;
  background-color: #000;
  display: none;
  width: 500px;
  height: 300px;
}

#modalContent .window {
  position: absolute;
  left: 0;
  top: 0;
  width: 440px;
  height: 200px;
  display: none;
  z-index: 9999;
  padding: 20px;
}

#modalContent #frameModal {
  width: 385px;
  height: 300px;
  padding: 5px;
  background-color: #ffffff;
  overflow: auto;
  left: 200;
  top: 150;
}

.close {
  display: block;
  text-align: right;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div>
  <input type="button" value="Open Modal Window" id="openWindow" onclick="javascript: buildModalWindow(3);">
</div>
<div id="modalContent">
  <div id="frameModal" class="window"></div>
  <div id="mask"></div>
</div>

#2


0  

You can try this:

你可以试试这个:

function buildModalWindow(values){
    jQuery(document).off('click', '#openWindow');
    jQuery(document).off('click', '#close');
    jQuery(document).off('click', '#mask');

    // the rest of your code here...

}

#3


0  

Try this: My example

试试这个:我的例子

Your button:

 <div>
     <input type="button" value="Open Modal Window" id="openWindow" data-values="3">
  </div>

OnClick event:

$(document).ready(function() {
    $("#openWindow").click(function(e) {
      e.preventDefault();
      // other way to manage the "values"
      // You also can add the values in hidden inputs 
      buildModalWindow($(this).attr("data-values"));
    });
});

Building the modal: Note that I deleted the additional event within this function, it was "duplicating" each time the button was clicked

构建模态:请注意,我删除了此函数中的附加事件,每次单击按钮时都会“复制”

function buildModalWindow(values){
   // modal content... 
   // mask effect
    $('#mask').fadeIn(150);
    $('#mask').fadeTo("slow",0.4);

// frame effect
    $('#frameModal').fadeIn(500);

// display the mask and the frame
    $('#mask').css("display","block");
    $('#frameModal').css("display","block");

// HTML content in the frame
$('#frameModal').html('<form id="formContent" name="formContent" method="post"><div class="myClass"><div class="linha fontmodalbold fontsize14"><label><span class="span-15">Some Form Title</span><span>Form Id</span></label></div><div class="linha"><label class="fontModalBold fontsize12">Atendant Type:</label><label class="fontModalBold fontsize12"><input type="radio" name="atendantType" id="correctiveAction" value="1"/>Corrective Action</label><label class="fontModalBold fontsize12"><input type="radio" name="atendantType" id="preventiveAction" value="2"/>Preventive Action</label><label class="fontModalBold fontsize12"><input type="radio" name="atendantType" id="project" value="3"/>Project</label><label class="fontModalBold fontsize12"><input type="radio" name="atendantType" id="contract" value="4"/>Contract</label></div><div class="direita"><input id="close" type="button" class="button" value="Close" /><input type="button" class="button" id="saveButton" value="Save" onclick="javascript: saveTheInformation();" /></div></div></form>');
   // Modal Buttons Events
   jQuery(document).on('click', '#close', function (e) {
      hideAll(); // reuse code
   });
   jQuery(document).on('click', '#mask', function(e) {
      hideAll(); // reuse code
   });
 }

HideAll function:

function hideAll(){
    $('#formContent').empty();
    $('#formContent').remove();
    $('#frameModal').hide();
    $('#mask').hide(); // Hide the mask
    $('#frameModal').empty();
   $('#frameModal').hide(); // also hide the frameModal
}