jQuery click event lost after appenTo - javascript

I am using appendTo to move list items between two list, upon a button click. The button resides in each li element. Each li has two buttons, of which only one is visible at a time, depending on the list the li currently resides.
Here is the function:
// 'this' is the first list
// Click Handler for remove and add buttons
$(this.selector + ', ' + settings.target + ' li button').click(function(e) {
var button = $(e.target);
var listItem = button.parent('li');
listItem.children("button").toggleClass("hidden");
if (button.hasClass("assign")) {
// Add Element to assignment list
listItem.appendTo(settings.target);
}
else
if (button.hasClass("remove")) {
// Remove Element from assignment list
listItem.appendTo(source);
}
})
As long as the list item reside in the original li, the click events in the buttons are triggered. However, once it is moved to the other list using listItem.apendTo. The click item no longer fires. Why is this the case? I cant find anything about this in the docs.

Sometimes jQuery won't be able to find something if it isn't present in the DOM when your script first loads. If it is a dynamically created element, try replacing your click event handlers with 'on'
Rather than:
$(".aClass").click(function(){
// Code here
})
Try:
$("body").on("click", ".aClass", function(){
Code here
})
http://api.jquery.com/on/

You should use on event.
$(".aClass").on("click", function(){
//Your custom code
})
on event is usful for Dynamically generated data + static data already in HTML.

As recommended by user 'apsdehal', a deleate was what i needed:
// Click Handler for remove and add buttons
$(source.selector + ', ' + settings.target ).delegate("li button", "click", function(e) {
var button = $(e.target);
var listItem = button.parent('li');
listItem.children("button").toggleClass("hidden");
if (button.hasClass("assign")) {
// Add Element to assignment list
listItem.appendTo(settings.target);
}
else
if (button.hasClass("remove")) {
// Remove Element from assignment list
listItem.appendTo(source);
}
});

Related

jQuery onChange event handler firing function twice

This is the table http://jsfiddle.net/djochw6L/1/
The event is supposed to fire when I enter value in the item column
$(document).on('change', '.item', function() {
var ite = $(this).closest('tr');
getdetails(ite);
})//event
function getdetails(dat){
var itemName = $(dat).find('.item').val();
alert (itemName);
};
The event handler works correct for the first row. But from the second row onwards it fires twice. Why is this?
The reason why it's firing twice is because your on change element fires for every class with the name item. If you look through your code you can see that on top of giving every table column the class item, you are also passing the item class to each row that is added. So the event fires twice, once for the row and once for the item column.
The code that's giving you the problem is
prot.attr("class", id + " item")
Try to fix your problem by not passing the item class to the table rows, instead of doing all kinds of hacky stuff to the event listener.
You could build your code to something along the lines of
prot.attr("class", "item-" + id)
try adding return false:
$(document).on('change', '.item', function () {
var ite = $(this).closest('tr');
getdetails(ite);
return false;
}) //event

on.click not working after first click on dynamically created table

I dynamically create a table full of links of 'actors', which allows to pull the actors information into a form to delete or update the row. The delete button only pops up when you select an actor.
I'm able to click a row, pull the information into the forms, and delete it on first try. However when I attempt to add a new 'Actor' and then delete it, or just delete an existing 2nd row, the button 'Delete Actor' doesn't work. It's only after the first successful delete does the button no longer work.
var addActor = function() {
// Creates a table of links for each added actor with an id based from # of actors
$("#actorsTable").append("<tr><td><a href='' onclick='deleteActor(this)' class='update' data-idx='" + actors.length + "'>" + newActor.fName + " " + newActor.lName + "</a></td></tr> ");
$(".update").off("click");
$(".update").on("click", selectActor);
};
var deleteActor = function(e) {
$("#deleteActor").on('click', function(event) {
event.preventDefault();
var row = e.parentNode.parentNode;
row.parentNode.removeChild(row);
clearForm(actorForm);
actorState("new");
});
};
I'm new to jQuery/javascript, and I'm pretty sure its due to the change in DOM, but I just don't know what to change to make it work.
Here is an Example of it in action
Try
var deleteActor = function(e) {
$("#deleteActor").unbind();
$("#deleteActor").on('click', function(event) {
event.preventDefault();
var row = e.parentNode.parentNode;
row.parentNode.removeChild(row);
clearForm(actorForm);
actorState("new");
});
};
Here is the link for unbind.
http://api.jquery.com/unbind/
The problem is because you're adding another click handler (in jQuery) within the click handler function run from the onclick attribute. You should use one method or the other, not both. To solve the problem in the simplest way, just remove the jQuery code from the deleteActor() function:
var deleteActor = function(e) {
var row = e.parentNode.parentNode;
row.parentNode.removeChild(row);
clearForm(actorForm);
actorState("new");
};
when you add html dynamically you need to attach the event to the parent static element like so:
$("#actorsTable").on("click","a.update", function() {
$(this).closest("tr").remove();
});

