Possible to only run code block inside for loop once? - javascript

I'm using the loop to find whole table columns containing cells with a certain class and it works fine for applying class and the other stuff below. The only problem is that I would also like to output the value of the cells once. Is this possible somehow?
$('td:first-child').each(function() {
for (var i = 0; i <= 5; i++) {
var col = $('.tabell tr').find('td:nth-child(' + i + ').check').length;
if (col == 5) {
$(".bingocl").fadeIn(2000);
var column = $('.tabell tr').find('td:nth-child(' + i + ')');
column.addClass("bingo", 2000);
var text = column.text().toUpperCase();
$("#textout").append(text + "!!");
}
}
});
Update:
$('td:first-child').each(function() {
for(var i = 0; i <= 5; i++) {
var col = $('.tabell tr').find('td:nth-child(' + i + ').check').length;
var column = $('.tabell tr').find('td:nth-child(' + i + ')');
if (col == 5) {
$( ".bingocl" ).fadeIn(2000);
column.addClass("bingo", 2000);
column.each(function() {
$("#textout").append($(this).html() + " ");
});
break;
}
}
});
function in it's entirety:
var main = function() {
//Styling the rows
$(".tabell tbody").find("tr").each(function(idx) {
var row = $(this);
if (row.find("td").length == row.find("td.check").length) {
row.addClass("bingo");
$(".bingocl").fadeIn(2000);
var text = row.find("td").text().toUpperCase();
$("#textout").append(text + "!!");
}
});
//styling cols
$('td:first-child').each(function() {
for (var i = 0; i <= 5; i++) {
var col = $('.tabell tr').find('td:nth-child(' + i + ').check').length;
if (col == 5) {
$(".bingocl").fadeIn(2000);
var column = $('.tabell tr').find('td:nth-child(' + i + ')');
column.addClass("bingo", 2000);
var text = column.text().toUpperCase();
$("#textout").append(text + "!!");
break;
}
}
});
}
$(document).ready(main);

