Need help w/ JavaScript and creating an html table from array - javascript

I've tried everything I can find via google and nothing has worked correctly. Output is just a single row with all the contents of the array listed. What I need is a way to write the contents of an array but after 3 cells, automatically start a new line. I'll post the code I've made below as well as the question. (yes this is from an assignment. :( )
//***(8) place the words in the string "tx_val" in a table with a one pixel border,
//*** with a gray backgound. Use only three cells per row. Empty cells should contain
//*** the word "null". Show the table in the span block with id="ans8"
var count = i % 3;
var nrow = "";
var out = "<table border='1' bgcolor='gray'><tr>"
for (var i=0; i<txArr.length; i++)
{
out += ("<td>" + txArr[i] + "</td>");
count++;
if (count % 3 == 0)
{
nrow += "</tr><tr>";
}
}
document.getElementById('ans8').innerHTML = out + nrow;

you need to print the tr's inside the table (annd add a </table>!):
var count = i % 3; // btw. what's this??
var nrow = "";
var out = "<table border='1' bgcolor='gray'><tr>"
for (var i=0; i<txArr.length; i++)
{
out += "<td>" + txArr[i] + "</td>";
count++;
if (count % 3 == 0)
out += "</tr><tr>";
}
out += "</table>";
document.getElementById('ans8').innerHTML = out;

Rather than try to write out the html, try manipulating the dom. It seems much more straightforward to me. Take a look at the following:
var row = table.insertRow();
msdn
mdc
var cell = row.insertCell();
msdn
mdc
var cellContent = document.createTextNode(txArr[i]);
msdn
mdc
cell.appendChild(cellContent);
msdn
mdc
For deciding when to start a new row, just use the modulus operator (%
msdn
mdc
) against i:
if (i % 3 == 0)
{
row = table.insertRow()
}
You'd end up with something like this:
var container = document.getElementById("ans8");
var t = container.appendChild(document.createElement("table"));
var row;
txArr.forEach(function (item, i)
{
if (i % 3 == 0)
{
row = t.insertRow()
}
row.insertCell().appendChild(document.createTextNode(item));
});
I'll leave a little for you to figure out - border, background color, getting the word "null" in there. It is your homework after all. :-)
Also, for older browsers you'll need to add Array.forEach in yourself.

I prefer using an array over concatination
var html = [];
html.push("<table><tr>");
var i = 0;
for (var k in txArr)
{
if(i>=3){
i=0;
html.push("</tr><tr>");
}
html.push("<td>" + txArr[k] + "</td>");
i++;
}
html.push("</tr></table>");
document.getElementById('ans8').innerHTML = html.join('');
// wrapped in function
function arrayToTable(a,cols){
var html = [];
html.push("<table><tr>");
var i = 0;
for (var k in a)
{
if(i>=cols){
i=0;
html.push("</tr><tr>");
}
html.push("<td>" + a[k] + "</td>");
i++;
}
html.push("</tr></table>");
return html.join('')
}
document.getElementById('ans8').innerHTML = arrayToTable(txArr, 3);

It might be a tad easier to accomplish with something like
buffer = "<table>";
for(var r = 0; r < 10; r++){
buffer += "<tr>";
for(var c = 0; c < 3 ; c++){
buffer += "<td>Cell: " + r + ":" + c + "</td>";
}
buffer += "</tr>";
}
buffer += "</table>";
document.getElementById("ans8").innerHTML = buffer;
That would create a table 30 rows long by 3 columns for each row.

you might be assigning values to "count" too early as you don't know what i is yet. and you are not spitting out the value of nrow anywhere... change it to out.
var count;
var nrow = "";
var out = "<table border='1' bgcolor='gray'><tr>"
for (var i=0; i<txArr.length; i++)
{
out += ("<td>" + txArr[i] + "</td>");
count++;
if (count % 3 == 0)
{
out += "</tr><tr>";
}
}
document.getElementById('ans8').innerHTML = out + nrow;

Basically I would split it up into 3 functions, for readability and maintenance. These functions would consist of creating a cell, a row, and a table. This definitely simplifies reading the code. As I have not tested it, below is an example of what I would do.
function createTableCell(value) {
return value == null? "<td>NULL</td>":"<td>" + value + "</td>";
}
function createTableRow(array) {
var returnValue = "";
for (var i = 0; i < array.length; i++) {
returnValue = returnValue + createTableCell(array[i]);
}
return "<tr>" + returnValue + "</tr>";
}
function arrayToTable(array, newRowAfterNArrayElements) {
var returnValue = "<table>";
for (var i = 0; i < array.length; i = i + newRowAfterNArrayElements) {
returnValue = returnValue + createTableRow(array.split(i, (i + newRowAfterNArrayElements) - 1));
}
return returnValue + "</table>";
}
document.getElementById("ans8").innerHTML = arrayToTable(txArr, 3);
In addition this makes your code much more dynamic and reusable. Suppose you have an array you want to split at every 4 element. Instead of hardcoding that you can simply pass a different argument.

