I am populating a html table using ajax call in the following manner-
$.ajax({
type: "POST",
url: "my_url",
data: JSON.stringify(result),
async: true,
dataType: "json",
contentType: "application/json; charset= Shift-JIS",
success: function (response) {
glResp = response;
populateTable(glResp);
},
error: function (error) {
console.log(error);
//alert("Error!!");
}
});
Function that I am using to populate the table is as follows -
JS -
function populateTable(finalObject) {
var obj = finalObject;
var headers1 = ['Name', 'City', 'Job', 'Salary'];
var table = $("<table id='my-table' />");
var columns = headers1;
columns.unshift('');
var columnCount = columns.length;
var row = $(table[0].insertRow(-1));
for (var i = 0; i < columnCount; i++) {
if (i == 0) {
var headerCell = $("<th><input type='button' id='sort'></th>");
row.append(headerCell);
}
else {
var headerCell = $("<th/>");
headerCell.html([columns[i]]);
row.append(headerCell);
}
}
$.each(obj, function (i, obj) {
$row = '<tr><td><input type="checkbox"></td><td>' + obj.Name + '</td><td>' + obj.City + '</td><td>' + obj.Job + '</td><td>' + obj.Salary + '</td></tr>';
table.append(row);
});
var dvTable = $("#dvCSV");
dvTable.html("");
dvTable.append(table);
}
Now I want the table headers to be fixed on top when the data is being scrolled. Any idea as to how this can be implemented?
You can use a plugin to have a fixed position to your header columns,
http://mkoryak.github.io/floatThead/
Hope this link will help you.
For fix the header you can add thead for title element (th) and tbody for the chlid tr element, with display:block for both and overflow:auto for tbody element.
var tab = '[{"Name":"check","City":"check","job":"check","Salary":"check"},{"Name":"check","City":"check","job":"check","Salary":"check"},{"Name":"check","City":"check","job":"check","Salary":"check"},{"Name":"check","City":"check","job":"check","Salary":"check"},{"Name":"check","City":"check","job":"check","Salary":"check"},{"Name":"check","City":"check","job":"check","Salary":"check"}]'
tab = JSON.parse(tab);
populateTable(tab);
function populateTable(finalObject) {
var obj = finalObject;
var headers1 = ['Name', 'City', 'Job', 'Salary'];
var table = $("<table id='my-table' />");
var columns = headers1;
columns.unshift('');
var columnCount = columns.length;
var th = ""
for (var i = 0; i < columnCount; i++) {
if (i == 0) {
var headerCell = "<th><input type='button' id='sort'></th>";
th = th + headerCell;
}
else {
var headerCell = "<th>"+[columns[i]]+"</th>";
// headerCell.html();
th = th + headerCell;
}
}
table.prepend("<thead>"+th+"</thead>")
$.each(obj, function (i, obj) {
row = '<tr><td><input type="checkbox"></td><td>' + obj.Name + '</td><td>' + obj.City + '</td><td>' + obj.job + '</td><td>' + obj.Salary + '</td></tr>';
table.append(row);
});
var dvTable = $("#dvCSV");
dvTable.html("");
dvTable.append(table);
}
table{
width:100%;
}
td, th {
min-width: 100px;
}
tbody{
overflow: auto;
display: block;
height: 100px;
}
thead{
display:block;
text-align:left;
background:green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="dvCSV"><div>
Related
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.
This is creating my table and working - It creates a table and I am going to have it check a list to hide columns. For testing purposes I am trying to hide the colun "Proj_Type" it does hide the header but does not hide the actual column of data. I want the entire thing to hide.
function createTab(Name, id) {
var $button = $('<button/>', {
'class': 'tablinks',
'onclick': 'return false;',
'id': name,
text: Name,
click: function () {
return false;
}
});
var $div = $('<div>').prop({
id: Name,
'name': id + 'MKTTAB',
className: 'tabcontent'
})
var $table = $('<table/>', {
'class': 'GRD1',
id: id + "GRDMKTLIST",
}
)
$table.append('<caption>' + Name + '</caption>')
var $tbody = $table.append('<tbody />').children('tbody');
$tbody.append('<tr />').children('tr:last');
$.ajax({
type: "POST",
url: "../WebMethods/MarketPersuitMethods.aspx/GetQueryInfo",
data: {},
contentType: "application/json; charset=utf-8",
dataType: 'json',
async: false,
success: function (d) {
var data = $.parseJSON(d.d);
var colHeader = Object.keys(data[0]);
for (var i = 0; i < colHeader.length; i++) {
if (colHeader[i] != "notes") {
$tbody.append("<th>" + colHeader[i] + "</th>");
}
}
//sets new line
$tbody.append('<tr />').children('tr:last')
for (var i = 0; i < data.length; i++) {
for (var j = 0; j < colHeader.length; j++) {
if (colHeader[j] != "notes") {
$tbody.append('<td>' + data[i][colHeader[j]] + '</td>');
}
}
$tbody.append('<tr />').children('tr:last')
}
setTimeout(function () {
}, 1000);
}
});
$($table.find('th')).each(function () {
var indextest = $(this).index() + 1;
if ($(this).text() == "Proj_Type") {
$('[id*=GRDMKTLIST] td:nth-child(' + indextest + '),th:nth-child(' + indextest + ')').hide();
}
})
$button.appendTo('#tabs');
$table.appendTo($div);
$div.appendTo('#TabbedMktList');
}
However, on the bottom where i have
if ($(this).text() == "Proj_Type") {
$('[id*=GRDMKTLIST] td:nth-child(' + indextest + '),th:nth-child(' + indextest + ')').hide();
}
This only hides the header and I am trying to hide the entire column TD included.
There are two main issues:
$('[id*=GRDMKTLIST]
will look in the DOM, but your $table has not yet been added to the DOM, so does nothing. Use $table.find(... to use the $table variable in memory.
$tbody.append('<td
will append the td (and equivalent code for th) to the tbody - but these should be in a tr.
The browser will do some "magic" and see an empty <tr></tr> and put a new row in for you, but selectors for tbody > tr > td won't work. This also means there's only a single :nth-child(n) per n, not per row (as all cells across all rows are siblings).
You can add a new row to $tbody and return the new row by using .appendTo
$tr = $("<tr>").appendTo($tbody);
then add the th/td to $tr and not $tbody
$tr.append('<td...`
Regarding the selector for $table.find("td,th") you don't need the th part as you're looping th and it's already this, so you can do:
$(this).hide();
$table.find('td:nth-child(' + indextest + ')').hide();
Also make sure you only create tr as you need it. Your code create a tr before the data row loop and inside the data row loop, leaving an empty tr.
for (var i = 0; i < data.length; i++) {
$tr = $("<tr>").appendTo($tbody);
for (var j = 0; j < colHeader.length; j++) {
if (colHeader[j] != "notes") {
$tr.append('<td id=' + colHeader[j] + '>' + data[i][colHeader[j]] + '</td>');
}
}
}
Also updated in the fiddle: https://jsfiddle.net/n168ra2g/3/
I am having a html table getting populated using JSON by an ajax call as follows -
$.ajax({
type: "POST",
url: "my_url",
data: JSON.stringify(result),
async: true,
dataType: "json",
contentType: "application/json; charset= Shift-JIS",
success: function (response) {
glResp = response;
populateTable(glResp);
},
error: function (error) {
console.log(error);
//alert("Error!!");
}
});
The function used for populating the table is as follows -
function populateTable(finalObject) {
var obj = finalObject;
var headers1 = ['Name', 'ID', 'Job', 'Salary','JoiningDate'];
var table = $("<table id='my-table' />");
var columns = headers1;
columns.unshift('');
var columnCount = columns.length;
var row = $(table[0].insertRow(-1));
for (var i = 0; i < columnCount; i++) {
if (i == 0) {
var headerCell = $("<th><input type='button' id='sort'></th>");
row.append(headerCell);
}
else {
var headerCell = $("<th/>");
headerCell.html([columns[i]]);
row.append(headerCell);
}
}
$.each(obj, function (i, obj) {
$row = '<tr><td><input type="checkbox"></td><td>' + obj.Name + '</td><td>' + obj.ID+ '</td><td>' + obj.Job + '</td><td>' + obj.Salary + '</td><td>'+ obj.JoiningDate+'</td></tr>';
table.append(row);
});
var dvTable = $("#dvCSV");
dvTable.html("");
dvTable.append(table);
}
Now I want to enable sorting for only two columns - ID & JoiningDate using DataTable plugin. I tried to understand the api but everytime something or the other problem came up. (E.g. for ID = M981-01) (E.g. for date: 2016-10-24) Can anyone help me to implement DataTable plugin or any other suitable approach to enable sort with respect to ID and JoiningDate?
i am new to mvc and jquery,
i have created one table with jquery but i don't know how we add one actionlink in each row and also i need to call one function on the onclick event.
my code is given bellow
function loadData(data) {
var tab = $('<table class="myTable"></table>');
var thead = $('<thead></thead>');
thead.append('<th>Id</th><th></th>');
thead.append('<th>Username</th>');
tab.append(thead);
$.each(data, function (i, val) {
var trow = $('<tr></tr>');
trow.append('<td>' + val.empID + '</td>');
trow.append('<td>' +"" + '</td>');
trow.append('<td>' + val.empName + '</td>');
trow.append('<td>' + '#Html.ActionLink("Edit", "Edit", new { id = val.empID })' + '</td>');
tab.append(trow);
});
here i got one error
"val is not in the current context"
please anyone help me to add one actionlink with click event.
You can achieve this by changing your code as below.
function loadData(data) {
var tab = $('<table class="myTable"></table>');
var thead = $('<thead></thead>');
thead.append('<th>Id</th><th></th>');
thead.append('<th>Username</th>');
tab.append(thead);
$.each(data, function (i, val) {
var trow = $('<tr></tr>');
trow.append('<td>' + val.empID + '</td>');
trow.append('<td>' +"" + '</td>');
trow.append('<td>' + val.empName + '</td>');
trow.append('<td></td>');
tab.append(trow);
});
Try this and let me know, if you required anymore information.
Below Code Work Perfectly and Bind Table dynamically with Control.
function bindTable (data)
{
usersTable = $('<table><thead><tr>'
+ '<th style="width: 300px;">Col 1</th><th>Col 2</th><th>Col 3</th><th>Col 4</th><th>Col 5</th>'
+ '</tr></thead ></table>').attr({ class: ["dataTable row-border hover"].join(' '), id: "table", style: "border: 1px solid; background-color:#d2d2d2;" });
var rows = new Number("10");
var cols = new Number("4");
var tr = [];
if (data != null) {
for (var i = 0; i < data.length; i++) {
var row = $("<tr></tr>").attr({ class: ["class1", "class2", "class3"].join(' ') }).appendTo(table);
$("<td></td>").html(data[i].Col1).appendTo(row);
$("<td></td>").html(data[i].Col2).appendTo(row);
$("<td></td>").html(data[i].Col3).appendTo(row);
$("<td></td>").html(data[i].Col4).appendTo(row);
$("<td></td>").html($('<a href=/ControllerName/Action?ParamId='+data[i].Id+'>Action</a>')).appendTo(row);
}
}
table.appendTo("#Div");
$("#table").DataTable({
"aoColumns": [null, null, null, null, { "bSortable": false }]
});
}
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>