I am using javascript to clone a row then renaming the element id's and incrementing one of the values by 1. This is not the actual code I'm working on but a generic example that shows the problem.
It is appending everything to the top of my row instead of below it
It increments once or twice then stops
The output I'm getting is:
10022018
10032018
10032018
10032018
10032018
10012018
What I'm expecting is:
10012018
10022018
10042018
10052018
10062018
10072018
<table id = "myTable">
<tr id="myRow">
<td>First cell <input type="text" id = "input" value = "10012018"></td>
</tr>
</table><br>
<button onclick="myFunction()">Try it</button>
<script>
function myFunction() {
var i;
for(i=0; i<5;i++){
var row=document.getElementById("myRow");
var cln = row.cloneNode(true);
row.id = "rows" + i;
var inpa = document.getElementById("input");
inpa.id = "input" + i;
var a = parseFloat(document.getElementById("input0").value);
inpa.value = (a + 10000);
document.getElementById("myTable").appendChild(cln);
}
}
</script>
Edit
Robin Zigmond added that input0 was the culprit and not incrementing (corrected but I failed to explain).
var a = parseFloat(document.getElementById("input0").value); // Should be "input"
inpa.value = (a + (10000)); // Needs increment ...a + (10000 * i));
My explanation refers to this assignment to row.
row.id = "rows" + i; /* This assigns a new #id to the original not a clone
-- changed to `cln.id` */
When using a for loop leverage the incremental variable. When the clone was created, your references were still pointing to the original and it wasn't being used to increment anything so that's why it was just copying and not progressing.
Demo
Details commented in demo
<table id="xTable">
<tr id="xRow">
<td>First cell <input type="text" id="input" value="10012018"></td>
</tr>
</table><br>
<button onclick="xFunction()">Try it</button>
<script>
function xFunction() {
// In for loops declare i with let inside loop
// Start with 1 instead of 0 because you cloned the increment starting at 1000
for (let i = 1; i < 5; i++) {
var row = document.getElementById("xRow");
var cln = row.cloneNode(true);
// You are dealing with the clone not the original anymore
// Use i form increments
cln.id = "rows" + i;
// Target the clone specifically
// Use querySelector() to get #id, .class, or <tag>
var inpa = cln.querySelector("input");
// Once again var i to increment
inpa.id = "input" + i;
var a = parseFloat(document.getElementById("input").value);
// Remember i to increment but this is a little trickier
inpa.value = (a + (10000 * i));
document.getElementById("xTable").appendChild(cln);
}
}
</script>
Id's must be unique. Apply class to tr and input instead.
A generic solution
// n -> How many?
// start -> Start value
// index -> Index of value that should be incremented
// id -> Table id
function addRows(n, start, index, id) {
var table = document.getElementById(id);
for (var i = 2; i <= n + 1; i += 1) {
var arr = start.split("");
arr[index] = i.toString();
var incremented = arr.join("");
var tr = table.insertRow(-1);
tr.className = "row-" + i;
var cell = tr.insertCell(-1);
cell.textContent = "Cell ";
var span = document.createElement("span");
span.textContent = i + ": ";
var input = document.createElement("input");
input.className = "input-" + i;
input.value = incremented;
cell.appendChild(span);
cell.appendChild(input);
}
}
<table id="myTable">
<tr class="row-1">
<td>Cell <span>1: </span><input type="text" class="input-1" value="10012018"></td>
</tr>
</table><br>
<button onclick="addRows(5, '10012018', 3, 'myTable')">Try it</button>
<hr>
<table id="mySecondTable">
<tr class="row-1">
<td>Cell <span>1: </span><input type="text" class="input-1" value="14444"></td>
</tr>
</table><br>
<button onclick="addRows(8, '14444', 0, 'mySecondTable')">Try it</button>
Related
I designed a table where you can add dynamic rows, the user can select a quantity and a price for each of them. I have a series of very simple functions that allow me to delete, empty the entire table or calculate the total of all products plugged.
So far everything works fine, the problem occurs when I create 3 rows, I add it to each of their values, then I decided to delete the second row and calculate the total. As you can see, the calculation is flawed, in fact I only returns the total of the first product added to the table. I can not understand why the script does not work properly. Can anyone help me solve this problem?
<html>
<table style='width:100%' id='table'>
<tr>
<td colspan='3'><input type="button" style="background-color:#00FA9A" value="add product" onclick="add()" id="button"><input type="button" style="background-color:red" value="Delete all" onclick="deleteall()" id="button">
</td>
</tr>
<tr>
<td>Quantity</td>
<td>€</td>
<td>Delete</td>
</tr>
</table>
<input type="button" id="button" value="Calc total" onclick="total()"><input type="text" class='input' id="total">€
</html>
<script>
var idx = 0;
var cont = 0;
var buttcont = 0;
var quantity, priece;
function deleteall()
{
location.reload();
}
function add()
{
var tableRef = document.getElementById('table').getElementsByTagName('tbody')[0];
var newRow = tableRef.insertRow(tableRef.rows.length);
newRow.id = "row" + cont;
cont++;
var newCell1 = newRow.insertCell(0);
var newCell2 = newRow.insertCell(1);
var newCell3 = newRow.insertCell(2);
var input1 = document.createElement('input'),
input2 = document.createElement('input');
input3 = document.createElement('button');
input1.type = 'number';
input1.style.width = "100%";
input1.id = "priece" + idx;
input1.min = 0;
input1.value = 1;
input2.type = 'text';
input2.min = 1;
input2.style.width = "100%";
input2.id = "quantity" + idx;
input3.class = 'button';
input3.innerHTML = "Delete";
if(input3.attachEvent) input3. attachEvent('onclick',function(e){deleted(e);})
else if(input3.addEventListener) input3.addEventListener('click',function(e){deleted(e);},false)
newCell1.appendChild(input1);
newCell2.appendChild(input2);
newCell3.appendChild(input3);
idx++;
}
function deleted(e)
{
if(document.removeChild && document.getElementById && document.getElementsByTagName)
{
if(!e) e = window.event;
var srg = (e.target)?e.target:e.srcElement;
while(srg.tagName != "TR"){srg = (srg.parentNode)?srg.parentNode:srg.parentElement}
var tb = document.getElementById('table').getElementsByTagName('TBODY')[0];
tb.removeChild(srg);
cont--;
idx--;
}
}
function total()
{
var total = 0;
for(var i = 0; i < idx; i++)
{
quantity = document.getElementById('quantity' + i).value;
priece = document.getElementById('priece' + i).value;
total += quantity * priece;
document.getElementById('total').value = total;
}
}
The problem comes from the fact that when you delete a row inside a table (not the last one) you have a gap in ids. getElementById will return null and your total function will raise an exception.
Add 3 products: idx is 3, ids in the DOM are 0, 1, 2;
Remove product 1: idx is 2, ids in the DOM are 0, 2; => total will throw for i == 1
Actually you can avoid looping through ids by assigning a class to your inputs. Demo.
function total()
{
var total = 0,
prices = document.querySelectorAll('.price'),
quantities = document.querySelectorAll('.quantity'),
i = 0, len = prices.length;
for(; i < len; i++) {
total += prices[i].value*quantities[i].value;
}
document.getElementById('total').value = total;
}
I am using a large dynamically created table. It is 2+ columns with the first column being text and the second+ being values in text input fields. When the page loads, the input boxes have a default value. I want to be able to save the value when I make changes in the text field.
When I use $("#ID_NAME").val(), I get whatever value the user entered. If I drill down to the input field by other means, .val() gives me the default value when the page loaded. The page doesn't actually use any ids, I just added one for debugging.
I've posted a jsfiddle showing the problem. http://jsfiddle.net/GdjKp/1/
HTML:
<fieldset>
<legend>test</legend>
<table id="menuSection">
<thead>
<tr>
<th>Id</th>
<th>field</th>
</tr>
</thead>
<tbody>
<tr id="row_1">
<td>description</td>
<td>
<input id="test_id" type="text" value="default value"></input>
</td>
</tr>
</tbody>
</table>
</fieldset>Chane text value and click
<input type="button" value="Go" onclick="run();"> the two elements found by jQuery will be in console.log() and the two values will pop up.
JS :
function run() {
var a = $("fieldset");
var b = $(a[0]).find("table > tbody > tr");
var c = $(b[0]).children();
var d = $(c[1].innerHTML);
var result_1 = $(c[1].innerHTML);
var result_2 = $("#test_id");
console.log(result_1);
console.log(result_2);
alert(result_1.val());
alert(result_2.val());
}
What is going on here?
[EDIT]
Here is the final working code
function save() {
var cols = $("fieldset:first > table > thead > tr > th");
var sections = $("fieldset");
var ret = {};
var sectionsTmp = {};
var translation = {};
for (var j=1; j < cols.length-1; j++) { //loop on language columns, skipping field names and delete columns (first and last columns)
var lang = cols[j].innerHTML;
sectionsTmp = {};
for (var i=0; i < sections.length; i++) { //loop on sections/fieldsets
var sectionName = $(sections[i]).children("legend")[0].innerHTML;
var translations = $(sections[i]).find("table > tbody > tr");
translation = {};
for (var k=0; k < translations.length; k++) { //loop on translations in a section
var translationId = translations[k].innerText.trim();
var translationText = $(translations[k]).children().eq(j).find('input').val();
translation[translationId] = translationText.replace(/'/g,''');
}
sectionsTmp[sectionName] = translation;
}
ret[lang] = sectionsTmp;
}
var url = '<?= $basePath?>/admin/save/item/translations/';
var form = $('<form accept-charset="UTF-8" action="' + url + '" method="post">' +
'<input type="text" name="translations" value=\'' + JSON.stringify(ret) + '\' />' +
'</form>');
$('body').append(form);
console.log(form);
form.submit();
}
You're not actually selecting the element in the case of result_1 - you're cloning it based on its html.
This line:
var result_1 = $(c[1].innerHTML);
is equivalent to this:
var result_1 = $('<input id="test_id" type="text" value="default value"></input>');
As you can see, result 1 has no relation to what's been typed into the input field - it's completely detached from the DOM.
I am trying to create a table that is generated by user input data.
The table is reflecting a grid therfore I want the id of each cell to be the co ordinate of that grid. So the id of the bottom left cell would be id00. The top right cell id would be the maximum size of the grid that the user has entered.
So for example if data entered; x value=3; y value=3
this would produce the following table:
<table>
<tr><td id="id03"></td><td id="id13"></td><td id="id23"></td><td id="id33"></td></tr>
<tr><td id="id02"></td><td id="id12"></td><td id="id22"></td><td id="id32"></td></tr>
<tr><td id="id01"></td><td id="id11"></td><td id="id21"></td><td id="id31"></td></tr>
<tr><td id="id00"></td><td id="id10"></td><td id="id20"></td><td id="id30"></td></tr>
</table>
I have identified the basic concept for the code as you can see below:
<table>
Create a loop, initial value of r= 0; maximum value of r=y
r =0 <tr> create a secondary loop, initial value of n=0; maximum value of n = x; r remains constant for row
n=0; r= 0 <td id = “id” + “[x- (x-n)]” + “[y-r]” > </td>
….
n=3; r= 0* <td id = “id” + “[x- (x-n)]” + “[y-r]” > </td>
</tr>
….
r =3 <tr> n=0; r= 3 <td id = “id” + “[x- (x-n)]” + “[y-r]” > </td>
….
n=3; r= 3<td id = “id” + “[x- (x-n)]” + “[y-r]” > </td>
</tr>
</table>
I want to develop it in Javascript but I am new to the language and I am having trouble coding it.
Any help anyone could provide would be greatly appreciated.
Try this :
var x = 3; // value from input
var y = 4; // value from input
var table = document.getElementById("myTable");
for(var i = 0; i < y; i++) {
var row = table.insertRow(-1);
for(var j = 0; j < x; j++) {
var cell = row.insertCell(-1);
cell.id = "id" + (j) + (y - i - 1);
cell.innerHTML = cell.id;
}
}
Working example
Try something like this :
var rows = parseInt(document.getElementById('rows').value,10); // get input value
var cols = parseInt(document.getElementById('cols').value,10); // get input value
var table = document.createElement('table'); // create table element
table.border = "1"; // set some attributes
var prevrow; // used to store previous row element
for (var r = 0; r < (rows+1); r++) { // loop rows
var row = document.createElement('tr'); // create tr
for (var c = 0; c < (cols+1); c++) { // loop cols
var col = document.createElement('td'); // create td
col.id = 'id' + r + c; // set id of tr
col.innerHTML = col.id; // add some text
row.appendChild(col); // append td to tr
}
// if first tr then create append to table else insert before previous tr
if (prevrow) {
table.insertBefore(row, prevrow);
} else {
table.appendChild(row);
}
// store newly create tr
prevrow = row;
}
// append the new table to the output div
document.getElementById('output').appendChild(table);
Uses document.createElement(), element.appendChild() and element.insertBefore() to build the table
Working example here
I want to be able to click the button and have it copy this:
<tr id="1">
<td>
<input type="number" class="cue">
</td>
<td>
<input type="time">
</td>
<td>
<input type="text">
</td>
</tr>
And be able to change the id of the <tr> based on what is before it. I also want it to change the value of the number box based on the variable cueset.
When you press the button to add a row it calls add_row()
function add_row(rowCount)
{
for(i=0; i<rowCount; i++)
{
index = index + 1;
$('table').append( $('#1').prop('id', index));
}
}
What im not sure how to do is have it change the id, or the value of the number box.
I don't understand the use of rowCount and the for loop from your explanation, so here it is without them
function add_row()
{
var mostRecentTr = [].pop.call($("tr"));
var newNum = 1+$(mostRecentTr).attr("id");
var newTr = $(mostRecentTr).clone().attr("id", newNum);
newTr.find(".cue").val(newNum);
$("table").append(newTr);
}
var lastRow = jQuery('tr[id]').last();
var currCount = parseInt(lastRow.id);
var newRow = lastRow.clone()
newRow.id = currCount++;
lastRow.parent().append(newRow);
Though I'd suggest something a bit better like this:
var lastRow = jQuery('tr[counter]').last();
var currCount = parseInt(lastRow.attr('counter'));
var newRow = lastRow.clone()
newRow.attr('counter', currCount + 1).id = ('myRow' + currCount + 1);
lastRow.parent().append(newRow);
I am creating a form and I have a field set for client information and the ability to add another field set for another client if needed.
As of now the additional field sets' field id adds by 1 which is good, but I would like for each of the fields in the field set to add by 1 as well.
var _counter = 0;
function Add() {
_counter++;
var oClone = document.getElementById("client1").cloneNode(true);
oClone.id += (_counter + "");
document.getElementById("placehere").appendChild(oClone);
Here's a page that clones and increments the fieldset as well as any children elements within the set. It's assuming that both fieldset and children inputs have a numeric suffix. i.e. fieldset1 and textfield2, etc.
Cheers.
<!DOCTYPE html>
<html>
<head>
<script type='text/javascript'>
// store a reference to the last clone so I can increment off that.
window.lastClone = null;
function incrementId(id) {
// regexp is looking for text with a number suffix. adjust accordingly.
var numberSuffixRegExp = /(.*?)(\d*)$/;
var regExpMatch = numberSuffixRegExp.exec(id);
// assuming a match will be made here, and position 1 and 2 are populated.
var prefix = regExpMatch[1];
var counter = parseInt(regExpMatch[2]);
counter++;
return prefix + counter;
}
function cloneFieldSet() {
if (!window.lastClone) {
window.lastClone = 'fieldset1';
}
var newFieldSet = document.getElementById(lastClone).cloneNode(true);
newFieldSet.id = incrementId(newFieldSet.id);
var tagNames = ['input', 'select', 'textarea']; // insert other tag names here
var elements = [];
for (var i in tagNames) {
// find all fields for each tag name.
var fields = newFieldSet.getElementsByTagName(tagNames[i]);
for(var k = 0; k < fields.length; k++){
elements.push(fields[k]);
}
}
for (var j in elements) {
// increment the id for each child element
elements[j].id = incrementId(elements[j].id);
}
document.getElementById("placehere").appendChild(newFieldSet);
window.lastClone = newFieldSet.id;
}
</script>
</head>
<body>
<input type='button' value='Clone' onclick='cloneFieldSet()'/><br/>
<fieldset id='fieldset1'>
<table>
<tr>
<td>Label One:</td>
<td><input type='text' id='fieldOne1'/></td>
</tr>
<tr>
<td>Label Two:</td>
<td><input type='text' id='fieldTwo1'/></td>
</tr>
<tr>
<td>Label Three:</td>
<td><select id='selectOne1'>
<option>Some Value</option>
</select></td>
</tr>
</table>
</fieldset>
<div id='placehere' style='margin:10px 0; border:1px solid black'>
</div>
</body>
</html>
Try This : It only adds an updated id to user input form elements.
If you want to updated all child elements in the fieldset, remove the if statement :)
var _counter = 0, _fcounter = 0;
function add(){
var i, j,
oClone = document.getElementById("client1").cloneNode(true),
fldTypes = "INPUT SELECT TEXTAREA CHECKBOX RADIO",
fields = oClone.children;
_counter++;
oClone.id += (_counter + "");
for(i=0, j= fields.length; i<j; i++){
if(fldTypes.indexOf(fields[i].nodeName) > -1){ //checks for user input form elements
_fcounter ++;
fields[i].id += (_fcounter + "");
}
}
document.getElementById("placehere").appendChild(oClone);
return oClone;
}
See Example: http://jsfiddle.net/yfn6u/8/