Problem with setting onclick function using createElement
I'm not very good at Javascript, but I can usually get done what I need to get done. Today, however, I've beat my head against the wall for hours and need some help.
I've got two simple functions. One adds a dynamic textbox and button to an existing form, the other removes the box/button. Any number of box/button combinations can be added.
The add code works fine. The remove code works fine IF I STATICALLY ADD THE BOX/BUTTON AND REFERENCE THE REMOVE CODE. However, if I dynamically add the box/button, the button never calls the remove code. I've tried a bunch of different ways, but it just sits there. Here's the code:
Code:
<script type="text/javascript">
function RemoveTask(intTaskNumber)
{
strFieldName = "txtTask" + intTaskNumber;
strFieldName2 = "btnTask" + intTaskNumber;
var objHandler = document.getElementById("lstValues");
objHandler.removeChild(document.getElementById(strFieldName));
objHandler.removeChild(document.getElementById(strFieldName2));
alert("Delete Code Invoked");
}
</script>
<script type="text/javascript">
function formvalidation(frmValues)
{
intCount = document.frmTestData.txtTaskCount.value;
intCount = parseInt(intCount) + parseInt(1);
document.frmTestData.txtTaskCount.value = intCount
strFieldName = "txtTask" + intCount;
strFieldName2 = "btnTask" + intCount;
alert('Name: ['+strFieldName2+']');
strSubName = "RemoveTask(" + intCount + ");"
var element = document.createElement("input");
element.setAttribute("type", "Textbox");
element.setAttribute("value", document.frmValues.txtNewValue.value);
element.setAttribute("name", strFieldName);
var foo = document.getElementById("lstValues");
//Append the element in page (in span).
foo.appendChild(element);
var button = document.createElement("button");
button.value = "Remove Task";
button.name = strFieldName2;
button.onclick = function(){RemoveTask(intCount);};
var foo = document.getElementById("lstValues");
//Append the element in page (in span).
foo.appendChild(button);
document.frmValues.txtNewValue.value = "";
return false;
}
</script>
This may help.
You can compare the code and comments to your original code
Code:
<script type="text/javascript">
//replaced intTaskNumber argument with a button object (n)
function RemoveTask(n)
{
//set the intTaskNumber variable from the buttons expando intCount property
intTaskNumber= n.intCount;
strFieldName = "txtTask" + intTaskNumber;
strFieldName2 = "btnTask" + intTaskNumber;
var objHandler = document.getElementById("lstValues");
objHandler.removeChild(document.getElementById(strFieldName));
objHandler.removeChild(document.getElementById(strFieldName2));
alert("Delete Code Invoked");
}
</script>
<script type="text/javascript">
function formvalidation(frmValues)
{
intCount = document.frmTestData.txtTaskCount.value;
intCount = parseInt(intCount) + parseInt(1);
document.frmTestData.txtTaskCount.value = intCount
strFieldName = "txtTask" + intCount;
strFieldName2 = "btnTask" + intCount;
alert('Name: ['+strFieldName2+']');
strSubName = "RemoveTask(" + intCount + ");"
var element = document.createElement("input");
element.setAttribute("type", "Textbox");
element.setAttribute("value", document.frmValues.txtNewValue.value);
element.setAttribute("name", strFieldName);
//you need to add an id to the element for getElementById use in RemoveTask
element.setAttribute("id", strFieldName);
var foo = document.getElementById("lstValues");
//Append the element in page (in span).
foo.appendChild(element);
var button = document.createElement("button");
button.value = "Remove Task";
button.name = strFieldName2;
//you need to add a button id for getElementById use in RemoveTask
button.id = strFieldName2;
//assign the current value of intCount as an expando property when the button is created
button.intCount=intCount;
//To removes the issue of intCount always returning its last assigned value,
//call RemoveTask with the clicked button object.
button.onclick = function(){RemoveTask(this)};
var foo = document.getElementById("lstValues");
//Append the element in page (in span).
foo.appendChild(button);
document.frmValues.txtNewValue.value = "";
return false;
}
Okay, I've cut out all non-essential code and this is what I have left. Yes, I know tables are the scourge of the earth and should be avoided at all costs. That said, they are still here. I don't think they are the issue though. My problem remains that I can't get the function to 'attach' to the button dynamically. It just does nothing. No errors....no nothing.
RDSpoons: Thanks for the coding suggestions. You are, of course, right, and those changes are very reasonable. However, I implemented them and am having the same problem. My issue is not so much passing the variable as it is getting the function to actually fire. It's like it is just not attached. I click the buttons and nothing happens -- no errors, nothing. The debugger just sits there too.....like I didn't click anything. It's really weird.
Your original code was very close to working - there only problem was that you were assigning the new elements names and then trying to delete them using IDs...
Code:
<script type="text/javascript">
function RemoveTask(intTaskNumber)
{
strFieldName = "txtTask" + intTaskNumber;
strFieldName2 = "btnTask" + intTaskNumber;
var objHandler = document.getElementById("lstValues");
objHandler.removeChild(document.getElementById(strFieldName));
objHandler.removeChild(document.getElementById(strFieldName2));
alert("Delete Code Invoked");
}
</script>
<script type="text/javascript">
function formvalidation(frmValues)
{
intCount = document.frmTestData.txtTaskCount.value;
intCount = parseInt(intCount) + parseInt(1);
document.frmTestData.txtTaskCount.value = intCount
strFieldName = "txtTask" + intCount;
strFieldName2 = "btnTask" + intCount;
alert('Name: ['+strFieldName2+']');
strSubName = "RemoveTask(" + intCount + ");"
var element = document.createElement("input");
element.setAttribute("type", "Textbox");
element.setAttribute("value", document.frmValues.txtNewValue.value);
element.id= strFieldName;
var foo = document.getElementById("lstValues");
//Append the element in page (in span).
foo.appendChild(element);
var button = document.createElement("button");
button.innerHTML = "Remove Task";
button.id = strFieldName2;
button.onclick = function(){RemoveTask(intCount);};
var foo = document.getElementById("lstValues");
//Append the element in page (in span).
foo.appendChild(button);
document.frmValues.txtNewValue.value = "";
return false;
}
</script>
Your original code was very close to working - there only problem was that you were assigning the new elements names and then trying to delete them using IDs...
I appreciate the thought, but that can't be it. If you will check the latest code that I put up (not the original), you will see that I am indeed using ID's now as well. The problem isn't in the delete routine -- that routine works fine. The problem is that I can't get it to actually call the delete routine. It just ignores it altogether.
did you try the code in my post? works ok for me...
Well, I'll be. It does work (almost). Sorry about that. I actually had to include the reference to 'this' that was mentioned above, as without that it always referenced a single button, but otherwise it works great now.
REALLY appreciate the help everyone. Thanks a bunch!
You need to watch out for overwriting your dynamic srcripts when you use .innerHTML.
The DOM can be used to add the break, instead of using innerHTML, and it will avoid overwrite issues:
In place of... document.getElementById("lstValues").innerHTML = document.getElementById("lstValues").innerHTML + "<br>";
You can use... document.getElementById("lstValues").appendChild(document.createElement("br"));
You need to watch out for overwriting your dynamic srcripts when you use .innerHTML.
The DOM can be used to add the break, instead of using innerHTML, and it will avoid overwrite issues:
In place of... document.getElementById("lstValues").innerHTML = document.getElementById("lstValues").innerHTML + "<br>";
You can use... document.getElementById("lstValues").appendChild(document.createElement("br"));
lol -- well that would have certainly been easier than the workaround I put in place. Will have to change my code to use what you just gave. I've been out of the loop for many years, so some of my programming methods/styles are severely antiquated. I can make it do what I want, but it ain't pretty. Thanks for the help.