javascript - Table row not created after second change of text input - javascript

This is my HTML code:
<table id="display_table"><tr>
<td>No. of Questions: </td>
<td><input type="text" id="questions_num"></td>
</tr><tr>
<td>No. of Options: </td>
<td><input type="text" id="options_num"></td>
</tr></table>
I want to make it such that when the user enters x in the text input (whose id is options_num), x rows will be created. For each new row that is created, there should be a left column and a right column. The left column will contain the "Option" + somenumber, where somenumber refers to the row that has been created, and the right column will create a text input.
This is what I have tried in my JS:
document.getElementById("options_num").onkeyup = function() {
var options_num = parseInt(document.getElementById("options_num").value);
var display_text = '<tr><td>No. of Questions: </td><td><input type="text" id="questions_num"></td></tr><tr><td>No. of Options: </td><td><input type="text" id="options_num"></td></tr>'
for(var i = 1; i <= options_num; i++) {
display_text += "<tr><td>Option " + i + ": </td><td>" + "<input type='text' id='option_" + i + "'</td></tr>";
}
document.getElementById("display_table").innerHTML = display_text;
document.getElementById("options_num").value = options_num.toString();
document.getElementById("options_num").focus();
}
And it works when I first enter a value into the text input (whose id is question_num), but when I change the value, it does not work (it does not do anything). Demo.
So how do I get my JS code to work?

The reason it doesn't work after the first time, is that innerHTML actually destroys event binding. So after you modify table.innerHTML browser completely rebuilds new DOM elements without original onkeyup event listener attached.
I would recommend to change HTML a little, it will make everything simpler:
<table id="display_table">
<tbody>
<tr>
<td>No. of Questions:</td>
<td><input type="text" id="questions_num"/></td>
</tr>
<tr>
<td>No. of Options:</td>
<td><input type="text" id="options_num"/></td>
</tr>
</tbody>
<tbody id="rows"></tbody> <!-- append generated HTML here -->
</table>
and modified JS:
document.getElementById("options_num").onkeyup = function () {
var options = document.getElementById("options_num"),
optionsNum = parseInt(options.value),
tbody = document.getElementById("rows"),
rows = '';
for (var i = 1; i <= optionsNum; i++) {
rows += "<tr><td>Option " + i + "</td><td>" + "<input type='text' id='option_" + i + "'</td></tr>";
}
tbody.innerHTML = rows;
options.focus();
}
So the idea is to put table rows into tbody and it makes easy adding new and replacing replacing old rows.
Demo: http://jsfiddle.net/8yYyW/2/

Related

HTML Table - Loop through dynamically created rows and if field in specific column contains date prevent row from editing

I'm trying to create a JavaScript to disable a row if EndDate contains a date.
The table is generate automatically so I thought to lookup how many rows the table has and start iterating through them. Check if fields in column EndDate contain a date.
If that row contains a date then disable any field in that row.
To track down the fields I used this to check if I could disable them.
document.getElementById("r0_LineItemCode").disabled = "true";
document.getElementById("r0_LineItemCode_ref_ref").disabled = "true";
document.getElementById("pr0_LineItemCode").disabled = "true";
document.getElementById("r0_ec_type").disabled = "true";
I accomplished to loop through the rows and find out how many rows there are and show the data on the console.
But now selecting that field to check if it contains a date and then disable those row items fails.
Code to track down the rows and iterate through the rows:
let text = "";
var endDateFields = [];
var rowData = document.querySelector("#RequestLinesGrid_RowIDs");
console.log(rowData);
console.log(rowData.value);
const rows = rowData.value.split(',');
rows.forEach(myFunction);
console.log(text);
console.log(r0_EndDate);
console.log(r1_EndDate);
console.log(r2_EndDate);
function myFunction(item, index) {
text += "indexNumber = " + index + " variableField: " + item + "_EndDate";
var str = item + "_EndDate";
eval(str);
console.log(str);
}
I have the feeling I'm almost there, but need a little push in the right direction :)
This is a simple logic of your problem, if date is not empty disable all inputs of the parent tr.
document.querySelector('table').querySelectorAll('td.date').forEach(el => {
if (el.innerHTML !== '') {
const parentTr = el.parentElement;
parentTr.querySelectorAll('input').forEach(input => {
input.disabled = true;
});
}
});
<table>
<thead>
<th>id</th>
<th>input1 Example</th>
<th>input2 Example</th>
<th>date Example</th>
</thead>
<tbody>
<tr>
<td>1</td>
<td><input name='test' type='text'></td>
<td><input name='test' type='text'></td>
<td class='date'>10/10/2021</td>
</tr>
<tr>
<td>2</td>
<td><input name='test' type='text'></td>
<td><input name='test' type='text'></td>
<td class='date'>10/10/2021</td>
</tr>
<tr>
<td>1</td>
<td><input name='test' type='text'></td>
<td><input name='test' type='text'></td>
<td class='date'></td>
</tr>
</tbody>
</table>
Instead of check all row just add a simple class on td have date then check it as my example.

