How to list events which were bind by jQuery for an element? I tried the methods from this question and none worked.
jsFiddle example
The code you linked to does work, it's just that because you used live() (which is a deprecated function from version 1.7 on), the handler is bound to the top level element, the document, and it uses event bubbling to figure out the original element and see if it matches your selector.
Because you tried to call the $.eventReport() for a specific selector, rather than document, nothing was returned.
If you change live to on, you will see that the alert does show something (jsFiddle). Alternatively, if you omit the selector to $.eventReport() altogether, you will also see that a click event is bound (jsFiddle).
Example for the former:
$(function() {
$('#firstname').on("click", function(e) {
alert('clicked');
});
alert($.eventReport('#firstname'));
});
Related
I'm new to jQuery and wrote the following code. Strangely, the jQuery code somehow works even after the time delay. alert() gets called onclick after the time delay. The same thing in javascirpt with .addEventListener() would give error since the element doesn't exist. Can someone explain me how and why jQuery does this?
<div id="outerId" class="outerHolder">
<div class="innerHolder"></div>
</div>
JS Code:
$("#outerId").on("click touchstart", "#newTag", function (e) {
alert("OK");
});
setTimeout(function() {
var tag = '<div id="newTag">Hello World</div>';
$("#outerId").append(tag);
}, 5000);
Here is a jsFiddle of the same: https://jsfiddle.net/jb6pmovb/
My guess is that your query is about the way on() is binding to to the object. When on() is first ran, #newTag does not exist, so you might be wondering why it still triggers when appended after a delay.
This is because #outerId is the object being bound to, which does exist the time on() is called. When you append #newTag, it doesn't alter the outer binding, it simply looks over the children when it is clicked.
With regular js I assume you are using addEventListener, which requires you bind the event to the specific object. If you do try and use that directly on #newTag before it exists, it obviously won't work.
You can see by the docs for on():
selector
Type: String
A selector string to filter the descendants of the selected elements that trigger the event. If the selector is null or omitted, the event is always triggered when it reaches the selected element.
If you are wondering how the click works on an element which is not there at the time of page load, then that's because you are attaching the listener on the outerDiv and using .on
Check out this for the difference between using .on and .click
In a jQuery plugin
I saw expression like this:
$( document ).on( 'click', this.selector, this.startImageLightbox);
I know what $("div").click(callback) mean, but the whole expression above, especially this.selector looks quite confusing to me.
What does the this here mean?
Does anyone have ideas about this?
It is a property of the jQuery object(Inside the plugin method this refers to the jQuery object), which is the selector used to find the element.
Ex:
$('div').selector -> div
$('div input').selector -> div input
$('div').find('input').selector -> div input
So the said code is used to register a delegated event handler targeting the element on which the plugin was initialized
.on("click", "selector", callback) vs. .click()
.click() attached a handler directly to the chosen selector. That means that any events that originate from that selector or one of its children will trigger the callback.
.on("click", "selector", callback) attaches the handler to the body. Because all elements are children here, everything will be a match. However, the second argument "selector" will filter out everything but that. This is especially useful if you are adding elements to your page after load has completed because you don't have to then attach handlers to the new element. The handler on the document will handle everything.
this.selector
This jQuery plugin stores the selector you provide as a property. this refers to the plugin, and this.selector refers to that property. The value that is being passed to the .on() function could be almost anything. For example ".classname" or "#elementId".
I've a simple code as following:
<html>
<body>
<div id="div1">
<input class="input1" type="text" value="click me 1" />
</div>
<script type="text/javascript">
$('.input1').click( function() { alert('clicked'); });
$('#div1').append('<input class="input1" type="text" value="click me 2" />');
</script>
</body>
</html>
I found that the 2nd textbox, which was appended to the "#div1", didn't get the click respond which is associated to the class "input1".
what am I missing? please advise me, thank you very much.
You should use event delegation with the .on() method...
$('#div1').on('click','.input1',function(...
This places the handler on #div1. When clicks happen inside of it, the '.input1' selector is run, and if the element clicked matches, the handler is invoked.
Or in older versions of jQuery (pre 1.7), use .delegate().
$('#div1').delegate('.input1','click',function(...
jQuery Live Function
: Attach an event handler for all elements which match the current selector, now and in the future.
When you are trying to bind the click event on .input1, it's not available yet, thus the bind will fail.
To fix it, you should use on:
$('#div1').on('click', '.input1', function(){alert('clicked')})
$('.something').click() appends the click listener/callback to anything that is currently in the dom.
When you have elements that were created after dom ready, you can use $('.something').live('click', function() { ... }); to do exactly the same thing for those newly created elements.
But if you're using the newest version of jQuery, use .on(...) because live was recently deprecated.
click and all of the other synonyms for bind only work for elements that exist when the function is called. If you want to also handle ones that may get created in the future, you either have to hook them up when you create them (usually a pain), or use event delegation. Event delegation works by hooking the event on a container of some kind that you're going to put the elements in, and then relies on how events bubble up the DOM from child to parent.
jQuery has excellent support for event delegation in its delegate and (more recently) on functions:
// `delegate` (jQuery 1.4.2 and later)
$("selector for container").delegate(".input1", "click", function() {
// I'll be called when there's a click on anything matching the
// selector ".input1" contained by the container
});
// `on` (jQuery 1.7.0 and later; note that the param order is different from `delegate`)
$("selector for container").on("click", ".input1", function() {
// I'll be called when there's a click on anything matching the
// selector ".input1" contained by the container
});
If the only common container the elements will have is the document itself, that's fine, you can use document as the container. (jQuery has the live function for that, but it's deprecated and it currently just calls on for you.) But in general, the more targeted you can be with the container, the better, from both a performance perspective and a code clarity perspective. For instance, use the form if you're adding form elements to a form; use the table if adding elements to a table. Etc.
Use the jQuery Live function as stated by Achmet.
This is needed because the second input field is created at run-time after the dom has been loaded.
With JQuery, is it possible to add an event listener to any element that currently, or will in the future, have a particular class?
I'm working on a project that makes heavy use of contentEditable, so the DOM is changing, and elements can have classes added and removed as a result of user input.
I would like to be able to say "elements of class X should do Y when clicked", but if I understand correctly, $(".X").click(Y) will only add the event listener to elements that currently have class X.
Furthermore, if an element is no-longer part of class X, then it will still have the click event listener.
How can I do this?
Yep. What you're talking about is called event delegation. Here's an example:
$('#container').on('click', '.innerElement', function(){
/// Do stuff
});
In your case, #container would be an element that is known to exist on page load which will contain the child elements you care about (either now or in the future). This approach takes advantage of event bubbling in the DOM.
As another poster mentioned, the live method will also work -- but it has been deprecated in jQuery 1.7, and is generally not as performant as using more selective delegation (such as the example above).
you'll want to use event delegation. jquery 1.7 has made this more abstract than previous versions, but it looks something like this:
$("#myWrappingElement").on("click", ".myclass", function(event){
alert($(this).text());
});
this basically adds a click event listener to the #myWrappingElement element, and jquery will automagically look to see what the original event target was and fire the proper function. this means you can add or remove .myclass elements and still have events fire on them.
the jQuery live() method swill allow to have a "live" action listener - so if new DOM elements match the selector, they will be attached to the action listener. For example:
$(".X").live("click", function(){
alert('some action');
});
See the documentation here for more info: http://api.jquery.com/live/
I'm not sure that the second part of your question about keeping the action listener attached after removing the class os possible - someone else might have a solution though.
I have an group of checkboxes with id's starting with somename and I want catch the click event of these checkboxes. Previously I have done this through jQuery. i.e.:
$("input[id^='somename']").click(function(){
// my code follows here
})
but this is not working this time around. Why?
P.S. The element is created via JavaScript after the page is fully loaded after making some ajax request. I don't know if this may be the problem?
just use live if elements are created after the page is loaded.
$("input[id^='somename']").live('click', function(){ // my code follows here })
P.S : Your search selector is "somename" but you search it on the attribute ID, are you sure that you don't want :
$("input[name^='somename']").live('click', function(){ // my code follows here })
instead?
This indeed could be the problem. Replace .click with .live()
$("input[id^='somename']").live('click', function(){ // my code follows here })
and you should be fine.
Since a call to .click is just a shortcut for .bind('click', fnc), this will not work if the element is not in the DOM when calling this. Even better than using .live() would be to use .delegate(). Have a read:
.live(), .delegate()
Using the standard binding functions only works on elements that exist at the time of the bind. You need to use something called event delegation, where elements further up the DOM tree are notified of events on descendant elements. The best way to do this is with .delegate():
$('#containingElement').delegate("input[id^='somename']", 'click', function(){
// your code here
});
This assumes that you have an element #containingElement that contains all the elements that you want to capture the events on.
NB that other answers recomment live. live and delegate use the same backend code, but for various reasons delegate is more efficient.
I believe that because you want this applied to dynamically created elements in the DOM you are going to have to use the the jQuery .live() method:
$("input[id^='somename']").live('click', function(e) {
// Your code
});
Instead of .click() try .change() event.