why is parent node for input element undefined? - javascript

I have a table in which I am adding some rows dynamically and in the new rows, I add one input text element. When the text in the input element changes, I wish to access the parent row and do something around it. But my code isn't able to access the parent node for input element. Following is the code sample. What is the reason for this? Is there some work around?
The creation of row looks something like this:
var newRow = document.createElement('tr');
dojo.place(newRow, row, "after");
var td = document.createElement('td');
dojo.place(td, newRow, 'last');
dojo.attr(td, 'colspan', 2);
dojo.place(document.createTextNode('Track id:'), td, 'last');
var input = document.createElement('input');
dojo.place(input, td, 'last');
dojo.attr(input, 'type', 'text');
dojo.attr(input, 'value', 0);
dojo.attr(input, 'onchange', "JavaScript: onTrackIdChange(event);");
The initial part of onTrackIdChange looks like:
function onTrackIdChange(event)
{
var textbox = event.target;
console.log(textbox);
// lets find the parent row
var row = findParentRow(btn);
The implementation of findParentRow looks like:
function findParentRow(node)
{
var parent = node;
do
{
console.log(parent);
parent = parent.parentNode;
}
while (parent.nodeName != 'TR');
return parent;
}
The findParentRow function fails since it says that parent for the input element is not defined.

In your call, findParentRow(btn), shouldn't you be passing textbox instead of btn?
There is no reference to this btn variable elsewhere in the code you've submitted, so if that's in order, you should post some more code relating to that.

parent is not defined, because node is not defined. node is not defined in findParentRow, because btn is not defined in onTrackIdChange.

Related

How to get the data inside a html table cell when clicked on it?

I created a html table and filled it dynamically. So I want to alert the data inside a cell of the table when i clicked it. Here is the code for the table
JSP
<table id="load-opt"></table>
I'm filling the data inside dynamically like this
var fillTable = function($element, data) {
var t_head = $("<tr></tr>");
for(var ind=0; ind<data.length; ind++) {
//name is the name and desc is the description for each option
var $option = $("<tr></tr>");
$option.html("<td>"+name+"</td><td>"+desc+"</td>");
}
};
I tried this but it's not working, it's giving "undefined".
var choice = $('table#load-opt tr td');
choice.click(function(){
alert(choice); // also tried alerting choice.textContent, choice.innerHTML and choice.firstChild
});
you are actually trying to alert the 'td' object not value of from that object so you can use following to solve the query.Here i am using on instead of direct click function because of dynamically added data.
var choice = $('table#load-opt tr td');
choice.on('click', function(){
alert($(this).text());
});
You can use $(this).text() to fetch the data in table cell.
This is a link.

how to use $(this) with foreach in javascript using jquery

I am working on a personal project in Javascript to allow people to create a table of "dream plays" in Scrabble. Here is the link: http://psyadam.neoclaw.net/tables8.html
I am currently trying to allow the user to edit a dream play.
Here is my code:
function editRow(e)
{
var eventEl = e.srcElement || e.target,
parent = eventEl.parentNode
parent = parent.parentNode
var test = $(parent.cells[0]).text()
$('tr').each(function(){
$(this).children("td:contains(test)").each(
function()
{
pageEnd.innerHTML += "success"
$(this).addClass('selected')
}
)
})
pageEnd.innerHTML += test
//pageEnd.innerHTML += $(parent.cells[3]).text()
insertRow()
}
// insertRow assumes that the correct row in the table has the "selected" class added to it
function insertRow()
{
var Row = $('<tr>').append(
$('<td>').append('<input id="input1">'),
$('<td>').append('<select id="input2"><option value=""></option><option value="Yes">Yes</option><option value="No">No</option></select>'),
$('<td>').append('<select id="input3"><option value=""></option><option value="Natural">Natural</option><option value="1 Blank Used">1 Blank Used</option><option value="2 Blanks Used">2 Blanks Used</option></select>'),
$('<td>').append('<select id="input4"><option value=""></option><option value="vs Computer">vs Computer</option><option value="Online Game">Online Game</option><option value="Friendly Game">Friendly Game</option><option value="Club Game">Club Game</option><option value="Tournament Game">Tournament Game</option></select>'),
$('<td>').append('<input id="input5">')
)
$("#myTable tr.selected").after(Row)
}
Right now I'm just trying to get my code to insert a row into the table. I am trying to do this by using the code $(this).addClass('selected') to tag the row the user selected and then use it in my insert function to insert a row. However, nothing seems to happen. I am using pageEnd.innerHTML += "success" as a debugging tool to see if it is even getting there. Unexpectedly, it prints success twice when it should only print once, as in the test I ran every word was unique.
In any case I can't figure out why it's not working. Any help is appreciated. Thanks, ~Adam
You have two options to achieve this:
The first one as the others are suggesting i.e. by keeping a variable of outer this and then using this:
$('tr').each(function() {
var outerThis = this;
// inside another loop (not sure about children method, just an example)
$(outerThis).children("td:contains(test)").each(function() {
// do something with outerThis to operate on further
});
});
Another option to use Javascript's bind() method:
$('tr').each(function(i, trElement) {
// this == trElement
// inside another loop
$(outerThis).children("td:contains(test)").each(function(index, tdElement) {
$(this) // will be now tr element
$(tdElement) // will be td element
}.bind(this));
});
Try this:
function editRow(e) {
var eventEl = e.srcElement || e.target,
parent = eventEl.parentNode
parent = parent.parentNode
var test = $(parent.cells[0]).text()
$('tr').each(function(){
var outerThis = this;
outerThis.children("td:contains(test)").each(
function()
{
pageEnd.innerHTML += "success";
$(this).children().css('text-align', 'center');
}
)
})
pageEnd.innerHTML += test
//pageEnd.innerHTML += $(parent.cells[3]).text()
insertRow()
}
I set the outer this to a variable which you can use. Also textAlign is not a jQuery function. You need to use .css() and then specify text-align in that.

get javascript dynimcally created control state

I'm dynamically adding some rows to my ASP.NET table, I have several cells in each row and each cell contains a control which is dynamically created:
var TD = document.createElement('td');
var spanCheck = document.createElement("span");
spanCheck.innerHTML = "<input type='checkbox' name='vehicle' value='Car'>mycheck";
spanCheck.id = "newfoodcheck0";
spanCheck.onclick = function () {
if (spanCheck.checked)
alert('checked');
else
alert('unchecked');
};
TD.appendChild(spanCheck);
I'm adding an onclick function for this span (which is rendered as a checkbox), I want to know when it is checked, but if (spanCheck.checked) doesn't work and I always get 'unchecked' in my alert, what is going wrong here? should I use spanCheck.checked or I should use document.getElementById(spanCheck.id).checked? I've tested it, but again with no luck! how can I know whether my checkbox is checked or know?
What you are doing is adding click event on spanCheck and checking for spanCheck.checked. However the checked property is on the input element which is the child of the spanCheck. You might want to do somewhat like this:
var TD = document.createElement('td');
var spanCheck = document.createElement("span");
spanCheck.innerHTML = "<input id='my_input' type='checkbox' name='vehicle' value='Car'>mycheck";
spanCheck.id = "newfoodcheck0";
spanCheck.onclick = function () {
var input = document.getElementById('my_input');
if (input.checked)
alert('checked');
else
alert('unchecked');
};
Also, I think you haven't inserted your TD into the body. So in the last line, you should use appendChild:
TD.appendChild(spanCheck);
document.body.appendChild(TD);
Another thing, you should not attach onclick event on the span. You should attach the same on input element. The following code is doing the same:
var TD = document.createElement('td');
var spanCheck = document.createElement("span");
spanCheck.innerHTML = "<input id='my_input' type='checkbox' name='vehicle' value='Car'>mycheck";
spanCheck.id = "newfoodcheck0";
TD.appendChild(spanCheck);
document.body.appendChild(TD);
var input = document.getElementById('my_input');
input.onclick = function () {
if (input.checked)
alert('checked');
else
alert('unchecked');
};
In your code, spanCheck is not rendered as a checkbox. It contains a checkbox. Therefore, there's no such property spanCheck.checked. There is a spanCheck.children[0].checked property, however.

Get An Element Within a Table Row

Firstly,
If possible, I would like to do this without JQuery, and purely Javascript.
Ok so I have an html table with rows getting added dynamically to it.
In each row is a:
Select Element (id = "ddFields")
Text Input Element (id = "tfValue")
Button Element (no id)
The Button Element removes the row for which it is situated
The Select Element has a default option of "" and then other 'valid' options
The Text Input is added to the row but it is hidden.
All elements are in the same
Basically I would like for the Select Element to show the hidden text input element if the selected index is != 0
so far I have this for my onchange function:
function itemChanged(dropdown) //called from itemChanged(this)
{
var cell = dropdown.parentNode;
var row = cell.parentNode;
var rowIndex = dropdown.parentNode.parentNode.rowIndex;
var index = dropdown.selectedIndex;
var option = dropdown.options[dropdown.selectedIndex].text;
if(index >0)
{
alert(row);
var obj=row.getElementById("tfValue"); //tfValue is the Text Field element
alert(obj);
//row.getElementById("tfValue").hidden = "false"; //doesn't work
//row.getElementById("tfValue").setAttribute("hidden","true"); //doesn't work
}
else
{
alert('none selected');
}
}
Finally figured it out. So here it is:
SCENARIO:
A table that has rows added to it dynamically.
In each row there is a select element and an input text element.
The select element changes text-value of the input text element based on the index of the select element.
in your select element set the onchange function to this:
onchange="selectionChanged(this)"
then create a javascript function shown below:
function selectionChanged(dropdown)
{
//get the currently selected index of the dropdown
var index = dropdown.selectedIndex;
//get the cell in which your dropdown is
var cell = dropdown.parentNode;located
//get the row of that cell
var row = cell.parentNode;
//get the array of all cells in that row
var cells = row.getElementsByTagName("td");
//my text-field is in the second cell
//get the first input element in the second cell
var textfield = cells[1].getElementsByTagName("input")[0];
//i use the first option of the dropdown as a default option with no value
if(index > 0)
{
textfield.value = "anything-you-want";
}
else
{
textfield.value = null;
}
}
Hope this helps whoever. It bugged me for a very long time. Thanks shub for the help! :)
first, I hope you are not repeating your ids. No two items should have the same id.
If you're iterating, create id1, id2, id3.
Also, this is not necessary but I suggest introducing your vars like this:
var a = x,
b = y,
c = z;
If you decide to use jQuery you could just do this:
$('#tableid').on('click','button',function(){
$(this).parent().parent().remove();
});
$('#tableid').on('change', 'select',function(){
if($(this).val()){ $(this).next().show(); }
});
Be sure to change #tableid to match your table's id.
This assumes the text input is the very next element after the select box. If not so, adjust as necessary or ask and I'll edit.

