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();
});
Related
I have the following code just to display some results and change the background of the <div> to yellow on hover. It works fine on all records (or loops) excluding the last one. Any hint?
function tryit(){
$(document).ready(function(){
var url="api2.php";
$.getJSON(url,function(json){
$.each(json,function(i,dat){
$(document).ready(function(){
$(".products").hover(function(){
$(this).css("background-color", "yellow");
}, function(){
$(this).css("background-color", "white");
});
});
$("#data").append(
'<div class="products">'+
'<h1>Product: '+dat.product+'</h1>'+
'<p>Seller : <em>'+dat.name+'</em>'+
'<p>Email : <em>'+dat.email+'</em></p>'+
''+
'<p>Phone: : <em>'+dat.phone+'</em></p>'+
'<p>Category : <em>'+dat.category+'</em></p>'+
'<p>Cost : <em>'+dat.cost+'</em></p>'+
'<p>Description : <em>'+dat.description+'</em></p>'+
'<p>Date : <em>'+dat.date+'</em>'+
'<hr>'+
'</div>'
);
});
});
});
}
The code does not work because when you attempt to bind the hover event to elements with the products class, these elements do not exist in the DOM yet as you call append after that.
As another answer has suggested you can bind the hover event after calling append.
An alternative is to use the on event handler function. Here is the documentation for that from jQuery: http://api.jquery.com/on/. With the on function you can use delegated events which will allow you to attach events on dynamically added elements.
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. This element could be the container element of a view in a Model-View-Controller design, for example, or document if the event handler wants to monitor all bubbling events in the document. The document element is available in the head of the document before loading any other HTML, so it is safe to attach events there without waiting for the document to be ready.
Some example code:
$(document).on('hover', '.products', function() {
// do your thing
});
When using the on method, you can move it out of the loop as you do not need to keep attaching the hover event multiple times.
A Stack Overflow thread discussing the differences between on and click methods is also a useful read: Difference between .on('click') vs .click()
You should set the ".hover()" be after the ".append()" method
$("#data").append('...');
$(".products").hover(function(){
$(this).css("background-color", "yellow");
}, function(){
$(this).css("background-color", "white");
});
You're adding .products handler before adding the element. Element added in previous loop will use the handler. Last one added does not.
change
$(".products").hover(function(){
to
$(document).on("hover", ".products", function(){
Also you can take the handler code out of the loop.
I want to use click() as eventhandler and that event handler is not working you can see code below
$('.ajax-close').click(function( event ){
event.preventDefault();
alert('hi');
$( '.ajax-live-on' ).removeClass('ajax-live-on');
});
I have used all the code to initialize the jquery no problem , all right. But this piece of code not working
Here is the jsBin link
http://jsbin.com/doxeravizo/1/edit?html,css,js,output
The $('.ajax-close') collection doesn't contain the elements taking that class after the binding.
Change
$('.ajax-close').click(function( event ){
to
$(document.body).on('click', '.ajax-close', function( event ){
You should also move that binding outside of the loop, there's no reason to do it at every iteration.
Note also that in order to have your span clickable, it must have some content.
Demonstration (I added the jQuery library to make the fiddle work)
I'm guessing that because you're using ajax, your .ajax-close is not created when the event listener is being created.
You're going to want to delegate your click function:
$(document).on('click', '.ajax-close', function(event) {
event.preventDefault();
alert('hi');
$('.ajax-live-on').removeClass('ajax-live-on');
});
This article will help, but just for reference, this bit in particular:
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. This element could be the container element of a view in a Model-View-Controller design, for example, or document if the event handler wants to monitor all bubbling events in the document. The document element is available in the head of the document before loading any other HTML, so it is safe to attach events there without waiting for the document to be ready.
One option is to listen on the click event using a delegate, like so:
$(document).on('click', '.ajax-close', function( event ){
//your code
});
Another option might be to move your click listener inside the original click listener, which creates the "Close" button, while the reason the issue arises is that the click event on "ajax-close" is bound too soon (before the <span> is appended to the DOM even):
ajaxcontent.click(function(event) {
event.preventDefault();
$( '.ajax-live' ).addClass('ajax-live-on');
$( this ).after('<span class="ajax-close animated bounceInRight">Close</span>');
$('.ajaxshow').append().load(ajaxUrl);
$('.ajaxshow').addClass('animated bounceInUp');
// Move this section here, which was previously located below
$('.ajax-close').click(function( event ){
event.preventDefault();
alert('hi');
$( '.ajax-live' ).removeClass('ajax-live-on');
});
});
Make sure to include some content in your "ajax-close" span to be able to click it like the word "Close".
Add JQuery library to your HTML head :
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
In your given link you are adding element dynamically, so need to use event delegate for dynamically created elements event binding.
$(document).on('click', '.ajax-close', function( event ){
//your code
});
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.
I have added a div dynamically into HTML,
When i have tried to trigger the click event of same element
what i have tried till yet is below ::
$(function(){
$("#id").bind("click",function(){
alert("hi");
})
});
i have also tried to use "on" instead of "bind" but it doesn't work.
but when i have write simple , it works fine
<div onclick="javascript:testFunction();"></div>
Delegate event using on(), you can give the static parent of element that is supposed to be added after execution of binding code.
$(function(){
$(document).on("click", "#id",function(){
alert("hi");
});
});
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, reference.
so i have some code in a page that is like this
<div id="main">
<div class='module' id ='test1'>1</div>
<div class='module' id ='test2'>2</div>
<div class='module' id ='test3'>3</div>
<div class='module' id ='test4'>4</div>
</div>
and a bit of js that has an event that is on the document.load
$('.module').on("click", function(){
if ($(this).hasClass('flipped')) {
$(this).toggleClass('flipped');
} else {
$('.module').removeClass('flipped');
$(this).toggleClass('flipped');
}
});
this works fine until an element is added dynamically so lets say i add
<div class='module' id ='test5'>5</div>
this is not going to be clickable because .on is not bound to this..
I have read posts here explaining that .on wont work... but i cannot find a solution..
can anyone help?
Delegate the events to the parent #main.
$('#main').on("click", ".module", function(){
if ($(this).hasClass('flipped')) {
$(this).toggleClass('flipped');
} else {
$('.module').removeClass('flipped');
$(this).toggleClass('flipped');
}
});
Your JavaScript code executes only when the page loads. So after your page is loaded, your code is executed and you telling it to attach the onclick event handler to the elements having the class module. During initial page load there are only 4 such elements. So the event handler will be attached only to these elements (speaking very abstractly).
Now when a new element is added dynamically, events wouldnt fire because there are no handlers tied to them.
In this case you should take advantage of Event Delegation. You need to tie your event handler to the enclosing element (#main or some use body).
So your code would be like:
$('#main').on("click", ".module", function(){
if ($(this).hasClass('flipped')) {
$(this).toggleClass('flipped');
} else {
$('.module').removeClass('flipped');
$(this).toggleClass('flipped');
}
});
So the Event would be tied only to the static #main but when the event occurs, it knows where to find the targeted element because you have specified the target as .module.
Have a look at this:
http://api.jquery.com/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(). 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.
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. This element could be the container element of a view in a Model-View-Controller design, for example, or document if the event handler wants to monitor all bubbling events in the document. The document element is available in the head of the document before loading any other HTML, so it is safe to attach events there without waiting for the document to be ready.
In addition to their ability to handle events on descendant elements not yet created, another advantage of delegated events is their potential for much lower overhead when many elements must be monitored. On a data table with 1,000 rows in its tbody, this example attaches a handler to 1,000 elements:
$( "#dataTable tbody tr" ).on( "click", function() {
alert( $( this ).text() );
});
A delegated-events approach attaches an event handler to only one element, the tbody, and the event only needs to bubble up one level (from the clicked tr to tbody):
$( "#dataTable tbody" ).on( "click", "tr", function() {
alert( $( this ).text() );
});
Note: Delegated events do not work for SVG.
Try this...
$('body').on("click", ".module" , function(){