Reassign name after .remove() [duplicate]

I have a function which creates a DOM element onClick. That Element contains inputs with array names.
At the start I already have one element (the same like those which I create onClick).
<tbody id="elementsBody">
<tr id="element1"> // 1 becomes 2 and so on when new element is added
<td>
<input type="hidden" name="numbers[]" value="1" /> // 1 becomes 2 and so on when new element is added
</td>
<td>
<input type="text" name="titles[]" />
</td>
</tr>
// Newly created Elements goes in here!!!
</tbody>
This is my function which creates more elements like the one above.
And also creates a Delete Button DIV for this newly created element.
function addElement() {
var elementsBody = document.getElementById('elementsBody');
var numbers = document.forms[1].elements['numbers[]'];
var number = numbers.length+1;
if (isNaN(number)) {
var number = 2;
}
var numberInput = '<td><input type="hidden" name="numbers[]" value="'+ number + '" /></td>';
var titleTd = '<td><input type="text" name="titles[]" /></td>';
// This is the Delete Button DIV
// I want to create a function (deleteElement) which Removes This Element
var deleteButton = '<td><div onClick="deleteElement('+ number + ')">Delete Element</div></td>';
elementsBody.insertAdjacentHTML('beforeend', '<tr id="element' + number + '">' + numberInput + titleTd + deleteButton + '</tr>');
}
I want to create a function (deleteElement) which Removes this Added Element onClick.
After Removing an Element, I want that function to reorder all the elements values and ID's. For example if I remove the Element number 2, the value and ID of the third Element must become 2.
Not JQuery.
Please Help me with that!
You are going to have build an array of all elements involved.
Delete From the target to the end.
Delete the target from the array
Renumber in the array
Then add what's left back.
If it was me I'd be looking at having an other ElementID (DisplayElmentID ?) then you wouldn't have to do all this stuff. ie leave the ID attibute used by the DOM the heck alone
Thanks #Esailija for help! Solution (fiddle):
function addElement() {
var elementsBody = document.getElementById('elementsBody');
var numberInput = '<td><input type="hidden" name="numbers[]" value="" /></td>';
var titleTd = '<td><input type="text" name="titles[]" /></td>';
var deleteButton = '<td><div onClick="this.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode); update();">Delete Element</div></td>';
elementsBody.insertAdjacentHTML('beforeend', '<tr>' + numberInput + titleTd + deleteButton + '</tr>');
update();
}
function update() {
var inputs = document.getElementById('elementsBody').querySelectorAll("input[type='text']");
[].forEach.call(inputs, function(input, index) {
input.value = index + 1;
});
}
<table>
<tbody id="elementsBody">
<tr>
<td>
<input type="hidden" name="numbers[]" value="1" />
</td>
<td>
<input type="text" name="titles[]" />
</td>
</tr>
</tbody>
</table><button onclick="addElement();">add</button>

HTML form with lists generated thru Javascript using onchange event - not working as expected

