Creating a table with 3 columns using javascript - javascript

I was advised that the following code would create a table but nothing seems to happen?
What I am wanting is a table with question numbers in A1 B1 C1 up to 8 questions in each column. Any help appreciated.
var totalQuestions;
function createSheet() {
var sheet = "";
totalQuestions = 8;
sheet += "<div><table>";
for (var i = 0; i < totalQuestions; i++) {
sheet += "<tr>";
sheet += "<td class='question'>";
sheet += "<div class='questionNumber'>" + "A" + (i + 1) + "</div>";
sheet += "</td>";
sheet += "<td class='question'>";
sheet += "<div class='questionNumber'>" + "B" + (i + 1) + "</div>";
sheet += "</td>";
sheet += "<td class='question'>";
sheet += "<div class='questionNumber'>" + "C" + (i + 1) + "</div>";
sheet += "</td>";
sheet += "</tr>";
}
sheet += "</table></div>";
}
table {
width: 98%;
}
td,
th {
font-size: 1.75em;
padding: 0.4em;
text-align: center;
}
th {
font-weight: normal;
width: 33.3%;
font-size: 1.8em;
padding: 0;
margin: 0;
background-color: rgb(51, 80, 58);
}

You need to insert the HTML text into your document. Also, do not forget to return the sheet at the end of the function.
See: Element.insertAdjacentHTML()
var totalQuestions;
function createSheet() {
var sheet = "";
totalQuestions = 8;
sheet += "<div><table>";
for (var i = 0; i < totalQuestions; i++) {
sheet += "<tr>";
sheet += "<td class='question'>";
sheet += "<div class='questionNumber'>" + "A" + (i + 1) + "</div>";
sheet += "</td>";
sheet += "<td class='question'>";
sheet += "<div class='questionNumber'>" + "B" + (i + 1) + "</div>";
sheet += "</td>";
sheet += "<td class='question'>";
sheet += "<div class='questionNumber'>" + "C" + (i + 1) + "</div>";
sheet += "</td>";
sheet += "</tr>";
}
sheet += "</table></div>";
return sheet;
}
document.body.insertAdjacentHTML('beforeend', createSheet());
table {
width: 98%;
}
td,
th {
font-size: 1.75em;
padding: 0.4em;
text-align: center;
}
th {
font-weight: normal;
width: 33.3%;
font-size: 1.8em;
padding: 0;
margin: 0;
background-color: rgb(51, 80, 58);
}
You could even create a function for this:
const appendHtmlTextAsChild = (htmlText, parentElement = document.body) => {
parentElement.insertAdjacentHTML('beforeend', htmlText);
};
appendHtmlTextAsChild(createSheet());
Update
You could simplify this with a template literal:
const range = (n, valueOrFunction) => (arr =>
typeof valueOrFunction === 'function'
? arr.fill(null).map((v, i) => valueOrFunction(i))
: arr.fill(valueOrFunction))(new Array(n));
const rangeMap = (n, valueOrFunction) => range(n, valueOrFunction).join('');
const appendHtmlTextAsChild = (htmlText, parentElement = document.body) =>
parentElement.insertAdjacentHTML('beforeend', htmlText);
const createQuestionSheet = (questions, choices) => `
<div>
<table>
<tbody>
${rangeMap(questions, question => `
<tr>
${rangeMap(choices, choice => `
<td class="question">
<div class="questionNumber">
${String.fromCharCode(65 + choice) + (question + 1)}
</div>
</td>
`)}
</tr>
`)}
</tbody>
</table>
</div>
`;
appendHtmlTextAsChild(createQuestionSheet(8, 4));
table {
width: 98%;
}
td,
th {
font-size: 1.75em;
padding: 0.4em;
text-align: center;
}
th {
font-weight: normal;
width: 33.3%;
font-size: 1.8em;
padding: 0;
margin: 0;
background-color: rgb(51, 80, 58);
}

Related

Why I have NaN on Node.js?

