.live()使用时,如何阻止子元素点击事件向父元素传播?

8
我在我的图片和内容上有一个'Back Board',链接如下:http://syndex.me。基本上,你点击一张图片,它将覆盖在点击的内容上方展示一个信息面板。
我想要做两件事情:
  • 点击网站背景淡化当前打开的信息面板
  • 能够在信息面板中点击标签、链接或社交图标而不触发其父函数,即面板再次消失。
我不能使用stopPropagation来防止子单击被父级单击覆盖,因为我需要通过.live()来处理单击事件 (请参见文档)。这是因为帖子是动态加载的。
我不能只是写像这样的代码: $("#Background").click(function(){//淡出信息面板} 因为它被整个帖子包装器所覆盖,我无法在上面放置事件,否则我就更陷入父级接管子级事件的困境了:-)
到目前为止,我至少能够只打开一个信息面板(比如我点击一个图片,然后又点击另一个图片,它会关闭已经打开的那个,并打开当前的那个)。所以这部分还不错:
    $('.theContent:not(.clicked)').live("click", function () {
            $(this).children('.postInfo').fadeIn(400);
            $(".clicked").each(function() {
                    $(this).find('.postInfo').fadeOut(400);
                    $(this).removeClass('clicked');
            });
        $(this).addClass("clicked");
 });
     $('.clicked').live("click", function () {
            $(".clicked").each(function() {
                $(this).find('.postInfo').fadeOut(400);
                $(this).removeClass('clicked');
            });
 });

关于 .live()、.delegate() 和 .stopPropagation() 方法:

.live() 方法处理事件时,事件已经传播到文档的顶部,因此无法停止 live 事件的传播。同样,由 .delegate() 处理的事件将传播到委托它们的元素;DOM 树中在其下方绑定的事件处理程序将在调用委托的事件处理程序时已经执行。因此,这些处理程序可能通过调用 event.stopPropagation() 或返回 false 来防止委托处理程序触发。


我不确定它是否有效,但你尝试在你的live()事件处理程序中使用return false;了吗? - Andre
不,刚刚试过了,但没有任何区别。不过那样做确实会很有意思! - RGBK
在“正常”的JavaScript中,这就是你应该做的 :) 看起来没有办法停止事件。你有没有想过设置一个全局变量并在动画处理程序中检查它? - Andre
我以前从没做过这种事,但在此期间我会研究全局变量。不过我相信这是一个常见的问题。最近很多用户界面都使用了“点击外部,点击内部”的方法。 - RGBK
1
嗯...你有任何想法为什么它能工作吗?http://jsfiddle.net/Quincy/PbxBH/2/ - Quincy
我猜测我的网站上的版本是超级嵌套的。不过那确实有效,不知道为什么? - RGBK
3个回答

6

那么,我们可以简单地检查事件是否在指定元素上触发:

function activate(el) {
    el.find('.postInfo').fadeIn(400);
    el.addClass('clicked');
}
function deactivate(el) {
    el.find('.postInfo').fadeOut(400);
    el.removeClass('clicked');
}
$('.theContent:not(.clicked)').live('click', function(e) {
    deactivate($('.clicked'));
    activate($(this));
});

$('.clicked').live("click", function(e) {
    if (! $(e.target).is('a')) {
        // this should not trigger if a click occured on one of the links
        deactivate($(this));
    }
});

$('#ape').click(function(e) {
    if ($(e.target).is('#ape')) {
        deactivate($('.clicked'));
    }
});

我认为您忘记添加 el.addClass('clicked'); 方面了,这是标记,表示“好的,我已经被点击了”。我假设您将其放在 activate 函数中,如果是这种情况,它会自行取消:http://syndex.me。哎呀。 - RGBK
@RGBK 是的,我忘了那行代码,所以不得不撤销 deactivate/activate 的调用。我已经更新了代码,请试一下。 - deviousdodo
问题已经解决了,我错过了反转的调用,谢谢。但它仍然没有停用父级。我在想,也许是因为目标还不准确?我正在研究目标,以更好地理解它,似乎是一个有用的函数。 - RGBK
背景也是同样的情况,这就是为什么我最初没有包含代码的原因。现在我已经添加了一个处理程序来处理它。 - deviousdodo
你知道吗,我很高兴通过点击信息面板外部来关闭它。你觉得怎么样?这样我就不用担心.clicked不起作用(仍然没有)。当我点击比如心形图标时,我追踪到被点击的元素,它说“div”。这可能是因为它嵌套在许多其他元素中。但是那里确实有一个a。我认为这已经足够了。谢谢! - RGBK

0

0

等等,我以为 bind 只处理当前元素而不是未来的元素?不过我会尝试一下看看。 - RGBK
就像我想的那样,bind函数无法识别来自另一个脚本的新加载内容。 - RGBK
@RGBK,啊。如果内容是从您无法控制的脚本加载的,则无法使用此方法。您是否对HTML具有控制权?您始终可以在动态内容周围包装一个div并在那里捕获单击事件。 - rkw

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接