Here's a live example of doing this with DOMBuilder, and of using the same code to generate DOM Elements and an HTML String.
http://jsfiddle.net/insin/hntxW/
Code:
var dom = DOMBuilder.elementFunctions;
function arrayToTable(a, cols) {
var rows = [];
for (var i = 0, l = a.length; i < l; i += cols) {
rows.push(a.slice(i, i + cols));
}
return dom.TABLE({border: 1, bgcolor: 'gray'},
dom.TBODY(
dom.TR.map(rows, function(cells) {
return dom.TD.map(cells);
})
)
);
}
var data = [1, 2, null, 3, null, 4, null, 5, 6];
document.body.appendChild(arrayToTable(data, 3));
document.body.appendChild(
dom.TEXTAREA({cols: 60, rows: 6},
DOMBuilder.withMode("HTML", function() {
return ""+arrayToTable(data, 3);
})
)
);

Yes, you can build from scratch...but there's a faster way. Throw a grid at it. The grid will take data in a string, array, json output, etc and turn it into a proper HTML outputted table and will allow you to extend it with sorting, paging, filtering, etc.
My personal favorite is DataTables, but there are numerous others out there.
Once you get proficient, setting one of these up literally takes 5 minutes. Save your brain power to cure world hunger, code the next facebook, etc....

Related

ID to many elements elements

I have maybe weird question, but it is very important to me to solve this.
I have table wich is not with stable amount of rows and columns, so i put the += operator to create cells, rows and etc. Now i need to identify every cell, but i don't understand how i can do it in this situation.
function drawBoard(board) {
var t="";
t="<table border: 2px >";
var x,y;
for(x=0; x<board.length; x++){
t+="<tr>";
for(y=0; y<board.length; y++){
t+="<td class='tablecell' onclick=''>X</td>"
}
t+="</tr>";
}
t+="</table>";
}
By identify a cell I'm assuming you would like to reference them later in different part of the code.
You could achieve it by giving your rows and cells classes and/or ids.
For a row, for example:
t += '<tr id="tr-' + x + '">';
for a cell
t += '<td class="tablecell tr-' + x + ' col-' + y + '" onclick="" id="td-' + x + '-' + y + '">X</td>'
Then rows can be referenced by #tr-x and cells #tr-x > td, and all specific columnd .col-y
As Matheus Avellar mentioned, added id to a cell as well in case you want to reference a particular cell on a grid using #td-x-y
You are able to use:
const cells = document.getElementsByClassName('tablecell')
Or you can collect every cell on the stage of creation, for example:
const cells = [];
for (let i = 0; i < board.length){
for (let j = 0; j < board.length){
const cell = document.createElement('td');
cells.push(cell);
}
}
You can set the id of each one equal to your 'y' variable.
Something like:
function drawBoard(board) {
var t = "";
t = "<table border: 2px >";
var x, y;
for (x = 0; x < board.length; x++) {
t += "<tr>";
for (y = 0; y < board.length; y++) {
t += `<td id="table-${y}" class='tablecell' onclick=''>X</td>`
}
t += "</tr>";
}
t += "</table>";
}
Using a bit of ES6 template literals, you can set tie your ID to your 'Y' variable since it's an incrementing number.

Printing a formatted multiplication table to the console

my current code currently prints a table to the console, but I want the table to be formatted so every column and row are aligned perfectly. I can do that using an HTML table, but I would prefer just printing in the console.
console.log(multiplicationTable(12));
function multiplicationTable(max)
{
var i,j;
for( i = 1; i<=max ; i++)
{
for( j = 1; j<=max; j++)
{
document.write( i*j + " " );
}
document.write("<br>");
}
}
Thanks a lot!
How about using the "console.table(~~)" ?
The trick is to use another string contain spaces to join your string.
You can have a look at this: Here
Short answer:
var str = ""; //your string
var pad = "0000"; //the buffer string
var ans = pad.substring(0, pad.length - str.length) + str //get the length of your buffer and minus your string to get the remaining '0'.
Here is a formatted table inside your console:
console.log(multiplicationTable(12));
function multiplicationTable(max) {
var i, j;
document.write("<table border='1'>");
for (i = 1; i <= max; i++) {
document.write("<tr>");
for (j = 1; j <= max; j++) {
document.write("<td>" + i * j + "</td>");
}
document.write("</tr>");
}
document.write("</table>");
}