I'm making a bulletin board now. Above is the template code for it, where page function has NaN. What is the reason for this error, and how should I fix it?
The code below is written in node.js.
module.exports = {
HTML:function(title, board, control, page){
return `
<!DOCTYPE html>
<html>
<head>
<title>${title}</title>
<meta charset="utf-8">
<style type="text/css">
ul.board, ol.board {
list-style: none;
margin: 0px;
padding: 5px;
}
form {
display: inline;
}
table.type09 {
border-collapse: separate;
text-align: left;
line-height: 2;
}
table.type09 thead th {
padding: 10px;
font-weight: bold;
vertical-align: top;
color: #369;
border-bottom: 3px solid #003699;
}
table.type09 tbody th {
width: 150px;
padding: 10px;
font-weight: bold;
vertical-align: top;
border-bottom: 1px solid #ccc;
background: #f3f6f7;
}
table.type09 td {
width: 350px;
padding: 10px;
vertical-align: top;
border-bottom: 1px solid #ccc;
}
</style>
</head>
<body>
<div id="board">
<table class="type09">
<thead>
<tr>
<th>제목</th>
<th>작성자</th>
<th>날짜</th>
<th>조회수</th>
</tr>
</thead>
<tbody>
${board}
</tbody>
</table>
${control}
</div>
${page}
</body>
</html>`;
},board: function (lifeboards) {
var board = ``;
for (i = 0; i < lifeboards.length; i++) {
var article = lifeboards[i];
var titleBold = article.titleBold;
board += `<tr>`;
if(titleBold == "1") {
board += `<td> <b><공지>${article.title}</b> </td>`;
board += `<td>${article.writer}</td>`;
board += `<td>${article.day}</td>`;
board += `<td>${article.see}</td>`;
board += `</tr>`;
}
}
for (i = 0; i < lifeboards.length; i++) {
var article = lifeboards[i];
var titleBold = article.titleBold;
board += `<tr>`;
if(titleBold == "1") {
board += `<td> ${i+1}. <b>${article.title}</b> </td>`;
} else if(titleBold == "0") {
board += `<td>${i+1}. ${article.title}</td>`;
}
board += `<td>${article.writer}</td>`;
board += `<td>${article.day}</td>`;
board += `<td>${article.see}</td>`;
board += `</tr>`;
}
return board;
},page:function (lifeboards) {
var page = ``;
page =+ `<tr>`;
page =+ `<td colspan="5">`;
for(j = 0; j < lifeboards.length/5; j++) {
page =+ `[${j+1}]`;
}
page =+ `</td>`;
page =+ `</tr>`;
return page;
}
}
The picture below shows how it works.
I don't know how much more detail Stackoverflow wants, but this is all my code and there's nothing more to explain.
Please use this one , you need to add concat ( + ) operator first then =. e.g. +=
page: function (lifeboards) {
var page = ``;
page += `<tr>`;
page += `<td colspan="5">`;
for (j = 0; j < lifeboards.length / 5; j++) {
page += `[${j + 1}]`;
}
page += `</td>`;
page += `</tr>`;
return page;
}
Hope this will solve the issue.

Getting back same row format

I have this code below that allows me to move the value from Green Fruits Table to Suggested Fruits Table and vice versa but the problem is that after I move all the value from Suggested Fruits Table to Green Fruit Table all the value comes back as a single column and i want it to follow the original format which is 3 cells in a row. Is there any easy way to accomplish this? Any help would be greatly appreciated.
var obj = {};
var obj2 = {};
var obj3 = {};
var key = "Red Fruits";
obj[key] = ['Apple', 'Cherry', 'Strawberry', 'Cranberry', 'Tomato'];
var myArray = [];
myArray.push(obj);
var key2 = "Green Fruits";
obj3[key2] = ['Watermelon', 'Durian', 'Avacado', 'Kiwi', 'HoneyDew'];
var myArray2 = [];
myArray2.push(obj3);
var key3 = "Random Fruits";
obj2[key3] = ['Pomegranate', 'Honeydew', 'Plum', 'Mango', 'Lime', 'Pineapple', 'Starfruit', 'Cantaloupe', 'Blueberry'];
var myArray3 = [];
myArray3.push(obj2);
function redraw(obj3) {
var bodyString = '<tr>';
var headString = '';
$.each(obj[key], function(index) {
if (index % 3 == 0 && index > 0) {
bodyString += ('</tr><tr>');
}
bodyString += ('<td>' + obj[key][index] + '</td>');
});
bodyString += '</tr>';
headString += ('<tr><th colspan="' + obj[key].length + '">' + 'Red Fruits' + '</th></tr>');
$('.redclass tbody').html(bodyString);
$('.redclass thead').html(headString);
var bodyString2 = '<tr>';
var headString2 = '';
$.each(obj3[key2], function(index) {
if (index % 3 == 0 && index > 0) {
bodyString2 += ('</tr><tr>');
}
bodyString2 += ('<td class = "greenpilltable">' + obj3[key2][index] + '</td>');
});
bodyString2 += '</tr>';
headString2 += ('<tr><th colspan="' + obj3[key2].length + '">' + 'Green Fruits' + '</th></tr>');
$('.greenclass tbody').html(bodyString2);
$('.greenclass thead').html(headString2);
var bodyString3 = '<tr>';
var headString3 = '';
$.each(obj2[key3], function(index) {
if (index % 6 == 0 && index > 0) {
bodyString3 += ('</tr><tr>');
}
bodyString3 += ('<td>' + obj2[key3][index] + '</td>');
});
bodyString3 += '</tr>';
headString3 += ('<tr><th colspan="' + obj2[key3].length + '">' + 'Suggested Fruits' + '</th></tr>');
$('.randomclass tbody').html(bodyString3);
$('.randomclass thead').html(headString3);
}
function redraw_after(obj3) {
var bodyString3 = '<tr>';
var headString3 = '';
$.each(obj2[key3], function(index) {
if (index % 5 == 0 && index > 0) {
bodyString3 += ('</tr><tr>');
}
bodyString3 += ('<td>' + obj2[key3][index] + '</td>');
});
bodyString3 += '</tr>';
headString3 += ('<tr><th colspan="' + obj2[key3].length + '">' + 'Suggested Fruits' + '</th></tr>');
$('.randomclass tbody').html(bodyString3);
$('.randomclass thead').html(headString3);
}
function listener(obj3) {
$(document).ready(function() {
$(document).on("click", "#randomid td", function() {
data = this.innerHTML;
k1 = Object.keys(obj2).find(k => obj2[k].indexOf(data) >= 0)
index = obj2[k1].indexOf(data);
obj2[k1].splice(index, 1);
obj3[key2].push(data);
var element = $(this).detach();
$('#greenid > tbody').append('<tr><td class="new-green-fruit">' + element.html() + '</td></tr>');
redraw_after();
});
});
$(document).ready(function() {
$('body').on('click', 'td.new-green-fruit', function() {
data2 = this.innerHTML;
k2 = Object.keys(obj3).find(k => obj3[k].indexOf(data2) >= 0)
index2 = obj3[k2].indexOf(data2);
obj3[k2].splice(index2, 1);
obj2[key3].push(data2);
$(this).parent().detach();
var element2 = $(this).detach();
$('#randomid > tbody').append('<td>' + element2.html() + '</td>');
redraw_after(obj3);
});
});
}
redraw(obj3);
listener(obj3);
.class {
font-family: Open Sans;
}
.center {
display: flex;
justify-content: center
}
table.pillstable {
float: left;
width: 70%
table-row: fixed;
}
div {
margin-bottom: 50px;
}
.new-green-fruit {
padding: 8px 15px;
text-align: center;
font-size: 15px;
border-radius: 25px;
background-color: #2196f3;
color: white;
cursor: pointer;
}
table.pilltable td {
padding: 8px 15px;
text-align: center;
font-size: 15px;
border-radius: 25px;
background-color: #2196f3;
color: white;
cursor: pointer;
}
table.pilltable th {
font-weight: normal;
border: 0;
padding: 10px 0;
}
.greenpilltable {
padding: 8px 15px;
text-align: center;
font-size: 15px;
border-radius: 25px;
background-color: #4caf50;
color: white;
cursor: pointer;
}
table.greenheader th {
font-weight: normal;
border: 0;
padding: 10px 0;
}
table.redpilltable td {
padding: 8px 15px;
text-align: center;
font-size: 15px;
border-radius: 25px;
background-color: #ff9800;
color: white;
cursor: pointer;
}
table.redpilltable th {
font-weight: normal;
border: 0;
padding: 10px 0;
}
<!DOCTYPE html>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<head>
<meta charset="utf-8" />
<link rel="shortcut icon" href="//#" />
</head>
<body>
<div class="center">
<table cellspacing="5" id="redid" cellspacing="5" class="redclass redpilltable class">
<thead></thead>
<tbody></tbody>
</table>
<table cellspacing="5" id="greenid" cellspacing="5" class="greenclass greenheader class">
<thead></thead>
<tbody></tbody>
</table>
</div>
<div class="center">
<table cellspacing="5" id="randomid" cellspacing="5" class="randomclass pilltable class">
<thead></thead>
<tbody></tbody>
</table>
</div>
</body>
</html>

