Compare arrays with JS and print result in matrix table - javascript

I am trying to make a matrix table by combining values from array. First array holds information about user for specific day. Second array holds list of users, third array holds days in month.
First I get data from api.
var odgovor = JSON.parse(http.responseText);
dataSetMoj = odgovor.urvPoDanuZaMjesec;
dataSetMojUposlenik = odgovor.uposlenici;
Get days for month
var mjesecImaDana = getDaysInMonth(1,2018);
var daniMjeseca = [];
for (i = 1; i <= mjesecImaDana; i++) {
daniMjeseca.push([i]);
}
Then I create table header
var k = '<thead>';
k +='<tr><th style="background-color: #f8f7f7" >' + rb + '</th>';
k +='<th style="background-color: #f8f7f7" >' + up + '</th>';
daniMjeseca.forEach(function(daysInmonth){
k += '<th style="background-color: #f8f7f7"> '+ daysInmonth +'</th>';
});
k += '</tr></thead>';
Table header display correct information, as could be seen in img.
Array rezultati holds information about each user on specific day
var rezultati = [];
for(i = 0;i < dataSetMoj.length; i++){
rezultati.push(dataSetMoj[i].ime+'-'+dataSetMoj[i].datum+'-'+dataSetMoj[i].urv);
}
Then I create table body, In table body I should match user with date.
k += '<tbody>'
for(i = 0;i < dataSetMojUposlenik.length; i++){
k+='<tr>';
k+='<td> ' + a++ + '</td>';
k+='<td> ' + dataSetMojUposlenik[i].ime + '</td>';
daniMjeseca.forEach(function(daysInmonth){
var dataSetVar = dataSetMojUposlenik[i].ime +'-'+daysInmonth;
//here I should check if variable 'datSetVar' is set in array rezultati, if yes I should print dataSetMoj[i].urv from rezultati
if(rezultati == dataSetVar ){
k+='<td> ' + dataSetMoj[i].urv + '</td>'; // It does not work, but I have no idea. I could not find solution any hint would help me.
}
else{
k+='<td> ' + c + '</td>';
}
});
k+='</tr>';
}
k+='</tbody>';
document.getElementById('tableData').innerHTML = k;
Array rezultati holds three element dataSetVar two. I am not able to make comparison got wrong answers.

Related

Problem with Javascript localStorage for-loop

I am using localStorage to store incoming message: {"lastTid":22,"Hour":10,"min":31,"Second":34} where the time is increasing in every new incoming object, e.g. next object: {"lastTid":22,"Hour":10,"min":31,"Second":35}.
The new messages are being stored in localStorage correctly as seen here:
My Javascript code implements the localStorage.getItem and .setItem correctly to retrieve and get my incoming data message, which will be rendered with .innerHTML to var hst, which hst = document.getElementById("highscores"). all code below
The ElementId "highscores" is assigned to <table> tag in my html and comes out as seen here:
#js code snippet#
var hst = document.getElementById("highscores");
function onMessageArrived(message) {
var data = JSON.parse(message.payloadString);
var highScores = [data];
var array = JSON.parse(localStorage.getItem('highscores') || '[]');
array.push(highScores);
localStorage.setItem('highscores', JSON.stringify(array));
for (var i = 0; i < array.length; i++) {
hst.innerHTML += "<tr><td>" + array[i][0].Hour + ":"+ array[i][0].min + ":" + array[i][0].Second + "</td><td>" + array[i][0].lastTid + "</td></tr>";
}
};
My problem is, because of my For loop, when a new message arrives, my loop goes through and renders the previous message and the new message, while the old message is still in the table(please see the table image above). It is displaying object 0, object 0 & 1, then object 0, 1 & 2 all in the same table. Instead of 0, then 1 after, then 2 ... n.
I wish to display the values in proper order and also keep those values even after the page is reloaded. Desired result:
Don't append directly hst.innerHTML +=...
try something like this
let html = ''
for (var i = 0; i < array.length; i++) {
html += "<tr><td>" + array[i][0].Hour + ":"+ array[i][0].min + ":" + array[i][0].Second + "</td><td>" + array[i][0].lastTid + "</td></tr>";
}
hst.innerHTML = html
I think the problem is your always appending the array content at hst.innerHTML each incoming message, so the previous loop content remains. It's also not recommended for performance to manipulate DOM inside loops.
let res = '';
for (var i = 0, l = array.length; i < l; i++) {
res += '<tr><td>' + array[i][0].Hour + ':' + array[i][0].min + ':' + array[i][0].Second + '</td><td>' + array[i][0].lastTid + '</td></tr>';
}
hst.innerHTML = res; // You overwrite the content instead of appending each time.

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.

Iterating every other AJAX object

