I apologize if the question is formulated sloppy. I'm just somewhere in the beginning of understanding jquery.
I want to implement a form builder based on drag and drop.
I added button to clone dropped element.
But after cloning "remove" and "clone" buttons are not working.
jsfiddle.net/284mx1vn/
Thanks for your help!
I've just adjusted your Fiddle
I've added the two lines
$(document).on("click", ".remove", function(){
$(this).closest(".input-block").remove();});
$(document).on("click", ".add", function(){
$(this).closest(".input-block").clone().appendTo("#drop-space");
});
so it works for dynamically created elements, and added the class "add" to the "add"-button for convenience.
The issue was/is that events have to be bound to elements already existing in the DOM when the document is loaded. As solution it is possible to use event delegation - meaning to delegate the event (in this case the click event for the buttons) from a static parent element, e.g. $(document). This parent element will delegate the event to all children of the class using the jquery on() function, even if these elements are added later.
For reference: http://api.jquery.com/on/ and https://api.jquery.com/on/#on-events-selector-data-handler, section "Direct and delegated events":
"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()."
Related
is there any difference between this both selectors in combination with a click event?
$("#container").find(".element").on("click",function(){
})
$("#container").on("click", ".element",function(){
})
For me I think technically the effect and consequence will be the same?
Thank you
They are not the same.
The first example using find().on() looks for the .element class in the DOM and adds the event handler to it. It will not work for any elements with that class that are added to the DOM later in the page lifecycle.
The second example using on() with a selector is a delegated event handler, and will therefore work for all matching elements in the DOM as well as those added later.
This part of code is an answer from this question.
$(document.body).on('change', 'select[name^="income_type_"]', function() {
alert($(this).val());
});
I Have two questions the first one is.
Is there a performance issue selecting 'document.body' instead of selecting the Parent element of select?
Something like this.
Second question is.
It will be function like '$.live()' when putting Parent element instead of document.body?
$("#IdOfParentHere").on('change', 'select[name^="income_type_"]', function() {
alert($(this).val());
});
Thanks!
There could be a performance impact(not much significant though) when attaching event handlers to body instead parent element.
Take a case where you are trying to delegate a click event, what you really want to is to handle dynamically created li elements which are in a static ul element. In event delegation when an event happens inside the attached element that events target will be evaluated against the delegation selector to see whether to trigger the handler. In this case if the event is attached to the ul only events inside the ul has to be tested, but if the hanlder is attached to body all the click in the page will have to be tested.
The live() method attaches the handler to the document object, so yes it will be similar to that.
This method provides a means to attach delegated event handlers to the
document element of a page, which simplifies the use of event handlers
when content is dynamically added to a page.
Is there a performance issue selecting 'document.body' instead of selecting the Parent element of select?
No. There is no significant difference in performance. Of course it would be a little faster if you put it closer on the DOM, but we are talking about an incalculably small difference.
Second question is. It will be function like '$.live()' when putting Parent element instead of document.body?
$.live does exactly the same thing as $("body").on("click", "selector",
I have some javascript that successfully clones a template and appends the resulting html to a div. However when I try to reference an element of the clone it is not accessible, even though if I place the exact same element with the exact same ID (confirmed with Firebug) outside the template (and the cloning system) it is accessible. I believe I need to do an update of some kind after cloning but I am not sure. The code I am trying to use to access the (cloned) element (does not log anything to console and is not working) is:
$("#depminusbutton0").on("click", function () {
console.log('I triggered minus 0');
});
And depminusbutton0 shows up like this in firebug inspect element once cloned (doesn't exist prior to cloning, as ID 0 is inserted dynamically:
<a id="depminusbutton0">
Any ideas how I can make this element accessible?
Two possibilities I can think of:
You are installing the event handler before the element exists so it can't find the element to attach the event handler to?
You have a conflicting ID elsewhere in the document.
If you're going to use this form of event handling:
$("#depminusbutton0").on("click", fn);
Then, the #depminusbutton0 element must exist at the time you run that line of code. It will search the DOM for that element at the time you run the code and will not hook up to an element that matches that ID that you create in the future.
You can work around that issue, either by running that line of code AFTER you create the #depminusbutton0 element and insert it in the DOM or you can switch to use delegated event handling which attaches the event handler to a common parent that does exist before you've created the child element.
To see more about how delegated event handling works, see these references:
jQuery .live() vs .on() method for adding a click event after loading dynamic html
Does jQuery.on() work for elements that are added after the event handler is created?
The general idea would be like this:
$(some parent selector).on("click", "#depminusbutton0", fn);
If you have multiple elements with the #depminusbutton0 id, then you will have to fix that and only have one element with that id. Often times with clones, you want to use a class name rather than an id since you can have multiple elements with the same class name.
Are you attaching the event to an element that doesn't exist yet? As described in the jQuery documentation:
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().
Just make sure you are attaching the event to the cloned element after you create it.
$(document).on('click', '.class-or-id-name', function() {
console.log("Heyyy its clickable");
// do more stuff
});
I have a set of three elements. And there are many coming elements after the page load by ajax when the user clicks on a certain element. I iterate over initial elements with each and attach an event to them like this:
tagSet.each(function(index, element){
tagSet.eq(index).on("click",function(){alert("Alerted! Clicked")});
}
But with this approach those ajax-created elements would not be attached with an event. Thus I have to make a little bit of change to on() for it accommodate the ajax-created elements:
tagSet.each(function(index, element){
$(document).on("click",tagSet.eq(index),function(){alert("Alerted! Clicked")});
}
It solve the problem of event attachment to those ajax-created elements but raises another issue. It attaches the event in a way that all of the elements of the page gets trigged with that specific event at once. I mean, since I have three elements, a click on one of them cause all three alert("Alerted!Clicke!) to trigger. What is the issue and the solution?
Use event delegation to bind to all current and future items that match a query:
$(document).on("click", ".some-class-here", function(){
alert("Alerted! Clicked")
});
Replace .some-class-here with a selector that matches your tagSet elements. Then remove your call to $.each.
I need to have multiple .click() functions populated on page load, based on how many image records are stored within a mysql database.
so far i have a page that will nicely switch between photos with a <ul> of image buttons
but i have to hand write the jquery that deals with it.
is there a way that i can populate a .js file with the correct amount of .click() functions based on the amount of records on in the data base.
In addition to Alex's answer, if you want to set the click event of elements that don't exist yet or haven't been added to the page, you could do:
$(body).on('click','a.record',function(){
//any existing or future a element with class record will have this click function
});
Instead of adding a separate onclick handler to each element, you should use event delegation and attach a single event handler to some container. Said event handles would catch all the onclick events , as the bubble up through DOM.
You don't need to write a click() for each unique element.
Instead, you could select a bunch of elements with a selector, such as $('a.record') and then chain click() to that...
$('a.record').click(function() {
// Any `a` element with a class of `record` was clicked.
});
The disadvantage of doing it this way is you add a bunch of event listeners and it won't be triggered for future elements.
As others have mentioned, event delegation using on() (if using a newer jQuery) or delegate() (if using an older) is the best, as it only attaches one event listener and will work with future elements added after the event is attached.
$(document).on('click', 'a.record', function() {
// Any `a` element with a class of `record` was clicked, now or in the future.
});
I've used document here, but you should use the nearest ancestor which won't change, which may be the ul element you have described.