I am taking user input from a form and trying to create a table from that input. The input should determine the number of rows and columns. I have tried the following but I am getting nothing. I am a bit stumped. Any help appreciated.
JS
function makeChart(){
var table = document.createElement("table");
var taskName = document.getElementById("taskname").value + "</br>";
var numDays = document.getElementById("days").value + "</br>";
var howOften = document.getElementById("times").value + "</br>";
var rows=table.insertRow(howOften);
var cols=rows.insertCell(numDays);
document.getElementById("holdTable").appendChild(table);
table.appendChild(rows);
table.appendChild(cols);
}
HTML
<div id="holdTable">
<form id="chartInput">
<label for="taskname">Task</label>
<input id="taskname" type="text" placeholder="Enter the task name here"> <br>
<label for="days">How many days</label>
<input id="days" name="days" type="number" min="1" max="7"> <br>
<label for="times">How many times a day</label>
<input id="times" name="times" type="number" min="1" max="4"> <br>
<input id="createChart" type="button" value="Make the chart" onClick="makeChart();"> <br>
</form>
</div>
I think you need to use loop.
for(var i = 1;i<=howOften;i++)
{
var row = table.insertRow(-1)
for(var i = 1;i<=numDays;i++)
{
row.insertCell(-1)
}
table.appendChild(row);//edited
}
Try using this in place of this 2 lines:
var rows=table.insertRow(howOften);
var cols=rows.insertCell(numDays);
EXPLANATION
insertRow function inserts new table row(<tr>) in at index position specified in brackets. It inserts only one row. So if index is 0 <tr> will be appended to the beggining of the table as a first row. Similarly -1 appends <tr> as the last row in the table.
insertCell function inserts cell(<td>) in at index position of the row(<tr>). Same as above -1 means it adds new cell at the last position in the row.
Each row than has to be appended to the table or stored in an array for later use therefore I added table.appendChild(row); which adds each consecutive row to the array.
table.insertRow and tableRow.insertCell take, as their parameters, the index at which you wish to do the insertion. You are, instead, passing a string which contains your field values appended to an HTML BR tag (a malformed one at that).
Furthermore, to add text to an element you need to create text nodes with document.createTextNode and append those nodes to the element in question.
Finally, cols should be a child of rows, not of table. So your line, table.appendChild(cols) is in error as well.
Beyond those comments, I cannot go further. I am not sure what exactly you're looking for in the outputted table structure. It seems to me you are wanting one row with two columns, but Dharman's answer shows that he reads it as you wanting multiple rows. Consider updating your question with some markup showing the desired table.
Edit: Using your comment for more information, I wrote the following code demo for you to try: http://jsfiddle.net/Kkb7n/ . For the sake of demonstration, I have it use the "task name" as the text content of the created cells.
Modified JS in case JSFiddle is down:
var makeChart = function () {
var table = document.createElement('table'),
taskName = document.getElementById('taskname').value,
numDays = document.getElementById('days').value, //columns
howOften = document.getElementById('times').value, //rows
row,
r,
col,
c;
for (r = 0; r < howOften; r++) {
row = table.insertRow(-1);
for (c = 0; c < numDays; c++) {
col = row.insertCell(-1);
col.appendChild(document.createTextNode(taskName));
}
}
document.getElementById('holdTable').appendChild(table);
};
Related
I have a simple method for adding input boxes after a button is clicked. The goal of this method is to generate a set of input boxes with a newline inserted after each div.
In the screenshot above you can see that the divs are spaced properly. However, when the add_more button is clicked the generated inputs do not come out properly.
Expected:
The code should generate new input boxes like so:
<div>
Key Term 2: <input id="el2" type="text" value=""> <br>
</div>
<br>
Actual:
function add_more() {
// we've added more inputs.
addMore = true;
// set html generated to false, because new inputs have been added.
htmlGenerated = false;
// increment the number of inputs.
numberOfInputs++;
//fetch the input boxes.
inputs = document.getElementById("inputBoxes");
// create newline
br_key = document.createElement("br");
// create newline
br_description = document.createElement("br");
//create a new row for a key term.
row = document.createElement("div");
// set the key term text.
row.innerHTML = "Key Term ";
row.innerHTML += numberOfInputs;
row.innerHTML += " :";
// create the input for the key.
key = document.createElement("input");
key.setAttribute("id", "el" + numberOfInputs);
//add the key to the row.
row.appendChild(key);
row.after(br_key);
//create a row for the new description.
row2 = document.createElement("div");
// set the description text.
row2.innerHTML = "Description "
row2.innerHTML += numberOfInputs;
row2.innerHTML += " :";
// create the description input
description = document.createElement("input");
description.setAttribute("id", "dl" + numberOfInputs);
// add the description to the row.
row2.appendChild(description);
row2.after(br_description);
// add the rows for the key and the description to the inputBoxes.
inputs.appendChild(row);
inputs.appendChild(row2);
}
<div>Key Term 5 :<input id="el5"></div>
Any help figuring out this issue would be greatly appreciated. Thanks.
Your issue here is essentially incorrect HTML, CSS. I'd implement your inputs, etc. like this:
.full-width-label {
display:block;
}
<label class="full-width-label" for="1">Label</label>
<input type="text" id="1"/>
There are multiple ways to achieve the above, this is just one of your options but now you no longer need to embed the look into the HTML and the format of your HTML (line breaks) is independent of your look.
You might want to look into an off the shelf solution for these kinds of things, like Bootstrap or Tailwind
You can use make it in a simple way
HTML
add this jquery cdn
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">
</script>
<button type="button">Click Here</button>
<div class="appendDiv">
</div>
Js
$(document).ready(function (){
var button = document.getElementsByTagName('button');
var appendDiv = document.getElementsByClassName('appendDiv');
var key = 1;
var descKey = 1;
$('button').click(function(event){
event.preventDefault();
$(appendDiv).append('<div class="child"><div class="grand-child"><label>Key Form :'+ ' '+(++key)+'</label><input type="text" value=""/></div><div class="grand-child"></div><label>Description :'+ ' '+(++descKey )+'</label><input type="text" value=""/></div>');
})
})
Here is my code:
<body>
<div id="metric_results">
<div id="form">
<form name="myForm" >
...//get course IDnumber and course score
</form>
</div>
<div id="table">
<table id="TABLE" border = '1'>
</table>
</div>
<script type="text/javascript">
//when click on "add" button,call "addTable" function.
document.getElementById("add_button").onclick = function() {addTable()};
document.getElementById("delete_button").onclick = function() {DeleteTableRow()};
var stock = new Array();
var i = 0;
function addTable() { //create table with 3 column(idnumber,score,checkbox)
var c = document.createElement("INPUT");
c.setAttribute("type", "checkbox");
stock[i] = new Array(id, score);//id= course ID number,score=course score, get from form
//Create table row and append it to end of table
var tr = document.createElement('TR');
for (j = 0; j < 3; j++) {
var td = document.createElement('TD');
if(j == 2){
td.setAttribute("id","check_box"+(i+1));
td.appendChild(c);}
else{
td.appendChild(document.createTextNode(stock[i][j]));}
tr.appendChild(td);
}
table.appendChild(tr);
i=i+1
}
// Delete courses that their checkbox is on.
function DeleteTableRow(){
var check_boxes=new Array();
for(j=0; j<i ;j++){
check_boxes[j]= document.getElementById("check_box"+(j+1));
if(check_boxes[j].checked==true){document.getElementById("TABLE").deleteRow(j+1);}
}
</script>
</body>
I create a form which get course idnumber and course score.At first, when I fill the form, javascript creates a table so when I click the "add" button, I can add courses. Now, I want to add another function named DeleteTableRow() to delete the selected rows.
When I create the table for each course,I create a checkbox column and set "id" for each rows checkbox(td.setAttribute("id","check_box"+(i+1));) so in the DeleteTableRow() function I use getElementById("check_box"+(j+1)) in the for loop.
Everything is OK but I can't check the value of the check box and I can't delete the selected rows. what should I do and how do I check it?
Your main problem is that in your addTable function you set the id attribute on the table cell, rather than the checkbox. Naturally, cells don't have a checked attribute. You could fix this by doing the setAttribute('id', ...) on c, before the loop.
Note there are a few strange things about your code - for example, you should really use the literal [] when defining a new array, rather than the new Array() call; but having said that there doesn't seem to be any need for the check_boxes array in the first place, since you never use it.
In any case, your code would be a lot simpler if you used something like jQuery, which is pretty much the default for doing DOM manipulation in Javascript these days.
I have a table of items available for purchases which I am displaying on the site. I am using mysql to fetch all the items and display them in a table. Among others, the table contains this:
<input type="hidden" name="price" id="price'.$id.'"> //id is one part of MySQL query results
<input type="text" name="count_'.$id.'">
All this is displayed for around 200 items with ID being not completely in sequence (I found some JavaScript code that used for (i = 0; i < rows.length; i++) {}, however, with my IDs not being in a sequence, this is not a good option for me).
I would like to display a total of an order using JavaScript and I am not experienced when it comes to JS. I would be very thankful for your advices.
You coul duse jQuery:
function orderTotal()
{
var total=0;
$('input[name="price"]').each(function(){
var price = parseFloat($(this).val());
var amount = parseFloat($('input[name="count_'+$(this).attr('name').substring(5)+'"]').val());
total += price+amount;
});
return total;
}
Consider adding a class to each element that you want to count and see the answer below on stackoverflow. You should be able to have a counter for each occurrence of the class and show this variable in the html
How to getElementByClass instead of GetElementById with Javascript?
<div class="item"> ... <your inputs> ... </div>
I suggest you wrap them in another element, lets use div. Add a class to that, lets say moneyline
<div class="moneyline">
<input class="price" type="hidden" name="price" id="price'.$id.'"> //id is one part of MySQL query results
<input class="quantity" type="text" name="count_'.$id.'">
</div>
Im going to give the example with jQuery, and some button to trigger it:
$('#someButton').on('click', function(){
var total = 0;
$('.moneyline').each(function(){
var price = parseInt($(this).find('.price'), 10);
var quantity = parseInt($(this).find('.quantity'), 10);
total+= quantity*price;
});
alert( total );
});
Here is what I have so far: http://jsfiddle.net/JEAkX/1/
I am trying to get the appended cells to come after the last tr. Furthermore, I am attempting to change the appendTable(id) function so that the output cells have their content inside an <input> field like the original cells.
For the <input> addition I have tried:
Adding the input field code <input type='text' size='1' value='subset[i++]' /> at various point with no luck I also tried it in another location but changed the value to value='c'.
For append after last tr I have tried:
Using jQuery and .insertAfter('#alphabetTable tbody>tr:last') I added it to various parts of the cell.appendChild(document.createTextNode(subset[i++])); line but had no luck..probably the wrong placement?
I feel like I am sort of on the right track but lack the Javascript knowledge to know exactly where to insert the code and if surrounding code needs change.
It'll be easier with JQuery but here's a hint:
function appendTable(id)
{
var tbody = document.getElementById(id).getElementsByTagName("tbody")[0];
var i = 0;
var html = '<tr>';
for(i=0;i<4;i++){
html += '<td><input type="text" size="1"/></td>';
}
html += '</tr>';
tbody.innerHTML += html;
}
Jquery:
var $tbody = $('#mytableid tbody:eq(0)');
var $tdLen = $('#mytableid tbody:eq(0) tr:eq(0) td').length; // cell length in row
$("<tr>").appendTo($tbody);
//append cells to row with input text
for (var i=0;i<$tdLen;i++){
var inp = $("<input>").attr("type","text").attr("name","text"+i).val(i);
var tdTemo = $("<td>");
inp.appendTo(tdTemo);
tdTemo.appendTo("tr:last");
}
this script will append row to table and add 4cells contain input type text :)
So the short version of this is: Can I traverse only the elements within the matched element of the selectors before the each()? Or is there a simpler way of getting what I want without an each() loop?
I thought this would be much easier, which makes me think I'm just missing some fundamental principle of element traversing with jquery.
So here's the scenario:
I have a table (and it is appropriate in this case), where each cell has a text input. The last input is read-only and is supposed to be the total sum of the other values entered on that row. I have a really messy js script for finding both the totals of each row and then the grand total of each row total.
Here's the basic HTML:
<table>
<thead>
<tr><th>Col 1</th><th>Col 2</th><th>Col 3</th><th>Total</th></tr>
</thead>
<tbody>
<tr id="row1"><td><input type="text" /></td><td><input type="text" /></td><td><input type="text" /></td><td class="total"><input type="text" readonly="readonly" /></td></tr>
<tr id="row2"><td><input type="text" /></td><td><input type="text" /></td><td><input type="text" /></td><td class="total"><input type="text" readonly="readonly" /></td></tr>
<tr id="row3"><td><input type="text" /></td><td><input type="text" /></td><td><input type="text" /></td><td class="total"><input type="text" readonly="readonly" /></td></tr>
</tbody>
</table>
The javascript will validate that the data entered is numerical, just to be clear.
So I have a event listener for each input for onchange that updates the total when the user enters data and moves to the next cell/input. Then I have a function called updateTotal that currently uses for loops to loop through each row and within that loop, each cell, and finally sets the input in the total cell to sum.
Quick note: I have included the code below to show that I'm not just looking for a hand out and to demonstrate the basic logic of what I have in mind. Please feel free to skim or skip this part. It works and doesn't need any debugging or critique.
This is what that looks like:
function updateTotal() {
table = document.getElementsByTagName("tbody")[0];
allrows = table.getElementsByTagName("tr");
grandtotal = document.getElementById("grand");
grandtotal.value = "";
for (i = 0; i < allrows.length; i++) {
row_cells = allrows[i].getElementsByTagName("input");
row_total = allrows[i].getElementsByTagName("input")[allrows.length - 2];
row_total.value = "";
for (ii = 0; ii < row_cells.length - 1; ii++) {
row_total.value = Number(row_total.value) + Number(row_cells[i][ii].value);
grandtotal.value = Number(grandtotal.value) + Number(row_cells[i][ii].value);
}
}
}
Now I am trying to re-write the above with jquery syntax, but I'm getting stuck. I thought the best way to go would be to use each() loops along the lines of:
function findTotals() {
$("tbody tr").each(function() {
row_total = 0;
$($(this) + " td:not(.total) input:text").each(function() {
row_total += Number($(this).val());
});
$($(this) + " .total :input:text").val(row_total);
});
}
But using $(this) doesn't seem to work in the way I thought. I read up and saw that the use of $(this) in an each loop points to each matched element, which is what I expected, but I don't get how I can traverse through that element in the each() function. The above also leaves out the grand_total bit, because I was having even less luck with getting the grand total variable to work. I tried the following just to get the row_totals:
$($(this).attr("id") + " td:not(.total) input:text").each(function() {
with some success, but then managed to break it when I tried adding on to it. I wouldn't think I'd need each row to have an id to make this work, since the each part should point to the row I have in mind.
So the short version of this is: Can I use the each loop to traverse only the elements within the matches, and if so, what is the correct syntax? Or is there a simpler way of getting what I want without an each loop?
Oh, one last thought...
Is it possible to get the numerical sum (as opposed to one long string) of all matched elements with jquery? I'll research this more myself, but if anyone knows, it would make some of this much easier.
You are trying to set your context incorrectly try this:
function findTotals() {
$("tbody tr").each(function() {
row_total = 0;
$("td:not(.total) input:text",this).each(function() {
row_total += Number($(this).val());
});
$(".total :input:text",this).val(row_total);
});
}
For more information about the context check out the jquery docs: http://docs.jquery.com/Core/jQuery#expressioncontext
There can be two parameters for a selector. The second parameter is the context htat that the search is to take place in. Try something like the following:
$('#tableID tbody tr).each(function(){
//now this is a table row, so just search for all textboxes in that row, possibly with a css class called sum or by some other attribute
$('input[type=text]',this).each(function(){
//selects all textbosxes in the row. $(this).val() gets value of textbox, etc.
});
//now outside this function you would have the total
//add it to a hidden field or global variable to get row totals, etc.
});