I have a JSON encoded AJAX object array and I need to iterate every other one. I'm new to jQuery and JS and are unsure how to do this. I need the numbers to be the option value and the string name as the object name.
The AJAX object (note although in this example the numerals are in order they might not be because the integers are an auto_id from a database and numbers might be skipped or out of order:
{"data":["1","chicken","2","beef","3","fish","4","pork","5","turkey","6","lamb","7","vennison","8","duck"],"error":false}
I tried the following code below which doesn't work. I tried to do a search for this answer but couldn't find it. TIA. Currently, newOption is returning "undefined".
$.each(data.data, function(i,s){
var count=s[i];
var newOption = s[i+1];
output += '<option value="' + count + '">' + newOption + '</option>';
i++;
});
Use a for loop, but increment the counter by 2 each loop:
var data = {"data":["1","chicken","2","beef","3","fish","4","pork","5","turkey","6","lamb","7","vennison","8","duck"],"error":false}
var output = '';
for(i = 0; i < data.data.length; i+=2) {
output += '<option value="' + data.data[i] + '">' + data.data[i+1] + '</option>';
}
https://jsfiddle.net/go98npym/
When Iterating over a Array using jQuery.each the first param is index and the second one is value in the index itself.
Instead of using jQuery use plain javascript.
try the following:
var d = data.data;
var output = "";
for (var i = 0 ; i< d.length; i=i+2) {
var count = d[i];
var newOption = d[i+1];
output += "<option value='"+count+"'>"+newOption+"</option>";
}
Can you use an if statement with modulus? And then initialize your count outside the loop.
var count = 0;
$.each(data.data, function(i,element){
if (i % 2 == 0) {
count++;
output += '<option value="' + count + '">' + element + '</option>';
}
i++;
});

Connect single image to single cell in a table with Javascript

I'm quite new both to programming and to this community, I'll try to be as clear as possible. I need to create an HTML table 16x16 with a button in every cell that displays a different image - a smiley - per cell, without ever showing the same smiley for different cells. I'm a bit stuck and I would also appreciate a hint, just to try and move on on my own. Thanks! Here is my code that creates the table and displays the image:
function displayImage(){
var num = Math.floor(Math.random() * 256);
document.canvas.src = '../../output/'+ imagesArray[num]+ '.png';
document.getElementById("YourImage").style.visibility = "visible";
}
for(var r = 0; r < rows;r++)
{
table += '<tr>';
for(var c= 0; c< cols;c++)
{
table += '<td style="width:50px" id="(i++)">' + '<button type="button" onclick="displayImage()">' +
"show me" + '</button>' + '</td>';
}
table += '</tr>';
}
document.write('<table id="grid" border="1">' + table + '</table>');
(ImagesArray is not shown for readability but it simply collects all 256 binary combinations).
The problem with this is that each time I click on a button it displays a random image and if I click again on the same button it shows another one, while I'd like it to show me always the same image for the same button.
NOTE: I cannot delete the button afterwards or similar tricks, as the player (it's an oTree experiment) needs to be able to go back to a smiley he saw any time.
Thanks a lot for your help!
I would change the point where the random number is generated and advance it from the display function to the initialization of the table.
Create an array with the numbers from 0 to 255. While looping through rows and columns to create the table, pick one random number from that array and assign it to the button's id attribute. Be sure to remove this number from the array, so it can't be used again for the following buttons. This way every of the 256 numbers will be used, but in random order. When a user clicks a button, with displayImage(this.id) the button's id is used as a parameter to call displayImage(). Thus always the same number of the button will be used the fetch the according image.
The code:
// call displayImage() with parameter
function displayImage(num){
document.canvas.src = '../../output/'+ imagesArray[num]+ '.png';
document.getElementById("YourImage").style.visibility = "visible";
}
// create array 'nums' with numbers from 0 to 255 (= rows * cols)
var nums = [];
for (var i = 0; i < (rows * cols); i++) {
nums.push(i);
};
for(var r = 0; r < rows; r++)
{
table += '<tr>';
for(var c = 0; c < cols; c++)
{
// get random index in array 'nums'
var random = Math.floor(Math.random() * nums.length);
// assign an id to the button with a random number from 'nums' and use this id in displayImage()
table += '<td style="width:50px" id="(i++)">' + '<button id="' + nums[random] + '" type="button" onclick="displayImage(this.id)">' +
"show me" + '</button>' + '</td>';
// remove the already used random number from 'nums'
nums.splice(random, 1);
}
table += '</tr>';
}
document.write('<table id="grid" border="1">' + table + '</table>');
This way you will have the same image connected to every button. It's randomized while creating the table, so the order is different every time you load the page.
I assume you are using HTML5 because only then it is permitted that id attributes consists only of digits.
Note: I don't know what exactly you want to achieve with id="(i++)" when creating the <td> element. The way you do it just names every id with the string (i++) which contradicts the idea that ids should be unique. If you want to name the ids ascending from for example td-0 to td-255 you should change the line to:
table += '<td style="width:50px" id="td-' + (r * rows + c) + '">' + '<button id="' + nums[random] + '" type="button" onclick="displayImage(this.id)">' + "show me" + '</button>' + '</td>';
You can't just use the numbers without adding something like td-, because the buttons already have pure numbers as id.
try this:
var rows = 16, cols = 16;
var table = '';
function shuffle(array) { // shuffle (randomize) array elements
var i = array.length, j, x;
while (i) {
j = Math.random() * i-- | 0;
x = array[i];
array[i] = array[j];
array[j] = x;
}
}
var rNums = new Array(rows * cols);
for (var i = 0; i < rows * cols; i++) {
rNums[i] = i;
}
shuffle(rNums);
function displayImage(num) {
//var num = Math.floor(Math.random() * 256);
document.canvas.src = '../../output/'+ imagesArray[num]+ '.png';
//document.getElementById("canvas").innerHTML = num;
document.getElementById("YourImage").style.visibility = "visible";
}
var i = 0;
for (var r = 0; r < rows; r++) {
table += '<tr>';
for (var c = 0; c < cols; c++) {
table += '<td style="width:50px" id="' + i + '"><button type="button" onclick="displayImage(' + rNums[i] + ')">show me</button></td>';
i++; //go to next element of rNums array
}
table += '</tr>';
}
document.write('<table id="grid" border="1">' + table + '</table>');

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

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....

Categories

Resources