jQuery.click之前的jQuery.on('click')?

时间:2014-02-28 21:29:22

标签: javascript jquery analytics

我有一个外部脚本,我无法修改。这个脚本加载一个按钮,并在其上添加一个jQuery .click ...它以“return false”结束。

我需要在此次点击时触发自己的代码。当我加载页面时,不存在,所以我需要使用.on('click')绑定“live”。但是看起来.on('click')在“.click之后加载”并且当他使用“return false”时,我的.on('click')没有加载。

所以问题是......如何触发我点击这个动态加载的#btn已经有一个.click函数返回false?

这是小提琴: http://jsfiddle.net/PLpqU/

这里有一个代码示例:

<div id="container"></div>
// I want this action to be executed on click, and the other too
// I can't use .click because on the "real" code, the a#btn is loaded after the page by another script
jQuery(document).on('click','a#btn',function(){
        ga('send', 'event', { eventCategory: 'xxxx', eventAction: 'yyyy' });
}) ;

// http://www.xxxxxx.com/distant-script.js
// This one is binded in a script that i cannot edit :
// Just before it load a#btn on the page, and then bind .click on it
// as he return false, the other on('click') are not executed
jQuery('#container').append('<a id="btn" />') ;
jQuery('a#btn').click(function(){
    // Some code stuff i need to be executed, but i can't manage
    return false ;
}) ;

尽可能地,目标是在由远程脚本加载的链接按钮上触发Google Analytics事件。

4 个答案:

答案 0 :(得分:4)

您似乎面临着多个问题,但更重要的是知道何时在DOM中呈现元素,以便您可以操纵它的事件集合。

一旦元素可访问,取消绑定插件的处理程序,绑定你的并重新绑定插件,知道可以访问jQuery的事件集合是非常简单的喜欢:$ ._ data(domEl,&#39; events&#39;);

以下是一个例子:

var $div = $('<div>').click(function () { console.log('plugin'); return false; }),
    clickListener = jQuery._data($div[0], 'events').click[0];

//unbind all
$div.off('click');

//bind yours
$div.click(function () { console.log('yours'); });

//rebind the plugin's one
//note that I do not register the listener by honoring the same configs, 
//but you could since you can see them in the clickListener object
$div.click(clickListener.handler);

//test out everyting
$div.triggerHandler('click');

如果您不想取消绑定,我相信您也可以使用DOM 0级事件模型并执行:

element.onclick = yourHandler;

知道,如果插件以异步方式呈现此元素并且不提供了解过程何时完成的方法,那么知道元素何时可用会更成问题。

如果你想支持旧的浏览器,除了覆盖插件的代码(假设有关的方法是公开的)或者用setInterval轮询DOM,你将别无选择,直到你的元素为止。寻找是DOM的一部分,然后你可以做我们上面讨论的。

如果您要定位现代浏览器,则可以使用MutationObserver对象来侦听DOM更改。

答案 1 :(得分:3)

您可以取消绑定事件,然后将您的函数添加为事件处理程序。 http://api.jquery.com/unbind/

检查此jsfiddle http://jsfiddle.net/Xm5MB/

$(function(){

    $("#testDiv").append("<a id='btn'>link</a>");
    $("a#btn").click(function(){
        alert("first bind");
    });
    $("a#btn").unbind("click");
    $("a#btn").on("click", function(){
        alert("second bind");
    });
});

答案 2 :(得分:2)

可能有用的一件事是将您要首先触发的click事件绑定到另一个click事件绑定到的元素的子节点。由于click事件会从DOM的最低级别升级到最高级别,因此它应该在绑定到父级之前触发绑定到子级的任何处理程序。

如果要阻止其他事件触发,您可以手动使用event.stopPropagation(),也可以从绑定到孩子的功能返回false,该功能同时调用event.stopPropagation()event.preventDefault()

答案 3 :(得分:0)

这是@plalx提供的解决方案:

var os = jQuery('#container') ; // the #container is written by me on the code. He's empty on load and is filled by the distant script wich add the a#btn on it.
if ( os.length > 0 ) // I just check if he is on my page, just in case.
{
    var timer = setInterval(function () 
    {
        var btn_os = jQuery('a#btn') ;
        if (btn_os.length) // Button is loaded on page : we can do the trick
        {
            clickListener = jQuery._data(btn_os[0], 'events').click[0]; // caching the first .click bind

            btn_os.off('click'); // Removing all binds

            // Adding my own bind
            btn_os.click(function () {
                console.log('test') ;
                ga('send', 'event', { eventCategory: 'xxxx', eventAction: 'yyyy', eventLabel : 'zzzz' });
                // You can either trigger here the previous handler or rebind it out of here, 6 lines bottom
                // In my case i prefer to trigger it myself, with a little delay to make sure that my ga('send') has time to register
                setTimeout(function(){clickListener.handler() ;}, 150);
            });

            // And rebinding the old one if needed
            // In my particular case i don't want to rebind it, i prefer triggering it manually on my .click function with a setTimeout delay
            // btn_os.click(clickListener.handler);
            clearInterval(timer) ; // Removing the interval timer
        }
    }
    , 100);
}