I'm learning JavaScript and got to the section in my book that described creating new DOM elements like tables, rows, and columns, so I wanted to create a table similar to the periodic table of elements that I could later go back to and fiddle with as I learned new things. My problem is that, from everything that I understand so far, this code should work. Except that it doesn't display anything, and there is nothing showing up in the console in FireFox v29.0.
Ideally, I wanted to create 7 rows (periods) and 18 columns (groups), and then display the elements that were associated at those locations in the table, and then try formatting it (for example, there are empty cells inserted between elements 1 and 18, since the only elements in that period are Hydrogen (1) and Helium (2). An example of this can be seen here: http://www.webelements.com/
However, my first task (creating a basic table) just doesn't seem to work, and either I'm using the wrong terminology or no one has posted about this before (and "javascript periodic table" links mostly to just things like http://www.webelements.com/). Any ideas on what I'm missing here?
<html>
<head>
<title>Periodic Table</title>
</head>
<body>
<script>
var periodicTable = createTable( 7, 18);
var period = 7;
var group = 18;
document.body.appendChild(periodicTable);
function createTable( period, group ) {
var elementId = 0;
var table = document.createElement('table');
for (var p = 1; p < period; ++p) {
var tr = table.appendChild(document.createElement('tr'));
for (var g = 1; g < group; ++g) {
var element = tr.appendChild(document.createElement('td'));
element.innerHTML = ++elementId;
}
}
return table;
}
</script>
</html>
Edit
Based on the helpful comments below, I've changed the code to look like this:
<script>
var periodicTable = createTable( 7, 18);
document.body.appendChild(periodicTable);
function createTable( period, group ) {
var elementId = 0;
var table = document.createElement('table');
for (var p = 1; p < period; ++p) {
var tr = table.appendChild(document.createElement('tr'));
for (var g = 1; g < group; ++g) {
var element = tr.appendChild(document.createElement('td'));
element.innerHTML = ++elementId;
}
}
return table;
}
</script>
In your original code you had this:
var periodicTable = createTable( 7, 18);
var period = 7;
var group = 18;
document.body.appendChild(periodicTable);
function createTable( rows, cols ) {
:
for (var p = 1; p < period; ++p) {
var tr = table.appendChild(document.createElement('tr'));
for (var g = 1; g < group; ++g) {...}
}
return table;
}
Thought vars are hoisted, i.e. variables are declared at the beginning of the scope, they are not initialized, values are assigned where ever an assignment is met. In your code period and group have value undefined until they are given values, after createTable has been executed.
You pass two arguments to createTable(), where their names are rows and cols. However, when you're needing those values, you use global variables period and group, which are undefined at the time the function is executed (they get their values after function has been finished).
To fix this, just rename the arguments rows and cols to period and group, and consider to remove the global variables (if they are not needed somewhere else ofcourse).
Related
I have a table I need to compare each of the values within to an existing parameter.
I have this Xpath here: //*[#id="maincontent"]/messages/div/div[1]/div[1]/table/tbody/tr[1]/td[4]/div/span
and would like to insert an increment variable from the loop to go through the /tr/ in the table only.
Here is what i have so far:
var i;
var max = 10;
var xpathleft = `*[#id="maincontent"]/messages/div/div[1]/div[1]/table/tbody/tr[`;
var xpathright = `]/td[4]/div/span`;
for (i = 1; i < max, i++)
{
var currentXpath = string.concat(xpathleft, i, xpathright);
}
if (currentXpath.innerHTML == PartnerIDs)
{
lr_log_message("Match Found!");
}
This is currently sitting in an Evaluate Javascript step in TruClient/VUgen and is giving me Syntax Error: Unexpected Token )
The element here doesn't have any ID I can reference and looks like this: Partner ID
and has been difficult to pull the needed Partner ID text within code.
Some of your JavaScript syntax is incorrect.
Try this:
var i;
var max = 10;
var xpathleft = `*[#id="maincontent"]/messages/div/div[1]/div[1]/table/tbody/tr[`;
var xpathright = `]/td[4]/div/span`;
for (i = 1; i < max; i++){
var currentXpath = `${xpathleft}${i}${xpathright}`;
if (currentXpath.innerHTML == PartnerIDs) {
lr_log_message("Match Found!");
}
}
I want to create a table by javascript. It should be a Appointment calender for events. with two rows and two lines per event. In the first line are the datenumber and the kind of event. In the second line are the weekday and the place, where the event are. For the Phase of Development I have only an exemple text. I include my js-file in my html-file but there isn't a table. Can someone check my code because I did not find a mistake
function dates(){
var test = 31;
var rows = 2;
var text_bsp = "example";
var tab = document.createElement("table");
var line1 = document.createElement("tr");
var line2 = document.createElement("tr");
var cell_date = document.createElement("td");
var cell_event = document.createElement("td");
var cell_day = document.createElement("td");
var cell_place = document.createElement("td");
var ausgabe = document.getElementById('content-container');
ausgabe.appendChild(tab);
for(var i=1;i < 32; i++)
{
tab.appendChild(line1);
for(var j=0;j<3;j++)
{
line1.appendChild(cell_date);
cell_date.createTextNode(text_bsp);
line1.appendChild(cell_event);
cell_event.createTextNode(text_bsp);
}
tab.appendChild(line2);
for(var k=0;j<3;k++){
line2.appendChild(cell_date);
cell_date.createTextNode(text_bsp);
line2.appendChild(cell_place);
cell_place.createTextNode(text_bsp);
}
}
}
I expected a table with 62 lines and 2 rows with the content 'example' in each cell.. But it dont work
If you call appendChild onto a Node that is already part of the DOM, it gets removed from its previous location and moved to the new one. You either have to clone before appending:
line1.appendChild(cell_date.cloneNode(true));
or just create new nodes inside of the loops.
There are are few changes required to achieve what you require. First, you'll need to move you row and cell creation inside the loop - currently you're creating one set of rows outside of the loop, before it begins.
Note also that you can't re-use the same row element, or cell element in the table to generate a table with multiple rows and cells - you need to create new element instances to achieve this.
Also consider using the insertRow(), insertCell() and document.createTextNode() methods as shown below:
function dates() {
var test = 31;
var rows = 2;
var text_bsp = "example";
var tab = document.createElement("table");
var ausgabe = document.getElementById('content-container');
ausgabe.appendChild(tab);
for (var i = 1; i < 32; i++) {
/*
Create line1 row inside of for loop, to produce
a new line for each iteration
*/
var line1 = tab.insertRow(line1);
for (var j = 0; j < 3; j++) {
/*
Create new cell_date and cell_event cells for
the current row we're creating
*/
var cell_date = line1.insertCell();
var cell_event = line1.insertCell();
/*
Create new text nodes for each cell via document
and append these to respective cell elements
*/
cell_date.append(document.createTextNode(text_bsp));
cell_event.append(document.createTextNode(text_bsp));
}
/*
As before, create line2 row inside of for loop
*/
var line2 = tab.insertRow();
for (var k = 0; j < 3; k++) {
var cell_date = line2.insertCell();
var cell_place = line2.insertCell();
cell_date.append(document.createTextNode(text_bsp));
cell_place.append(document.createTextNode(text_bsp));
}
}
}
dates();
<div id="content-container"></div>
I'm creating an HTML table from a server-side array (google apps script; so tableArray is coming from there). I have two forEach functions which work. However, I'm attempting to use two for loops instead because I'd like to be able to add different classes to different <td>'s.
The output doesn't come out as expected (see #1 below). I can either get an array in one column (instead of each element of the array as a separate <td> or the arrays are repeated in each <td> (see #2 below).
What do I need to change in my for loops to get the expected output?
You can see the version that works HERE.
1 (works with forEach)
2 (does not work with for)
Index.html
function buildTable(tableArray) {
var table = document.getElementById('table');
var tableBody = document.createElement('tbody');
var tbodyID = tableBody.setAttribute('id', 'tbody');
for (var i = 0; i < tableArray.length; ++i) {
var column = tableArray[i];
var colA = column[0];
var colB = column[1];
var colC = column[2];
var colD = column[3];
if (colA != "") {
var row = document.createElement('tr');
for (var j = 0; j < column.length; ++j) {
var cell = document.createElement('td');
cell.appendChild(document.createTextNode(column));
row.appendChild(cell);
}
}
tableBody.appendChild(row);
}
table.appendChild(tableBody);
document.body.appendChild(table);
}
Instead of line cell.appendChild(document.createTextNode(column));
write cell.appendChild(document.createTextNode(column[j]));
You've forgotten to add index [j]
// Loop over rows
for (var i = 0; i < tableArr.length; i++) {
var row = tableArr[i];
// loop over columns
for( var j =0; j<row.length; j++){
//create each column and append to row
}
// append row to table body
}
// append table body to DOM
For performance reasons you want to write to the DOM only once and create the table in memory first.
Change
cell.appendChild(document.createTextNode(column));
to
cell.appendChild(document.createTextNode(column[i]));
This will make it loop through all of your column data properly instead of appending the same content of the whole array repeatedly.
I don't know the proper way to ask this, as I have searched and tried to implement different approaches without luck. Javascript isn't my strong suit so bear with me.
I have an input that looks like, each entry can be of varied width:
#abcde#fghij#klmno
I split the input based on the characters and end up with an array that looks like:
["abcde","fghij","klmno"]
I need to output a table such that the first column contains all letters from the first string which each letter in its own row, essentially ending up with a table that looks like:
a f k
b g l
c h m
d i n
e j o
As of right now I have split the strings effectively, but am having trouble creating the table. I've tried multiple different solutions on SO without luck. My inexperience is messing me up in handling the processing at each step. I've added comments for what I think needs to go in each block of my for loop, though the implementations I have tried are not successful.
var table = document.createElement("table");
var tr = document.createElement("tr");
var td = document.createElement("td");
var th = document.createElement("th");
var checkbox = document.createElement("input");
checkbox.type("checkbox");
//split string
var splitStringArray = inputString.split("#");
for (var i = 0; i < splitStringArray; i++) {
//iterate through array and create a column for each string in the array
tr.appendChild(document.createElement(th));
//for each string, iterate through each character
var temp = splitStringArray[i].split("");
for (var j = 0; j < temp.length; j++) {
//add a row for each character in the string, each cell should have a checkbox and the letter associated with it
td.appendChild(document.createTextNode[i][j]);
td.appendChild(checkbox);
//This this the step that I'm running into issues with
}
}
tableArea.appendChild(table);
One of the problem areas I'm running into is that the strings are not going to be identical length and need to displayed in the same order than they come in.
That makes it difficult to create a set number of rows and then populate them row by row instead of column by column.
First, we split the input string on the hash character (#). Next, we filter the resultant array, returning only the elements which aren't an empty string.
From there, we create another array with the length of each of the strings in our first array. We sort this length array in descending order and take the first element - this corresponds to the length of the longest word - this will be the number of rows we need. The number of columns comes from the length of the array we calculated first - the number of words in the initial input string.
From there, we simply step through the data and create table, tr and td elements. Ideally, we should also be creating a tbody element and placing the tr elements in it instead of the table.
function newEl(tag){return document.createElement(tag)}
window.addEventListener('load', onDocLoaded, false);
function onDocLoaded(evt)
{
var tbl = testFunc('#abcde#fghij#klmno');
document.body.appendChild(tbl);
}
function testFunc(inputStr)
{
var wordArray = inputStr.split('#').filter(function(str){return str != '';});
var lengthArray = wordArray.map( function(str) {return str.length;} );
var numColumns = wordArray.length;
lengthArray.sort( function(a, b){return b-a} );
var maxRows = lengthArray[0];
var tbl = newEl('table');
var tbody = newEl('tbody');
tbl.appendChild(tbody);
for (var row=0; row<maxRows; row++)
{
var tr = newEl('tr');
for (var col=0; col<numColumns; col++)
{
var td = newEl('td');
td.textContent = wordArray[col][row];
tr.appendChild(td);
}
tbody.appendChild(tr);
}
return tbl;
}
It would look something like this:
//<![CDATA
var pre = onload, doc, bod, htm, C, E, weirdTable;
onload = function(){
if(pre)pre();
doc = document; bod = doc.body; htm = doc.documentElement;
C = function(e){
return doc.createElement(e);
}
E = function(id){
return doc.getElementById(id);
}
weirdTable = function(inputString, appendTo){
var a = inputString.split(/#/), t = C('table'), b = C('tbody');
for(var i=0,l=a.length; i<l; i++){
var r = C('tr'), s = a[i].split('');
for(var n=0,c,q=s.length; n<q; n++){
c = C('td'); c.innerHTML = s[n]; r.appendChild(c);
}
b.appendChild(r);
}
t.appendChild(b); appendTo.appendChild(t);
}
weirdTable(yourStringHere, E('yourIdHere'));
}
//]]>
Script part:
function makeTable() {
var num = document.getElementById('Numb').value;
var myPara = document.getElementById('para');
var tb = new Array();
for (var i = 1; i <= 10; ++i) {
var result = num * i;
tb.push(result);
tb[i] = tb[i] + "<br>";
}
tb = tb.join("");
myPara.innerHTML = tb;
}
HTML part
<input type = "number" value = "" id = "Numb" placeholder = "TABLE NUMBER">
<input type = "button" value = "Give me Table" onClick = "makeTable()">
<p align = "center" name = "myownpara" id = "para"> </p>
When I run this code it returns undefined with first element of array
Arrays start at 0, not 1. Change it to var i= 0 in your 'for' loop and add the line if(i==0) continue; right after starting your for loop to skip over 0.
Actually, another problem is your array. It might be best to initialise your 0th element because you are looking at it later. Change new Array() to new Array(""): To already add a 0th element so you dont have to when you use my aforementioned continue statement.
Update, refinement
I refined your code below. I don't know why you are using an array, as you want to output a string anyway. So Just add it to the string for every element as it reduces the amount of things you need to do. The below will work. I also removed you 'myPara' as you only use it once anyway, so theres no point in saving it.
Also note that in this case we don't need to start at 0 as we don't have an array to add to.
function makeTable() {
var num = document.getElementById('Numb').value;
// lets use a string since thats what you want in the end and its easier.
var tb = "";
for (var i = 1; i <= 10; ++i) {
// add it to the string. I reduced the number of steps as its so simple
// You don't need to save stuff in vars for this thing.
tb += (num * i) + "<br>";
}
document.getElementById('para') = tb;
}