I have an external script, wich i can't modify. This script load a button, and add a jQuery .click on it... and it finish with "return false".
我有一个外部脚本,我无法修改。这个脚本加载一个按钮,并在其上添加一个jQuery .click ...它以“return false”结束。
I need to trigger my own code on this click. When i load the page the doesn't exists, so i need to use .on('click') to bind "live". But it looks like the .on('click') is loaded "after" the .click and as he use "return false", my .on('click') is not loaded.
我需要在这次点击时触发我自己的代码。当我加载页面时,不存在,所以我需要使用.on('click')来绑定“live”。但看起来.on('click')在“.click之后”加载,并且当他使用“return false”时,我的.on('click')没有被加载。
So the question is... How can i trigger my on click on this dynamically loaded a#btn wich already has a .click function returning false ?
所以问题是......如何触发我点击这个动态加载的#btn已经有一个.click函数返回false?
Here is the fiddle : http://jsfiddle.net/PLpqU/
这是小提琴:http://jsfiddle.net/PLpqU/
And here a code example :
这里有一个代码示例:
<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 ;
}) ;
As you can the, the objective is to trigger a Google Analytics event on a link button loaded by a distant script.
尽可能地,目标是在由远程脚本加载的链接按钮上触发Google Analytics事件。
4 个解决方案
#1
3
It seems that you are facing multiple issues, but the more important one would be knowing when the element is rendered in the DOM so that you can manipulate it's events collection.
您似乎面临着多个问题,但更重要的是知道何时在DOM中呈现元素,以便您可以操纵它的事件集合。
Once the element is accessible, it's quite simple to unbind the plugin's handlers, bind yours and rebind the plugin's one knowing that the jQuery's event collection can be accessed like: $._data(domEl, 'events');
一旦元素可访问,取消绑定插件的处理程序,绑定你的并重新绑定插件就知道jQuery的事件集合可以被访问,如:$ ._ data(domEl,'events');
Here's an example:
这是一个例子:
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');
If you do not want to unbind, I believe that you can also use the DOM level 0 event model and do:
如果您不想解除绑定,我相信您也可以使用DOM 0级事件模型并执行:
element.onclick = yourHandler;
Know, to know when the element is available is much more of an issue if the plugin renders this element asynchronously and doesn't provide a way to know when the process is complete.
知道,如果插件以异步方式呈现此元素并且不提供了解过程何时完成的方法,那么知道元素何时可用是更多问题。
If you want to support old browsers, you will have no other choice than either override the plugin's code (assuming the concerned methods are public) or poll the DOM with setInterval
until the element you were looking for is part of the DOM and then you can do what we discussed above.
如果你想支持旧的浏览器,除了覆盖插件的代码(假设有关的方法是公共的)或者用setInterval轮询DOM,直到你要查找的元素是DOM的一部分然后你可以做我们上面讨论过的事情。
If you are targetting modern browsers, you can use the MutationObserver
object to listen to DOM changes.
如果您要定位现代浏览器,则可以使用MutationObserver对象来侦听DOM更改。
#2
3
You can unbind an event and then add your function as the event handler. http://api.jquery.com/unbind/
您可以解除绑定事件,然后将您的函数添加为事件处理程序。 http://api.jquery.com/unbind/
Check this jsfiddle http://jsfiddle.net/Xm5MB/
检查这个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");
});
});
#3
2
One thing that might work is to bind the click event that you want to fire first to a child of the element that the other click event is bound to. Since the click event will bubble up from the lowest level of the DOM to the highest, it should fire any handlers bound to children before the ones bound to their parents.
可能有用的一件事是将您要首先触发的click事件绑定到另一个click事件绑定到的元素的子节点。由于click事件将从DOM的最低级别冒泡到*别,因此它应该在绑定到其父级之前绑定到子级的任何处理程序。
If you want to stop the other event from firing, you can either manually use event.stopPropagation()
or else return false
from the function you have bound to the child, which calls both event.stopPropagation()
and event.preventDefault()
.
如果要阻止其他事件触发,可以手动使用event.stopPropagation(),或者从绑定到子节点的函数返回false,该函数调用event.stopPropagation()和event.preventDefault()。
#4
0
Here is a solution provided by @plalx :
这是@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);
}
#1
3
It seems that you are facing multiple issues, but the more important one would be knowing when the element is rendered in the DOM so that you can manipulate it's events collection.
您似乎面临着多个问题,但更重要的是知道何时在DOM中呈现元素,以便您可以操纵它的事件集合。
Once the element is accessible, it's quite simple to unbind the plugin's handlers, bind yours and rebind the plugin's one knowing that the jQuery's event collection can be accessed like: $._data(domEl, 'events');
一旦元素可访问,取消绑定插件的处理程序,绑定你的并重新绑定插件就知道jQuery的事件集合可以被访问,如:$ ._ data(domEl,'events');
Here's an example:
这是一个例子:
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');
If you do not want to unbind, I believe that you can also use the DOM level 0 event model and do:
如果您不想解除绑定,我相信您也可以使用DOM 0级事件模型并执行:
element.onclick = yourHandler;
Know, to know when the element is available is much more of an issue if the plugin renders this element asynchronously and doesn't provide a way to know when the process is complete.
知道,如果插件以异步方式呈现此元素并且不提供了解过程何时完成的方法,那么知道元素何时可用是更多问题。
If you want to support old browsers, you will have no other choice than either override the plugin's code (assuming the concerned methods are public) or poll the DOM with setInterval
until the element you were looking for is part of the DOM and then you can do what we discussed above.
如果你想支持旧的浏览器,除了覆盖插件的代码(假设有关的方法是公共的)或者用setInterval轮询DOM,直到你要查找的元素是DOM的一部分然后你可以做我们上面讨论过的事情。
If you are targetting modern browsers, you can use the MutationObserver
object to listen to DOM changes.
如果您要定位现代浏览器,则可以使用MutationObserver对象来侦听DOM更改。
#2
3
You can unbind an event and then add your function as the event handler. http://api.jquery.com/unbind/
您可以解除绑定事件,然后将您的函数添加为事件处理程序。 http://api.jquery.com/unbind/
Check this jsfiddle http://jsfiddle.net/Xm5MB/
检查这个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");
});
});
#3
2
One thing that might work is to bind the click event that you want to fire first to a child of the element that the other click event is bound to. Since the click event will bubble up from the lowest level of the DOM to the highest, it should fire any handlers bound to children before the ones bound to their parents.
可能有用的一件事是将您要首先触发的click事件绑定到另一个click事件绑定到的元素的子节点。由于click事件将从DOM的最低级别冒泡到*别,因此它应该在绑定到其父级之前绑定到子级的任何处理程序。
If you want to stop the other event from firing, you can either manually use event.stopPropagation()
or else return false
from the function you have bound to the child, which calls both event.stopPropagation()
and event.preventDefault()
.
如果要阻止其他事件触发,可以手动使用event.stopPropagation(),或者从绑定到子节点的函数返回false,该函数调用event.stopPropagation()和event.preventDefault()。
#4
0
Here is a solution provided by @plalx :
这是@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);
}