【问题标题】:Unbinding a jQuery listener from a subset of elements从元素子集解除 jQuery 侦听器的绑定
【发布时间】:2015-09-20 12:44:44
【问题描述】:

我正在使用 Zurb Foundation 工具提示 (http://foundation.zurb.com/docs/components/tooltips.html)。我想稍微定制他们的行为。他们利用源元素上的mouseover 事件侦听器来创建工具提示(在第一次调用时),然后将其淡入。我正在尝试做的是让 jQuery 选择工具提示源的子集页面,只删除他们的鼠标悬停侦听器,并绑定新的侦听器,让工具提示在鼠标移开后消失之前停留一秒钟。

这是棘手的部分。 Zurb 像这样绑定它的监听器:

$('body.off-canvas').on('mouseenter', '.has-tooltip', ...);

以下将按预期成功删除此侦听器:

$('body.off-canvas').off('mouseenter', '.has-tooltip');

但我只想删除其中一些元素的侦听器,如下所示:

$('body.off-canvas').off('mouseenter', '.has-tooltip.my-custom-class');

事实证明,jQuery 不会将其识别为更大的.has-tooltip 元素集的“减法”,而是本质上说,“没有事件侦听器匹配这个精确的选择器,因此我什么也不做。”有没有人有一个好的解决方法?如果您自己创建原始侦听器,我发现有些方法会起作用,但这里不是这样。

【问题讨论】:

  • 有点从不同的角度来解决这个问题,但也许考虑使用.filter()方法或:not()选择器在应用.on()之前过滤掉.my-custom-class
  • 感谢您的意见;如果我自己创建原始侦听器,这将起作用,但不幸的是它是第三方库的一部分。我想我可以修改库,但我不想这样做,因为那不是很好的做法。
  • 所以库不能让你在配置中指定它?真可惜

标签: javascript html jquery dom jquery-events


【解决方案1】:

我认为,如果您想防止应用在正文元素上的“mouseenter”功能被触发,您可以停止这些锚链接上的事件冒泡。

使用 JQUERY :

$(".has-tooltip.my-custom-class").on("mouseenter", function(event){
   event.stopPropagation();
   ....
   ....
});

希望对你有帮助。

【讨论】:

  • 感谢您的反馈。我确实尝试过这个。不知道是听者顺序的问题还是什么,但没有任何效果。
【解决方案2】:

我通过采用不同的方法解决了这个问题。我原以为我无法删除所有正常工具提示的默认 Foundation 事件,因为我仍然需要 Foundation 来构建工具提示元素。解决方法很棘手,但它完成了工作。

页面加载后,我在所有的工具提示上手动触发了mouseenter 事件,使用特殊的 CSS 类强制它们在初始化后保持不可见而不是淡入。我必须在事件中模拟鼠标数据,因为 Foundation 依赖于它来初始定位工具提示。完成 DOM 修改后,我可以将侦听器添加到模仿默认行为的普通工具提示中,同时将自定义侦听器添加到我的自定义元素。

// simulate and trigger default tooltip hover event to allow Foundation to create spans
$('body.off-canvas .has-tip').each(function(){
    var event = $.Event('mouseenter');

    var offset = $(this).offset();
    var position = $(this).position();

    event.clientX = offset.left;
    event.clientY = offset.top;
    //event.offsetX = ;
    //event.offsetY = ;
    event.pageX = offset.left;
    event.pageY = offset.top;
    event.screenX = offset.left;
    //event.screenY = ;
    $(this).trigger(event);
});
$('body.off-canvas .has-tip').trigger('mouseleave');

// remove default events
$('body.off-canvas').off('mouseenter', '.has-tip');
$('body.off-canvas').off('mouseleave', '.has-tip');

// restore normal tooltips to normal behavior
$('body.off-canvas').on('mouseenter', '.has-tip:not(.has-details)', function(){
    $('span.tooltip[data-selector="' + $(this).data('selector') + '"]').removeClass('force-visibility-hidden').fadeIn();
});
$('body.off-canvas').on('mouseleave', '.has-tip:not(.has-details)', function(){
    $('span.tooltip[data-selector="' + $(this).data('selector') + '"]').fadeOut();
});

// set up custom details tooltip listener
$('body.off-canvas').on('mouseenter', '.has-tip.has-details', function(e){
    ...
});

作为旁注,我还必须将整个内容包装在 setTimeout(..., 200); 中,以确保在应用了 Foundation 侦听器后它会执行。

总而言之,这是我写过的最复杂的代码之一,但它的作用就像一个魅力。

【讨论】:

    【解决方案3】:

    您可以使用stopImmediatePropagation() 来停止该元素上的所有其他处理程序。由于处理程序是按添加顺序执行的,因此请确保在添加 Zurb 代码之前添加您的代码。以下是如何测试my-custom-class 的示例:

    $(function(){
        $('body.off-canvas').on('mouseenter', '.has-tooltip', function(event){
            if($(event.target).hasClass('my-custom-class')){
                event.stopImmediatePropagation();
            }
        });
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-10
      • 2015-11-24
      • 1970-01-01
      • 2021-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多