Inject JavaScript variable as value in anonymous function - javascript

I have a form where I add inputs dynamically. When I add a new input I increment a global id variable and concatenate it to the input's id so it will be unique. I also create a delete button for each input that should remove that input and himself (through removing the container <div> they are in). I do the remove process by adding an anonymous function to the delete button's click event via JQuery:
$('#deletebutton' + id).click(function(){
$('#inputcontainer' + id).remove();
});
The only problem with this solution that it isn't work in the way I excepted it. When I click any of the delete buttons it will delete the last input container because when I click, it executes the anonymous function and evaluate the id variable at that time, so the selected id will be the last input's id. So always the last input container will be deleted.
Is there a way to rewrite this function so when I add it to the click event, than it will evaluate the id, inject it and handle the selection as if it had been written like #inputcontainer1, #inputcontainer2, etc.
I can make this by adding the function's body to the button's onclick() event:
var newbutton = '<button id="deletebutton' + id + '" type="button" onclick="javascript:$(\'#inputcontainer' + id + '\').remove();">x</button>';
But is there a way doing this with the JQuery click() way?

To answer the specific question, you'd have to dig the id out of the DOM:
$('#deletebutton' + id).click(function(){
var id = $(this).attr("id").replace('deletebutton','');
$('#inputcontainer' + id).remove();
});
You could also store it as data when you create the delete button:
<button data-id="1" id="deletebutton1">
$('#deletebutton' + id).click(function(){
var id = $(this).data("id");
$('#inputcontainer' + id).remove();
});
Note that in both of these cases, id is a string, not an integer.

When I click any of the delete buttons it will delete the last input container [...]
If your 1st snippet is inside a loop, id probably isn't being scoped to each iteration. So, by the time one of the click() events is triggered and it's trying to use .remove(), id will have already been set to the last value given while looping.
You can use an IIFE to create an additional function scope for keeping a different id for each iteration (ref: closure).
/* loop */ {
var id = ...;
(function (id) {
$('#deletebutton' + id).click(function(){
$('#inputcontainer' + id).remove();
});
})(id);
}
Though, for future reference, ECMAScript 6 is adding block scoping which should allow for:
/* loop */ {
let id = ...;
$('#deletebutton' + id).click(function(){
$('#inputcontainer' + id).remove();
});
}

$('#deletebutton' + id).click(function(){
$(this).parent().remove();
});
If the container isn't a direct parent and doesn't have a class you could do:
$('#deletebutton' + id).click(function(){
var idNum = $(this).attr("id").replace('deletebutton','');
$("#inputcontainer"+idNum).remove();
});
If you've got appropriate classes (or can add them), this would be best:
$(document).on("click",".deleteButton",function() {
$(this).parents(".inputContainer").remove();
});

Related

Passing id into function from onclick method

