Output javascript object as html table - javascript

I have a JS object, I have been trying to output it as an HTML table. I have been trying to achieve that by looping through the object, appending the results to a string and putting it inside the table via innerHTML.
The header row is OK
The first data row is OK
However, the subsequent rows do not break of into a new row in the HTML table.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<table>
<tr id="headeris">
</tr>
<tr id="duomenys">
</tr>
</table>
<script>
var AdenTalisman =
{
"Enchant" : ["+0","+1","+2","+3","+4","+5","+6","+7","+8","+9","+10"],
"P.Atk" : ["-","-", "-", "-", "-", 50, 80, 135, 180, 225, 270],
"M.Atk" : ["-","-", "-", "-", "-", 100, 150, 250, 360, 420, 490],
"P.Def" : ["-",5, 10, 10, 20, 30, 40, 60, 80, 120, 160],
"M.Def" : ["-",5, 10, 10, 30, 40, 60, 80, 120, 160, 200],
"Atk.Speed": ["-",10, 12, 15, 20, 25, 40, 70, 80, 90, 100],
"C.Speed" : ["-",10, 12, 15, 20, 25, 45, 75, 95, 110, 125],
"HP" : ["-",100, 120, 150, 180, 220, 260, 520, 640, 910, 1120],
"MP" : ["-", 30, 50, 70, 100, 130, 160, 320, 360, 430, 530],
"XP/SP" : ["-", "-", "-", "-", 10, 15, 20, 50, 50, 50, 50]
}
tableH = [];
tableR = [];
let header = '';
for (let k of Object.keys(AdenTalisman)) {
header = [];
header += k.padEnd(10);
tableH += `
<th> ${header} </th>
`
}
console.log(header);
document.getElementById('headeris').innerHTML = tableH;
for (let i = 0; i <= 10; i++) {
tableR += "</tr>"
console.log(tableR)
document.getElementById('duomenys').innerHTML += tableR;
var tableR = '';
tableR += `<tr>`
for (let k of Object.keys(AdenTalisman)) {
row = [];
row += AdenTalisman[k][i];
tableR += `
<td> ${row} </td>
`
}
}
</script>
</body>
</html>

document.getElementById('duomenys').innerHTML += tableR; will:
Convert the DOM of that element into a string of HTML source code
Append a new string to the end of that string
Convert the string into an HTML DOM
The first time you do that, the end tag for the <table> is missing, so it gets added automatically as error recovery.
The second time you do that you end up with something like:
<table>...</table><tr>...
and it is just broken.
If you are going to build a table with JavaScript either:
Build the entire thing (from <table> to </table> with everything inside) as a regular string then then set set some element's innerHTML to that string once and at the end. or
Use createElement, appendChild and friends instead.

Use thead and tbody elements
const AdenTalisman = {
"Enchant": ["+0", "+1", "+2", "+3", "+4", "+5", "+6", "+7", "+8", "+9", "+10"],
"P.Atk": ["-", "-", "-", "-", "-", 50, 80, 135, 180, 225, 270],
"M.Atk": ["-", "-", "-", "-", "-", 100, 150, 250, 360, 420, 490],
"P.Def": ["-", 5, 10, 10, 20, 30, 40, 60, 80, 120, 160],
"M.Def": ["-", 5, 10, 10, 30, 40, 60, 80, 120, 160, 200],
"Atk.Speed": ["-", 10, 12, 15, 20, 25, 40, 70, 80, 90, 100],
"C.Speed": ["-", 10, 12, 15, 20, 25, 45, 75, 95, 110, 125],
"HP": ["-", 100, 120, 150, 180, 220, 260, 520, 640, 910, 1120],
"MP": ["-", 30, 50, 70, 100, 130, 160, 320, 360, 430, 530],
"XP/SP": ["-", "-", "-", "-", 10, 15, 20, 50, 50, 50, 50]
}
const EL_theadRow = document.querySelector("#headeris tr");
const EL_tbody = document.querySelector("#duomenys");
const ELNew = (sel, att) => Object.assign(document.createElement(sel), att || {});
Object.entries(AdenTalisman).forEach(([name, items]) => {
// Create THs for THEAD>TR
EL_theadRow.append(ELNew("th", {textContent: name}));
// Create TR for TBODY
const TR = ELNew("tr");
// Create TD for TBODY>TR
items.forEach((val) => TR.append(ELNew("td", {textContent: val})));
EL_tbody.append(TR);
});
<table>
<thead id="headeris"><tr></tr></thead>
<tbody id="duomenys"></tbody>
</table>

