【问题标题】:jQuery event bubbling issue with dynamic data()动态数据()的jQuery事件冒泡问题
【发布时间】:2012-12-05 04:29:14
【问题描述】:

我有一点 jQuery,但把它放在这里是一个简化的版本,以更好地识别任何可能的故障。我提供了一些内联代码的 cmets,以更好地突出我的尝试和问题。请在代码中找到我的评论。

我的问题是“清除”按钮,清除之前点击的所有输入,而它应该只清除当前活动的输入。闻起来像事件冒泡问题,但我现在无法识别它,非常感谢您的帮助。

工作流程是这样的:

  1. 我在 .container 中点击 input.trigger (input[name="a"])

  2. div#popup 弹出/启动

  3. 我单击#popup 中的“清除”按钮,它确实清除了input[name="a"]。我做了一个“还原”来放回值,到目前为止很好,如果有一些默认值,它会还原(这部分不包含在代码中,因为它不是主要问题,如果解决了以下问题)。关闭它。因此输入“a”被清除,但后来通过存储的数据默认值恢复为默认值。

  4. 很好,到目前为止。

  5. 我单击另一个 input.trigger (input[name="b"]),#popup 启动,更多操作.. 很好,但是 ....

  6. 我点击“清除”按钮,它会清除输入“a”和“b”,而预计只会清除当前的input.trigger[name="b"](而不是之前的输入,“a”)。

解决方案here 还没有帮助。

$('.container').on('focus', 'input.trigger', function(e) {
   e.preventDefault();
   // First fix attempt, no use
   // https://stackoverflow.com/questions/9153501/how-do-you-stop-children-from-propagating-an-event-triggered-by-a-live-delegate
   // Trying to solve problem with event bubbling, but no use
   if (e.target != this){ 
     return true; 
   }
   var input = $(this);
   // somewhere added a class focused on input focused, please ignore.
   // we add blur here to make any button or input inside popup clickable.
   $('input:not(.focused)').blur();

  // Added dynamic data("popup") based on input name (a, b, c, d)
  $("#popup").data("popup", this.name).css({
    left: "20px",
    top: input.offset().top + 24 + "px"
  })
  // Second fix attempt, no use
  .stop(true, true)
  .show('slow', function () {
    var currentPopup = $(this),
      popupName = currentPopup.data("popup"),
      // Trying to get input/trigger name from data "popup" per clicked input name.
      // I tried putting this after `var input = $(this);` above but put it here later
      // thinking it should solve the problem, but alas not.
      theinput = $('input[name="' + popupName + '"]'),
      // Used for other dynamic interaction with some classes (.a_popup, .b_popup, etc).
      popupid = theinput.data('popupid');

    currentPopup.on('click', '.clear', function(e) {
      // Third fix attempt, no use
      e.stopPropagation();
      // The problem is here:
      // The button clears out any previous (opened) input.trigger,
      // while it should only clears the input with name == current popupName

      // Why this also bubbles to previously opened input.trigger "popupid"
      console.log(popupid); 

      theinput.val("");
    });
    // More buttons here: Revert and Close. But once the "Clear" button issue is solved, this is no issue. So excluded.
  });
 })
.on('blur', 'input.trigger', function (e) {
  e.preventDefault(); // no use
  var hidden = $("#popup"),
    popupName = this.name;
  if (hidden.data("popup") === popupName) {
    hidden.hide().removeData("popup");
  }
});

HTML:

<body>
<div id="page-wrapper">
  <div class="container">
    <form>
      <!-- This input value is dynamically changed via other function -->
      <input class="trigger" name="a" value="one" data-popupid=".a_popup" data-default="a_value">
      <input class="trigger" name="b" value="" data-popupid=".b_popup" data-default="">
      <input class="trigger" name="c" value="three" data-popupid=".c_popup" data-default="c_value">
      <input class="trigger" name="d" value="four" data-popupid=".d_popup" data-default="d_value">
    <form>

    <!-- Ignore below divs, but here to have a general idea with above data-popid 
      This is not directly addressed in the code above -->
    <div class="a_popup">Content</div>
    <div class="b_popup">Content</div>
    <div class="c_popup">Content</div>
    <div class="d_popup">Content</div>
  </div>