I have a HTML form with a #List1, #Text1 and #List2. #List1 is generated through JSON via PHP from MySQL. #Text1 changes on user input. #List2 should also be generated through JSON from MySQL every time the user changes #Text1, using both the value selected in #List1 AND the contents of #Text1.
The data from the form is further used in PHP to generate a table with data via a query to MySQL.
I tried to use the onchange() event to generate #List2, but it doesn't work - #List2 remains empty after user input in #Text1, although the onchange() function is executed.
HTML
<div class="input_frm">
<form method="post" action="<?php print data_clean($_SERVER["PHP_SELF"]);?>">
<table class="input_tbl">
<tr>
<td class="a">Select county</td>
<td class="b"><select id="selJudet" name="Alfa" onchange="judetChg()"></select></td>
<td class="c"><input class="button_face" type="submit" value="Submit"></td>
</tr>
<tr>
<td class="a">Search zone as</td>
<td class="b"><input type="text" id="selText" name="Beta" maxlength="35" placeholder="Wildcard string" onchange="textChg()" /></td>
<td class="c"></td>
</tr>
<tr>
<td class="a">Select zone</td>
<td class="b"><select id="selZona" name="Gamma" onchange="zonaChg()"></select></td>
<td class="c"></td>
</tr>
</table>
</form>
</div>
JavaScript
$(document).ready(function()
{
$.getJSON("/scripts/033A_GetJudet.php", success = function(data)
{
var str_options = "";
for (var i=0; i < data.length; i++)
{
str_options += "<option value='" + data[i] + "'>" + data[i] + "</option>";
}
$("#selJudet").append(str_options);
var selOption = document.getElementById("selJudet");
selOption.selectedIndex = localStorage.getItem("selJudIndex") || 0;
document.getElementById("selJudet").selectedIndex = selOption.selectedIndex;
});
});
function judetChg()
{
var selOption = document.getElementById("selJudet");
localStorage.setItem("selJudIndex", selOption.selectedIndex);
}
function textChg()
{
var selTextValue = document.getElementById("selText").value;
localStorage.setItem("selTextValue", selTextValue);
var selJudet = localStorage.getItem("selJudIndex");
//alert(selJudet);
var str_http = "/scripts/033B_GetJudetWildcdZona.php?judet=" + selJudet + "&textwildcd=" + selTextValue;
//alert(str_http);
$.getJSON(str_http, success = function(data)
{
var str_options = "";
for (var i=0; i < data.length; i++)
{
str_options += "<option value='" + data[i] + "'>" + data[i] + "</option>";
}
$("#selZona").html("");
$("#selZona").append(str_options);
});
}
function zonaChg()
{
var selOption = document.getElementById("selZona");
localStorage.setItem("selZonaIndex", selOption.selectedIndex);
}
It works ! And now it seems very natural, considering it is based on events. (Just like in Visual Studio - only much harder to debug :)). The code might be improved to fire also on #List1.change - or not, depending on the logic of the form.
I had a single error in my PHP code, a $row['...'] variable which had an erroneous index which I did not notice, the error being there exactly because I copied the code from another script so as not to make mistakes !

input text size attribute not working IE8