Try this
Change table to use thead and tbody as stated on Roko answer
<table>
<thead id="headeris">
</thead>
<tbody id="duomenys">
</tbody>
</table>
Change multi array looping like this
var tableR = '';
for (let i = 0; i <= 10; i++) {
tableR += `<tr>`
for (let k of Object.keys(AdenTalisman)) {
row = [];
row = AdenTalisman[k][i];
tableR += `
<td> ${row} </td>
`
}
tableR += `</tr>`
}
document.getElementById('duomenys').innerHTML += tableR;
var AdenTalisman = {
"Enchant": ["+0", "+1", "+2", "+3", "+4", "+5", "+6", "+7", "+8", "+9", "+10"],
"P.Atk": ["-", "-", "-", "-", "-", 50, 80, 135, 180, 225, 270],
"M.Atk": ["-", "-", "-", "-", "-", 100, 150, 250, 360, 420, 490],
"P.Def": ["-", 5, 10, 10, 20, 30, 40, 60, 80, 120, 160],
"M.Def": ["-", 5, 10, 10, 30, 40, 60, 80, 120, 160, 200],
"Atk.Speed": ["-", 10, 12, 15, 20, 25, 40, 70, 80, 90, 100],
"C.Speed": ["-", 10, 12, 15, 20, 25, 45, 75, 95, 110, 125],
"HP": ["-", 100, 120, 150, 180, 220, 260, 520, 640, 910, 1120],
"MP": ["-", 30, 50, 70, 100, 130, 160, 320, 360, 430, 530],
"XP/SP": ["-", "-", "-", "-", 10, 15, 20, 50, 50, 50, 50]
}
tableH = [];
tableR = [];
let header = '';
for (let k of Object.keys(AdenTalisman)) {
header = [];
header += k.padEnd(10);
tableH += `
<th> ${header} </th>
`
}
document.getElementById('headeris').innerHTML = tableH;
var tableR = '';
for (let i = 0; i <= 10; i++) {
tableR += `<tr>`
for (let k of Object.keys(AdenTalisman)) {
row = [];
row = AdenTalisman[k][i];
tableR += `
<td> ${row} </td>
`
}
tableR += `</tr>`
}
document.getElementById('duomenys').innerHTML += tableR;
<table>
<thead id="headeris">
</thead>
<tbody id="duomenys">
</tbody>
</table>