par.rowIndex is null in this code

I'm really new to JavaScript but I can't find out why this program won't work.
I want when I click the dynamically created button which is situated in a cell in my dynamically created table to get the rowindex of the row in which the button is situated.
Thanks in advance - here is my code:
<html>
<head>
<script>
function whichrow(obj) {
var par = obj.parentNode;
while(par.nodeName.toLowerCase()! = 'tr') {
par = par.parentNode;
}
alert(par.rowIndex);
}
</script>
</head>
<body>
<script>
mybody = document.getElementsByTagName("body")[0];
mytable = document.createElement("table");
mytablebody = document.createElement("tbody");
for(var i = 0; i<5; i++) {
mycurrent_row = document.createElement("tr");
mycurrent_row.id = "row"+i;
for(var j = 0; j<4; j++) {
mycurrentcell = document.createElement("td");
currenttext = document.createTextNode("Row" + i + "Column" + j);
mycurrentcell.appendChild(currenttext);
mycurrent_row.appendChild(mycurrentcell);
}
mybutoncell = document.createElement("td");
but = document.createElement("button");
mybutoncell.appendChild(but);
mycurrent_row.appendChild(mybutoncell);
mytablebody.appendChild(mycurrent_row);
but.onClick = whichrow(this);
}
mytable.appendChild(mytablebody);
mybody.appendChild(mytable);
mytable.setAttribute("border", "2");
</script>
</body>
</html>
Ok, so a few points to note here.
In the javascript eventing system, the system calls your callback with its own event object containing different properties according to what happened.
So, here are the mistakes:
When you're assigning to the event handler, when you say but.onclick = whichrow(this) you're setting but.onclick to the result of whichrow, which is undefined since you're not returning anything anyway. It should be but.onclick = whichrow; which will call whichrow when the user clicks your button. The parameter passed is a MouseEvent object. The link I've supplied should serve as a good start to read up on what kind of properties are available to you.
I have to check, since I use el.addEventListeners a lot, but onclick needs to be in lower case, not camelCase like you've done.
Inside the event callback, this usually refers to the element that was clicked, so you should use that.
There is no rowIndex property.
Now, trying to find a solution to your problem. rowIndex can be gleaned by traversing the dom. I'm not sure what purpose this will serve since you're creating the DOM by hand anyway and know the rowIndex already, but if it were unknown, here's what I would do
function whichRow(e) {
// here this should be the button.
var curRow = this.parentElement.parentElement,
rowIndex = 0;
while(curRow) {
curRow = curRow.previousElementChild;
rowIndex++;
}
return rowIndex;
}
I'm writing this off the top of my head, but the point is to give the main idea. In the above snippet, I've taken the parent of the parent of the button, since here's the approximate markup of the button section:
<tr>
<td>
<button></button>
</td>
</tr>
so, the parentElement of the parentElement of the button element should give you the <tr>. Then we'll traverse backwards till we don't have any previous elements, counting as we go. Once the previous element is null, return the count.
The obj you are passing to whichrow() is a button, which I assume inside a TD. So your while loop will exit in its first iteration itself, resulting in par holding a TD - which does not have a property named rowIndex

Categories

Resources