JQuery bind event after adding element dynamic - javascript

I have an issue after adding a element dynamically it doesn't have the click event, so i have the following:
$(".myclass > li").click(function () {
...
});
so basically when i click on LI element something should happen and it works.
But when i add a new LI element to myclass which is UL element, this newly added element doesn't call this function.
My question how do i rebind or bind this newly element to this function ..?
Because the other elements when i click on them they work, but only the new element doesn't ... i suppose it is that the binding happens on postback or somethnig but in my case there is no postback :/

You need to use Event Delegation. You have to use .on() using delegated-events approach.
i.e.
$(document).on('event','selector',callback_function)
In your case
$(document).on('click', '.myclass > li', function () {
...
});
OR if you want to apply to ALL list items:
$(".myclass").on('click', '> li', function () {
...
});

need to use event delegation to support dynamic elements
$(".myclass").on('click', '> li' function () {
...
});

Since the element is added after you bind the event, it doesn't have the handler attached and the bind function doesn't listen for any new elements that might be added.
Thus, you need to use event delegation. When an event triggers, it will bubble up all the way to the parent document. Using the jQuery .on() function you can listen for events that have bubbled up from their target.
In your case, you should use the following:
$(parent).on("click", "li", function() { ... });
The above will listen for click events that occur on li elements and bubble up to parent. Inside the event handler this will refer to the li element on which the event triggered. In case you don't know the parent, you can listen on document.
You can learn more about the .on() function here.

Related

Remove function for a specific element │$(this).off() does not work

I am binding a click event to .call elements like that
$('body div').on('click', '.call', function() {
$(this).off('click'); //after click i want to unbind the 'click' for this .call only
//however its not workinng.
*... some code here ....*
})
If i do $(body div).off('click', '.call'), all .call elements lost their functionality. I dont want that. How i can remove click function from just clicked .call
You can not unbind the click from the element since the event is not attached to that element. So you need to handle it by either removing the class that you are looking for in the event delegation or add logic of some sort to see if it is clicked.
If you can remove the class, that would be the easiest solution.
$('body div').on('click', '.call', function() {
$(this).removeClass("call");
/* rest of logic */
})
or you can add a class and check for it
$('body div').on('click', '.call', function() {
var elem = $(this);
if (elem.hasClass("called")) return;
elem.addClass("called");
/* rest of logic */
})
you could use data() instead of a class or you could add :not logic to the event delegation selector.
You might look into using $().one http://api.jquery.com/one/
This binds a callback to an element once, and unbinds it once it has been executed.

Single click on dynamically added element