Reflow/repaint issues? Optimize app that is way too slow

Alright so I have run into what I believe is an optimization issue. I have written a short app that grabs data from two fields, rips them apart character by character and matches them to each other, highlighting discrepancies. The issue seems to be that because the function loops through and not only prints each character one at a time, but changes color in a new span one at a time, there is a severe amount of bottlenecking for large data entries. One sentence of even five work just fine, but when you get up to a full page of text, things bog down and in some cases crash. I have tried to look up some fixes for repaints/reflows, but I haven't run into this issue before and don't know much about it. ANy tips welcome.
Code is here:
HTML:
<!DOCTYPE html>
<html>
<head>
<title>Data Comparison</title>
</head>
<body>
<p><strong>Insert text into fields one and two and press 'Compare'. Matching data is green non-matching is red. </strong></p>
<div class="userField">
<h1>Input Field 1</h1>
<textarea id="textAreaOne" rows="30" cols="65"></textarea>
</div>
<div class="userField">
<h1>Input Field 2</h1>
<textarea id="textAreaTwo" rows="30" cols="65"></textarea>
</div>
<div id="submission">
<button onclick="compare(textAreaOne);">Compare</button>
</div>
<div id="divOne">
<h1 id="titleOne">Output Field 1</h1>
<p id="outputOne"></p>
</div>
<div id ="divTwo">
<h1 id="titleTwo">Output Field 2</h1>
<p id="outputTwo"></p>
</div>
</body>
</html>
CSS:
body {
width: 100%;
margin: 0;
padding: 0;
font-family: Verdana, Geneva, sans-serif;
font-size: 15px;
}
.userField {
display: inline-block;
width: 44%;
margin: 15px;
padding: 15px;
background-color: lightgrey;
border-radius: 13px;
box-shadow: 3px 3px 3px slategrey;
}
#submission {
text-align: center;
}
#divOne {
display: inline-block;
margin: 15px;
padding: 15px;
width: 44%;
word-wrap: break-word;
background-color: lightgrey;
}
#divTwo {
display: inline-block;
background-color: lightgrey;
width: 44%;
word-wrap: break-word;
margin: 15px;
padding: 15px;
}
#titleOne {
background-color: white;
width: 240px;
border-radius: 30px;
padding: 6px;
}
#titleTwo {
background-color: white;
width: 240px;
border-radius: 30px;
padding: 6px;
}
JS:
const fieldOne = document.querySelector("#textAreaOne");
const fieldTwo = document.querySelector("#textAreaTwo");
function compare(){
document.querySelector("#outputOne").innerHTML = "";
document.querySelector("#outputTwo").innerHTML = "";
document.querySelector("#divOne").style.visibility = "hidden";
document.querySelector("#divTwo").style.display = "hidden";
let dataOne = [];
let arrOne = fieldOne.value;
let temp = arrOne.split("");
dataOne.push(temp);
let dataTwo = [];
let arrTwo = fieldTwo.value;
let tempTwo = arrTwo.split("");
dataTwo.push(tempTwo);
if (fieldOne.value.length <= fieldTwo.value.length){
for (var i = 0; i<fieldOne.value.length; i++){
if (dataOne[0][i] === dataTwo[0][i]){
document.querySelector("#outputOne").innerHTML += "<span style='color:green'>" + dataOne[0][i] + "</span>";
document.querySelector("#outputTwo").innerHTML += "<span style='color:green'>" + dataTwo[0][i] + "</span>";
} else {
document.querySelector("#outputOne").innerHTML += "<span style='color:red'>" + dataOne[0][i] + "</span>";
document.querySelector("#outputTwo").innerHTML += "<span style='color:red'>" + dataTwo[0][i] + "</span>";
}
}
if (fieldOne.value.length < fieldTwo.value.length){document.querySelector("#outputTwo").innerHTML += "<span>...</span>";}
}
else {
for (var i = 0; i<fieldTwo.value.length; i++){
if (dataOne[0][i] === dataTwo[0][i]){
document.querySelector("#outputOne").innerHTML += "<span style='color:green'>" + dataOne[0][i] + "</span>";
document.querySelector("#outputTwo").innerHTML += "<span style='color:green'>" + dataTwo[0][i] + "</span>";
} else {
document.querySelector("#outputOne").innerHTML += "<span style='color:red'>" + dataOne[0][i] + "</span>";
document.querySelector("#outputTwo").innerHTML += "<span style='color:red'>" + dataTwo[0][i] + "</span>";
}
}
if (fieldTwo.value.length < fieldOne.value.length){ document.querySelector("#outputOne").innerHTML += "<span>...</span>";}
}
document.querySelector("#divOne").style.visibility = "visible";
document.querySelector("#divTwo").style.visibility = "visible";
}
https://codepen.io/Axfinger/pen/QxvbqM?editors=0010
Thanks
The main reason your code is slow it's because you keep modify innerHtml for every letter.
This approach is way faster even with several paragraph:
[...]
let outOne = '';
let outTwo = '';
if (fieldOne.value.length <= fieldTwo.value.length){
for (var i = 0; i<fieldOne.value.length; i++){
if (dataOne[0][i] === dataTwo[0][i]){
outOne += dataOne[0][i];
outTwo += dataTwo[0][i];
} else {
outOne += "<span style='color:red'>" + dataOne[0][i] + "</span>";
outTwo += "<span style='color:red'>" + dataTwo[0][i] + "</span>";
}
}
if (fieldOne.value.length < fieldTwo.value.length){outTwo += "...";}
}
[...]
outputOne.innerHTML = outOne;
outputTwo.innerHTML = outTwo;
Note that I omitted parts of the code for clearness.
That said if you still need more speed:
Lookup for fitting as much data as possible into the red spans. That is the whole consecutive subsequence of different letters.
Execute the function in a webworker (Will take similar time but at least won't freeze the browser).

Getting back same number of rows

I have this code below that allows me to move the value from Green Fruits Table to Random Fruits Table and vice versa but the problem is that after I move all the value from Green Fruits Table back to Random Fruit Table all the value comes back as a single row but I want it to return the value like how it was originally. Is there any simple way to fix this Any suggestion would be greatly appreciated?
var obj = {};
var obj2 = {};
var key = "Red Fruits";
obj[key] = ['Apple', 'Cherry', 'Strawberry'];
var myArray = [];
myArray.push(obj);
var key2 = "Green Fruits";
obj[key2] = ['Watermelon', 'Durian', 'Avacado'];
var myArray2 = [];
myArray2.push(obj);
var key3 = "Random Fruits";
obj2[key3] = ['Kiwi', 'Pomegranate', 'Honeydew', 'Plum', 'Mango', 'Lime', 'Pineapple', 'Starfruit', 'Cantaloupe', 'Blueberry'];
var myArray3 = [];
myArray3.push(obj2);
function redraw(obj) {
var $header = $("<tr>"),
cols = 0,
bodyString = "";
$.each(obj, function(key, values) {
cols = Math.max(cols, values.length);
$header.append($('<th/>').text(key));
});
for (var i = 0; i < cols; i++) {
bodyString += '<tr>';
$.each(obj, function(key, values) {
bodyString += '<td>' +
(values[i] ? values[i] : "") +
'</td>';
});
bodyString += '</tr>';
}
$('.fruitsclass thead').html($header);
$('.fruitsclass tbody').html(bodyString);
var bodyString = '<tr>';
var headString = '';
$.each(obj2[key3], function(index) {
if (index % 5 == 0 && index > 0) {
bodyString += ('</tr><tr>');
}
bodyString += ('<td>' + obj2[key3][index] + '</td>');
});
bodyString += '</tr>';
headString += ('<tr><th colspan="' + obj2[key3].length + '">' + 'Suggested Fruits' + '</th></tr>');
$('.carsclass tbody').html(bodyString);
$('.carsclass thead').html(headString);
}
function listener(obj) {
$(document).ready(function() {
$(document).on("click", "#carsid td", function() {
data = this.innerHTML;
k1 = Object.keys(obj2).find(k => obj2[k].indexOf(data) >= 0)
index = obj2[k1].indexOf(data);
obj2[k1].splice(index, 1);
obj[key2].push(data);
var element = $(this).detach();
$('#fruitsid > tbody').append('<tr><td></td><td class="new-green-fruit">' + element.html() + '</td></tr>');
});
});
$(document).ready(function() {
$('body').on('click', 'td.new-green-fruit', function() {
data2 = this.innerHTML;
k2 = Object.keys(obj).find(k => obj[k].indexOf(data2) >= 0)
index2 = obj[k2].indexOf(data2);
obj[k2].splice(index2, 1);
obj2[key3].push(data2);
$(this).parent().detach();
var element2 = $(this).detach();
$('#carsid > tbody').append('<td>' + element2.html() + '</td>');
});
});
}
redraw(obj);
listener(obj);
.class {
font-family: Open Sans;
}
.center {
display: flex;
justify-content: center
}
table.skillsTable th {
border-left: 1px solid #AAA5A4;
border-right: 1px solid #AAA5A4;
color: #0080ff;
font-weight: normal;
border-bottom: 1px solid #AAA5A4;
padding-bottom: 5px;
}
table.skillsTable {
float: left;
border-collapse: collapse;
width: 70%
}
table.pillstable {
float: left;
width: 70% table-row:fixed;
}
table.skillsTable td {
border-left: 1px solid #AAA5A4;
border-right: 1px solid #AAA5A4;
padding-top: 8px;
padding-left: 11px;
font-size: 15px;
}
div {
margin-bottom: 50px;
}
.new-green-fruit {
color: lime;
}
table.pilltable td {
padding: 8px 15px;
text-align: center;
font-size: 15px;
border-radius: 25px;
background-color: #2196f3;
color: white;
}
table.pilltable th {
font-weight: normal;
border: 0;
padding: 10px 0;
}
<!DOCTYPE html>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<head>
<meta charset="utf-8" />
<link rel="shortcut icon" href="//#" />
</head>
<body>
<div id="result"> </div>
<div class="center">
<table id="fruitsid" class="fruitsclass skillsTable class">
<thead></thead>
<tbody></tbody>
</table>
</div>
<div class="center">
<table cellspacing="5" id="carsid" cellspacing="5" class="carsclass pilltable class">
<thead></thead>
<tbody></tbody>
</table>
</div>
</body>
</html>
To fix this, I am adding some data properties in your random fruits, which I'm later using to get the right row and column to insert at. Have added some comments in code below to navigate.
Probably not the best implementation, but something like this should help you. (See snippet).
var obj = {}
var obj2 = {}
var key = 'Red Fruits'
obj[key] = ['Apple', 'Cherry', 'Strawberry']
var myArray = []
myArray.push(obj)
var key2 = 'Green Fruits'
obj[key2] = ['Watermelon', 'Durian', 'Avacado']
var myArray2 = []
myArray2.push(obj)
var key3 = 'Random Fruits'
obj2[key3] = ['Kiwi', 'Pomegranate', 'Honeydew', 'Plum', 'Mango', 'Lime', 'Pineapple', 'Starfruit', 'Cantaloupe', 'Blueberry']
var myArray3 = []
myArray3.push(obj2)
function redraw (obj) {
var $header = $('<tr>'),
cols = 0,
bodyString = ''
$.each(obj, function (key, values) {
cols = Math.max(cols, values.length)
$header.append($('<th/>').text(key))
})
for (var i = 0; i < cols; i++) {
bodyString += '<tr>'
$.each(obj, function (key, values) {
bodyString += '<td>' +
(values[i] ? values[i] : '') +
'</td>'
})
bodyString += '</tr>'
}
$('.fruitsclass thead').html($header)
$('.fruitsclass tbody').html(bodyString)
var bodyString = '<tr>'
var headString = ''
$.each(obj2[key3], function (index) {
if (index % 5 == 0 && index > 0) {
bodyString += ('</tr><tr>')
}
// adding data row and data column attributes
bodyString += ('<td data-row="' + parseInt(index / 5) + '" data-column="' + index % 5 + '">' + obj2[key3][index] + '</td>')
})
bodyString += '</tr>'
headString += ('<tr><th colspan="' + obj2[key3].length + '">' + 'Suggested Fruits' + '</th></tr>')
$('.carsclass tbody').html(bodyString)
$('.carsclass thead').html(headString)
}
function listener (obj) {
$(document).ready(function () {
$(document).on('click', '#carsid td', function () {
data = this.innerHTML
k1 = Object.keys(obj2).find(k => obj2[k].indexOf(data) >= 0)
index = obj2[k1].indexOf(data)
obj2[k1].splice(index, 1)
obj[key2].push(data)
var element = $(this).clone() // cloning to keep the placeholder in random fruits
$(this).replaceWith('<td></td>') // and removing it's content.
element.addClass('new-green-fruit')
// using outerHTML to get the whole attributes of the fruit including row and col
$('#fruitsid > tbody').append('<tr><td></td>' + element[0].outerHTML + '</tr>')
})
})
$(document).ready(function () {
$('body').on('click', 'td.new-green-fruit', function () {
data2 = this.innerHTML
k2 = Object.keys(obj).find(k => obj[k].indexOf(data2) >= 0)
index2 = obj[k2].indexOf(data2)
obj[k2].splice(index2, 1)
obj2[key3].push(data2)
$(this).parent().detach()
var element2 = $(this).detach()
var row = element2.data('row')
var col = element2.data('column')
// inserting in right row and column gathered from above.
$($($('#carsid > tbody tr')[row]).find('td')[col]).replaceWith(element2)
return false;
})
})
}
redraw(obj)
listener(obj)
.class {
font-family: Open Sans;
}
.center {
display: flex;
justify-content: center
}
table.skillsTable th {
border-left: 1px solid #AAA5A4;
border-right: 1px solid #AAA5A4;
color: #0080ff;
font-weight: normal;
border-bottom: 1px solid #AAA5A4;
padding-bottom: 5px;
}
table.skillsTable {
float: left;
border-collapse: collapse;
width: 70%
}
table.pillstable {
float: left;
width: 70% table-row:fixed;
}
table.skillsTable td {
border-left: 1px solid #AAA5A4;
border-right: 1px solid #AAA5A4;
padding-top: 8px;
padding-left: 11px;
font-size: 15px;
}
div {
margin-bottom: 50px;
}
.new-green-fruit {
color: lime;
}
table.pilltable td {
padding: 8px 15px;
text-align: center;
font-size: 15px;
border-radius: 25px;
background-color: #2196f3;
color: white;
}
table.pilltable th {
font-weight: normal;
border: 0;
padding: 10px 0;
}
<body>
<!DOCTYPE html>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<head>
<meta charset="utf-8" />
<link rel="shortcut icon" href="//#" />
</head>
<body>
<div id="result"> </div>
<div class="center">
<table id="fruitsid" class="fruitsclass skillsTable class">
<thead></thead>
<tbody></tbody>
</table>
</div>
<div class="center">
<table cellspacing="5" id="carsid" cellspacing="5" class="carsclass pilltable class">
<thead></thead>
<tbody></tbody>
</table>
</div>
</body>
</html>
To do this, I've created a new function redraw_after(obj) by slightly modifying your redraw(obj) function and placing both of the functions in the script. Now, just call the new redraw_after(obj) function after each of the listener functions to get the desired output.
What is happening here is that after each click, all the objects are redrawn to that 5 column in each row style. That's why it is working. Though, the new elements are added at the last of the queue each time, I guess the implementation is perfect, however.
var obj = {};
var obj2 = {};
var key = "Red Fruits";
obj[key] = ['Apple', 'Cherry', 'Strawberry'];
var myArray = [];
myArray.push(obj);
var key2 = "Green Fruits";
obj[key2] = ['Watermelon', 'Durian', 'Avacado'];
var myArray2 = [];
myArray2.push(obj);
var key3 = "Random Fruits";
obj2[key3] = ['Kiwi', 'Pomegranate', 'Honeydew', 'Plum', 'Mango', 'Lime', 'Pineapple', 'Starfruit', 'Cantaloupe', 'Blueberry'];
var myArray3 = [];
myArray3.push(obj2);
function redraw(obj) {
var $header = $("<tr>"),
cols = 0,
bodyString = "";
$.each(obj, function(key, values) {
cols = Math.max(cols, values.length);
$header.append($('<th/>').text(key));
});
for (var i = 0; i < cols; i++) {
bodyString += '<tr>';
$.each(obj, function(key, values) {
bodyString += '<td>' +
(values[i] ? values[i] : "") +
'</td>';
});
bodyString += '</tr>';
}
$('.fruitsclass thead').html($header);
$('.fruitsclass tbody').html(bodyString);
var bodyString = '<tr>';
var headString = '';
$.each(obj2[key3], function(index) {
if (index % 5 == 0 && index > 0) {
bodyString += ('</tr><tr>');
}
bodyString += ('<td>' + obj2[key3][index] + '</td>');
});
bodyString += '</tr>';
headString += ('<tr><th colspan="' + obj2[key3].length + '">' + 'Suggested Fruits' + '</th></tr>');
$('.carsclass tbody').html(bodyString);
$('.carsclass thead').html(headString);
}
function redraw_after(obj) {
var bodyString = "";
var bodyString = '<tr>';
var headString = '';
$.each(obj2[key3], function(index) {
if (index % 5 == 0 && index > 0) {
bodyString += ('</tr><tr>');
}
bodyString += ('<td>' + obj2[key3][index] + '</td>');
});
bodyString += '</tr>';
headString += ('<tr><th colspan="' + obj2[key3].length + '">' + 'Suggested Fruits' + '</th></tr>');
$('.carsclass tbody').html(bodyString);
$('.carsclass thead').html(headString);
}
function listener(obj) {
$(document).ready(function() {
$(document).on("click", "#carsid td", function() {
data = this.innerHTML;
k1 = Object.keys(obj2).find(k => obj2[k].indexOf(data) >= 0)
index = obj2[k1].indexOf(data);
obj2[k1].splice(index, 1);
obj[key2].push(data);
var element = $(this).detach();
$('#fruitsid > tbody').append('<tr><td></td><td class="new-green-fruit">' + element.html() + '</td></tr>');
redraw_after(obj);
});
});
$(document).ready(function() {
$('body').on('click', 'td.new-green-fruit', function() {
data2 = this.innerHTML;
k2 = Object.keys(obj).find(k => obj[k].indexOf(data2) >= 0)
index2 = obj[k2].indexOf(data2);
obj[k2].splice(index2, 1);
obj2[key3].push(data2);
$(this).parent().detach();
var element2 = $(this).detach();
$('#carsid > tbody').append('<td>' + element2.html() + '</td>');
redraw_after(obj);
});
});
}
redraw(obj);
listener(obj);
.class {
font-family: Open Sans;
}
.center {
display: flex;
justify-content: center
}
table.skillsTable th {
border-left: 1px solid #AAA5A4;
border-right: 1px solid #AAA5A4;
color: #0080ff;
font-weight: normal;
border-bottom: 1px solid #AAA5A4;
padding-bottom: 5px;
}
table.skillsTable {
float: left;
border-collapse: collapse;
width: 70%
}
table.pillstable {
float: left;
width: 70% table-row:fixed;
}
table.skillsTable td {
border-left: 1px solid #AAA5A4;
border-right: 1px solid #AAA5A4;
padding-top: 8px;
padding-left: 11px;
font-size: 15px;
}
div {
margin-bottom: 50px;
}
.new-green-fruit {
color: lime;
}
table.pilltable td {
padding: 8px 15px;
text-align: center;
font-size: 15px;
border-radius: 25px;
background-color: #2196f3;
color: white;
}
table.pilltable th {
font-weight: normal;
border: 0;
padding: 10px 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="result"> </div>
<div class="center">
<table id="fruitsid" class="fruitsclass skillsTable class">
<thead></thead>
<tbody></tbody>
</table>
</div>
<div class="center">
<table cellspacing="5" id="carsid" class="carsclass pilltable class">
<thead></thead>
<tbody></tbody>
</table>
</div>
That happens because you push the elements outside the rows and you don't save their positions. Solution: save the position and insert inside tr
function getPosition(data) {
return {
row: Number(data.split(' ')[0]),
column: Number(data.split(' ')[1])
};
}
Array.from(document.getElementsByClassName('elem')).forEach(elem => {
elem.addEventListener('click', e => {
if(e.target.parentNode.classList.contains('tr')) {
let position = getPosition(e.target.dataset.position);
let row = document.querySelector('.tab').querySelectorAll('tr')[position.row];
row.insertBefore(e.target, row.children[position.column]);
} else {
document.querySelector('.tr').appendChild(e.target);
}
});
});
.elems {
border: 1px solid black;
}
.elem {
background: rgb(0, 120, 255);
padding: 10px 10px;
border-radius: 10px;
}
<table class='elems'>
<tr class='tr'>
</tr>
</table>
<table class='tab'>
<tr><td class='elem' data-position='0 0'>ELem1</td>
<td class='elem' data-position='0 1'>Long ELem2</td>
<td class='elem' data-position='0 2'>Longer ELem3</td></tr>
<tr><td class='elem' data-position='1 0'>Even Longer ELem4</td>
<td class='elem' data-position='1 1'>Short ELem5</td>
<td class='elem' data-position='1 2'>Just ELem6</td></tr>
</table>
You could also use flexbox
Array.from(document.getElementsByClassName("elem")).forEach(elem => {
elem.addEventListener('click', e => {
document.querySelector('.flex-box').appendChild(e.target);
});
});
.flex-box {
display: flex;
width: 500px;
flex-wrap: wrap;
}
.elem {
background: rgb(0, 120, 255);
padding: 10px 10px;
border-radius: 10px;
}
.flex-box .elem {
flex: 1 0 content;
}
<div class='elems'>
<div class='elem'>ELem1</div>
<div class='elem'>Long ELem2</div>
<div class='elem'>Longer ELem3</div>
<div class='elem'>Even Longer ELem4</div>
<div class='elem'>Short ELem5</div>
<div class='elem'>Just ELem6</div>
</div>
<div class='flex-box'></div>
This solution requires more code because you have to move elements from table to div (possible to avoid with some changes to the table). Other than that, the elements are not automatically stretched when using flexbox, so you don't have to play with the elements to prevent overstretching when one of them has long contents.
If you want to preserve the order, use the order property.

Remove Row from table using jQuery

I want to generate a table with content of the array with an option to delete the rows. I got a basic block of code that I think that should work but it's not doing anything and it's giving me "Uncaught SyntaxError: Unexpected token }" error.
function newtest2() {
$(this).parents('tr').remove();
}
function newtest() {
var name = ["Avengers", "Black Mirror", "Star Wars"];
var r = name.length;
$("#table1").empty();
for (var i = 0; i < r; i += 1) {
$("#table1").append("<tr><td>" + name[i] + "</td><td>" + "<button onclick='newtest2(this)'>Remove</button>" + "</td></tr>");
}
}
#table1 {
background: gray;
}
td {
border: 1px solid black;
text-align: center;
color: white;
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<table id="table1">
</table>
<br>
<button onclick="newtest()">TEST</button>
this doesn't refers to TABLE/BUTTON in the newtest2() method, it refers to window object thus the code didn't work.
Accept the this argument in function and use it
function newtest2(elem) {
$(elem).closest('tr').remove();
}
function newtest2(elem) {
$(elem).closest('tr').remove();
}
function newtest() {
var name = ["Avengers", "Black Mirror", "Star Wars"];
var r = name.length;
$("#table1").empty();
for (var i = 0; i < r; i += 1) {
$("#table1").append("<tr><td>" + name[i] + "</td><td>" + "<button onclick='newtest2(this)'>Remove</button>" + "</td></tr>");
}
}
#table1 {
background: gray;
}
td {
border: 1px solid black;
text-align: center;
color: white;
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<table id="table1">
</table>
<br>
<button onclick="newtest()">TEST</button>
I would recommend, you to use unobtrusive event handler use .on() to attach event handler with elements instead of ugly inline event handler.
Using .on() method with Event Delegation approach to attach event handler for dynamic elements (Remove Button).
$("#table1").on('click', '.remove', function() {
$(this).closest('tr').remove();
})
$("#create").on('click', function() {
var name = ["Avengers", "Black Mirror", "Star Wars"];
var r = name.length;
$("#table1").empty();
for (var i = 0; i < r; i += 1) {
$("#table1").append("<tr><td>" + name[i] + "</td><td>" + "<button class='remove' type='button'>Remove</button>" + "</td></tr>");
}
})
#table1 {
background: gray;
}
td {
border: 1px solid black;
text-align: center;
color: white;
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<table id="table1">
</table>
<br>
<button id="create">TEST</button>
To remove a row on click of the button:
$('#table_id').on('click', '#remButton', function(){
var indexRow = this.parentNode.parentNode.rowIndex;
document.getElementById("table_ID").deleteRow(indexRow);
});
You need to specify an argument in your function, and then you need to get the parent of the parent of the this element, because it is a button, and not the <td>.
Here is a working example. Note there might be a better way of doing this with click events and ids
function newtest2(evt) {
$(evt).parent().parent().remove();
}
function newtest() {
var name = ["Avengers", "Black Mirror", "Star Wars"];
var r = name.length;
$("#table1").empty();
for (var i = 0; i < r; i += 1) {
$("#table1").append("<tr><td>" + name[i] + "</td><td>" + "<button onclick='newtest2(this)'>Remove</button>" + "</td></tr>");
}
}
#table1 {
background: gray;
}
td {
border: 1px solid black;
text-align: center;
color: white;
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<table id="table1">
</table>
<br>
<button onclick="newtest()">TEST</button>
You are passing this on the on HTML - newtest2(this).
On your function, you need to recieve the variable and use it to delete the <tr>
function newtest2(e) { //Add e as parameter
$(e).parents('tr').remove(); //Use the e to delete
}
Here is the snippet:
function newtest2(e) {
$(e).parents('tr').remove();
}
function newtest() {
var name = ["Avengers", "Black Mirror", "Star Wars"];
var r = name.length;
$("#table1").empty();
for (var i = 0; i < r; i += 1) {
$("#table1").append("<tr><td>" + name[i] + "</td><td>" + "<button onclick='newtest2(this)'>Remove</button>" + "</td></tr>");
}
}
#table1 {
background: gray;
}
td {
border: 1px solid black;
text-align: center;
color: white;
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<table id="table1">
</table>
<br>
<button onclick="newtest()">TEST</button>
you can't use $(this) inside your function because it does not refer to the button being clicked.
Since you are including the function inside onclick and passing this as parameter, just use that parameter inside your function, like so
Secondary suggestion: use .closest('tr') instead of .parents('tr'), in case, you know, in the future you might want a table inside a table, ;)
function newtest2(caller) {
$(caller).closest('tr').remove();
}
function newtest() {
var name = ["Avengers", "Black Mirror", "Star Wars"];
var r = name.length;
$("#table1").empty();
for (var i = 0; i < r; i += 1) {
$("#table1").append("<tr><td>" + name[i] + "</td><td>" + "<button onclick='newtest2(this)'>Remove</button>" + "</td></tr>");
}
}
#table1 {
background: gray;
}
td {
border: 1px solid black;
text-align: center;
color: white;
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<table id="table1">
</table>
<br>
<button onclick="newtest()">TEST</button>
Change parent by closest. Parent is the immediate parent, closest is
traversing the dom.
this in the function newttest2 doesn't refer to the button
element, just refer to it as a function parameter
function newtest2(el) {
$(el).closest('tr').remove();
}
function newtest() {
var name = ["Avengers", "Black Mirror", "Star Wars"];
var r = name.length;
$("#table1").empty();
for (var i = 0; i < r; i += 1) {
$("#table1").append("<tr><td>" + name[i] + "</td><td>" + "<button onclick='newtest2(this)'>Remove</button>" + "</td></tr>");
}
}
#table1 {
background: gray;
}
td {
border: 1px solid black;
text-align: center;
color: white;
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<table id="table1">
</table>
<br>
<button onclick="newtest()">TEST</button>
try this
for (var i = 0; i < name.length; i += 1) {
$("#table1").append("<tr id=" + name[i] + "><td>" + name[i] + "</td><td>" + "<button id=" + name[i] + " onclick='newtest2(this.id)'>Remove</button>" + "</td></tr>");
}
function newtest2(id) {
$('#' + id + '').remove();
}

Categories

Resources