Im trying to remove a row. But i can't figure it out really.
First of all I've got a button that'll add a new row, that works.
But I want to give the user the possibility to remove the just added row.
The row has an 'div' inside what acts as an deletebutton. But the deletebutton doesn't work?
I'm I missing something?
Greet,
Juki
function addrow() {
$("#container").append("<div id=\"row_added\"><div class=\"deletebutton\" id=\"delbuttonnumber\"></div><div id=\"addedcolor\" class=\"colorcube\"></div></div>");
}
// deleterow the row
$(".deletebutton").click(function() {
rowclrid = "#" + $(this).parent().attr("id");
$(rowclrid).remove();
});
My guess is that you have assigned the click handler before adding the new content, so the handler is not attached to this particular element. You can use .delegate() to listen for events on all elements below a particular parent element, whether or not they already exist:
$('#container').delegate('.deletebutton', 'click', function(){
$(this).parent().remove();
});
This listens for all click events that happen inside the element #container using a feature of the DOM called event bubbling, then checks to see if they happened on a .deletebutton element, and, if so, calls the handler.
Note also the simplified code inside the handler.
I think what you need to do is use the live method. This will add the events for any new item that is added to the DOM, not just the ones that exist when you set the click handler.
// deleterow the row
$(".deletebutton").live('click', function() {
$(this).parent().remove();
});
You also don't need to get the row by getting the ID - it's simpler in the way above.
Related
I've looked all over the internet with everyone giving the same answer
$(document).on('click', '#targetID', function() {
// do stuff
});
instead of
$('#targetID').click(function() {
// do stuff
});
This is nice and it works fine, if you have a click event. But within that on click function, the part where it says do stuff, how can I now target an appended element? For instance say I append 2 divs back to back.
<div id="mainDiv"></div>
<script>
socket.on('event', function (data) {
$('#mainDiv').append ('<div class="1st" id="'+data.id+'">one</div>
<div class="2nd" id="'+data.id+'">second</div>');
});
$(document).on('click', '.1st', function() {
//and right here i would like to`enter something like
$('.2nd').css('background-color','yellow');
}
</scirpt>
This however seems not to work because to my knowledge, this element hasn't been added to the DOM. So what should I do? Should i use angular.js for this?
PS I've also tried adding the entire appended content into a variable first before appending that variable. and then using variable.find to find the element within to no avail. The variable only has context within that function, but is null in the on click function. Thanks in advance for any information that broadens my understanding of this.
The delegation of 'on' is correct. Once the div element exists in the dom, clicking should work. My only concern is you have named your classname beginning with a number. Maybe name it with an alpha character followed by a number.
The difference between the 2 is the concept of event binding vs event delegation.
$('#targetID').click(function() { is event binding which works on elements as long as they exist in the markup when the page or document loads.
$(document).on('click', '#targetID', function() { is event delegation which means the event would listen to the document for the click event on the element with ID targetID if it exists in the DOM when the page loads or if it is dynamically added.
So In your case, its event delegation since you are dynamically adding the elements. But in order to make it work, you need to register the listener on the document ready event for the document to listen to the event on the element #targetID
<script>
$(document).ready(function() // Add this
{
socket.on('event', function (data) {
$('#mainDiv').append ('<div class="1st" id="'+data.id+'">one</div><div class="2nd" id="'+data.id+'">second</div>');
});
$(document).on('click', '.1st', function() {
//and right here i would like to`enter something like
$('.2nd').css('background-color','yellow');
});
});
</script>
Here's an example : https://jsfiddle.net/nobcp0L7/1/
I am appendend a hyperlink to the html page using append() method, It is a list of hyperlinks, and I get all other elements id by this.id, but am not able for the appended row, why this happening? is there any other way to append ??
thanks in advance
It sounds like somewhere in your code you have this:
$("selector for links").on("click", function() {
// Using this.id here
return false; // Since they're links I assume you do this or e.preventDefault();
});
and after that code runs, you add another link, but clicking it doesn't trigger the handler above. That's because the code above hooks the event on the elements that exist as of when it runs; since the link you add didn't exist, its click event didn't get hooked.
You can use event delegation to solve this, by changing the code above to:
$("selector for container").on("click", "selector for links", function() {
// Using this.id here
return false;
});
That hooks click on a container that holds the links, but fires the handler as though the event had been hooked on individual links. So since the event is hooked on the container, you get the event even when you add new links.
Concrete example:
$(document).on("click", "a", function() {
alert(this.id);
return false;
});
i'm trying to register the second click on a link, by adding a new class and finding it with jQuery. But it won't change the class after the 1st click.
Hope it makes sense and thank you in advance.
// Listen for when a.first-choice are being clicked
$('.first-choice').click(function() {
// Remove the class and another one
$(this).removeClass('first-choice').addClass('one-choice-made');
console.log('First Click');
// Some code goes here....
});
// Make sure the link isn't fireing.
return false;
});
// Listen for when a.one-choice-made are being clicked
$('.one-choice-made').click(function() {
// Remove the class and another one
$(this).removeClass('one-choice-made').addClass('two-choice-made');
console.log('Second Click');
// Some code goes here....
});
// Make sure the link isn't fireing.
return false;
});
At load, .one-choice-made does not exist, so when you call $('.one-choice-made'), it returns an empty jQuery object, hence the click() handler is not added to anything.
What you want to do is attach the handler to something that will always exist, which will respond to the click event (i.e. a parent/ancestor element). This is what $.on() will do for you when called in a delegated handler syntax (i.e. with a filter selector):
$(document).on('click', '.one-choice-made', function() {
// my second function
}
In this case, jQuery attaches a special handler to document, which watches for click events that propagate to it from children elements. When it receives a click, jQuery looks at the target of the click and filters it against the selector you provide. If it matches, it calls your function code. This way, you can add new elements with this class at any time, as long as they are children of the elements from the selector(s) you applied .on() to. In this case, we used document, so it will always work with new elements.
You can pare this down to a known permanent parent element to reduce click events, but for simple cases document is fine.
NOTE: In the same way, removing the class first-choice will not have any affect on whether the first click handler is called, because the handler is applied to the element. If you remove the class, the element will still have the handler. You will need to use a delegated handler for that as well:
$(document).on('click', '.first-choice', function() {
// my first function
}
Demo: http://jsfiddle.net/jtbowden/FxqX9/
Since you're changing the class you need to use .on()s syntax for delegated events.
Change:
$('.one-choice-made').click(function() {
to:
$(document).on('click', '.one-choice-made', function() {
Ideally you want to use an element already in the DOM that's closer than document, but document is a decent fallback.
I am working on a mobile app, and I am currently using the on() method to implement a swipe-to-delete feature (I understand that there are libraries that would allow me to do this, and am open to any thoughts you have on the merits of different options). I have code that looks like this:
var favArticles = $('#favoritesList li');
favArticles.each(function(i, li){
var id = $(li).attr('id');
$(li).on("swipeLeft",function(){
//console.log('SwipeLeft ' + id);
var html = $(li).html();
var button = '<div ><button onclick="favDelete(id, i)">Delete</a></div>';
$(li).html('<div style="position:relative;">' + html + button + '</div>');
});
});
I am trying to manage a mutable list of articles that, so whenever I render the favorites list, I grab all the current articles, and bind a swipe event to them. If swiped, a button is brought up on top of the article, and when the user hits the button a function runs that removes the swiped li from the list, and deletes it from the stored favorites.
Within favDelete, I use the index i to remove() the correct li. This means that I need to recreate all the events with updated values of i each time an element is deleted.
So, my question: if I call on() again, for the same event on the same DOM element, will the old binding be overwritten? Or do I create a memory leak by constantly adding new on() actions to my list elements?
UPDATE: Yes, JQuery, not Javascript. Apologies. And I know that my favDelete call won't work as it is shown, I omitted chopped a bunch of quotation marks out for the post to try to improve readability.
I would just use two event handlers and event delegation: One for the swipe event and one for the click on the delete button.
I don't know if swipeLeft works with event delegation, but even if not, it would not change much:
$('#favoritesList').on('swipeLeft', 'li', function() {
// show delete button
// or $(this).html(...)
$(this).append('<div class="deleteButton"><button>Delete</a></div>');
}).on('click', '.deleteButton button', function() {
// find ancestor li element
var $li = $(this).closest('li');
// and pass it to favDelete
favDelete($li);
// if you don't remove the element in the favDelete, do it here:
$li.remove();
});
Using event delegation for the delete buttons makes the most sense, since you are "constantly" adding and removing them.
Learn more about event delegation.
All the styling you can do with a CSS rule for the deleteButton class. You'd also have to change your favDelete method to accept a li element (or rather a jQuery object with a li element) instead of an ID and index.
if I call on() again, for the same event on the same DOM element, will the old binding be overwritten?
.on() will always add a new event handler. In your code, you even create a new event handler function for every list element, which is indeed a waste of memory.
In my code above, there are only two event handlers for all li and button elements.
Two other ways you could do this, rather than a hard-coded index:
Use the ID to select the correct LI element (in your favDelete function)
Pass in a selector instead of the index (i.e. $(this).closest('li'))
If You'll call 'on' again, previous bindings will still be alive - for ex. If You'll call few times (let's say 5 times) on('click', function() { console.log('fired'); }. When You'll click one time on the object it'll thorw 'fired' five times.
When I access <div> or <p> elements by class with jQuery for a click function, it repeats the event by how many elements are in the array or stack. So, if I have 3 <div> elements on top of each other or next to each other, the one on the bottom, or the one to the right, will go through the event once and the one on the top or the left will go through the event 3 times.
Am I doing something wrong? Or is this not meant to be done with jQuery?
[revision]
sorry if i worded this in a confusing way. here is a link... you will better understand my problem there. just add a couple new elements via the form and click on them.
http://jsfiddle.net/rNj6e/
Now that you've posted a fiddle showing the problem, I can actually answer. The problem is that you bind the click event handler to .dp inside the click event handler bound to #add. So what happens is this:
You fill in the form and click #add, which creates a new element with class dp and appends it
It then binds a click event handler to every element with class dp (there's only 1, the 1 we just added)
You fill in the form again, click #add, which repeats steps 1 and 2, so it binds another click event listener to the first .dp element, and binds one to the new element.
Repeat as necessary, binding more and more event handlers to the existing elements every time you click #add!
To fix this, you need to bind the event handler to .dp outside of the #add event handler. The problem is that you're creating new .dp elements on the fly, so just using .click won't bind to elements that are not in the DOM yet. To solve that, you can use delegate, which binds an event handler to elements matching the selector now and in the future:
$("#preview").delegate(".dp", "click", function(event){
alert(this.id);
});
Here's an updated fiddle.
Try:
$(".some_class").click(function(event){
alert(event.target.id);
}).children().click(function(event) {
return false;
});
This should prevent the click event from bubbling through the children, this happens when you click on the children contained in the div.
You are recieving a blank ID because the target of your clicks is most likely the child you clicked and you haven't given it an ID.
To prove this try...
$(".some_class").click(function(event){
alert(event.target.nodeName);
});
which alerts you the nodeName (the name of the html tag) you just clicked.
Change it to this:
$(".some_class").each( function () {
jQuery(this).click(function(event){
alert(event.target.id);
});
});