取消 jQuery 侦听器与元素子集的绑定

Unbinding a jQuery listener from a subset of elements

提问人:Brandon 提问时间:7/3/2015 最后编辑:Brian Tompsett - 汤莱恩Brandon 更新时间:4/22/2021 访问量:294

问:

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

这是棘手的部分。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

JavaScript HTML jQuery DOM JQuery-事件

评论

0赞 CrayonViolent 7/5/2015
有点从不同的角度来看,但也许可以考虑使用方法或选择器来过滤掉之前。是否应用?.filter():not().my-custom-classon()
0赞 Brandon 7/6/2015
感谢您的输入;如果我自己创建原始侦听器,那会起作用,但不幸的是,它是第三方库的一部分。我想我可以修改库,但我宁愿不这样做,因为这不是很好的做法。
0赞 CrayonViolent 7/6/2015
所以库没有能力让你在配置中指定它?那真是太可惜了

答:

0赞 Prateek 7/5/2015 #1

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

使用 JQUERY :

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

希望对你有所帮助。

评论

0赞 Brandon 7/6/2015
感谢您的反馈。我确实尝试过这个。我不知道是听众排序的问题还是什么,但它没有任何影响。
0赞 Brandon 7/8/2015 #2

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

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

// 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){
    ...
});

顺便说一句,我还必须将整个事情包装在一个 a 中,以确保它在应用基金会监听器后执行。setTimeout(..., 200);

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

0赞 Klaassiek 4/22/2021 #3

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

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