why this code didn't work correctly?

I have the following problem to resolve, I don't understand why my code doesn't work correctly.
Write a JavaScript function that takes as input an array of two numbers (start and end) and prints at the console a HTML table of 3 columns.
Column 1 should hold a number num, changing from start to end.
Column 2 should hold num*num.
Columns 3 should hold "yes" if num is Fibonacci number or "no" otherwise.
The table should have header cells titled "Num", "Square" and "Fib". See the below examples.
Input
The input data comes as array of two numbers: start and end. The input data will always be valid and in the format described. There is no need to check it explicitly.
Output
Print at the console the above described table in the same format like the examples below. Don't add additional spaces. Whitespace and character casing are important, so please use the same as in the below examples.
Constraints
• The input is passed to the first JavaScript function found in your code as array of 2 elements.
• The numbers start and end are positive integers in the range [1…1 000 000] and start ≤ end.
• Allowed working time for your program: 0.2 seconds.
• Allowed memory: 16 MB.
This code is not the same by the requirement of problem, but the idea is the same I guess.
Here is my code:
var fib = [];
var a, b, result;
a = 0;
b = 1;
result = b;
for (var i = 1; i < 31; i++) {
result = a + b;
a = b;
b = result;
fib.push(result);
}
console.log("<table>");
console.log("<tr><th>Num</th><th>Square</th><th>Fib</th></tr>");
var start = 2;
var end = 6;
function isFib(start, end) {
for (i = start; i < end; i++) {
fib.forEach(function (element) {
if (i === element) {
return "yes";
}
else
{
return "no";
}
});
}
}
function buildTable() {
for(var j = start; j < end; j++) {
console.log("<tr><td>" + j + "</td><td>" + j * j + "</td><td>" + isFib(start, end) + "</td></tr>");
}
}
buildTable(start, end);
This code is not the same by the requirement of problem, but the idea is same i guess.
This kind of feels like I am doing one of your homework assignments but here you go.
var a = [1,25];
function fib(n){
return n<2?n:fib(n-1)+fib(n-2);
}
function isFib(n){
var tryNum = 0;
do {
var fibNum = fib(tryNum++);
} while (fibNum < n);
return (fibNum==n);
}
function printTable(a){
var table = "<table><thead><tr><td>Num</td><td>Square</td><td>Fib</td></tr></thead>";
for(var i=a[0]; i<=a[1]; i++){
table += "<tr>";
table += "<td>"+i+"</td>";
table += "<td>"+(i*i)+"</td>";
table += "<td>"+((isFib(i))?"yes":"no")+"</td>";
table += "</tr>";
}
table += "</table>";
return table;
}
document.write( printTable(a) );
table td {
border: 1px solid black;
}
thead {
background: #eee;
}
Here is an improved isFib function that stores the old values so its faster. It still takes about 1 second to calculate all fibs from 1 to 1,000,000 but its way faster than before. If you try to print the table with 1,000,000 records in it to the DOM you will likely crash your browser so dont even bother trying.
var fibs = [1, 2];
function isFib(n) {
if (fibs[fibs.length - 1] < n) { // not calculated to n yet
do {
fibs.push(fibs[fibs.length - 1] + fibs[fibs.length - 2]); // get next fib
} while (fibs[fibs.length - 1] < n); // do until found to (or above) n
}
return (fibs.indexOf(n) > -1); // Is n in the list of fibs?
}
Last time i optimized it for speed and got a dramatic speed increase (still not fast enough for your requirements). This attempt optimizes for memory because it only ever stores the last two fibs, but is just as fast, runs in about 1 second.
function printTable(a){
var previousFib = 1;
var currentFib = 2;
function nextFib(){
var temp = currentFib;
currentFib += previousFib;
previousFib = temp;
}
var table = "<table><thead><tr><td>Num</td><td>Square</td><td>Fib</td></tr></thead>";
for(var i=a[0]; i<a[1]; i++){
table += "<tr>";
table += "<td>"+i+"</td>";
table += "<td>"+(i*i)+"</td>";
table += "<td>";
if(i==0||i==1) table += "yes";
else {
while (currentFib < i){
nextFib();
console.log(currentFib);
}
table += (currentFib==i)?"yes":"no";
}
table += "</td>";
table += "</tr>";
}
table += "</table>";
return table;
}