Most people know how to bind "click' event to dynamically added element with
$('#main').on('click','.link',function(){ //some code here });
Where .link is a dynamically added element. But how the code above should look like when i want to fire function only on first click? Yes, i know about .one(), but the question is to merge .one() with .on().
jQuery docs for show .one() and .on() are the same as of 1.7:
.one( events [, selector ] [, data ], handler )
.on( events [, selector ] [, data ], handler )
If you just want it to fire on the first click, you can unbind the listener after the execution.
$('#main').on('click', '.link', function() {
$('#main').off('click', '.link');
// do whatever you need here
});
.one()
Description: Attach a handler to an event for the elements. The handler is executed at most once per element per event type.
$('#main').one('click','.link',function(){
//some code here
});
I dont think it is possible straight-away to create delegated on() which will be fired at most once( i.e one()) because of the way delegated handler is wired up.
on(): When a selector is provided, the event handler is referred to as delegated. The handler is not called when the event occurs directly on the bound element, but only for descendants (inner elements) that match the selector. jQuery bubbles the event from the event target up to the element where the handler is attached (i.e., innermost to outermost element) and runs the handler for any elements along that path matching the selector.
Thus the event will always be fired on descendent, even you detach the handler for the current element .link using .off() method inside the handler body.
However you can still achieve this by maintaining a list of DOM elements as a closure and match the list before doing actual code work.
var elements = [];//list of elements which is responded to events at once
$('#main').on('click', '.link', function() {
if(matched){//match $(this)/ uniqueIdentifier in 'elements' array
// prevent default and stopPropagation
return;
}
elements.push($(this));//or push something like 'id' to uniquely identify current element
//..codes
});

jQuery remove function not working

I have a Div with a link remove when I click on the remove this Div removed.
JS FIDDLE
<div class="bar">
<p style="float:left"> Hello world</p>
remove
</div>
Here the div with Class .bar will remove when I click on the link remove which is working fine.
But I also created a link below the div(.bar) which is :
+ Add New
On clicking +Add New will create a new .bar div.
$('.add').click(function() {
$(".holder").prepend('<div class="bar"><p style="float:left"> Hello world</p> remove </div>');
});
But the Problem is when this new .bar div is created clicking on the remove not working. This new .bar div not remove.
why is that ? is there any other way to do this ? Any help will be much appreciated.
You need to use Event Delegation. You have to use .on() using delegated-events approach.
i.e.
$(document).on('event','selector',callback_function)
Example
$('.holder').on('click', '.delete', function() {
$(this).parent('.bar').remove();
});
In place of document you should use closest static container.
DEMO
The delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time. By picking an element that is guaranteed to be present at the time the delegated event handler is attached, we can use delegated events to bind the click event to dynamically created elements and also to avoid the need to frequently attach and remove event handlers.
You should use event delegation:
$('.holder').on('click', '.delete', function() {
$(this).parent('.bar').remove();
});
Here .holder is the closest static parent element.
DEMO: http://jsfiddle.net/jnLfh/5/
You need event delegation for dynamically added elements which are not present in DOM at the time of execution of event binding code. You can delegate event to static parent of dynamic element, in the given example you can delegate it to .holder or document
Live Demo
$(".holder").on('click', '.delete', function() {
$(this).parent('.bar').remove();
});
Delegated events
Delegated events have the advantage that they can process events from
descendant elements that are added to the document at a later time. By
picking an element that is guaranteed to be present at the time the
delegated event handler is attached, you can use delegated events to
avoid the need to frequently attach and remove event handlers, jQuery Doc
Change to this:
$(document).on('click', '.delete', function(e) {
e.preventDefault(); // stops the jump
also a note, if you want to delegate the event then you should always try to delegate to the closest static parent (Which was available at the time of doc ready), so here in your case is <div class='holder'> then you can change to this:
$('.holder').on('click', '.delete', function(e) {
e.preventDefault(); // stops the jump
but here one more thing for note if you are delegating to the closest static parent then you have to put this click event in your "document ready block".
The selector will not recognize the new div added by the script. For this you need to add event delegation. Here's an example
using "on"
$('.delete').on('click', function(){
$(this).parent('.bar').remove();
});
using "live" (might be depreciated now. Please check)
$('.delete').live('click', function(){
$(this).parent('.bar').remove();
});

JQuery selector still working after I remove the class?

I have two jquery functions that work together, one depends on a class, another removes the class.
Once it is removed I would expect the functionality to stop working, but it carries on?
Whats going on?
Here is the fiddle, try it out for yourself.
<div class="container disabled">
Go to Google
</div>
<label>
<input type="checkbox" />Enable link</label>
The JS
$('.disabled > a').click(function (e) {
e.preventDefault();
e.stopPropagation();
alert('should stop working');
});
$('input[type=checkbox]').change(function () {
$('.container').removeClass('disabled');
});
It looks like you want to be using delegated event handlers rather than static event handlers. Let me explain.
When you run a line of code like this:
$('.disabled > a').click(function (e) {
this installs an event handler on any objects that match the selector at that moment in time. Those event handlers are then in place forever. They no longer look at what classes any elements have. So changing a class after you install a static event handler does not affect which elements have event handlers on them.
If you want dynanamic behavior where which elements respond to an event does depend upon what classes are present at any given moment, then you need to use delegated event handling.
With delegated event handling, you attach the event "permanently" to a parent and then the parent evaluates whether the child where the event originated matches the select each time the event fires. If the child no longer matches the select, then the event handler will not be triggered. If it does, then it will and you can add/remove a class to cause it to change behavior.
The general form of delegated event handlers are like this:
$("#staticParent").on("click", ".childSelector", fn);
You ideally want to select a parent that is as close to the child as possible, but is not dynamic itself. In your particular example, you don't show a parent other than the body object so you could use this:
$(document.body).on("click", ".disabled > a", function() {
e.preventDefault();
e.stopPropagation();
alert('should stop working');
});
This code will then respond dynamically when you add remove the disabled class. If the disabled class is present, the event handler will fire. If it is not present, the event handler will not fire.
Working demo: http://jsfiddle.net/jfriend00/pZeSA/
Other references on delegated event handling:
jQuery .live() vs .on() method for adding a click event after loading dynamic html
jQuery .on does not work but .live does
Should all jquery events be bound to $(document)?
JQuery Event Handlers - What's the "Best" method
jQuery selector doesn't update after dynamically adding new elements
Changing the class after the event handler is bound has absolutely no effect as the event handler is not suddenly unbound, it's still bound to the same element.
You have to check for the class inside the event handler
$('.container > a').click(function (e) {
if ( $(this).closest('.container').hasClass('disabled') ) {
e.preventDefault();
e.stopPropagation();
}
});
$('input[type=checkbox]').change(function () {
$('.container').toggleClass('disabled', !this.checked);
});
FIDDLE
When the selector runs, it gets a list of elements including the one in question and adds a click event handler to it.
Then you remove the class - so any subsequent jQuery selectors wouldn't get your element - but you have already attached the event so it will still fire.
The selector you have used runs on the line you declared it - it isn't lazily initialized when clicks happen.

jQuery.on() both self and children

The .on() method in jQuery will either match on the matched element if no selector is provided or only on it's children if ther is a selector.
Is it possible to combine these two behaviours to end up with a single .on() statement that matches both the element and any specified children?
Example: http://jsfiddle.net/mwvdlee/YFF2k/
You can simply bind the event handler to the parent and use event.target [docs] to the get actual target element of the event:
$('.foo').on('click', function(event) {
console.log('click', event.target);
});
Since events bubble up (that's how event delegation works in the first place), every click on a descendant of .foo will trigger the event handler of .foo (unless the event was stopped somehow of course).
By default the events are bubbling up. Just avoid passing a delegate selector and attach the event-handler on the parent. When children will get clicked, the event should bubble up to the parent and the event will get fired.
DEMO: http://jsfiddle.net/YFF2k/2/
$('.foo').on('click', function (e) {
console.log('click', e.target);
});
you can try something like:
$('.foo').children().andSelf().on('click', function (event){
//something
});

Categories