I have the following code:
$(document).ready(function () {
$("tr").live('click',function(){
alert("TR");
});
$("input").live('click',function(){
alert("INPUT");
});
});
Fiddle here
How can I just trigger the click function for the checkbox without triggering the tr function? Is there any solution with jQuery?
I will not set return false at the end of the input function and I really need the tr element too.
Info: event.stopPropagation doesn't work on live() events.
You can use the stopPropagation() method on the event object.
It will prevent the event from bubbling up without cancelling the default event behavior.
$(document).ready(function () {
$("tr").click(function(){
alert("TR");
});
$("input").click(function(e){
alert("INPUT");
e.stopPropagation();
});
});
As it seems you are using .live() and not direct event binding, you can't use stopPropagation().
First of all, .live() is legagcy code and has been deprecated, which means it could be removed from the library in any future new version. I don't know which version of jQuery you are using but you should consider moving to the latest (which is more optimized anyway) and use .on() for event delegation.
Nevertheless, if you can't upgrade your jquery library, here's maybe a solution to your problem. The event parameter passed to all event handler contains a property target which reference the element from which the event was initiated. So you could do something like:
$("tr").live('click',function(e){
if (e.target.nodeName !== "INPUT") {
// if ($(e.target).is('input') === false) { // jquery style but maybe less efficient
alert("TR");
}
});
Not very elegant but does the trick. Here's an example.
The problem with .live() is that events are binded to the document so as more complex as your application would become, you may end up with headaches to stop propagation.
In the meantime I've made a fiddle using .on() (here) and one using .delegate() (here).
You need to add stopPropagation() to your input click handler. It will stop the event bubbling up the DOM to parent elements.
$(document).ready(function () {
$("tr").click(function(){
alert("TR");
});
$("input").click(function(e){
alert("INPUT");
e.stopPropagation();
});
});
Example fiddle
OP Updated Question:
$(document).ready(function () {
$("TABLE").delegate("tr", 'click',function() {
alert("TR");
});
$("TABLE").delegate("input", 'click',function(e) {
e.stopPropagation();
alert("INPUT");
});
});
Use stopPropagation() for input handler
http://jsfiddle.net/KJg6Q/
http://jsfiddle.net/LwvYD/2/
e.stopPropagation() in handle on input or use e.relatedTarget
$("tr").click(function(e){
if( e.relatedTarget.tagName != "input" )
alert("TR");
});
Related
This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 5 years ago.
<html>
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$("button").click(function() {
$("h2").html("<p class='test'>click me</p>")
});
$(".test").click(function(){
alert();
});
});
</script>
</head>
<body>
<h2></h2>
<button>generate new element</button>
</body>
</html>
I was trying to generate a new tag with class name test in the <h2> by clicking the button. I also defined a click event associated with test. But the event doesn't work.
Can anyone help?
The click() binding you're using is called a "direct" binding which will only attach the handler to elements that already exist. It won't get bound to elements created in the future. To do that, you'll have to create a "delegated" binding by using on().
Delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time.
Source
Here's what you're looking for:
var counter = 0;
$("button").click(function() {
$("h2").append("<p class='test'>click me " + (++counter) + "</p>")
});
// With on():
$("h2").on("click", "p.test", function(){
alert($(this).text());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<h2></h2>
<button>generate new element</button>
The above works for those using jQuery version 1.7+. If you're using an older version, refer to the previous answer below.
Previous Answer:
Try using live():
$("button").click(function(){
$("h2").html("<p class='test'>click me</p>")
});
$(".test").live('click', function(){
alert('you clicked me!');
});
Worked for me. Tried it with jsFiddle.
Or there's a new-fangled way of doing it with delegate():
$("h2").delegate("p", "click", function(){
alert('you clicked me again!');
});
An updated jsFiddle.
Use the .on() method with delegated events
$('#staticParent').on('click', '.dynamicElement', function() {
// Do something on an existent or future .dynamicElement
});
The .on() method allows you to delegate any desired event handler to:
current elements or future elements added to the DOM at a later time.
P.S: Don't use .live()! From jQuery 1.7+ the .live() method is deprecated.
Reason:
In jQuery, Click() event Direct binding which attaches the event handler to the element only if the particular element(Html code) exists on the page(after page loads).
Dynamic elements are created with the help of javascript or jquery(not in Html).
It won't consider the future elements(Dynamic) which are created after the page gets loaded.
So the normal click event won't fire on the dynamic element.
Solution :
To overcome this, we should use on() function. on() can delegate the event for both the current and future elements.
Delegated events have the advantage that can attach the handler to the elements which are being added to the document in the future.
Note : delegate(),live() and on() functions have the advantages over the DOM elements. As of JQuery 1.7 delegate() and live() are deprecated(Don't use these).
on() only Can delegate the event for both current and future elements.
So, Your code should be like this
Remove the code from $(document).ready:
$(".test").click(function(){
alert();
});
Change into:
$(document).on('click','.test',function(){
alert('Clicked');
});
Add this function in your js file.
It will work on every browser
$(function() {
$(document).on("click", '#mydiv', function() {
alert("You have just clicked on ");
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='mydiv'>Div</div>
Change
$(".test").click(function(){
To
$(".test").live('click', function(){
LIVE DEMO
jQuery .live()
You need to use .live for this to work:
$(".test").live("click", function(){
alert();
});
or if you're using jquery 1.7+ use .on:
$(".test").on("click", "p", function(){
alert();
});
Try .live() or .delegate()
http://api.jquery.com/live/
http://api.jquery.com/delegate/
Your .test element was added after the .click() method, so it didn't have the event attached to it. Live and Delegate give that event trigger to parent elements which check their children, so anything added afterwards still works. I think Live will check the entire document body, while Delegate can be given to an element, so Delegate is more efficient.
More info:
http://www.alfajango.com/blog/the-difference-between-jquerys-bind-live-and-delegate/
I found two solutions at the jQuery's documentation:
First: Use delegate on Body or Document
E.g:
$("body").delegate('.test', 'click', function(){
...
alert('test');
});
Why?
Answer: Attach a handler to one or more events for all elements that match the selector, now or in the future, based on a specific set of root elements.
link: http://api.jquery.com/delegate/
Second: Put the your function at the "$( document )", using "on" and attach it to the element that you want to trigger this.
The first parameter is the "event handler", the second: the element and the third: the function.
E.g:
$( document ).on( 'click', '.test', function () {
...
alert('test');
});
Why?
Answer: Event handlers are bound only to the currently selected elements; they must exist on the page at the time your code makes the call to .on(). To ensure the elements are present and can be selected, perform event binding inside a document ready handler for elements that are in the HTML markup on the page. If new HTML is being injected into the page, select the elements and attach event handlers after the new HTML is placed into the page. Or, use delegated events to attach an event handler, as described next ...
link: https://api.jquery.com/on/
Best way to apply event on dynamically generated content by using delegation.
$(document).on("eventname","selector",function(){
// code goes here
});
so your code is like this now
$(document).on("click",".test",function(){
// code goes here
});
$(.surrounding_div_class).on( 'click', '.test', function () {
alert( 'WORKS!' );
});
Will only work if the DIV with the class .surrounding_div_class is the immediate parent to the object .test
If there is another object in the div that will be filled it wont work.
The problem you have is that you're attempting to bind the "test" class to the event before there is anything with a "test" class in the DOM. Although it may seem like this is all dynamic, what is really happening is JQuery makes a pass over the DOM and wires up the click event when the ready() function fired, which happens before you created the "Click Me" in your button event.
By adding the "test" Click event to the "button" click handler it will wire it up after the correct element exists in the DOM.
<script type="text/javascript">
$(document).ready(function(){
$("button").click(function(){
$("h2").html("<p class='test'>click me</p>")
$(".test").click(function(){
alert()
});
});
});
</script>
Using live() (as others have pointed out) is another way to do this but I felt it was also a good idea to point out the minor error in your JS code. What you wrote wasn't wrong, it just needed to be correctly scoped. Grasping how the DOM and JS works is one of the tricky things for many traditional developers to wrap their head around.
live() is a cleaner way to handle this and in most cases is the correct way to go. It essentially is watching the DOM and re-wiring things whenever the elements within it change.
An alternate and more succinct alternative (IMHO) is to use a raw javascript function that responds to an on click event, then pass the target element back to jQuery if you like. The advantage of this approach is that you can dynamically add your element anywhere, and the click handler will 'just work', and you need not concern yourself with delegating control to parent elements, and so on.
Step 1: Update the dynamic html to fire an onclick event. Be sure to pass the 'event' object as an argument
$("button").click(function() {
$("h2").html("<p class='test' onclick='test(event)'> click me </p>")
});
Step 2: Create the test function to respond to the click event
function test(e){
alert();
});
Optional Step 3: Given you are using jQuery I'm assuming it will be useful to get a reference back to the source button
function test(e){
alert();
// Get a reference to the button
// An explanation of this line is available here
var target = (e.target)? e.target : e.srcElement;
// Pass the button reference to jQuery to do jQuery magic
var $btn = $(target);
});
.live function works great.
It is for Dynamically added elements to the stage.
$('#selectAllAssetTypes').live('click', function(event){
alert("BUTTON CLICKED");
$('.assetTypeCheckBox').attr('checked', true);
});
Cheers,
Ankit.
The Jquery .on works ok but I had some problems with the rendering implementing some of the solutions above. My problem using the .on is that somehow it was rendering the events differently than the .hover method.
Just fyi for anyone else that may also have the problem. I solved my problem by re-registering the hover event for the dynamically added item:
re-register the hover event because hover doesn't work for dynamically created items.
so every time i create the new/dynamic item i add the hover code again. works perfectly
$('#someID div:last').hover(
function() {
//...
},
function() {
//...
}
);
I'm working with tables adding new elements dynamically to them, and when using on(), the only way of making it works for me is using a non-dynamic parent as:
<table id="myTable">
<tr>
<td></td> // Dynamically created
<td></td> // Dynamically created
<td></td> // Dynamically created
</tr>
</table>
<input id="myButton" type="button" value="Push me!">
<script>
$('#myButton').click(function() {
$('#myTable tr').append('<td></td>');
});
$('#myTable').on('click', 'td', function() {
// Your amazing code here!
});
</script>
This is really useful because, to remove events bound with on(), you can use off(), and to use events once, you can use one().
I couldn't get live or delegate to work on a div in a lightbox (tinybox).
I used setTimeout successfullly, in the following simple way:
$('#displayContact').click(function() {
TINY.box.show({html:'<form><textarea id="contactText"></textarea><div id="contactSubmit">Submit</div></form>', close:true});
setTimeout(setContactClick, 1000);
})
function setContactClick() {
$('#contactSubmit').click(function() {
alert($('#contactText').val());
})
}
Also you can use onclick="do_something(this)"inside element
If you have a dinamically added link to some container or the body:
var newLink= $("<a></a>", {
"id": "approve-ctrl",
"href": "#approve",
"class": "status-ctrl",
"data-attributes": "DATA"
}).html("Its ok").appendTo(document.body);
you can take its raw javascript element and add an event listener to it, like the click:
newLink.get(0).addEventListener("click", doActionFunction);
No matter how many times you add this new link instance you can use it as if you where using a jquery click function.
function doActionFunction(e) {
e.preventDefault();
e.stopPropagation();
alert($(this).html());
}
So you will receive a message saying
Its ok
It has better performance than other alternatives.
Extra: You could gain better performance avoiding jquery and using plain javascript. If you are using IE up to version 8 you should use this polyfill to use the method addEventListener
if (typeof Element.prototype.addEventListener === 'undefined') {
Element.prototype.addEventListener = function (e, callback) {
e = 'on' + e;
return this.attachEvent(e, callback);
};
}
You CAN add on click to dynamically created elements. Example below. Using a When to make sure its done. In my example, i'm grabbing a div with the class expand, adding a "click to see more" span, then using that span to hide/show the original div.
$.when($(".expand").before("<span class='clickActivate'>Click to see more</span>")).then(function(){
$(".clickActivate").click(function(){
$(this).next().toggle();
})
});
Use 'on' as click gets bind to the elements already present.
For e.g
$('test').on('click',function(){
alert('Test');
})
This will help.
This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 8 years ago.
Suppose I have some jQuery code that attaches an event handler to all elements with class .myclass.
For example:
$(function(){
$(".myclass").click( function() {
// do something
});
});
And my HTML might be as follows:
<a class="myclass" href="#">test1</a>
<a class="myclass" href="#">test2</a>
<a class="myclass" href="#">test3</a>
That works with no problem.
However, consider if the .myclass elements were written to the page at some future time.
For example:
<a id="anchor1" href="#">create link dynamically</a>
<script type="text/javascript">
$(function(){
$("#anchor1").click( function() {
$("#anchor1").append('<a class="myclass" href="#">test4</a>');
});
});
</script>
In this case, the test4 link is created when a user clicks on a#anchor1.
The test4 link does not have the click() handler associated with it, even though it has class="myclass".
Basically, I would like to write the click() handler once and have it apply to both content present at page load, and content brought in later via AJAX / DHTML. Any idea how I can fix this?
I am adding a new answer to reflect changes in later jQuery releases. The .live() method is deprecated as of jQuery 1.7.
From http://api.jquery.com/live/
As of jQuery 1.7, the .live() method is deprecated. Use .on() to attach event handlers. Users of older versions of jQuery should use .delegate() in preference to .live().
For jQuery 1.7+ you can attach an event handler to a parent element using .on(), and pass the a selector combined with 'myclass' as an argument.
See http://api.jquery.com/on/
So instead of...
$(".myclass").click( function() {
// do something
});
You can write...
$('body').on('click', 'a.myclass', function() {
// do something
});
This will work for all a tags with 'myclass' in the body, whether already present or dynamically added later.
The body tag is used here as the example had no closer static surrounding tag, but any parent tag that exists when the .on method call occurs will work. For instance a ul tag for a list which will have dynamic elements added would look like this:
$('ul').on('click', 'li', function() {
alert( $(this).text() );
});
As long as the ul tag exists this will work (no li elements need exist yet).
Sometimes doing this (the top-voted answer) is not always enough:
$('body').on('click', 'a.myclass', function() {
// do something
});
This can be an issue because of the order event handlers are fired. If you find yourself doing this, but it is causing issues because of the order in which it is handled.. You can always wrap that into a function, that when called "refreshes" the listener.
For example:
function RefreshSomeEventListener() {
// Remove handler from existing elements
$("#wrapper .specific-selector").off();
// Re-add event handler for all matching elements
$("#wrapper .specific-selector").on("click", function() {
// Handle event.
}
}
Because it is a function, whenever I set up my listener this way, I typically call it on document ready:
$(document).ready(function() {
// Other ready commands / code
// Call our function to setup initial listening
RefreshSomeEventListener();
});
Then, whenever you add some dynamically added element, call that method again:
function SomeMethodThatAddsElement() {
// Some code / AJAX / whatever.. Adding element dynamically
// Refresh our listener, so the new element is taken into account
RefreshSomeEventListener();
}
Hopefully this helps!
Regards,
After jQuery 1.7 the preferred methods are .on() and .off()
Sean's answer shows an example.
Now Deprecated:
Use the jQuery functions .live() and .die(). Available in
jQuery 1.3.x
From the docs:
To display each paragraph's text in an
alert box whenever it is clicked:
$("p").live("click", function(){
alert( $(this).text() );
});
Also, the livequery plugin does this and has support for more events.
If you're adding a pile of anchors to the DOM, look into event delegation instead.
Here's a simple example:
$('#somecontainer').click(function(e) {
var $target = $(e.target);
if ($target.hasClass("myclass")) {
// do something
}
});
You can bind a single click event to a page for all elements, no matter if they are already on that page or if they will arrive at some future time, like that:
$(document).bind('click', function (e) {
var target = $(e.target);
if (target.is('.myclass')) {
e.preventDefault(); // if you want to cancel the event flow
// do something
} else if (target.is('.myotherclass')) {
e.preventDefault();
// do something else
}
});
Been using it for a while. Works like a charm.
In jQuery 1.7 and later, it is recommended to use .on() in place of bind or any other event delegation method, but .bind() still works.
Binds a handler to an event (like click) for all current - and future - matched element. Can also bind custom events.
link text
$(function(){
$(".myclass").live("click", function() {
// do something
});
});
If your on jQuery 1.3+ then use .live()
Binds a handler to an event (like
click) for all current - and future -
matched element. Can also bind custom
events.
You want to use the live() function. See the docs.
For example:
$("#anchor1").live("click", function() {
$("#anchor1").append('<a class="myclass" href="#">test4</a>');
});
I have been experimenting with capturing click events outside of elements using stopPropagation().
$(".container").children().on('click',function(e){
e.stopPropagation();
});
$(".container").on("click",function(){
alert("outside the box?");
})
Here is a jsFiddle set up to demonstrate it functioning. An alert should fire when you click anywhere outside of the white box.
Now, I am trying to have the same principle applied to dynamically created elements. As far as I understand, the on() method of event assignment in jQuery should allow this to function without changing the script.
Here is a second jsFiddle where you must first click a link to create the elements. Once you have done this, the theory is that the same script will work, but it does not. What am I missing about this method?
When the item is added dynamically, you should attach the handler to the closest parent that will surely be there - in your case this is body. You can use on() this way to achieve a functionality that delegate() used to offer:
$(selector-for-parent).on(events, selector-for-dynamic-children, handler);
So your code rewritten would simply be this:
$("body").on('click', '.container', function(e){
var $target = $(e.target);
if ($target.hasClass('container')) {
alert("outside the box!");
}
});
I used e.target to find which element actually triggered the event. In this case, I identify the item by checking whether it has the container class.
jsFiddle Demo
In short word you need to put on() on existing parent element to make it works:
$('body').on('click', 'a', function(e){
e.preventDefault();
$('<div class="container"><div class="box"></div></div>').appendTo('body');
$(this).remove();
});
$('body').on('click', '.container > *', function(e){
e.stopPropagation();
});
$('body').on('click', '.container', function(){
alert("outside the box?");
})
Code: http://jsfiddle.net/GsLtN/5/
For more detail check '.on()' on official site at section 'Direct and delegated events'
The demo.
When you bind a event handler to a element use .on, the target you bind to must exist in the domcument.
$('body').on('click', '.container > *', function(e){
e.stopPropagation();
});
$('body').on("click",'.container',function(){
alert("outside the box?");
})
You need to bind the .on() to a parent.
What you're trying to do is - bind the handler to a parent that listens for an event, then checks whether the event was triggered by an element that matches that selector.
$("body").on("click", '.container',function(){
alert("outside the box?");
})
Updated fiddle here
According to the documentation for jQuery.on():
Event handlers are bound only to the currently selected elements; they
must exist on the page at the time your code makes the call to .on().
You will have to bind the event to a parent container. Perhaps something like THIS.
How can I get this code to only execute its button:
<span id="spanClicker">
<span id="subClicker">
[Click Me]
</span>
</span>
like this fiddle: http://jsfiddle.net/rpCVy/
http://jsfiddle.net/malet/rpCVy/3/
You can use e.stopPropagation() to prevent the click event firing for both elements.
Also on a side note the .live function is deprecated as of jQuery 1.7 .on should be used instead.
Here is what you're looking for:
$( '#subClicker' ).on( 'click', function (e) {
alert( 'subClicker' )
// Now here is the magic you want:
e.stopPropagation( )
} )
As you can guess, e.stopPropagation() allows you to prevent the event from propagating to its parent elements.
This ought to do it.
http://jsfiddle.net/rpCVy/2/
New javascript
$(function()
{
$("#spanClicker").live("click",function()
{
alert('Span Clicked');
});
$("#subClicker").live("click",function(e)
{
alert('Button Clicked');
e.stopPropagation();
});
});
The anonymous function associated with .click can take an event for the first argument. Call the stopPropagation() method of the event object to stop the click event from bubbling up to containers of the target element of the event.
I really liked the .live method as it was straightforward and essentially not much different than your standard event handler.
Alas, it was deprecated and I'm left with the .on method.
Basically, I'm loading and dynamically loading content that I'll need the same event handler triggered on. Rather than add the event handler twice or however many times. .live was great for this, but .on has replaced it and I just can't seem to get it to work.
check this code:
jQuery('#who_me').live('click', function(){
alert('test123');
return false;
});
should be the same as:
jQuery('#who_me').on('click', function(){
alert('test123');
return false;
});
but when I replace content with the .html method after an ajax call only the live method works.
Can anyone clear this up for me?
You aren't using .on() correctly. This is a better implementation if the #who_me object comes and goes.
jQuery(document.body).on('click', '#who_me', function(){
alert('test123');
return false;
});
The selector you use in the jQuery object for .on() must be an object that is present at the time you install the event handler and never gets removed or recreated and is either the object you want the event installed on or a parent of that object. The selector passed as the 2nd argument to .on() is an optional selector that matches the object you want the event on. If you want .live() type behavior, then you must pass a static parent object in the jQuery object and a selector that matches the actual object you want the event on in the 2nd argument.
Ideally, you put a parent object in the jQuery object that is relatively close to the dynamic object. I've shown document.body just because I know that would work and don't know the rest of your HTML, but you'd rather put it closer to your actual object. If you put too many dynamic event handlers on the document object or on document.body, then event handling can really slow down, particularly if you have complicated selectors or handlers for frequent events like click or mousemove.
For reference, the 100% equivalent to your .live() code is this:
jQuery(document).on('click', '#who_me', function(){
alert('test123');
return false;
});
.live() just installs all its event handlers on the document object, and uses event bubbling to see all the events that happen on other objects in the page. jQuery has deprecated .live() because it's better to NOT install all your live event handlers on the document object (for performance reasons). So, pick a static parent object that is closer to your object.
The context when using .live was document, therefore the selector for .on should be document
$(document).on("click","#who_me",function(){...});
The way you're using on, it's basically a replacement for bind, rather than live. With on, as with live and delegate, you can use event delegation, but you must supply a specific containing element (as was always the case with delegate).
At the simplest level, this can be document. In this case, the handler will function exactly as live would have:
jQuery(document).on('click', '#who_me', function() {
alert('test123');
return false;
});
It would be better, however, to find the closest element to contain the elements that will exist. This gives performance gains.
jQuery('#some_el').on('click', '#who_me', function() {
alert('test123');
return false;
});
jQuery(document).on('click', '#who_me', function(){
alert('test123');
return false;
});
should be the equivalent of jQuery.live('#who_me', function() { // code here });
Nope.
$( '#who_me' ).live( 'click', function () { ... });
is the same as:
$( document ).on( 'click', '#who_me', function () { ... });
However, you usually don't want to bind to much handlers to the document object. Instead you bind to the nearest static ancestor (of #who_me, in this case). So:
$( '#wrapper' ).on( 'click', '#who_me', function () { ... });
where #wrapper is an ancestor of #who_me.
To replace .live() you need one more parameter int he .on() call.
// do not use! - .live(events, handler)
$('#container a').live('click', function(event) {
event.preventDefault();
console.log('item anchor clicked');
});
// new way (jQuery 1.7+) - .on(events, selector, handler)
$('#container').on('click', 'a', function(event) {
event.preventDefault();
console.log('item anchor clicked');
});
Source: http://www.andismith.com/blog/2011/11/on-and-off/