How To Make Link on Parent Node Active in Tree View?

I want to make link on parent node active in tree view. So far I do this:
<li>A - Referensi Spasial <!--this is parent node-->
<ul>
<li>Jaring Kerangka Referensi Geodesi</li>
<li>Model Geoid
<ul>
<li>AB01010010</li>
<li>AB01010020</li>
</ul>
</li>
<li>Stasiun Pasang Surut</li>
</ul>
</li>
When I click the parent node, it just expand the children nodes. What I want is when I click it, it open the link I set on <a></a>
Here is my screenshot of my tree view:
And this is the javascript code:
$.fn.extend({
treed: function (o) {
var openedClass = 'glyphicon-minus-sign';
var closedClass = 'glyphicon-plus-sign';
if (typeof o != 'undefined'){
if (typeof o.openedClass != 'undefined'){
openedClass = o.openedClass;
}
if (typeof o.closedClass != 'undefined'){
closedClass = o.closedClass;
}
};
//initialize each of the top levels
var tree = $(this);
tree.addClass("tree");
tree.find('li').has("ul").each(function () {
var branch = $(this); //li with children ul
branch.prepend("<i class='indicator glyphicon " + closedClass + "'></i>");
branch.addClass('branch');
branch.on('click', function (e) {
if (this == e.target) {
var icon = $(this).children('i:first');
icon.toggleClass(openedClass + " " + closedClass);
$(this).children().children().toggle();
}
})
branch.children().children().toggle();
});
//fire event from the dynamically added icon
tree.find('.branch .indicator').each(function(){
$(this).on('click', function () {
$(this).closest('li').click();
});
});
//fire event to open branch if the li contains an anchor instead of text
tree.find('.branch>a').each(function () {
$(this).on('click', function (e) {
$(this).closest('li').click();
e.preventDefault();
});
});
//fire event to open branch if the li contains a button instead of text
tree.find('.branch>button').each(function () {
$(this).on('click', function (e) {
$(this).closest('li').click();
e.preventDefault();
});
});
}
});
//Initialization of treeviews
$('#tree1').treed();
So, how can I do that thing? Can anyone help me? Thanks
If my understanding is correct, you are asking why your links seem to have no effect at all, and clicking on them just expands the tree as if it were normal text?
It seems to me that this is simply due to the code that attaches events on those links, i.e. the block below comment "fire event to open branch if the li contains an anchor instead of text".
The $(this).closest('li').click(); instruction generates a new click event on the parent "li" item.
The e.preventDefault(); instruction prevents the link from receiving the "click" event, therefore it does not redirect the page / scroll to anchor.
So the result is as if the "click" had "jumped" your link and be passed to the parent "li", therefore not redirecting but expanding the tree.
You could simply remove that block to restore the links normal behaviour. However, the "click" event would still bubble to the parent "li" element, and expand the tree. Not an issue if the pages is redirected, but it is noticeable if the link goes to a local anchor (same page).
To prevent this (but still let the link do its normal job), keep the block but replace the 2 inner instructions by e.stopPropagation();. On the contrary of preventDefault(), it lets the current event happening, but it stops the event bubbling (parent elements do not receive it).
Now I am not sure about the reason for that block. It seems that it was more intended for anchors (which use the same "a" tag but with "name" attribute instead of "href"). But there would be no reason to prevent the "click" event on an anchor?