I know there are many of these types of questions already on here, but I can't find one that matches my specific case.
I just want to pass an id variable into a function from an onclick event, but there's something not right about the way I've got is set up
The goal is to be able to remove the rows that have been added when the X is clicked
$(document).ready(function () {
$("#subjectlist")
.change(function () {
console.log("hit");
$("select option:selected").each(function () {
console.log($("select option:selected"));
var id = 1;
$('#overview').append("<tr id='id'><td>" +
$(this).text() + "</td><td id='id'
onclick='removeItem(id)'>" + "X" + "</td></tr>");
id = id + 1;
});
})
.trigger("change");
$(".btn1").click(function () {
$("#subjectlist").toggle();
});
});
function removeItem(id) {
console.log(id.val);
console.log(id);
$('#overview').find('tr td').eq(id).remove();
}
If your goal is to remove the 'td' element that is clicked. Try this...
$(document).ready(function () {
var id = 1;
$("#subjectlist")
.change(function () {
console.log("hit");
$("select option:selected").each(function () {
console.log($("select option:selected"));
//var id = 1; moved this initialization up a scope level
//on the line below I corrected the concatenation to have unique id's, and removed inline click event.
$('#overview').append("<tr id='id'><td>" + $(this).text() + "</td><td id="+id+">" + "X" + "</td></tr>");
id = id + 1;
});
})
.trigger("change");
$(".btn1").click(function () {
$("#subjectlist").toggle();
});
// added click event to your dynamic element
$("#overview").on('click','td', function() {
$(this).parent().remove();
});
});
/* removed
function removeItem(id) {
console.log(id.val);
console.log(id);
$('#overview').find('tr td').eq(id).remove();
}*/
Your appending string is incorrectly formatted.
Drop the id attribute on the table column since your removeItem() function should be targeting the table row.
You can use back ticks to generate template literals like so...
$('#overview').append(`<tr id="${id}">
<td>${$(this).text()}</td>
<td onclick="removeItem(${id});"> X </td>
</tr>`);
The jQuery.eq() function is an index based filter, not an selector filter. You can then utilise the id selector...
function removeItem (id) {
$(`#${id}`).remove();
}
Try changing this
$('#overview').append("<tr id='id'><td>" + $(this).text() + "</td><td id='id' onclick='removeItem(id)'>" + "X" + "</td></tr>");
To this... should be less confusing, regarding the quote-nesting... notice the use of backticks (`) on the outermost quote level. Also restyled it to make it easier to read, and match html syntax more visually.
$('#overview').append(
`<tr id=x_id_`+id+`>` +
`<td>` +
$(this).html() +
`</td>` +
`<td onclick="$('#x_id_` +
id +
`').remove()">` +
`X` +
`</td>` +
`</tr>`
);
You can ditch the removeItem function entirely.
Since I don't have the rest of your code, not totally sure about the change to the $().html vs $().text, but this should produce a clickable element that will remove the whole row with that id label, which is coded into the rows id and the onclick function.
This will produce html like:
<tr id=x_ix_1><td>PREVIOUS STUFF HERE</td><td onclick='removeItem(`x_id_1`)'>X</td></tr>
Couple things:
First, keep in mind you can only have one element with a particular id at a time. Duplicates will cause errors (but you can remove an element with a particular id and make a new one with that same id, they just can't co-exist).
If you don't want the row removed, but just the td, move the bit about the elements id from the tr to the td-- can't have same id on both.
The quote-nesting was incorrect with the id variable, so was adding it as litteral text (just the string 'id', not the variable content)...
And html id's need to start with a letter. So I re-nested it so the id will parse as variable contents, and the html output will contain 'x_id_' prepended to the variable content... i.e. x_id_0 x_id_1 etc.

For through html elements and appending only appends to last element

I have a text input and on focusout, I have couple of select elements which I want to fill with the text field's value.
And I have bunch of select tags with 'NameSelect' class
$('.textField').focusout(function() {
var name = $(this).val();
var NameOption = $('<option>', { value: name, text: name, attrid: '1'});
var selects = $('#mainForm').find('.NameSelect');
$(selects).each(function(i, obj) {
console.log($(obj)); // it seems to get the right select
$(obj).append(NameOption);
})
}
However, when I do that, even though the selects get all the right elements and for loop for the right count, it only appends the option input to the latest object, not all of them.
What am I missing here?
The issue is because NameOption holds a reference to the option, hence if you append() it multiple times it will move between each parent element.
To fix this you can either clone() the element when you append it:
selects.append(NameOption.clone());
Or you could just provide append() with a string to create a new element each time it's called:
$('.textField').focusout(function() {
var name = $(this).val();
$('#mainForm').find('.NameSelect').append('<option value="' + name + '" attrid="1">' + name + '</option>');
})
});
Note that in both cases the each() is not required.

Javascript append + click remove them

I got a question, what I have already solved, but it's just so annoying.
I have a js code, which is putting down some html code when a button is pushed with "append", and with that code I'm giving an id to an x button, and an id to the container element. I wanted to use these id-s to identify them with a click function, to remove the html code:
var num = 0;
$('.button').click(funcion(){
num++;
var code = '\
<div class="container" id="text' + num + '">\
<div id="x' + num + '">\
x\
</div>\
Some stuff\
</div>\
';
$('.puthere').append(code);
$('#x' + num).click(function(){
$('#text' + num).remove();
});
});
Now the annoying part is the click function on the x. What I would expect is, that this code would work somehow like this:
1st click on the "button" class element should give this code:
$('#x1').click(function(){
$('#text1').remove();
});
after 2nd click I should have this:
$('#x1').click(function(){
$('#text1').remove();
});
$('#x2').click(function(){
$('#text2').remove();
});
instead what I'm getting after the 2nd click is this:
$('#x1').click(function(){
$('#text2').remove();
});
$('#x2').click(function(){
$('#text2').remove();
});
so it's always the last element what the x buttons want to remove. My question is, why can my "num" variable stay "1" at the #x1, but not at the #text1?
My solution was to address the parent element instead:
$('#x' + num).click(function(){
$(this).parent('.container').remove();
});
I know, that there is the "live" function too, what I could use, and I wouldn't need to mess with id-s, but that just seems more heavy. Is that correct? Or I'm overcomplicating things too much without making it more efficent?
It's because num is global and you access it after you create second button. To fix this you can wrap your code with anonymouse self executing function:
(function(num) {
$('#x' + num).click(function(){
$('#text' + num).remove();
});
})(num);
or better use only one click
$('.parent').on('click', '.container > div', function() {
$(this).parent().remove();
});

Click function remove random ID

The plan for what I'm building is: You can click a button to create some houses, and they will be assigned a random ID. (I know is not a unique ID right now).
When you click on one of the houses that you have created you will be able to see some information about the house and a DELETE button:
$('.House').click(function(){
var iDivHouseId = $(this).attr('id');
var oHouse = findHouseId(iDivHouseId);
$('#ShowId').text("ID: " + oHouse.getId());
$('#ShowStreetName').text("Street name: " +oHouse.getStreetName());
$('#ShowNumber').text("Number: " +oHouse.getNumber());
$('#WindowDisplayPersonInfo').append('<input type="button" id="DeleteHouse" value="DELETE" />');
$('#DeleteHouse').click(function () {
$(?????).remove();
});
});
But as marked with the question marks, I don't know what I have to put in to delete the house by it's randomly created ID. I can just add the class .House, but then all houses will be deleted.
// Also, right now, several delete buttons shows when you click the house a couple of times, since it appends a new button each time. How do I replace the old button with a new, instead of just creating a new each time.
I would make the delete button static markup, so you don't have to append it or bind the click handler multiple times. I would then keep track of the current element id using data() and reference that from your click handler.
$('.House').click(function(){
var iDivHouseId = $(this).attr('id');
$('#WindowDisplayPersonInfo').data('current-elem-id', iDivHouseId);
var oHouse = findHouseId(iDivHouseId);
$('#ShowId').text("ID: " + oHouse.getId());
$('#ShowStreetName').text("Street name: " +oHouse.getStreetName());
$('#ShowNumber').text("Number: " +oHouse.getNumber());
});
$('#DeleteHouse').click(function () {
$('#' + $('#WindowDisplayPersonInfo').data('current-elem-id')).remove();
});
By the JSFiddle, if you want to just remove the div from the right side you can try remove the launcher of the click event. To prevent errors with "this" in js, as it always changes values, you can receive a argument in your click function.
Something like this:
$('.House').click(function(e){
var iDivHouseId = $(this).attr('id');
var oHouse = findHouseId(iDivHouseId);
$('#ShowId').text("ID: " + oHouse.getId());
$('#ShowStreetName').text("Street name: " +oHouse.getStreetName());
$('#ShowNumber').text("Number: " +oHouse.getNumber());
$('#WindowDisplayPersonInfo').append('<input type="button" id="DeleteHouse" value="DELETE" />');
$('#DeleteHouse').click(function () {
$(oHouse).remove();
$(e.target).remove();
});
});
});