</div><!-- page wrapper -->

<!-- This popup has data("popup") namee by above inputs (a, b, c, d) assigned dynamically -->
<div id="popup">
  <!-- Sometext and additional inputs -->
  <button class="revert">Revert</button>
  <button class="clear">Clear</button>
  <button class="close">Close</button>
</div> 
</body>

CSS:

#popup {
  background: #fff;
  display: none;
  height: 200px;
  width: 200px;
  z-index: 99999;
  position: absolute;
}

我希望我能说清楚,但如果不是,我会更新上面简化代码中遗漏的任何内容。 感谢您发现实际问题的任何提示。

更新: $('.container').off('input.trigger'); 附加到关闭按钮。

【问题讨论】:

  • 如果您使用委托的事件处理程序,则停止传播为时已晚,因为在调用您的处理程序之前事件已经冒泡到容器中。我没有看到在您的代码中使用 .off() 来删除以前绑定的处理程序 - 您只需在每次显示弹出窗口时再次调用 .on() 绑定越来越多的处理程序...
  • 谢谢,我更新了上面的内容。 .off() 附加到关闭按钮,但恐怕没有任何好处。
  • 但这不会清除使用currentPopup.on('click', '.clear', function(e) {...}) 设置的处理程序吗?
  • 恐怕不行。将按钮事件从弹出窗口中取出,然后查看。谢谢。这些按钮在那里是因为页面中有 3 个具有相同类按钮的弹出窗口,只有基于实际活动弹出窗口的不同操作。而且我需要根据上下文/活动弹出窗口轻松访问。

标签: jquery


【解决方案1】:

我发现 JavaScript 太复杂且难以理解。所以让我们简单地说:

$(document).ready(function() {
    $('.container').on('focus', 'input.trigger', function(e) {
        var input = $(this);
        var position = input.position();

        $("#popup")
            .data('target', $(e.target))
            .css('top', position.top + 24)
            .css('left', position.left + 20)
            .show();
     });

    $('.clear').on('click', function(e) {
        e.preventDefault();
        var input = $(e.target).closest('#popup').data('target');
        input.val('');
        $(e.target).closest('#popup').hide();
    });
    $('.revert').on('click', function(e) {
        e.preventDefault();
        $(e.target).closest('#popup').hide();
    });
    $('.close').on('click', function(e) {
        e.preventDefault();
        $(e.target).closest('#popup').hide();
    });
});​

下面是这种更简单方法的一个工作示例:http://jsfiddle.net/UZ4QM/

加回金光闪闪

现在我们可以添加 bling 了:

$(document).ready(function() {
    $('.container')
        .on('focus', 'input.trigger', function(e) {
            var input = $(this);
            var position = input.position();

            $("#popup")
                .data('target', $(e.target))
                .css({'top':  position.top + 24,
                      'left': position.left + 20 })
                .show('slow');
         })
        .on('blur', 'input.trigger', function(e) {
            $("#popup").hide();
        });

    $('.clear').on('click', function(e) {
        e.preventDefault();
        var input = $(e.target).closest('#popup').data('target');
        input.val('');
        $(e.target).closest('#popup').hide();
    });
    $('.revert').on('click', function(e) {
        e.preventDefault();
        $(e.target).closest('#popup').hide();
    });
    $('.close').on('click', function(e) {
        e.preventDefault();
        $(e.target).closest('#popup').hide();
    });
});​

这是一个更接近原版的工作示例:http://jsfiddle.net/C9JM5/

【讨论】:

  • 非常感谢,请给我一些时间来合并。
  • 没问题。我修复了 blinged 版本中的一个错误(刚刚更新了答案)。
  • 我有几个弹出窗口,类似的分类按钮,用于我的作业,但你的工作没有问题。谢谢
猜你喜欢
  • 2023-04-02
  • 2011-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多