I have an html page dynamically generated by javascript with the onLoad event.
This is the javascript:
function populateTable(q,a1,a2,a3,a4) {
var i;
for (i=0;i<10;i++) {
table = document.createElement("table");
table.appendChild(createQuestion(q,i));
for (var j=0;j<4;j++) {
var answer= eval("a" + (j+1));
table.appendChild(createAnswers(j,answer,i));
}
var tabform= document.getElementById("tablesform");
tabform.appendChild(table);
}
}
function createQuestion(quest,i) {
var row = document.createElement("tr");
var tabd = document.createElement("td");
tabd.setAttribute("class","question");
var qinput=document.createElement("input");
qinput.setAttribute("type","text");
qinput.setAttribute("name","q" + (i+1));
qinput.setAttribute("value",quest[i]);
qinput.setAttribute("readonly","readonly");
qinput.setAttribute("size","50");
row.appendChild(qinput);
var tabd1 = document.createElement("td");
var rdiv = document.createElement("div");
rdiv.setAttribute("id","result" + (i+1));
tabd1.appendChild(rdiv);
row.appendChild(tabd1);
return row;
}
in FF it works fine, it makes 10 neat tables, each with the question inside the text input on the first row, with all of the text input fields of the same size (50), etc etc..
on IE8 the text field remains empty, and moreover its size is not fixed! The strange thing is that if I go look at the html that was generated i see:
<FORM id=tablesform method=post action=processquiz.php>
<INPUT value=" - Correct The Test - " type=submit>
<INPUT onclick="window.location='logout.php'" value=" - Log Out - " type=button>
<TABLE>
<TR>
<INPUT value="What browser has the most DHTML extentions?" readOnly size=50 type=text name=q1>
<TD><DIV id=result1></DIV></TD>
</TR>
which is perfectly fine! What could be the problem?
EDIT: document is html 4.01 strict

Removing Dynamic Elements and Reordering those Elements Values and ID's

I have a function which creates a DOM element onClick. That Element contains inputs with array names.
At the start I already have one element (the same like those which I create onClick).
<tbody id="elementsBody">
<tr id="element1"> // 1 becomes 2 and so on when new element is added
<td>
<input type="hidden" name="numbers[]" value="1" /> // 1 becomes 2 and so on when new element is added
</td>
<td>
<input type="text" name="titles[]" />
</td>
</tr>
// Newly created Elements goes in here!!!
</tbody>
This is my function which creates more elements like the one above.
And also creates a Delete Button DIV for this newly created element.
function addElement() {
var elementsBody = document.getElementById('elementsBody');
var numbers = document.forms[1].elements['numbers[]'];
var number = numbers.length+1;
if (isNaN(number)) {
var number = 2;
}
var numberInput = '<td><input type="hidden" name="numbers[]" value="'+ number + '" /></td>';
var titleTd = '<td><input type="text" name="titles[]" /></td>';
// This is the Delete Button DIV
// I want to create a function (deleteElement) which Removes This Element
var deleteButton = '<td><div onClick="deleteElement('+ number + ')">Delete Element</div></td>';
elementsBody.insertAdjacentHTML('beforeend', '<tr id="element' + number + '">' + numberInput + titleTd + deleteButton + '</tr>');
}
I want to create a function (deleteElement) which Removes this Added Element onClick.
After Removing an Element, I want that function to reorder all the elements values and ID's. For example if I remove the Element number 2, the value and ID of the third Element must become 2.
Not JQuery.
Please Help me with that!
You are going to have build an array of all elements involved.
Delete From the target to the end.
Delete the target from the array
Renumber in the array
Then add what's left back.
If it was me I'd be looking at having an other ElementID (DisplayElmentID ?) then you wouldn't have to do all this stuff. ie leave the ID attibute used by the DOM the heck alone
Thanks #Esailija for help! Solution (fiddle):
function addElement() {
var elementsBody = document.getElementById('elementsBody');
var numberInput = '<td><input type="hidden" name="numbers[]" value="" /></td>';
var titleTd = '<td><input type="text" name="titles[]" /></td>';
var deleteButton = '<td><div onClick="this.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode); update();">Delete Element</div></td>';
elementsBody.insertAdjacentHTML('beforeend', '<tr>' + numberInput + titleTd + deleteButton + '</tr>');
update();
}
function update() {
var inputs = document.getElementById('elementsBody').querySelectorAll("input[type='text']");
[].forEach.call(inputs, function(input, index) {
input.value = index + 1;
});
}
<table>
<tbody id="elementsBody">
<tr>
<td>
<input type="hidden" name="numbers[]" value="1" />
</td>
<td>
<input type="text" name="titles[]" />
</td>
</tr>
</tbody>
</table><button onclick="addElement();">add</button>

Categories

Resources