Or you can do it like this:
const AT = {
"Enchant": ["+0", "+1", "+2", "+3", "+4", "+5", "+6", "+7", "+8", "+9", "+10"],
"P.Atk": ["-", "-", "-", "-", "-", 50, 80, 135, 180, 225, 270],
"M.Atk": ["-", "-", "-", "-", "-", 100, 150, 250, 360, 420, 490],
"P.Def": ["-", 5, 10, 10, 20, 30, 40, 60, 80, 120, 160],
"M.Def": ["-", 5, 10, 10, 30, 40, 60, 80, 120, 160, 200],
"Atk.Speed": ["-", 10, 12, 15, 20, 25, 40, 70, 80, 90, 100],
"C.Speed": ["-", 10, 12, 15, 20, 25, 45, 75, 95, 110, 125],
"HP": ["-", 100, 120, 150, 180, 220, 260, 520, 640, 910, 1120],
"MP": ["-", 30, 50, 70, 100, 130, 160, 320, 360, 430, 530],
"XP/SP": ["-", "-", "-", "-", 10, 15, 20, 50, 50, 50, 50]
};
document.querySelector("table").innerHTML = Object.entries(AT).map(([k,v],i)=>
"<tr><th>"+k+"</th>"+(i?"<td>":"<th>")+v.join(i?"</td><td>":"</th><th>")+(i?"</td>":"</th>")+"</tr>"
).join("");
table {border:1px solid grey}
th,td {text-align:right; padding:4px}
tr:nth-child(even) {background-color:#ddd}
<table></table>

Related

How to remove certain elements from the inner array in JavaScripts

var array = [[10, 20, 30, 20, 50], [40, 50, 60, 20, 20], [70, 80, 90, 20, 20], [70, 80, 90, 20, 20]];
For example i want to delete elements == 50
I want this result -> array= [[10,30,20], [40,60,20], [70,90,20], [70,90,20]];
I try this solution but it is not working ->
for (var i = 0; i < array.length; i++) {
for (var j = 0; j < array[i].length; j++) {
if (array[i][j] == 50) {
array[i].splice(j, 1);
}
}
}
You need to collect unwanted indices first and then return.
const
data = [
[10, 20, 30, 20, 50],
[40, 50, 60, 20, 20],
[70, 80, 90, 20, 20],
[70, 80, 90, 20, 20]
],
// ^^ ^^ cols with 50
//
indices = data.reduce(
(r, a) => a.map((v, i) => v === 50 ? false : r[i] ?? true),
[]
),
result = data.map(a => a.filter((_, i) => indices[i]));
result.forEach(a => console.log(...a));
const array = [[10, 20, 30, 20, 50], [40, 50, 60, 20, 20], [70, 80, 90, 20, 20], [70, 80, 90, 20, 20]];
const filteredArr = array.map(item => [...new Set(item.filter(i => i !== 50))])
// filterdArr = [[10, 30, 20], [40, 60, 20], [70, 80, 90, 20], [70, 80, 90, 20]];

Plotly.js - Hover label of multiple traces overlaps with xaxis hover label

I'm facing an issue where the hover label of multiple traces overlaps with the x-axis's hover label when all the trace values are close to 0.
In the example below, you can see the overlap when you mouseover x=1000
const data = []
const x = [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000];
data.push({
x: x,
y: [100, 105, 132, 150, 130, 103, 2, 200, 301, 1],
});
data.push({
x: x,
y: [200, 205, 232, 250, 230, 193, 1, 100, 201, 0],
})
data.push({
x: x,
y: [0, 205, 232, 250, 230, 193, 10, 100, 0, 0],
})
const layout = {
height: 350,
xaxis: {
// tickformat: ',.2r',
},
hoverlabel: {
font: {
family: 'Helvetica Neue',
size: 11,
}
}
}
Plotly.plot('graph', data, layout);
<head>
<!-- Plotly.js -->
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
</head>
<body>
<div id="graph"></div>
</body>
https://codepen.io/anon/pen/RBpQPg
Any workarounds would be appreciated. For example, would it be possible to combine all the hover labels into 1 label somehow?

remove all dups and negative numbers from 3 arrays [duplicate]

This question already has answers here:
Remove negative numbers from array
(3 answers)
Closed 5 years ago.
I recently had a technical job interview. the code challenge i was asked to solve was given 3 arrays of numbers. goal was to remove all dups and negative nums
i was able to remove dups but not duplicates, so far i have the following code. what am i missing?
let array1=[10, 200, 10, 200, 100, 100, 200, 200, 200, 200, -99, -6, 0, -859]
let array2 = [100, 200, 100, 200, 689, 689, 200, 400, 210, 200, -58, 200, -305, -6, 0, -859]
let array3 =[100, 200, 100, 200, 689, 689, 200, 400, 210, 400, -6, 200, -305, -6, 0, -859]
const arrays = {
array1,array2,array3
}
let nodups=Array.from(new Set(array1.concat(array2,array3)))
console.log(nodups);
After getting a duplicate free array, you need to filter the array for only positive values.
var array1 = [10, 200, 10, 200, 100, 100, 200, 200, 200, 200, -99, -6, 0, -859],
array2 = [100, 200, 100, 200, 689, 689, 200, 400, 210, 200, -58, 200, -305, -6, 0, -859],
array3 = [100, 200, 100, 200, 689, 689, 200, 400, 210, 400, -6, 200, -305, -6, 0, -859],
result = Array
.from(new Set(array1.concat(array2, array3)))
.filter(v => v >= 0);
console.log(result);
Put them in a Set and apply a filter
let array1=[10, 200, 10, 200, 100, 100, 200, 200, 200, 200, -99, -6, 0, -859]
let array2 = [100, 200, 100, 200, 689, 689, 200, 400, 210, 200, -58, 200, -305, -6, 0, -859]
let array3 =[100, 200, 100, 200, 689, 689, 200, 400, 210, 400, -6, 200, -305, -6, 0, -859]
let res = [...new Set([...array1, ...array2, ...array3])].filter(e => e >= 0);
console.log(res);

JavaScript arrays - efficiently calculate average in given intervals

I have two arrays, one of them represents data, and the other one - intervals. Both are sorted and their start and end values match. I go through nested for loops to calculate the average of data points in a given interval. As a result, I end up with one data value for each interval. For smaller size arrays, < 100-500 length, these linear loops do the work, however, this approach becomes an issue with several thousand data points. Any recommendation will be appreciated.
Please see a simplified code below with a link to JSfiddle at the end
var TimelineArray = [0, 10, 20, 30, 40, 40, 60, 70, 80, 90, 100],
DataArray = [0, 2, 4, 5, 8, 11, 19, 22, 24, 25, 30, 31, 38, 39, 51, 56, 57, 58, 59, 64, 74, 76, 89, 91, 92, 94, 98, 100],
DataArrayA = [];
for (i = 0; i < TimelineArray.length-1; i++) {
var dataPointsInGivenTimeInterval = [];
for (j = 0; j < DataArray.length; j++) {
if (DataArray[j] > TimelineArray[i] && DataArray[j] <= TimelineArray[i+1]) {
dataPointsInGivenTimeInterval.push(DataArray[j]);
}
};
if (dataPointsInGivenTimeInterval.length == 0) {
DataArrayA.push(null);
}
else {
var sumOfdataPoints = null;
for (k = 0; k < dataPointsInGivenTimeInterval.length; k++) {
sumOfdataPoints += dataPointsInGivenTimeInterval[k];
}
var avg = sumOfdataPoints / dataPointsInGivenTimeInterval.length;
DataArrayA.push(avg);
}
} // end for
console.log(TimelineArray);
console.log(DataArrayA);
.as-console-wrapper {
max-height: 100% !important;
top: 0;
}
The console output is
[0, 10, 20, 30, 40, 40, 60, 70, 80, 90, 100]
[4.75, 15, 25.25, 36, null, 56.2, 64, 75, 89, 95]
Here is the code at JSfiddle - calculating average values for given intervals
Since the arrays are sorted, you can do it linearly with respect to the size of the timeline and data:
var timeline = [0, 10, 20, 30, 40, 40, 60, 70, 80, 90, 100],
data = [0, 2, 4, 5, 8, 11, 19, 22, 24, 25, 30, 31, 38, 39, 51, 56, 57, 58, 59, 64, 74, 76, 89, 91, 92, 94, 98, 100];
var averages = new Array(timeline.length - 1);
for (var i = 0, j = 0; i < timeline.length; i++) {
var sum = 0,
items = 0;
for (; data[j] <= timeline[i]; j++) {
sum += data[j];
++items;
}
if(i) averages[i-1] = sum / items;
}
console.log(averages);
.as-console-wrapper {
max-height: 100% !important;
top: 0;
}
You don't need to re-scan DataArray from the beginning on each iteration.
var TimelineArray = [0, 10, 20, 30, 40, 40, 60, 70, 80, 90, 100];
var DataArray = [0, 2, 4, 5, 8, 11, 19, 22, 24, 25, 30, 31, 38, 39, 51, 56, 57, 58, 59, 64, 74, 76, 89, 91, 92, 94, 98, 100];
var res = [], pos = 0;
TimelineArray.forEach(function(v, i) {
for(var sum = 0, n = 0; DataArray[pos] <= v; n++) {
sum += DataArray[pos++];
}
i && res.push(n ? sum / n : null);
});
console.log(res);
Not sure if it'll be any faster, but here's a crack at it in a different way:
var TimelineArray = [0, 10, 20, 30, 40, 40, 60, 70, 80, 90, 100],
DataArray = [0, 2, 4, 5, 8, 11, 19, 22, 24, 25, 30, 31, 38, 39, 51, 56, 57, 58, 59, 64, 74, 76, 89, 91, 92, 94, 98, 100],
DataArrayA = [];
function avg(arr){
if(arr!= null && arr.length > 0)
return arr.reduce(function(a, b){ return a+b;}, 0) / arr.length;
return null;
}
for(var i = 0; i < TimelineArray.length-1; i++){
var interval = [TimelineArray[i], TimelineArray[i+1]];
var data = DataArray.filter(function(a){ return a > interval[0] && a <= interval[1]});
DataArrayA.push(avg(data));
}
console.log(DataArrayA);
edit 1: removed a loop.

Kinetic : Sprite mouseenter stop

I'm trying, using KineticJS, to set a sprite animation and when I'm hover this sprite, to move to another animation and stop it.
var stage = new Kinetic.Stage({
container: 'container',
width: 600,
height: 600
});
var layer = new Kinetic.Layer();
var animations = {
close: [
0, 0, 127, 70,
127, 0, 127, 70,
254, 0, 127, 70,
381, 0, 127, 70,
508, 0, 127, 70,
635, 0, 127, 70,
0, 70, 127, 70,
127, 70, 127, 70,
254, 70, 127, 70,
381, 70, 127, 70,
508, 70, 127, 70,
635, 70, 127, 70
],
closed: [
635, 70, 127, 70
],
openclose: [
0, 0, 127, 70,
127, 0, 127, 70,
254, 0, 127, 70,
381, 0, 127, 70,
508, 0, 127, 70,
635, 0, 127, 70,
0, 70, 127, 70,
127, 70, 127, 70,
254, 70, 127, 70,
381, 70, 127, 70,
508, 70, 127, 70,
635, 70, 127, 70,
635, 70, 127, 70,
508, 70, 127, 70,
381, 70, 127, 70,
254, 70, 127, 70,
127, 70, 127, 70,
0, 70, 127, 70,
635, 0, 127, 70,
508, 0, 127, 70,
381, 0, 127, 70,
254, 0, 127, 70,
127, 0, 127, 70,
0, 0, 127, 70
]
}
var imageObj = new Image();
imageObj.onload = function() {
var eye = new Kinetic.Sprite({
x: 250,
y: 250,
image: imageObj,
animation: 'openclose',
animations: animations,
frameRate: 12
});
layer.add(eye);
stage.add(layer);
eye.start();
eye.on('mouseenter', function(){
this.animation('close').afterFrame(11, function() {
this.animation('closed').stop();
});
});
};
imageObj.src = 'http://localhost/canvas/eye/sprite.png';
I tried to use function afterFrame, found here Kinetic.js [How can I stop one sprite]
But it seemes that this function is over and I don't know what to use instead.
No clue here too : http://kineticjs.com/docs/Kinetic.Sprite.html
So if someone know how to do and maybe have a better website for the doc !
Thanks you !
sprite.on('frameIndexChange', function(evt) {
if( evt.newVal === 11 ){
// stop
}
});
http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-sprite-tutorial/

Categories

Resources