Dynamic tables printing wrong row and columns in html and jquery - javascript

I'm trying to dynamically generate a table on my website but it's giving me the wrong rows(width) and column(height)
For an input of row=1 and column=4 it generates a tables of 2 rows with 1 row of 5 columns and the other with 4 columns
$("#sizePicker").submit(function(event) {
var height = event.currentTarget[0].value,
width = event.currentTarget[1].value;
console.log(height + "width" + width);
for (var i = 0; i < height; i++) {
console.log(i);
$('#pixelCanvas').append("<tr>");
for (j = 0; j < width; j++) {
console.log(j);
$('tr').append("<td></td>");
}
$('#pixelCanvas').append("</tr>");
}
event.preventDefault();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="sizePicker">
Grid Height:
<input type="number" id="inputHeight" name="height" min="1" value="1"> Grid Width:
<input type="number" id="inputWeight" name="width" min="1" value="1">
<input id="click" type="submit">
</form>
<table id="pixelCanvas">
</table>

It is happening because you append td to every tr that is in table.
This is wrong
Here is an working example
$("#sizePicker").submit(function(event) {
var table = $('#pixelCanvas'),
height = event.currentTarget[0].value,
width = event.currentTarget[1].value;
console.log("height: " + height + ", width: " + width);
table.html("");
for (var i = 0; i < height; i++) {
table.append("<tr class='row" + i +"'></tr>");
for (j = 0; j < width; j++) {
$("tr.row" + i).append("<td>" + i + j + "</td>");
}
}
event.preventDefault();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="sizePicker">
Grid Height:
<input type="number" id="inputHeight" name="height" min="1" value="4"> Grid Width:
<input type="number" id="inputWeight" name="width" min="1" value="5">
<input id="click" type="submit">
</form>
<table id="pixelCanvas">
</table>

According to your logic td goes on appending inside every tr as loop goes. So you need to append td to this tr not on all tr inside table. Here is an working example.
$(function() {
$("#click").on('click', function(event) {
var height = $('#inputHeight').val();
var width = $('#inputWeight').val();
var html = '';
for (var i=0;i<height;i++)
{
html +='<tr>';
for (j=0;j<width;j++)
{
html+= "<td>"+i + '' + j+"</td>";
}
html += ("</tr>");
}
$('#pixelCanvas').html(html);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="sizePicker">
Grid Height:
<input type="number" id="inputHeight" name="height" min="1" value="1">
Grid Width:
<input type="number" id="inputWeight" name="width" min="1" value="1">
<input id="click" type="button" value="submit">
</form>
<table id="pixelCanvas">
</table>

The issue is because you append a new td to every tr that exists in the table, even those created in previous iterations.
You can fix this, and improve the logic, by creating arrays containing the td and tr elements based on the extents specified in the input values. Something like this:
$("#sizePicker").submit(function(e) {
e.preventDefault();
var height = parseInt($('#inputHeight').val(), 10);
var width = parseInt($('#inputWeight').val(), 10);
var columns = new Array(width).fill('<td></td>').join('');
var rows = new Array(height).fill(`<tr>${columns}</tr>`);
$('#pixelCanvas').html(rows.join(''));
});
table {
margin: 10px;
}
table td {
padding: 5px 20px;
border: 1px solid #CCC;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="sizePicker">
Grid Height: <input type="number" id="inputHeight" name="height" min="1" value="5"><br />
Grid Width: <input type="number" id="inputWeight" name="width" min="1" value="5"><br />
<input id="click" type="submit">
</form>
<table id="pixelCanvas"></table>

I found the error in your script, this is how the submit function should look like:
$("#sizePicker").submit(function(event) {
height = parseInt(event.currentTarget[0].value),
width = parseInt(event.currentTarget[1].value);
console.log(height + "width" + width);
for (var i = 0; i < height; i++)
{
if(height>0)
{
let tr = $('<tr></tr>');
for (j = 0; j < width; j++)
{
tr.append("<td></td>");
}
$('#pixelCanvas').append(tr);
}
}
event.preventDefault();
});

Related

Creating a table using JavaScript

I am new to front-end web development and right now I am working on a test task to create a table using javascript.Here is my html file:
<title>Pixel Art Maker!</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Monoton">
<link rel="stylesheet" href="styles.css"> </head> <body>
<h1>Lab: Pixel Art Maker</h1>
<h2>Choose Grid Size</h2>
<form id="sizePicker">
Grid Height:
<input type="number" id="inputHeight" name="height" min="1" value="1">
Grid Width:
<input type="number" id="inputWeight" name="width" min="1" value="1">
<input type="submit" onclick="makeGrid()">
</form>
<h2>Pick A Color</h2>
<input type="color" id="colorPicker">
<h2>Design Canvas</h2>
<table id="pixelCanvas"></table>
<script src="designs.js"></script> </body> </html>
And my javascript file:
function makeGrid() {
var rows=inputHeight; var cols=inputWeight; //Referencw for the body var body=document.getElementsbyTagName("body")[0];
//create a table element and a <tbody> element var table1=document.createElement("table"); var tableBody=document.createElement("tbody");
//creating cells for (var i=0;i<rows;i++){ //creating a table row var R=document.createElement("tr"); for(var j=0;j<cols;j++){ //create a table data element var C=document.createElement("td"); R.appendchild(C);
} //adding the row to the end of the table body
tableBody.appendChild(R); } //putting the <tbody> in the <table> table1.appendChild(tableBody); //appending <table> into <body> body.appendChild(table1);
}
I am supposed to get user input of rows and columns via submit button and generate a table according to that specification.So far my attmepts are unsuccessful,more precisely when I hit submit,nothing happens and the values revert back to "1".
I would really appreciate your guidance and feedback.
You don't need a <form>. There's nothing to submit to.
Use document.getElementById
You already have a <table id> in HTML. Reference it!
You don't need therefore a document.body reference.
To retrieve the integer use parseInt( number, radix ) since input value is a String
Clear your table from existing content before appending new stuff.
Use addEventListener(EventName, callback) instead of inline JavaScript (onclick)
Weight is not Width!
function makeGrid() {
var ELTable = document.getElementById("pixelCanvas"); // You already have it!
var ELInputHeight = document.getElementById("inputHeight");
var ELInputWidth = document.getElementById("inputWidth");
var rows = parseInt(ELInputHeight.value, 10);
var cols = parseInt(ELInputWidth.value, 10); // Weight? you mean Width!
ELTable.innerHTML = ""; // Empty table before inserting new stuff
var tbody = document.createElement("tbody");
for (var i = 0; i < rows; i++) { // N rows...
var R = document.createElement("tr"); // Make row.
for (var j = 0; j < cols; j++) { // N cells...
var C = document.createElement("td"); // Make cell.
R.appendChild(C); // Insert cell into row.
}
tbody.appendChild(R); // Insert row into tbody
}
ELTable.appendChild(tbody); // Insert tbody into table
}
document.getElementById("makeGrid").addEventListener("click", makeGrid);
td { padding:10px; background:#000; }
Height: <input type="number" id="inputHeight" min="1" value="1">
Width: <input type="number" id="inputWidth" min="1" value="1">
<button id="makeGrid">MAKE</button>
<br>
Color: <input type="color" id="colorPicker">
<table id="pixelCanvas"></table>
I create function for generate body of table, and listener for butto
function createTableBody(height, width) {
let tr = document.createElement('tr');
let td = document.createElement('td');
let docFr = new DocumentFragment();
for (let i = 0; i < width; i++) {
tr.append(td.cloneNode());
}
for (let i = 0; i < height; i++) {
docFr.append(tr.cloneNode(true));
}
return docFr;
}
let table = document.getElementById('pixelCanvas');
let createTableButton = document.getElementById('createTableButton');
let inputHeight = document.getElementById('inputHeight');
let inputWidth = document.getElementById('inputWeight');
createTableButton.addEventListener('click', () => {
let parentTable = table.parentNode;
let tableClone = table.cloneNode();
parentTable.replaceChild(tableClone, table);//clear old table
table = tableClone;
tableClone.append(createTableBody(inputHeight.value, inputWidth.value));
// if you need , you can add ajax request
console.log(table)
});
<title>Pixel Art Maker!</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Monoton">
<link rel="stylesheet" href="styles.css"> </head> <body>
<h1>Lab: Pixel Art Maker</h1>
<h2>Choose Grid Size</h2>
Grid Height:
<input type="number" id="inputHeight" name="height" min="1" value="1">
Grid Width:
<input type="number" id="inputWeight" name="width" min="1" value="1">
<input type="button" id="createTableButton">
<h2>Pick A Color</h2>
<input type="color" id="colorPicker">
<h2>Design Canvas</h2>
<table id="pixelCanvas"></table>
</body> </html>
If you need send data to server, you can use ajax, and i replace your submit to button, remove form.
Try this:
<form id="form-grid" method="post" onsubmit="makeGrid()">
<h2 id="grid-size">Choose Grid Size</h2>
<label for="inputHeight">Grid height:</label>
<input type="number" id="inputHeight" name="height" min="1" value="1" aria-describedby="grid-size" />
<label for="inputWeight">Grid width:</label>
<input type="number" id="inputWeight" name="width" min="1" value="1" aria-describedby="grid-size" />
<h2>Pick a color</h2>
<label for="colorPicker">Color:</label>
<input type="color" id="colorPicker" name="color" />
<input type="submit" value="Make Grid" />
</form>
<div id="pixelCanvas"></div>
Do note the addition of explicit label's here. These are important for accessibility!
I've added a submit handler to the form, and removed it from the button. I find it's a bit cleaner, but your approach would ultimately work too.
Then in your designs.js file, you might have:
function makeGrid(event) {
event.preventDefault(); // prevents the form from submitting
var form = document.querySelector('#form-grid');
var rows = form.querySelector('#inputHeight').value;
var cols = form.querySelector('#inputWeight').value;
var wrapper = document.querySelector('#pixelCanvas');
var table = document.createElement('table');
for (var r = 0; r < rows; r++) {
var tr = table.insertRow();
for (var c = 0; c < cols; c++) {
var td = tr.insertCell();
}
}
wrapper.appendChild(table);
}
A few reminders:
Use label to associate a form field with it's visible label. This is necessary for assistive technology such as screen readers.
Consider a fieldset to group all of the options, increasing its accessibility.
Good luck!
As #Katamari said, it looks like you're not properly accessing the elements and getting their values.
To access an element, you can use document.querySelector and pass in a CSS selector.
var rowInput = document.querySelector("#inputHeight");
var colInput = document.querySelector("#inputWidth");
Since you have assigned IDs, you could use document.getElementById
var rowInput = document.getElementById("inputHeight");
var colInput = document.getElementById("inputWidth");
Either way, you'll get an element or null if the element can't be found. Once you have the element, just get the value property to get the user results.
var rows = rowInput.value;
var cols = colInput.value;
If you want to avoid error that could be caused by not finding the element, you can check for the element before referencing the value.
var rows = 1;
var cols = 1;
if (rowInput) {
rows = rowInput.value;
}
if (colInput) {
cols = colInput.value;
}
This can be converted into a single line using a tenary operator
var rows = rowInput
? rowInput.value
: 1;
var cols = colInput
? colInput.value
: 1;

To use the data from input tag in html in javascript

I want to use the data from input tags in html. The html code is shown below.
<form id="sizePicker">
Grid Height:
<input type="number" id="input_height" name="height" min="1" value="1">
Grid Width:
<input type="number" id="input_width" name="width" min="1" value="1">
<input type="submit">
The data values from input tags should be used in javascript code shown below:
function makeGrid() {
for(let td_row=0; td_row < 6; td_row++){
$(<tr></tr>).appendTo(<table id="pixel_canvas"></table>);
for(let td_cell =0; td_cell < 6; td_cell++){
$(<td></td>).appendTo(<tr></tr>);
}
}
Can somebody please help me in this?
Try this solution. Get the values from the inputs and set them as the range for the conditions in the loops. Then add your create tr in the first loop, in the second one append td to it. After all append the tr with tds to the table.
const table = $('#pixel_canvas');
const inputHeight = $('#input_height');
const inputWidth = $('#input_width');
function makeGrid() {
const height = parseInt(inputHeight.val());
const width = parseInt(inputWidth.val());
for(let row = 0; row < height; row++) {
const tr = $('<tr></tr>');
for(let cell = 0; cell < width; cell++) {
tr.append(`<td>${row}${cell}</td>`);
}
table.append(tr);
}
}
$('#submitBtn').on('click', makeGrid);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="sizePicker">
Grid Height:
<input type="number" id="input_height" name="height" min="1" value="1">
Grid Width:
<input type="number" id="input_width" name="width" min="1" value="1">
<button id="submitBtn" type="button">Generate</button>
<table id="pixel_canvas">
</table>
You need to use strings, when creating HTML element (e.g. $('')) instead of raw markup. I updated the function from the question, so that it creates a table and returns it. You only need to insert it wherever you need.
function makeGrid() {
var rowsCount = ParseInt($('#input_height').val()) || 0;
var columnsCount = ParseInt($('#input_width).val()) || 0;
var table = $('<table id="pixel_canvas"></table>');
for(let td_row = 0; td_row < rowsCount; td_row++){
var tr = $('<tr></tr>').appendTo(table);
for(let td_cell = 0; td_cell < columnsCount; td_cell++){
$('<td></td>').appendTo(tr);
}
}
return table;
}

How to add rows dynamically in a html table

I want to add rows dynamically in a HTML table and the number of the column should be fixed. After adding rows I want to input some text values in each row and column. After entering the text values I want to store it in a database table. How to do that? Here is my code
function addRow() {
var root = document.getElementById('mytab').getElementsByTagName('tbody')[0];
var rows = root.getElementsByTagName('tr');
var clone = cloneEl(rows[rows.length - 1]);
root.appendChild(clone);
}
function addColumn() {
var rows = document.getElementById('mytab').getElementsByTagName('tr'), i = 0, r, c, clone;
while (r = rows[i++]) {
c = r.getElementsByTagName('td');
clone = cloneEl(c[c.length - 1]);
c[0].parentNode.appendChild(clone);
}
}
function cloneEl(el) {
var clo = el.cloneNode(true);
return clo;
}
#mytab td {
width: 100px;
height: 20px;
background: #cccccc;
}
<html>
<head>
<title>Untitled Document</title>
</head>
<body>
<form action="">
<input type="button" value="Add a Row" onclick="addRow()">
<input type="button" value="Add a Column" onclick="addColumn()">
</form>
<br>
<table id="mytab" border="1" cellspacing="0" cellpadding="0">
<tr>
<td><input type="text" name="enter1"></td>
<td><input type="text" name="enter2"></td>
</tr>
</table>
</body>
</html>
In this code, the problem is when I enter some text and after that, I add rows or column the same text appears in the newly added rows and column. But I want to enter different text in different boxes and I want the no of the column should be fixed to say no of the column should be 5.
Updated
Hi, you have to clear input values after cloning elements, as below. cleanUpInputs(clone); will check cloned DOM and will remove input values. Check the code below.
function addRow() {
var root = document.getElementById('mytab').getElementsByTagName('tbody')[0];
var rows = root.getElementsByTagName('tr');
var clone = cloneEl(rows[rows.length - 1]);
cleanUpInputs(clone);
root.appendChild(clone);
}
function addColumn() {
var rows = document.getElementById('mytab').getElementsByTagName('tr'), i = 0, r, c, clone;
while (r = rows[i++]) {
c = r.getElementsByTagName('td');
clone = cloneEl(c[c.length - 1]);
cleanUpInputs(clone);
c[0].parentNode.appendChild(clone);
}
}
function cloneEl(el) {
var clo = el.cloneNode(true);
return clo;
}
function cleanUpInputs(obj) {
for (var i = 0; n = obj.childNodes[i]; ++i) {
if (n.childNodes && n.tagName != 'INPUT') {
cleanUpInputs(n);
} else if (n.tagName == 'INPUT' && n.type == 'text') {
n.value = '';
}
}
}
#mytab td {
width: 100px;
height: 20px;
background: #cccccc;
}
<html>
<head>
<title>Untitled Document</title>
</head>
<body>
<form action="">
<input type="button" value="Add a Row" onclick="addRow()">
<input type="button" value="Add a Column" onclick="addColumn()">
</form>
<br>
<table id="mytab" border="1" cellspacing="0" cellpadding="0">
<tr>
<td><input type="text" name="enter1"></td>
<td><input type="text" name="enter2"></td>
</tr>
</table>
</body>
</html>

how to change the div width according to a variable

I have a table which is editable. I want to change the div width when the td content changes. I think my jQuery code is not working. How can I solve this problem?
var form = document.getElementById('form');
number = document.getElementById('number');
form.onchange = function() {
var variable = number.value;
var unit = "px";
var z = variable + unit;
$("#check").css("width", z);
};
#check {
background-color: red;
height: 15px;
width: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<td>
<form id="form">
<input id="number" type="number" min="1" name="number">
</form>
<div id="check"></div>
</td>
</tr>
</table>
You can use jquery with keyup and change
var form = document.getElementById('form');
number = document.getElementById('number');
$("#number").on("keyup change",function() {
var variable = number.value;
var unit = "px";
var z = variable + unit;
$("#check").css("width", z);
});
#check {
background-color: red;
height: 15px;
width: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<td>
<form id="form">
<input id="number" type="number" min="1" name="number">
</form>
<div id="check"></div>
</td>
</tr>
</table>

Looping through multiple divs and pulling each input value from each

I have created an html page the will dynamically add or remove inputs, all within a parent div, each having their own div to determine each seperatly. I have the logic to loop through and find these child divs, however I cannot seem to figure out how to grab the inputs from each div, only the first child div even though I am looping through all children.
Any idea how?
html:
<div id="volumeRateDiv">
<div id="volumeRateDivNew_0" class="volumeRateDivChild">
<input id="kc_start" type="number" name="kc_start" maxlength="9" step="1" min="0" placeholder="0">
<input id="volume_rate" type="number" name="volume_rate" maxlength="12" step=".0001" min="0" placeholder="0.0000">
<input id="delete_VolumeRate" type="button" name="delete_VolumeRate" value="Delete" onclick="removeItem('volumeRateDivNew_0')">
</div>
<div id="volumeRateDivNew_1" class="volumeRateDivChild">
<input id="kc_start" type="number" name="kc_start" maxlength="9" step="1" min="0" placeholder="0">
<input id="volume_rate" type="number" name="volume_rate" maxlength="12" step=".0001" min="0" placeholder="0.0000">
<input id="delete_VolumeRate" type="button" name="delete_VolumeRate" value="Delete" onclick="removeItem('volumeRateDivNew_1')">
</div>
</div>
Javascript:
var divs = document.getElementsByClassName("volumeRateDivChild");
for(var i = 0; i < divs.length; i++)
{
var div = divs[i];
alert (div.className+" - "+div.id+" - "+document.getElementById("kc_start").value );
}
You could add the same index number (0, 1, etc) to the end of the inputs' IDs, and then use that in the for loop, eg:
for(var i = 0; i < divs.length; i++)
{
var div = divs[i];
alert (div.className+" - "+div.id+" - "+document.getElementById("kc_start_" + i).value );
}
The first comment in your answer is correct all id's should be unique.
If you can be certain that the input you want to extract the value of is always the first child then you could do the same as this jsfiddle
<div id="volumeRateDiv">
<div id="volumeRateDivNew_0" class="volumeRateDivChild">
<input id="kc_start" type="number" name="kc_start" maxlength="9" step="1" min="0" placeholder="0" value="0"/>
<input id="volume_rate" type="number" name="volume_rate" maxlength="12" step=".0001" min="0" placeholder="0.0000"/>
<input id="delete_VolumeRate" type="button" name="delete_VolumeRate" value="Delete" onclick="removeItem('volumeRateDivNew_0')"/>
</div>
<div id="volumeRateDivNew_1" class="volumeRateDivChild">
<input id="kc_start" type="number" name="kc_start" maxlength="9" step="1" min="0" placeholder="0" value="0"/>
<input id="volume_rate" type="number" name="volume_rate" maxlength="12" step=".0001" min="0" placeholder="0.0000"/>
<input id="delete_VolumeRate" type="button" name="delete_VolumeRate" value="Delete" onclick="removeItem('volumeRateDivNew_1')"/>
</div>
</div>
var divs = document.getElementsByClassName("volumeRateDivChild");
for(var i = 0; i < divs.length; i++)
{
var div = divs[i];
alert (div.className+" - "+div.id+" - "+div.children[0].value );
}
First of all, as #tymeJV already had mentioned, ids of HTML elements must be unique. So you need remove them or make them unique, if you plan to use them anywhere else (not in this case).
To locate elements inside your divs you could use classes or names. You can call getElementsByClassName or getElementsByName not only on document, but on any DOM-element. It could look like this:
var divs = document.getElementsByClassName("volumeRateDivChild");
for(var i = 0; i < divs.length; i++)
{
var div = divs[i];
alert(div.className+" - "+div.id+" - "+div.getElementsByName("kc_start")[0].value );
}
Do it this way
var divs = document.getElementsByClassName("volumeRateDivChild");
for(var i = 0; i < divs.length; i++)
{
var div = divs[i];
alert (div.className+" - "+div.id+" - "+div.children["kc_start"].value );
}
Demo: Demo

Categories

Resources