Provided you already have access to your winning row/column (you add a bingo class to them), you can access each individual element to output it's value.
Your code becomes:
var main = function() {
//Styling the rows
$(".tabell tbody").find("tr").each(function(idx) {
var row = $(this);
if (row.find("td").length == row.find("td.check").length) {
row.addClass("bingo");
$(".bingocl").fadeIn(2000);
// Iterate your row elements
row.each(function(){document.write($(this).html() + " ");});
}
});
//styling cols
//$('td:first-child').each(function() { <- remove this
for (var i = 0; i <= 5; i++) {
var col = $('.tabell tr').find('td:nth-child(' + i + ').check').length;
if (col == 5) {
$(".bingocl").fadeIn(2000);
var column = $('.tabell tr').find('td:nth-child(' + i + ')');
column.addClass("bingo", 2000);
// Iterate your column elements
column.each(function(){document.write($(this).html() + " ");});
break;
}
}
//}); <- remove this
}
$(document).ready(main);
Live example
var column = $(".selected_column");
var row = $(".selected_row");
column.addClass("bingo");
row.addClass("bingo");
column.each(function() {
$("#textout").append($(this).html() + " ");
});
row.each(function() {
$("#textout").append($(this).html() + " ");
});
.selected_column {
background: blue;
}
.selected_row {
background: yellow;
}
.selected_column.selected_row {
background: green;
}
.bingo {
border: 2px solid lime;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<td>A</td>
<td class="selected_column">B</td>
<td>C</td>
<td>D</td>
<td>E</td>
</tr>
<tr>
<td>F</td>
<td class="selected_column">G</td>
<td>H</td>
<td>I</td>
<td>J</td>
</tr>
<tr>
<td>K</td>
<td class="selected_column">L</td>
<td>M</td>
<td>N</td>
<td>O</td>
</tr>
<tr>
<td class="selected_row">P</td>
<td class="selected_column selected_row">Q</td>
<td class="selected_row">R</td>
<td class="selected_row">S</td>
<td class="selected_row">T</td>
</tr>
<tr>
<td>U</td>
<td class="selected_column">V</td>
<td>W</td>
<td>X</td>
<td>Y</td>
</tr>
</table>
<p id="textout">#textout : </p>

You can do column.html(); to get the cell content

You could always try with break.
Link: MDN

Try to use break:
$('td:first-child').each(function() {
for (var i = 0; i <= 5; i++) {
var col = $('.tabell tr').find('td:nth-child(' + i + ').check').length;
if (col == 5) {
$(".bingocl").fadeIn(2000);
var column = $('.tabell tr').find('td:nth-child(' + i + ')');
column.addClass("bingo", 2000);
var text = column.text().toUpperCase();
$("#textout").append(text + "!!");
break;
}
}
});

Related

I have a mysterious <BR> being added to my table

I cant figure out why a double <BR> is automatically being added to my newly appended table rows.
All you have to do is hit the enter key to cause the problem.
I don't want any <br> to be added, it screws up my data entry process.
The problem appears to be happening in the appenNewRow() function.
<!DOCTYPE html>
<html>
<head>
<title>jQuery Text Area Order Input</title>
<style>
.myInputClass {
width: 120px;
}
.myOutputClass {
width: 240px;
}
</style>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script>
storeflag = true;
attribstart = "";
attribend = "";
output_result = "";
var row = 0;
var storeIndex = 0;
var productIndex = 0;
var thisstore_id=0;
function appendNewRow(inputType)
{
row++;
var markup = "<tr id='"+row+"'><td input-row='"+row+"' input-type='"+inputType+"' class='myInputClass' height='auto' contenteditable='true' placeholder='Next'></td><td output-row='"+row+"' class='myOutputClass'></td><td extra-row='"+row+"' class='extra'></td></tr>";
$("table tbody").append(markup);
myjunk = document.querySelector('[input-row="' + row + '"]').innerHTML;
document.querySelector('[input-row="' + row + '"]').innerHTML = "zzz";
document.getElementById(row).getElementsByClassName('myInputClass')[0].focus();
}
function getStore(thisstore)
{
}
function getProduct(thisstore_id, thisproduct_nickname)
{
}
$(document).ready(function(){
document.getElementById('1').getElementsByClassName('myInputClass')[0].focus();
lastKey = 13;
$("tbody").on('keypress', ".myInputClass", (function(event){
if (event.which == 13) { // Enter Key.
attribstart = "";
attribend = "";
row = Number($(this).attr('input-row'));
thishtml = $(this).html();
if ($(this).text().length > 0) {
x = $(this).text();
if (storeflag == true) {
thisstore_id = getStore(x);
} else {
getProduct(thisstore_id,x);
}
} else {
$(this).text("---");
appendNewRow('store');
storeflag = true;
//$('#YourContainer').find('br').remove();
$('[input-row="' + row + '"]').find('br').remove(); // Fixes an ajax bug.
}
} else {
} //end if
lastKey = event.which;
}));
});
</script>
</head>
<body>
<table>
<thead>
<tr>
<th>Input</th>
<th>Output</th>
<th>Extra</th>
</tr>
</thead>
<tbody>
<tr id='1'>
<td input-row='1' input-type='store' class='myInputClass' height='auto' contenteditable='true' placeholder='Just Start Typing a storename'></td>
<td output-row='1' class='myOutputClass'></td>
<td extra-row='1' class='extra'></td>
</tr>
</tbody>
</table>
</body>
</html>
I cleaned up the code you presented. It's a better practice to use all jQuery or all JavaScript. Based on the following testing, you may need to add the content and then make it Editable.
$(function() {
$("#empty").click(function() {
$("<tr>").appendTo($("table tbody"));
$("<td>").appendTo($("table tr:last")).prop("contenteditable", true);
});
$("#full").click(function() {
$("<tr>").appendTo($("table tbody"));
$("<td>").appendTo($("table tr:last")).html("Edit").prop("contenteditable", true);
});
});
table {
border: 1px solid black;
border-collapse: collapse;
padding: 0;
margin: 0;
}
table tr {
height: 1.5em;
}
table tr td {
border: 1px dashed black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tbody>
<tr>
<td>Non-Edit</td>
</tr>
</tbody>
</table>
<button id="empty">Add Empty Row</button>
<button id="full">Add Full Row</button>
We apply this to your code.
$(function() {
var storeflag = true,
attribstart = "",
attribend = "",
output_result = "",
row = 0,
storeIndex = 0,
productIndex = 0,
thisstore_id = 0;
function appendNewRow(inputType) {
var markRow = $("<tr>", {
id: ++row
}).appendTo($("table tbody"));
$("<td>", {
class: "myInputClass",
height: "auto",
placeholder: "Next",
"input-row": row,
"input-type": inputType
}).appendTo(markRow);
$("<td>", {
class: "myOutputClass",
"output-row": row
}).appendTo(markRow);
$("<td>", {
class: "extra",
"extra-row": row
}).appendTo(markRow);
$("td:eq(0)", markRow).html("Start").prop("contenteditable", true).focus();
}
function getStore(thisstore) {
$.ajax({
url: 'ajax_getstore',
data: "store=" + thisstore,
method: "GET",
dataType: "json",
cache: false,
success: function(data) {
var markup = "";
if (data.length > 1) {
$.each(data, function(thisname, thisvalue) {
var output = attribstart + thisvalue.fields.name + attribend;
markup += "<tr id='" + row + "'><td class='dyninput'>row:" + row + " - " + output + "</td></tr>";
});
} else {
$('[input-row="' + row + '"]').html(thisstore); // Fixes an ajax bug.
$('[output-row="' + row + '"]').attr('input-type', 'store');
$('[output-row="' + row + '"]').html(attribstart + data[0].fields.name + attribend);
}
thisstore_id = data[0].pk;
appendNewRow('product');
output_result = "";
}, // End success.
error: function() {
alert('error');
},
}); //End Ajax.
attribstart = "<b>";
attribend = "</b>";
storeflag = false; //reset storeflag.
}
function getProduct(thisstore_id, thisproduct_nickname) {
var qty = parseInt(thisproduct_nickname);
if (isNaN(qty)) {
qty = '1';
} else {
thisproduct_nickname = thisproduct_nickname.replace(qty, '');
}
$.ajax({
url: 'ajax_getproduct',
data: 'store_id=' + thisstore_id + '&qty=' + qty + '&product_nickname=' + thisproduct_nickname,
method: "GET",
dataType: "json",
cache: false,
success: function(data) {
var markup = "";
if (data.length > 1) {
$.each(data, function(thisname, thisvalue) {
var output = attribstart + thisvalue.fields.product_name + attribend;
markup = markup + "<tr id='" + row + "'><td class='dyninput'>row:" + row + " - " + output + "<br></td></tr>";
row++;
});
} else {
$('[input-row="' + row + '"]').html(thisproduct_nickname); // Fixes an ajax bug.
$('[output-row="' + row + '"]').attr('input-type', 'product');
$('[output-row="' + row + '"]').html(attribstart + qty + ' ' + data[0].fields.product_default_uom_code + ' ' + data[0].fields.product_name + attribend);
}
appendNewRow('product');
output_result = "";
}, // End success.
error: function() {
alert('error');
},
}); //End Ajax.
}
function display_result(data_output_result) {
var badjson = JSON.parse(data_output_result);
var myjson = badjson.replace("\\", "");
var goodjson = JSON.parse(myjson);
var markup = "";
$.each(goodjson, function(thisname, thisvalue) {
row = row + 1;
var output = attribstart + thisvalue.fields.name + attribend;
markup += "<tr id='" + row + "'><td class='dyninput'>row:" + row + " - " + output + "<br></td></tr>";
console.log(thisvalue.fields.id, thisvalue.fields.name);
});
$("table tbody#myOutputBodyId").append(markup);
output_result = "";
}
$('#1 .myInputClass').focus();
var lastKey = 13;
$("tbody").on('keypress', ".myInputClass", function(event) {
event.preventDefault();
if (event.which == 13) { // Enter Key.
attribstart = "";
attribend = "";
row = Number($(this).attr('input-row'));
thishtml = $(this).html();
if ($(this).text().length > 0) {
x = $(this).text();
if (storeflag == true) {
thisstore_id = getStore(x);
} else {
getProduct(thisstore_id, x);
}
} else {
$(this).text("---");
appendNewRow('store');
storeflag = true;
//$('#YourContainer').find('br').remove();
$('[input-row="' + row + '"]').find('br').remove(); // Fixes an ajax bug.
}
} //end if
lastKey = event.which;
});
});
.myInputClass {
width: 120px;
}
.myOutputClass {
width: 240px;
}
table,
td {
margin: 0px;
border-collapse: collapse;
padding: 0px;
border-spacing: 0px;
vertical-align: top;
}
table th {
border: 1px solid #6C220B;
border-spacing: 0px;
padding: 0px;
text-align: left;
}
table#myOutputTableId {
border: 0px;
padding: 0px;
margin: 0px;
align: top;
}
[xcontentEditable=true]:empty:before {
content: attr(placeholder);
opacity: 0.6;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<th>Input</th>
<th>Output</th>
<th>Extra</th>
</tr>
</thead>
<tbody>
<tr id='1'>
<td input-row='1' input-type='store' class='myInputClass' height='auto' contenteditable='true' placeholder='Just Start Typing a storename'></td>
<td output-row='1' class='myOutputClass'></td>
<td extra-row='1' class='extra'></td>
</tr>
</tbody>
</table>
The issue was the key capture from the Enter. This was injecting the new line in the editable and creating the <br>. We can use .preventDefault() to address this.
I am unable to test this code as it does not connect to any of the AJAX Urls.

Format result after looping object

I'm looping an object and expect the result as elements of a table
var db = {
"id": "8",
"user_id": "24",
"batchno": "367727",
"ht_number": "jibhbu",
"ht_taste": "uvyutvc",
"pp_flavour": "ytv,yurtcrc,urt",
"pp_fruit_batch": "cuyt,cytc,yt",
"sl_flavour": "ouihyuigytvytc",
"sl_appearance": "rtctr"
},
pp_ = '<table><tbody>';
for (var i in db) {
if (db.hasOwnProperty(i)) {
var js = db[i].split(',');
for (var x in js) {
if (i.startsWith('pp_')) {
pp_ += '<tr><td>' + i + ' ' + x + ' : ' + js[x] + '</td></tr>';
}
}
}
}
pp_ += '</tbody></table>';
document.write(pp_);
I am splitting values that have commas so that each index of an array sits on 1 row (tr)
what I can't figure out is how to place elements with the same index on the same level (row) so I can I have something like
table, td {
border: 1px solid black;
}
<table>
<tbody>
<tr>
<td> pp_flavour 0 - its value </td>
<td> pp_fruit_batch 0 - its value </td>
</tr>
<tr>
<td> pp_flavour 1 - its value </td>
<td> pp_fruit_batch 1 - its value </td>
</tr>
<tr>
<td> pp_flavour 2 - its value </td>
<td> pp_fruit_batch 2 - its value </td>
</tr>
</tbody>
</table>
<br>
<table>
<tbody>
<tr>
<td> sl_favour 0 - its value </td>
<td> sl_appearance 0 - its value </td>
</tr>
<tr>
<td> sl_favour 1 - its value </td>
<td> sl_appearance 1 - its value </td>
</tr>
</tbody>
</table>
and so on...
You could try indexing the database like this:
var db = {
"id": "8",
"user_id": "24",
"batchno": "367727",
"ht_number": "jibhbu",
"ht_taste": "uvyutvc",
"pp_flavour": "ytv,yurtcrc,urt",
"pp_fruit_batch": "cuyt,cytc,yt",
"sl_flavour": "ouihyuigytvytc",
"sl_appearance": "rtctr"
};
var prefixes = ["pp", "ht", "sl"];
var prefixedDb = {};
var result = "";
for (var i in db) {
if (db.hasOwnProperty(i)) {
var parts = i.split("_");
var prefix = parts[0];
if (prefixes.indexOf(prefix) === -1) continue;
if (prefixedDb[prefix] === undefined) {
prefixedDb[prefix] = {};
}
prefixedDb[prefix][parts.slice(1).join("_")] = db[i];
}
}
for (var k in prefixedDb) {
if (prefixedDb.hasOwnProperty(k)) {
var db = prefixedDb[k];
var dbIndexed = {};
for (var i in db) {
if (db.hasOwnProperty(i)) {
var vals = db[i].split(',');
vals.forEach(function(val, j) {
if (dbIndexed[j] === undefined) {
dbIndexed[j] = {};
}
dbIndexed[j][i] = val;
});
}
}
result += "<table><tbody>";
for (var i in dbIndexed) {
if (dbIndexed.hasOwnProperty(i)) {
result += "<tr>";
var indexVals = dbIndexed[i];
for (var j in indexVals) {
if (indexVals.hasOwnProperty(j)) {
result += "<td>" + j + " " + i + " - " + indexVals[j] + "</td>";
}
}
result += "</tr>";
}
}
result += "</tbody></table>";
}
}
document.write(result);
table, td {
border: 1px solid black;
}
Please note that this code may not be the most optimized code for this task.
You can try adding each value of the table to a 2-D array and than form the table from this 2-D array
try below solution
NOTE: this will also work with different number of rows and Column.
var db = {
"id": "8",
"user_id": "24",
"batchno": "367727",
"ht_number": "jibhbu",
"ht_taste": "uvyutvc",
"pp_flavour": "ytv,yurtcrc,urt",
"pp_fruit_batch": "cuyt,cytc,yt",
"sl_flavour": "ouihyuigytvytc",
"sl_appearance": "rtctr"
};
function createTable(myKey){
var rows = [];
for (var dbKey in db) {
if (db.hasOwnProperty(dbKey)) {
if (dbKey.startsWith(myKey)) {
var values = db[dbKey].split(',');
for (var val in values) {
if (!rows[val])
rows[val] = [];
rows[val].push('<td>' + dbKey + ' ' + val + ' : ' + values[val] + '</td>');
}
}
}
}
var myTable = '<table><tbody>';
for (var i = 0; i < rows.length; i++) {
myTable += "<tr>" + rows[i].join("") + "</tr>";
}
myTable += '</tbody></table>';
return myTable;
}
var ht_table = createTable("ht_");
document.getElementById("myTable").innerHTML +="<br/>"+ ht_table;
var pp_table = createTable("pp_");
document.getElementById("myTable").innerHTML +="<br/>"+ pp_table;
var sl_table = createTable("sl_");
document.getElementById("myTable").innerHTML += "<br/>"+ sl_table;
table, td {
border-style: solid;
}
<p id="myTable">
</p>
You could take the wanted values out of the object, split them and take the max length for iterating the rows for the table. Then assemble the table by iterating the values.
var db = { pp_flavour: "ytv,yurtcrc,urt", pp_fruit_batch: "cuyt,cytc,yt,42" },
values = Object.keys(db).filter(k => k.startsWith('pp_')).map(k => (db[k] || '').split(',')),
length = values.reduce((r, a) => Math.max(r, a.length), 0),
table = document.createElement('table'),
tr,
i;
for (i = 0; i < length; i++) {
tr = document.createElement('tr');
table.appendChild(tr);
values.forEach(function (a) {
var td = document.createElement('td');
td.appendChild(document.createTextNode(i in a ? a[i] : ''));
tr.appendChild(td);
});
}
document.body.appendChild(table);
Create a loop, incrementing a counter, which will determine if a key's split value should be output.
If there are no more values found at the index of the counter, stop looping.
var db = {
"id": "8",
"user_id": "24",
"batchno": "367727",
"ht_number": "jibhbu",
"ht_taste": "uvyutvc",
"pp_flavour": "ytv,yurtcrc,urt",
"pp_fruit_batch": "cuyt,cytc,yt",
"sl_flavour": "ouihyuigytvytc",
"sl_appearance": "rtctr"
},
s = '';
['pp_', 'ht_', 'sl_'].forEach(function(type) {
var i,
found = true;
s += '<table>';
for(i = 0 ; found ; i++) {
s += '<tr>';
found = false;
Object.keys(db).forEach(function(key) {
var js = db[key].split(',');
if(js[i] && key.startsWith(type)) {
found = true;
s += '<td>' + key + ' ' + i + ' : ' + js[i] + '</td>';
}
});
s += '</tr>';
}
s += '</table>';
});
document.write(s);
td {
border-bottom: 1px solid #bbb;
border-right: 1px solid #ddd;
padding: 0.5em;
}
table {
border: 1px solid black;
margin-bottom: 1em;
border-spacing: 0;
}

Get Table data in json format

Hello everyone I'm trying to get table data in json format here is my table
<table>
<thead>
<tr>
<th>srno</th>
<th>name</th>
<th>email</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Jhon One</td>
<td>Doe one</td>
</tr>
<tr>
<td>2</td>
<td>Jhon two</td>
<td>Doe Two</td>
</tr>
</tbody>
</table>
<button>
convert
</button>
the result which i am getting is this
{
"0": {
"1",
"Jhon One",
"Doe one"
}
,
"1": {
"2",
"Jhon two",
"Doe Two"
}
}
using the below javascript
$("button").click(function() {
var json = html2json();
alert(json);
});
function html2json() {
var json = '{';
var otArr = [];
// var i = 1;
var tbl2 = $('table tbody tr').each(function(e) {
x = $(this).children();
var itArr = [];
x.each(function() {
itArr.push('"' + $(this).text() + '"');
});
otArr.push('"' + e + '": {' + itArr.join(',') + '}');
})
json += otArr.join(",") + '}'
return json;
}
but i want to add key to every value and the number should start from one and not zero.
i have a set of desire result and it should look like this
any help is appreciated
{
"1": {
no: "1",
name:"Jhon One",
lastname "Doe one"
}
,
"2": {
no: "1",
name:"Jhon two",
lastname "Doe two"
}
}
here is the fiddel link which i have tried
https://jsfiddle.net/k228n2bn/
Just change the following line
otArr.push('"' + e + '": {' + itArr.join(',') + '}');
to
otArr.push('"' + (e+1) + '": {' + itArr.join(',') + '}');
The parenthesis will add the values as numbers not strings.
Also, add keys array for internal object keys.
function html2json() {
var json = '{';
var otArr = [];
// var i = 1;
var tbl2 = $('table tbody tr').each(function(e) {
x = $(this).children();
var itArr = [];
var keys = ['no','name','lastname'];
x.each(function(i) {
itArr.push('"' + keys[i] + '":"' + $(this).text() + '"');
});
otArr.push('"' + (e+1) + '": {' + itArr.join(',') + '}');
})
json += otArr.join(",") + '}'
return json;
}
You can convert e to a Number and add one to it like in this fiddle.
function html2json() {
var json = '{';
var otArr = [];
// var i = 1;
var tbl2 = $('table tbody tr').each(function(e) {
x = $(this).children();
var itArr = [];
x.each(function() {
itArr.push('"' + $(this).text() + '"');
});
otArr.push('"' + (Number(e) + 1) + '": {' + itArr.join(',') + '}');
})
json += otArr.join(",") + '}'
return json;
}
The json you're returning is not valid though. You may want to do something like this fiddle if you can to simplify and ensure valid json and to create your objects from any table structure.
function html2json() {
var otArr = [];
var tblHeaders = Array.from($('table thead tr')
.children())
.map(header => $(header).text());
var tbl2 = $('table tbody tr').each(function(e) {
const values = Array.from($(this).children());
const row = {};
for (let i = 0; i < tblHeaders.length; i++){
row[tblHeaders[i]] = $(values[i]).text();
}
otArr.push({
[e+1]: row
})
})
json = JSON.stringify(otArr);
return json;
}
Try e+1
change otArr.push('"' + e + '": {' + itArr.join(',') + '}');
to
otArr.push('"' + (e+1) + '": {' + itArr.join(',') + '}');
$("button").click(function() {
var json = html2json();
});
function html2json() {
var json = '{';
var otArr = [];
var tbl2 = $('table tbody tr').each(function(e) {
x = $(this).children();
var itArr = [];
x.each(function(e) {
var items='';
if(e == 0){
items +='no : "'+ $(this).text()+'"';
}
if(e == 1){
items +='name : "' +$(this).text()+'"';
}
if(e == 2){
items +='email : "' +$(this).text()+'"';
}
itArr.push(items);
});
otArr.push('"' + (e+1) + '": {' + itArr.join(',') + '}');
})
json += otArr.join(",") + '}'
alert(json);
return json;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<th>srno</th>
<th>name</th>
<th>email</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Jhon One</td>
<td>Doe one</td>
</tr>
<tr>
<td>2</td>
<td>Jhon two</td>
<td>Doe Two</td>
</tr>
</tbody>
</table>
<button>
convert
</button>
Maybe you can use theads as keys for the generated objects.
Check this jsfiddle.
function html2json() {
var $table = $('table');
var $ths = $table.find('thead>tr>th');
var rows = {};
$table.find('tbody>tr').each(function () {
var row = {};
$(this).children().each(function (index) {
row[$ths[index].textContent] = this.textContent;
});
rows[row.srno] = row;
});
return JSON.stringify(rows);
}

How to optimize jquery script (table creation N rows X 56 cols)

Hi I have a jquery scripts that takes table template and adds N rows (N=[1...100]) as clones of first TR. then each cell in each row is populated with some data (not all cells are always filled), each cell has " on clik " event attached, and on cell hover row, cell, coll is highlighted.
The problem i am facing is the optimization of generation (time) and usability (the mouse movemnts aren't smooth)
the code:
HTML template table:
<table id='schedulerview' class='myGrid'>
<colgroup id='col_0'></colgroup>
<colgroup id='col_1'></colgroup>
<colgroup id='col_2'></colgroup>
<colgroup id='col_3'></colgroup>
....
<colgroup id='col_55'></colgroup>
<thead>
<tr>
<th>0</th>
<th>1</th>
<th>2</th>
<th>3</th>
....
<th>51</th>
</tr>
</thead>
<tbody>
<tr id='template' style='display:none'>
<td id='0' HID='W0_Y_I' class='scheddata'>Week 1</td>
.....
<td id='51' HID='W55_Y_I' class='scheddata'>Week 52</td>
</tr>
</tbody>
</table>
CSS :
.litrow { background-color: #eee; }
.litcell { background-color: yellow; }
file codebehind.js
$(document).ready(function () {
//turn on row, cell, column highlight on hover
$("table#schedulerview tbody").on('mouseenter', 'tr', function () {
$(this).addClass('litrow');
});
$("table#schedulerview tbody").on('mouseleave', 'tr', function () {
$(this).removeClass('litrow');
});
$("table#schedulerview tbody").on('mouseenter', 'td', function () {
$(this).addClass('litcell');
$("colgroup").eq($(this).index()).addClass("litrow");
});
$("table#schedulerview tbody").on('mouseleave', 'td', function () {
$(this).removeClass('litcell');
$("colgroup").eq($(this).index()).removeClass("litrow");
});
//function for getting data and create schedule table from template table
getSchedule();
});
getschedule function:
function getSchedule() {
var data = "{userid:'" + userid + "',year:" + year + "}";
$.ajax({
type: "POST",
url: "/Scheduler.aspx/getSchedule",
data: data,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (ret) {
var areas = JSON.parse(ret.d.Areas);
var schedule = JSON.parse(ret.d.Schedule);
//remove all rows from table that are not template
$('table#schedulerview tr.eventSchedule').remove();
//create row for each element from DB - prepare matrix elementsXWeeks
var $tr = $('#template');
$.each(areas, function (i, x) {
var $clone = $tr.clone();
$clone.css('display', 'block');
$clone.attr('id', 'new_row_' + i);
$clone.addClass('eventSchedule');
$clone.children('td:first').text(x.AreaName);
//for each cell in new row
$clone.children('td.scheddata').each(function () {
var $this = $(this);
var HID = $this.attr("HID").replace('_Y_', '_' + year + '_').replace('_I', '_' + x.IDObszaru);
$this.attr("HID", HID);
});
$tr.before($clone);
});
//fill in the matrix with scheduled data
$.each(schedule, function (i, x) {
$td = $("table#schedulerview td[HID='" + x.HID + "']");
$td.addClass(x.Status);
$td.attr("WeekNum", x.WeekNum);
$td.attr("PlanID", x.Id);
$td.parent().addClass('plannedrow');
});
},
error: function (ret) {
alert(ret.responseText);
}
});
}
The getSchedule() function lasts few seconds, is it possible to optimize it so it would be faster?
CHANGES:
I've tried different approach for row creation:
for (i = 0; i < areas.length; i++) {
$lasttr = $("table#schedulerview tbody").append("<tr id='new_row_" + i + "' class='eventSchedule' ></tr>");
$lasttr = $("table#schedulerview tbody tr#new_row_" + i);
for (j = 0; j < 56; j++) {
var sclass = "";
if (j == 0)
$lasttr.append("<td>" + areas[i].AreaName + "</td>");
if (j == 1)
$lasttr.append("<td>" + areas[i].AreaSubName + "</td>");
if (j == 2)
$lasttr.append("<td>" + areas[i].AreaParentName + "</td>");
if (j > 2) {
sclass = "'scheddata'";
k = j - 2;
$lasttr.append("<td class=" + sclass + " HID='W" + k + "_" + year + "_" + areas[i].AreaID + "'></td>");
}
}
}
but it's not fast enough- and the problem with hovering remains. (also when using css :hover pseudoclass.
Can you do something like this?
$(function () {
for (i = 0; i < 56; i++)
$("thead tr").append("<th>" + (i+1) +"</th>");
for (i = 0; i < 20; i++){
$("tbody").append("<tr />");
for (j = 0; j < 56; j++)
$("tbody tr:last-child").append("<td>" + ((i+1) + ": " + (j+1)) +"</td>");
}
});
table tr:hover td {background: #99f;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<table>
<thead><tr></tr></thead>
<tbody></tbody>
</table>

Get Cell Location

So I have this table, and when I click on a td I would like to know where is that(which row and cell) without any attributes on the elements.
<table>
<tbody>
<tr>
<td>1</td>
<td>2</td> // If I click on this I would like to know tr:1 & td:2
<td>3</td>
</tr>
<tr>
<td>4</td>
<td>5</td>
<td>6</td>
</tr>
<tr>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
</tbody>
</table>
Javascript:
// Track onclicks on all td elements
var table = document.getElementsByTagName("table")[0];
var cells = table.getElementsByTagName("td"); //
for(var i = 1; i < cells.length; i++){
// Cell Object
var cell = cells[i];
// Track with onclick
cell.onclick = function(){
// Track my location;
// example: I'm in table row 1 and I'm the 2th cell of this row
}
}
In the handler, this is the table cell, so for the cell index do this:
var cellIndex = this.cellIndex + 1; // the + 1 is to give a 1 based index
and for the row index, do this:
var rowIndex = this.parentNode.rowIndex + 1;
Example: http://jsfiddle.net/fwZTc/1/
This script block will provide you the information you desire, by adding the information as properties to the cell and then accessing them in the onclick function:
// Track onclicks on all td elements
var table = document.getElementsByTagName("table")[0];
// Get all the rows in the table
var rows = table.getElementsByTagName("tr");
for (var i = 0; i < rows.length; i++) {
//Get the cells in the given row
var cells = rows[i].getElementsByTagName("td");
for (var j = 0; j < cells.length; j++) {
// Cell Object
var cell = cells[j];
cell.rowIndex = i;
cell.positionIndex = j;
cell.totalCells = cells.length;
cell.totalRows = rows.length;
// Track with onclick
console.log(cell);
cell.onclick = function () {
alert("I am in row " + this.rowIndex + " (out of " + this.totalRows + " rows) and I am position " + this.positionIndex + " (out of " + this.totalCells + " cells)");
};
}
}
Well, When you have rowspan/colspan you can have a lot more fun, however, if the grid is regular, you can just determine your position from the index by doing:
row = Math.floor(i / rows);
column = i % columns;
Using "this" on cells table
function myFunction(x) {
var tr = x.parentNode.rowIndex;
var td = x.cellIndex;
document.getElementById("tr").innerHTML = "Row index is: " + tr;
document.getElementById("td").innerHTML = "Column index is: " + td;
}
tr, th, td {
padding: 0.6rem;
border: 1px solid black
}
table:hover {
cursor: pointer;
}
<table>
<tbody>
<tr>
<td onclick="myFunction(this)">1</td>
<td onclick="myFunction(this)">2</td>
<td onclick="myFunction(this)">3</td>
</tr>
<tr>
<td onclick="myFunction(this)">4</td>
<td onclick="myFunction(this)">5</td>
<td onclick="myFunction(this)">6</td>
</tr>
<tr>
<td onclick="myFunction(this)">7</td>
<td onclick="myFunction(this)">8</td>
<td onclick="myFunction(this)">9</td>
</tr>
</tbody>
</table>
<p id="tr"></p>
<p id="td"></p>

Categories