jQuery: Moving element to another element and back again renders the element unclickable

In my script, I'm attempting to move an element (list) from one parent (just the text) to another and then back again (to the list). The problem is that when I have moved the element back to the original parent (ul), it has become un-clickable. I thought using the detach() over the remove() might do the trick but it doesn't make a difference.
$(document).ready(function() {
$("#inventoryWeapon li").click(function(event) {
var clickedId = event.target.id;
if ($("td#weapon").is(":empty")) {
$("td#weapon").text(clickedId);
$(this).detach();
}
});
$("td#weapon").click(function(event) {
var unequipping = $(this).text();
$("#inventoryWeapon").append("<li id='" + unequipping + "'>" + unequipping + "</li>");
$(this).detach();
});
});
As suggested in the popular comment above, you are not moving the element. To move it, do this.
$("td#weapon").click(function(event) {
$(this).appendTo($("#inventoryWeapon"));
});
You're not moving the element, you're removing the element in one function, and creating a new element with the same ID and content in the other. But the original event handler was only bound to the original element.
If you want your event handler to work with dynamically created elements, use event delegation:
$("#inventoryWeapon").on("click", "li", function(event) {
...
});
Alternatively, you could save the element when you detach it, instead of recreating it:
var savedLI;
$("#inventoryWeapon li").click(function() {
if ($("td#weapon").is(":empty")) {
savedLI = $(this).detach();
$("td#weapon").text(this.id);
}
});
$("td#weapon").click(function() {
if (savedLI) {
$("#inventoryWeapon").append(savedLI);
$(this).detach();
}
});

Create hidden field element for each drop

I know this is a similar question to my previous one however its slightly different.
I have this script adding each 'dropped' element to a list. Now i need it adding into a variable / hidden field so i can pass it to the next page via a form.
When i run it at the moment. It alerts for each one however, it does it not just for every item dropped but if there are 10 items dropped it will run 10 times per item droped rather than once per item dropped.
Any help would be great.
//Record and add dropped items to list
var txt = $("#listbox");
var dtstart = copiedEventObject.start + '\n'
var caltitle = copiedEventObject.title
var txt = $('#listbox');
txt.append("<li class ='listItem'> "+dtstart +"</li>")
var listItems = $('.listItem');
$('#calendarform').submit(function() {
listItems.each(function(){ //For each event do this:
alert( listItems.text() );
});
return false;
});
// remove the element from the "Draggable Events" list
$(this).remove();
the problem lies in this code
listItems.each(function(){ //For each event do this:
alert( listItems.text() );
});
you are alerting the text of all the list items for each list item.
use jQuery(this) to access the current item within an each block
listItems.each(function(){ //For each event do this:
alert( $(this).text() );
});
Assuming your code is within a drop event handler, you are also adding a submit handler each time you drop. This means that each time you drop, you queue up another submit event. This is probably not desired. Move this submit(function(){}) block outside your drop handler to prevent it from firing that function more than once.
$('#calendarform').submit(function(e) {
var listItems = $('.listItem');
listItems.each(function(){ //For each event do this:
alert( listItems.text() );
});
e.preventDefault();//stop normal behavior
return false;
});
and to create elements on the fly you just pass jQuery the html, and append it to your form.
$('<input type="hidden" name="listItem[]"/>').appendTo("#calendarForm").val(listItem.text())
you may have to fiddle with the name element to get it to submit as an array in your server side language, but you're also within an each loop, which provides you with an index, so you can do the following.
$('#calendarform').submit(function(e) {
var form = $(this);
var listItems = $('.listItem');
listItems.each(function(index){ //For each event do this:
var listItem = $(this);
$("<input type='hidden'/>").val(listItem.text()).appendTo(form).attr('name', 'listItem[' + index + ']');
});
e.preventDefault();//stop normal behavior
return false;
});

Categories

Resources