javascript button click function not working

I have a website where user can select an item, the detail is then displayed, including the quantity. I have also included a button inside the div so that when clicked, it should decrease the quantity by 1.
$("#btnBuy1").click(function()
{
if (!sessionStorage['quantity1'])
{
sessionStorage['quantity1']=1;
}
else
{
sessionStorage['quantity1']++;
}
$("#dropbox").html('<div id = "1"><img class = "thumb" id = "t1" src="../images/birthday_metoyou.jpg" />' + teddy[1].desc + ", Price £"
+ teddy[1].price + ", Quantity: " + sessionStorage.getItem('quantity1') + "<button id = 'btnRemove1'>Remove</button></div><br/>");
updateBasket();
sessionStorage["total1"] = parseInt(sessionStorage.getItem('quantity1')) * teddy[1].price;
updateSubtotal();
if (Modernizr.sessionstorage)
{ // check if the browser supports sessionStorage
myids.push(teddy[1].partnum); // add the current username to the myids array
sessionStorage["ids"]=JSON.stringify(myids); // convert it to a string and put into sessionStorage
}
else
{
// use cookies instead of sessionStorage
}
});
$("#btnRemove1").click(function()
{
alert(remove);
});
I put in an alert message to see if the button is working properly, but when I click the btnRemove1 button, nothing happens.
Since the button is dynamically added, can you try:
$(document).on('click', '#btnRemove1', function() {
{
alert("remove"); //I dont know what remove was is the example, added quotes around it.
});
That is because the button is added later (dynamicly). You will have to use a delegate.
You don't have to use body for this. Any non dynamicly inserted element that is a parent of #btnRemove1 will do.
$('body').on('click','#btnRemove1',function(){
alert(remove);
});
The reason is that you bind the event before the element #btnRemove1 is present on your page. Therefore there is nothing to bind the event to. The body element however - will be present on the page and delegate your event to #btnRemove1.
You can either tie the event to the document (what jQuery live used to do before it was deprecated)
now it is:
$(document).on("click", "#btnRemove1", function(){})
or you can rebind the event after #btnRemove1 is added to the Dom.
Most likely, your Remove button isn't in the DOM before you try to attach the click event to it. It is hard to tell from your code snippets, but if the Buy button action hasn't completed successfully, then Remove won't exist.
At the point that you attach the click event to Remove, try console logging $("#btnRemove1").length to see if it exists, or use break points.
An improvement to your code would be to cache in a variable $("#dropbox") and then look for your buttons within it, as in:
var $dropBoxNode = $("#dropbox");
$dropBoxNode.find("#btnRemove1");
And you should use .on() instead of the deprecated .click().
Try putting the remove button click handler addition after you create the remove button
///Code snippit
$("#dropbox").html('<div id = "1"><img class = "thumb" id = "t1" src="../images/birthday_metoyou.jpg" />' + teddy[1].desc + ", Price £"
+ teddy[1].price + ", Quantity: " + sessionStorage.getItem('quantity1') + "<button id = 'btnRemove1'>Remove</button></div><br/>");
$("#btnRemove1").click(function()
{
alert(remove);
});
updateBasket();
///Code snippit
$('a.edit').on('click','a.edit',function(){
if (confirm("Are you sure you want to Edit this Photo?"))
{
....
....
}
});
Not Working When Data is Loading with AJAX on a DIV Area
Just Like
EDIT

Categories