Trying to pass by value in Javascript multi-dim array

So, I'm building a web site that you can play othello on as a code sample. I've got a multidimensional array as the behind-the-scenes gameboard, and then iterate through every 'td' in a table to match the value of the corresponding array member. The problem i'm encountering is that iterating through the table. and using the iterators as essentially coordinates to my array doesn't work. As the iterator increases in value, so too does the coordinates in each of my 'td's. I'm stumped, and running on fumes. Any help would be appreciated.
function gridArray() {
// creates game board's array.
for (var i = 0; i < gameArray.length; i++) {
gameArray[i] = new Array(8);
}
for (var row = 0; row < gameArray.length; row++) {
for (var col = 0; col < gameArray[row].length; col++) {
gameArray[row][col] = "green";
}
}
}
function drawGrid(){
// writes table to HTML document
var htmlString = "<table id='othelloGrid'><tr>";
for (var i = 0; i < 8; i++) {
htmlString += "<th>" + i + "</th>";
}
htmlString += "</tr>";
for (var j = 0; j < 8; j++) {
htmlString += "<tr>";
xPos = j;
for (var x = 0; x < 8; x++) {
yPos = x;
// HERE!!! I now realize javascript passes by reference, so as this loop iterates,
// every single 'td' is getting 'onclick = 'changeClass(7, 7)''.
// for my game grid to work, I need each td to have a unique xPos, yPos to
// connect back to gameArray.
htmlString += "<td onclick = 'changeClass(xPos, yPos)'></td>";
}
htmlString += "</tr>";
}
htmlString += "</table>";
return htmlString;
}
Variables are not expanded inside strings. So all your TDs have the literal attribute onclick='changeClass(xPos, yPos)' in them, not the values of these variables from the loop. So when you actually click on them, they all use the most recent values of those variables.
You need to use string concatenation to get the values. And there's no need for the global variables xPos and yPos, you can use the local j and x variables.
htmlString += "<td onclick = 'changeClass(" + j + ", " + x + ")'></td>";

Need for/while/do while loops to repeat asterisks

I have this problem, to repeat 30 asterisks for 3 lines. I made this example code but it repeats 30 numbers (1..30) from 1 number for first line, up to 30 numbers for the last line. So, I'd need the code to repeat 30 asterisks, for 3 lines each but not quite like within this code.
Sorry for bad elaboration.
var text = "";
var max = 30;
for(i = 0; i < max; i++)
{
for(j = 0; j <= i; j++)
{
text += (j+1)+" ";
}
text += "<br />";
}
A more re-usable solution will be to make a generic repeatString function that simply makes multiple copies of any string.
function repeatString(s, times) {
for (var i = 0, r = ''; i < times; i++) {
r += s;
}
return r;
}
var line = repeatString('*', 30) + '<br />',
content = repeatString(line, 3);
http://jsfiddle.net/611y2vmz/1/
Repeat the loop three times, like this:
for ( var i = 0; i < 3; i++ ) { // this is the line loop
for ( var j = 0; j < 30; j++ ) { //this is the asterix loop
document.write('*');
}
document.write('<br>');
}
Here's a simple demo
If you are using ES2015 (ES6) syntax you can leverage repeat function and string templating. Using those features your code will look like this
let text = (`${'*'.repeat(30)}<br/>`).repeat(3);
Here is an example of ES2015 (ES6) code
if you are using ES5 then you can do this way:
String.prototype.repeat = function(count) {
return count < 1 ? '' : new Array(count + 1).join(this);
};
var text = ('*'.repeat(30) + '<br/>').repeat(3);
Here is an example of ES5 code
You need your outer loop to iterate 3 times, and your inner loop to iterate 30 times. Each iteration of your inner loop should add an asterisk (instead of adding j+1 like you are doing now). This will produce 3 rows of 30 asterisks.
var TEXT = "*";
var LINE_SEPARATOR = "<br/>";
var TEXT_COUNT = 30;
var LINE_COUNT = 3;
var output = "";
for (line = 1; line <= LINE_COUNT; ++line) {
for (text = 1; text <= TEXT_COUNT; ++text) {
output += TEXT;
}
output += LINE_SEPARATOR;
}
document.write(output);
An alternative would be to use recursion:
function stars(num) {
return num > 0 ? stars(num - 1) + '*' : '';
}
var content = stars(30) + '<br/>' + stars(30) + '<br/>' + stars(30);
DEMO

Categories

Resources