While Loop: Generated table rows and column inconsistency - javascript

Please explain why the code I borrowed from another SO question produces inconsistent results. The program accepts 2 inputs, rows and columns. It should then generate a table with the exact amount of table rows and table columns that was input. However, the first row seems to multiply out the cells and decrease each row until the final row actually renders what every other row should be.
Also, I noticed that when I move line 25 inside of the inner while loop, that a table that is akin to a pyramid is generated (which is cool) but I cannot explain what it is doing.
$("<tr class='tableRow'>").appendTo('table#container');
So with that said, please help me generate a table that will evenly render rows and columns when the input is equal.
Note: Entering 1 for rows and 1 for columns does return the intended result, but that is the only scenario where it "works". Entering 2 for rows and 2 for columns, produces unintended results.
Sandbox Fiddle
//Table Generator
var c = 10; //parseInt(prompt("Enter column "), 10);
var r = 10; //parseInt(prompt("Enter row "), 10);
var cTmp = c;
var rTmp = r;
function rowLoop() {
$('tr.tableRow').each(function(index) {
var trFound = $("tr.tableRow:eq(" + index + ")");
var rowNum = parseInt(($("tr.tableRow:eq(" + index + ")").index()), 10);
var tdAdd = "<td>test</td>";
if ($(this).index() === rowNum) {
trFound.append(tdAdd);
console.log("Add a TD");
console.log(rowNum + "=" + $(this).index());
console.log(rowNum + "=" + $(this).index());
} else {
console.log(rowNum + "<>" + $(this).index());
console.log(rowNum + "<>" + $(this).index());
}
});
}
while (0 < rTmp) {
cTmp = c;
$("<tr class='tableRow'>").appendTo('table#container');
while (0 < cTmp) {
rowLoop();
cTmp--;
}
document.getElementById("container").innerHTML = document.getElementById("container").innerHTML + "</tr>";
rTmp--;
}
table {
border-collapse: collapse;
border: solid 1px #ACE;
}
tr {
height: 15px;
}
td {
border: solid 1px red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<table id='container'></table>

Instead of using a while-loop why don't you just use a simple nested for-loop? This will make this task much easier to read and comprehend.
//Table Generator
var cols = 10; //parseInt(prompt("Enter column "), 10);
var rows = 10; //parseInt(prompt("Enter row "), 10);
generateTable('container', rows, cols, 'test');
function generateTable(id, rows, cols, fill) {
var elTable = document.getElementById(id);
createRows(elTable, rows, cols, fill);
}
function createRows(elTable, rows, cols, fill) {
for (var row = 0; row < rows; row++) {
elTable.appendChild(createRow(row, cols, fill));
}
}
function createRow(row, cols, fill) {
var elRow = document.createElement('tr');
elRow.className = 'tableRow';
createCols(elRow, row, cols, fill);
return elRow;
}
function createCols(elRow, row, cols, fill) {
for (var col = 0; col < cols; col++) {
elRow.appendChild(createCol(row, col, fill));
}
}
function createCol(row, col, fill) {
var elCol = document.createElement('td');
elCol.innerHTML = fill || row + 'x' + col;
return elCol;
}
table {
border-collapse: collapse;
border: solid 1px #ACE;
}
tr {
height: 15px;
}
td {
border: solid 1px red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table id='container'></table>

jQuery Plugin
You can skip the loop altogether and use a range-map. You can actually define an array using:
Array.apply(null, Array(n)) // Where n is an integer greater than 0
You can then map each item in the array to either a function or the current index in the map function.
map(function(_, idx) {
// Return the current index in the map's "loop" callback.
if (val == null) return idx;
// Execute the value as a function; pass index as 1st param.
if (isFunction(val)) return val.call(null, idx);
// Return the value as an (assumed) scalar value.
return val;
});
Here is a jQuery plugin to generate rows and columns using the explained trick above to generate an array at a desired size with an option default value.
//Table Generator
(function($) {
$.fn.generateTable = function(options) {
var defaults = {
rows: 0,
cols: 0,
fill: function(row, col) {
return row + 'x' + col;
}
};
var opts = $.extend(defaults, options);
function fillArray(n, val) {
return Array.apply(null, Array(n)).map(function(_, idx) {
return val == null ? idx : isFunction(val) ? val.call(null, idx) : val;
});
}
function isFunction(value) {
return typeof value == 'function';
}
return $(this).append(fillArray(opts.rows, function(row) {
return $('<tr>', {
class: 'tableRow'
}).append(fillArray(opts.cols, function(col) {
return $('<td>', {
text: isFunction(opts.fill) ? opts.fill.call(null, row, col) : opts.fill
});
}));
}));
};
}(jQuery));
$(function() {
$('#container').generateTable({
rows: 10, //parseInt(prompt("Enter row count"), 10)
cols: 10, //parseInt(prompt("Enter column count"), 10)
fill: 'test'
});
});
table {
border-collapse: collapse;
border: solid 1px #ACE;
}
tr {
height: 15px;
}
td {
border: solid 1px red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table id='container'></table>
Stages of Development
Below, you will see how each successive block of code has evolved from its predecessor.
I. Vanilla JavaScript translated to jQuery
//Table Generator
var cols = 10; //parseInt(prompt("Enter column "), 10);
var rows = 10; //parseInt(prompt("Enter row "), 10);
generateTable('#container', rows, cols, 'test');
function generateTable(selector, rows, cols, fill) {
var $el = $(selector)
createRows($el, rows, cols, fill);
}
function createRows($table, rows, cols, fill) {
for (var row = 0; row < rows; row++) {
$table.append(createRow(row, cols, fill));
}
}
function createRow(row, cols, fill) {
var $row = $('<tr>', {
class: 'tableRow'
});
createCols($row, row, cols, fill);
return $row;
}
function createCols($row, row, cols, fill) {
for (var col = 0; col < cols; col++) {
$row.append(createCol(row, col, fill));
}
}
function createCol(row, col, fill) {
return $('<td>', {
text: fill || row + 'x' + col
});
}
table {
border-collapse: collapse;
border: solid 1px #ACE;
}
tr {
height: 15px;
}
td {
border: solid 1px red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table id='container'></table>
II. Simple jQuery Plugin
//Table Generator
(function($) {
$.fn.generateTable = function(options) {
var $table = $(this);
_createRows($table, options.rows, options.cols, options.fill);
};
_createRows = function($table, rows, cols, fill) {
for (var row = 0; row < rows; row++) {
$table.append(_createRow(row, cols, fill));
}
};
_createRow = function(row, cols, fill) {
var $row = $('<tr>', {
class: 'tableRow'
});
_createCols($row, row, cols, fill);
return $row;
};
_createCols = function($row, row, cols, fill) {
for (var col = 0; col < cols; col++) {
$row.append(_createCol(row, col, fill));
}
};
_createCol = function(row, col, fill) {
return $('<td>', {
text: fill || row + 'x' + col
});
};
}(jQuery));
var cols = 10; //parseInt(prompt("Enter column "), 10);
var rows = 10; //parseInt(prompt("Enter row "), 10);
$(function() {
$('#container').generateTable({
rows: rows,
cols: cols,
fill: 'test'
});
});
table {
border-collapse: collapse;
border: solid 1px #ACE;
}
tr {
height: 15px;
}
td {
border: solid 1px red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table id='container'></table>
III. Advanced jQuery Plugin
//Table Generator
(function($) {
$.fn.generateTable = function(options) {
$(this).append(_fillArray(options.rows, function(row) {
return $('<tr>', {
class: 'tableRow'
}).append(_fillArray(options.cols, function(col) {
return $('<td>', {
text: options.fill || row + 'x' + col
});
}));
}));
};
function _fillArray(n, defaultValue) {
return Array.apply(null, Array(n)).map(function(val, idx) {
if (defaultValue === undefined) return idx;
if (typeof defaultValue == 'function') return defaultValue.call(null, idx);
return defaultValue;
});
}
}(jQuery));
var colCount = 10; //parseInt(prompt("Enter column "), 10);
var rowCount = 10; //parseInt(prompt("Enter row "), 10);
$(function() {
$('#container').generateTable({
rows: rowCount,
cols: colCount,
fill: 'test'
});
});
table {
border-collapse: collapse;
border: solid 1px #ACE;
}
tr {
height: 15px;
}
td {
border: solid 1px red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table id='container'></table>

Your problem likely stems from the fact that within each rowLoop() execution, you are using this as selector for iteration:
$('tr.tableRow')
This will grab all rows that are currently in DOM for iteration, not just the current row you are working on.
A few options:
Build a single row object with X number of columns first, then make clones of it and append to table for Y number of rows.
Build Y empty TR's first, then iterate over each TR, appending X TD's.

Related

Is it possible to create a table automatically?

Im beginner. I use a HTML table code like this (see below) for Unicode print using char's Decimal values:
<table border="1">
<tr><td>1</td><td></td>
<tr><td>2</td><td></td>
<tr><td>3</td><td></td>
...
<!-- last one: thousandth row -->
<tr><td>1000</td><td>Ϩ</td>
</table>
Is it possible to convert this code into an auto-generated table as follows using JavaScript or JQuery?
<table border="1">
<tr><td>rowNumber</td><td>innerHTML = "\u0026\u0023 + rowNumber + \u003B";</td>
...
<!-- thousandth row -->
<tr><td>rowNumber</td><td>innerHTML = "\u0026\u0023 + rowNumber + \u003B";</td>
</table>
You can start by creating a record-generating function.
function generateRecords(recordFn, limit) {
var records = [];
for (var i = 0; i < limit; i++) {
records.push(recordFn.call(null, i, records));
}
return records;
}
Then you can generate the JSON.
generateRecords(i => {
return {
dec: i,
entity: '&&num;' + i + '&semi;',
rendered: '&#' + i + ';'
}
}, 1000);
Finally, all you need to do is render the JSON to a table.
Example
(function($) {
$.fn.attrs = function(attrs) {
var $self = this;
if (attrs != null) {
$.each(attrs, function(attr, value) {
$self.attr(attr, value);
});
return $self;
} else {
var result = {};
$.each(this[0].attributes, function(index, attribute) {
result[attribute.name] = attribute.value;
});
return result;
}
};
$.fn.tableFromJson = function(data, attrs, indexField) {
return this.replaceWith($.tableFromJson.apply(this, arguments));
};
$.tableFromJson = function(data, attrs, indexField) {
var fields = Object.keys(data[0]);
if (indexField != null) fields.unshift(indexField);
return $('<table>')
.append($('<thead>').append($('<tr>').append(fields
.map(field => $('<th>').text(field)))))
.append($('<tbody>').append(data
.map((rec, row) => $('<tr>').append(fields
.map((field, col) => $('<td>').html(field === indexField ? (row + 1) : rec[field])))))).attrs(attrs);
};
})(jQuery);
function generateRecords(recordFn, limit) {
var records = [];
for (var i = 0; i < limit; i++) {
records.push(recordFn.call(null, i, records));
}
return records;
}
$('.column:nth-child(1) .result').tableFromJson(generateRecords(i => {
return {
dec: i,
entity: '&&num;' + i + '&semi;',
rendered: '&#' + i + ';'
}
}, 1000), $('.column:nth-child(1) .result').attrs());
$('.column:nth-child(2) .result').tableFromJson(generateRecords(i => {
return {
dec: i,
rendered: '\u0026\u0023' + i + '\u003B'
}
}, 1000), $('.column:nth-child(2) .result').attrs());
.container { width: 100%; }
.column { display: inline-block; width: 49%; }
table.result {
margin-bottom: 0.5em;
}
table.result,
table.result th,
table.result td {
border: 1px solid black;
border-collapse: collapse;
}
table.result th,
table.result td {
padding: 0.25em;
}
table.result tbody tr td {
text-align: center;
}
table.result thead tr {
background: #BBB;
}
table.result tbody tr:nth-child(even) {
background: #EEE;
}
table.result tbody tr:nth-child(odd) {
background: #FFF;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="column">
<table class="result"></table>
</div>
<div class="column">
<table class="result"></table>
</div>
</div>
You can try with this
var table = $('<table>').prop('border', 1);
for(i=0; i<1000; i++){
var row = $('<tr><td>' + i + '</td><td>&#'++'</td></tr>'
table.append(row);
}
$('#mytable').append(table);
Yes, Thats possible using javascript/JQuery.For that you need to use proper js code. Below is the sample code that can help you to create table and row,data using jquery.
Below code is responsible to create table tag
$('.class-name').append('<table border="3"></table>');
This will create table element inside your HTML having classname as .class-name.
Once the table tag is created you can create table row and data element as below.
$("table").append(createRow());
function createRow(){
var firstVal = '1st val';
var secondVal = '2nd val';
var tr = '<tr>' ;
tr += '<td>' + firstVal + '</td>';
tr += '<td>' + secondVal + '</td>';
tr +='</tr>';
return tr;
}
This code will generate the table row and will print the table data as st val and 2nd val.
Hope this code may help you

Sort table data with expandable parts

Right now I have this:
<style>
table {
border-spacing: 0;
width: 100%;
border: 1px solid #ddd;
}
th, td {
text-align: left;
padding: 16px;
}
tr:nth-child(even) {
background-color: #f2f2f2
}
</style>
<table id="schInfoTable">
<thead>
<th onclick="sortTable(0)">Date</th>
<th>Amount</th>
<th>Count</th>
</thead>
<tbody>
<tr>
<td><a onclick="openView('2018-11-14')">2018-11-14</a></td>
<td>$23,000.00</td>
<td>12</td>
</tr>
<tr style="display:none; background-color: #cbe7cb;" class="2018-11-14">
<td>Mandy</td>
<td>Designer</td>
<td>View</td>
</tr>
<tr style="display:none; background-color: #cbe7cb;" class="2018-11-14">
<td>Robert</td>
<td>Cook</td>
<td>View</td>
</tr>
<tr>
<td><a onclick="openView('2018-11-13')">2018-11-13</a></td>
<td>$13,000.00</td>
<td>8</td>
</tr>
<tr style="display:none; background-color: #cbe7cb;" class="2018-11-13 branches">
<td>James</td>
<td>Driver</td>
<td>View</td>
</tr>
</tbody>
</table>
<script>
function openView(showID){
$("."+showID).toggle();
}
function sortTable(n) {
var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;
table = document.getElementById("schInfoTable");
switching = true;
//Set the sorting direction to ascending:
dir = "asc";
/*Make a loop that will continue until
no switching has been done:*/
while (switching) {
//start by saying: no switching is done:
switching = false;
rows = table.rows;
/*Loop through all table rows (except the
first, which contains table headers):*/
for (i = 1; i < (rows.length - 1); i++) {
//start by saying there should be no switching:
shouldSwitch = false;
/*Get the two elements you want to compare,
one from current row and one from the next:*/
x = rows[i].getElementsByTagName("TD")[n];
y = rows[i + 1].getElementsByTagName("TD")[n];
/*check if the two rows should switch place,
based on the direction, asc or desc:*/
if (dir == "asc") {
if (x.innerHTML.toLowerCase() > y.innerHTML.toLowerCase()) {
//if so, mark as a switch and break the loop:
shouldSwitch= true;
break;
}
} else if (dir == "desc") {
if (x.innerHTML.toLowerCase() < y.innerHTML.toLowerCase()) {
//if so, mark as a switch and break the loop:
shouldSwitch = true;
break;
}
}
}
if (shouldSwitch) {
/*If a switch has been marked, make the switch
and mark that a switch has been done:*/
rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
switching = true;
//Each time a switch is done, increase this count by 1:
switchcount ++;
} else {
/*If no switching has been done AND the direction is "asc",
set the direction to "desc" and run the while loop again.*/
if (switchcount == 0 && dir == "asc") {
dir = "desc";
switching = true;
}
}
}
}
</script>
jsfiddle code here: jsfiddle
When you click on dates it will expand and show additional table row with its data:
But when you click on Date header in order sort by date it all goes wrong:
As you can see, green highlighted table data goes all together to the bottom but they should be like this:
How do I achieve this?
UPDATE: Thanks to David784's code I was able to get desired result, had to do a little tweek though but all credit to David. Here is what I have now:
function openView(showID) {
$("." + showID).toggle();
}
function sortTable(n) {
var table, rows, i, x, y = 0;
var compare1, compare2;
table = document.getElementById("schInfoTable");
switching = true;
rows = table.querySelectorAll('tr.sort');
var sortArr = [];
for (i = 0; i < rows.length; i++) {
x = rows[i];
if (i + 1 in rows) y = rows[i + 1].previousElementSibling;
else y = x.parentElement.lastChild;
var obj = {
sort: x.getElementsByTagName("TD")[n].textContent.toLowerCase(),
range: document.createRange()
};
obj.range.setStartBefore(x);
obj.range.setEndAfter(y);
sortArr.push(obj);
}
function fnSortArrAsc(a, b) {
if (a.sort > b.sort) return 1;
else if (a.sort < b.sort) return -1;
else return 0;
}
function fnSortArrDesc(a, b) {
if (a.sort < b.sort) return 1;
else if (a.sort > b.sort) return -1;
else return 0;
}
compare1 = rows[0].getElementsByTagName("TD")[0].textContent.toLowerCase();
compare2 = rows[rows.length-1].getElementsByTagName("TD")[0].textContent.toLowerCase();
if(compare1 < compare2){
sortArr = sortArr.sort(fnSortArrDesc);
}else{
sortArr = sortArr.sort(fnSortArrAsc);
}
frag = document.createDocumentFragment();
for (i = 0; i < sortArr.length; i++) {
x = sortArr[i];
frag.appendChild(x.range.extractContents());
}
table.appendChild(frag);
}
Full working code is here: jsfiddle
This would be one way of accomplishing what you're trying to do, assuming you want to keep your table structure pretty much the same.
Brief description of the javascript:
assumptions:
add class on each "top level" TR. These are the rows that get sorted
any non-top-level TR is assumed to be a sub-row of the top-level TR above it, and will be moved with that row.
methodology
use that new class added to top-level TRs in a querySelectorAll to get a list of everything we want to sort.
loop: create an array of objects, consisting of
sort value (lower case string contents of correct TD)
DOM range of row and all sub-rows under it
then use built-in javascript Array.sort with simple custom sorting function.
loop: extract all range contents in order into a documentFragment
append documentFragment back to the table
The reason why I'm using the documentFragment is that it saves on DOM reflow and rendering, as described here on MDN, compared with appending each range directly back to the table element one at a time.
Note: if you have a table footer, you would probably want to make use of the tbody element instead of just dealing directly with the table.
function openView(showID) {
$("." + showID).toggle();
}
function sortTable(n) {
var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;
table = document.getElementById("schInfoTable");
switching = true;
//Set the sorting direction
dir = 1;
var thEl = table.querySelectorAll('th')[n];
if (thEl.classList.contains('asc')) dir = -1;
thEl.classList.toggle('asc');
rows = table.querySelectorAll('tr.sort');
var sortArr = [];
for (i = 0; i < rows.length; i++) {
x = rows[i];
if (i + 1 in rows) y = rows[i + 1].previousElementSibling;
else y = x.parentElement.lastChild;
var obj = {
sort: x.getElementsByTagName("TD")[n].textContent.toLowerCase(),
range: document.createRange()
};
obj.range.setStartBefore(x);
obj.range.setEndAfter(y);
sortArr.push(obj);
}
function fnSortArr(a, b) {
if (a.sort > b.sort) return 1 * dir;
else if (a.sort < b.sort) return -1 * dir;
else return 0;
}
sortArr = sortArr.sort(fnSortArr);
console.log(JSON.stringify(sortArr, null, 2));
frag = document.createDocumentFragment();
for (i = 0; i < sortArr.length; i++) {
x = sortArr[i];
frag.appendChild(x.range.extractContents());
}
table.appendChild(frag);
}
table {
border-spacing: 0;
width: 100%;
border: 1px solid #ddd;
}
th,
td {
text-align: left;
padding: 16px;
}
tr:nth-child(even) {
background-color: #f2f2f2
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="schInfoTable">
<thead>
<th onclick="sortTable(0)">Date</th>
<th>Amount</th>
<th>Count</th>
</thead>
<tbody>
<tr class='sort'>
<td><a onclick="openView('2018-11-14')">2018-11-14</a></td>
<td>$23,000.00</td>
<td>12</td>
</tr>
<tr style="display:none; background-color: #cbe7cb;" class="2018-11-14">
<td>Mandy</td>
<td>Designer</td>
<td>View</td>
</tr>
<tr style="display:none; background-color: #cbe7cb;" class="2018-11-14">
<td>Robert</td>
<td>Cook</td>
<td>View</td>
</tr>
<tr class='sort'>
<td><a onclick="openView('2018-11-13')">2018-11-13</a></td>
<td>$13,000.00</td>
<td>8</td>
</tr>
<tr style="display:none; background-color: #cbe7cb;" class="2018-11-13 branches">
<td>James</td>
<td>Driver</td>
<td>View</td>
</tr>
</tbody>
</table>
*EDIT: add sort order toggle
An alternative method commonly used would be to put your sub-rows into a child table. For example, your child data would look something like this:
<tr><td colspan='3'> <table>...</table> </td></tr>.
Then every top-level row has a single child-table row beneath it, and you always sort/move the rows in pairs, instead of dealing with any number of child-rows from zero to infinity.
I was very intrueged by your question and I programmed out the idea I had for it.
I hope this aproach will help you.
let testData = [{
date: "2018-11-14",
amount: 23000,
count: 12,
people: [{
name: "Mandy",
designation: "Designer",
detail: "View",
},
{
name: "Robert",
designation: "Cook",
detail: "View",
}
]
},
{
date: "2018-11-13",
amount: 13000,
count: 8,
people: [{
name: "James",
designation: "Driver",
detail: "View",
}]
}
]
let testDiv = document.querySelector('#test');
let main = function() {
let mainTable = document.createElement('table');
mainTable.classList.add('table-style');
let mainTbody = document.createElement('tbody');
let mainTheader = document.createElement('tr');
mainTheader.onclick = sort;
let dateHeader = document.createElement('th');
dateHeader.textContent = 'Date';
mainTheader.appendChild(dateHeader);
let amountHeader = document.createElement('th');
mainTheader.appendChild(amountHeader);
amountHeader.textContent = 'Amount';
let countHeader = document.createElement('th');
countHeader.textContent = 'Count';
mainTheader.appendChild(countHeader);
mainTable.appendChild(mainTheader);
let counter = 0;
testData.forEach(object => {
console.log('MAIN', object);
counter++;
let rowEl = document.createElement('tr');
if (counter % 2 === 0) {
rowEl.classList.add('uneven-row');
}
rowEl.onclick = toggle;
rowEl.id = object.date;
let keys = Object.keys(object);
keys.forEach(key => {
console.log(key, ": ", object[key]);
if (key !== 'people') {
let colEl = document.createElement('td');
colEl.textContent = object[key];
rowEl.appendChild(colEl);
} else {
mainTbody.appendChild(rowEl);
let subTableRow = document.createElement('tr');
subTableRow.id = 'detail-' + object.date;
subTableRow.classList.add('hidden');
let subTable = document.createElement('table');
subTable.classList.add('sub-table-style');
subTableRow.appendChild(subTable);
let subTbody = document.createElement('tbody');
object[key].forEach(detail => {
console.log('DETAIL', detail);
let subRowEl = document.createElement('tr');
let detailKeys = Object.keys(detail);
detailKeys.forEach(detailKey => {
console.log(detailKey, ": ", detail[detailKey]);
let subColEl = document.createElement('td');
subColEl.textContent = detail[detailKey];
subRowEl.appendChild(subColEl);
});
subTbody.appendChild(subRowEl);
});
subTable.appendChild(subTbody);
mainTbody.appendChild(subTableRow);
}
});
});
mainTable.appendChild(mainTbody);
testDiv.appendChild(mainTable);
}
let toggle = function() {
let detailEl = document.querySelector('#detail-' + this.id);
console.log('TOGGLE', detailEl);
if (detailEl.classList.contains('hidden')) {
detailEl.classList.toggle('hidden');
console.log('SHOW', detailEl.id);
} else {
detailEl.classList.toggle('hidden');
console.log('HIDE', detailEl);
}
}
let compareAsc = function(a, b) {
console.log('A', a);
console.log('B', b);
if (a.date > b.date) {
return 1;
}
if (a.date < b.date) {
return -1;
}
if (a.date === b.date) {
return 0;
}
}
let compareDesc = function(a, b) {
console.log('A', a);
console.log('B', b);
if (a.date < b.date) {
return 1;
}
if (a.date > b.date) {
return -1;
}
if (a.date === b.date) {
return 0;
}
}
let redraw = function() {
while (testDiv.firstChild) {
testDiv.removeChild(testDiv.firstChild);
}
main();
}
let sort = function() {
console.log('SORT', this.classList)
if (!window.sorted) {
console.log('SORT ASC', this);
testData.sort(compareAsc);
window.sorted = true;
redraw();
} else {
console.log('SORT DESC', this);
testData.sort(compareDesc);
window.sorted = false;
redraw();
}
}
main();
body {
font-family: 'Courier New', Courier, monospace;
}
table {
border: 1px solid #ccc;
border-collapse: collapse;
table-layout: fixed;
width: 600px;
}
.sub-table-style {
border: 0px;
background: lawngreen;
}
td {
width: 150px;
padding: 10px;
margin: 0;
border: 0px;
}
.uneven-row {
background: #ddd;
}
.hidden {
visibility: hidden;
display: none;
height: 0px;
overflow: hidden;
}
<div id="test">
</div>

How to create diagonal of table using jquery

I would like to create diagonal in my table. For example if i have table 5x5 i have to grab first row and first column in this row and set background of thic column to be red. For the second row i have to do the same on second column in second row.
var cols = 6,
rows = 6;
for (r = 0; r < rows; r++) {
var row = $('<tr></tr>')
$('table').append(row);
for (c = 0; c < cols; c++) {
var col = $('<td></td>');
row.append(col);
$(col[r][c]).addClass('kolorek')
}
}
table td {
width: 20px;
height: 20px;
border: 1px solid;
}
.kolorek {
background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
</table>
Here is a fiddle
You're almost there.
var cols = 6,
rows = 6,
$table = $('table'); // Caching the table, because this will be called many times (perf improvement)
for (r = 0; r < rows; r++) {
var row = $('<tr></tr>')
for(c = 0; c < cols; c++){
var col = $('<td></td>')
if(c==r) col.addClass('kolorek') // col[r][c] is undefined. This matches the same column and row numbers
row.append(col)
}
$table.append(row);
}
table td {
width: 20px;
height: 20px;
border: 1px solid;
}
.kolorek {
background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table></table>
You can just check if the row index equals the column index to make a diagonal line from left top to right bottom:
var cols = 6,
rows = 6;
for (r = 0; r < rows; r++) {
var row = $('<tr></tr>')
$('table').append(row);
for (c = 0; c < cols; c++) {
var col = $('<td></td>');
row.append(col);
if (r == c) col.addClass('kolorek'); // add this in place of your current kolerik adder
}
}
table td {
width: 20px;
height: 20px;
border: 1px solid;
}
.kolorek {
background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
</table>

Continuously adding arrays to a 2D array

Every time I click on a cell in a grid, it logs an array of [rows,column] of the cell into a variable, either bla (for black) or whi (for white). However, the next time I click on a cell, it changes the variable. For example, I click on a cell and variable whi is [1,2] then I click on another cell, variable bla is [2,2] and after that, I click on a third cell and variable whi is changed from [1,2] (from the original click) to [3,2]. (I made up random numbers for this). I want to create two 2D arrays, one for the variable bla and one for the variable whi. Using my example, one of the 2D arrays should be [[1,2],[3,2]] (for the white cells) and the other one should be [[2,2]] (for the black cells)
Test out the code:
var white=true;
function generateGrid( rows, cols ) {
var grid = "<table>";
for ( row = 1; row <= rows; row++ ) {
grid += "<tr>";
for ( col = 1; col <= cols; col++ ) {
grid += "<td></td>";
}
grid += "</tr>";
}
return grid;
}
$( "#tableContainer" ).append( generateGrid( 10, 10) );
$( "td" ).click(function() {
$(this).css('cursor','default');
var index = $( "td" ).index( this );
var row = Math.floor( ( index ) / 10) + 1;
var col = ( index % 10) + 1;
var $td = $(this);
if ($td.data('clicked'))
return;
if (white===true){
var whi=[row,col]; //I want to log the array for whi into a 2D array
console.log("white coord is "+whi);
} else {
var bla=[row,col]; //I want to log this array into another 2D array
console.log("black coord is "+bla);
}
$td.data('clicked', true);
$td.css('background-color', white ? 'white' : 'black');
white = !white;
});
html{
background-color:#7189ea;
}
td {
border: 1px solid;
width: 25px;
height: 25px;
border-radius:100%;
}
table {
border-collapse: collapse;
}
<link type="text/css" rel="stylesheet" href="stylesheet.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<div id="tableContainer"></div>
Initialize whi and bla as arrays and push [row,col] to them - see demo below:
var white = true;
var whi = [];
var bla = [];
function generateGrid(rows, cols) {
var grid = "<table>";
for (row = 1; row <= rows; row++) {
grid += "<tr>";
for (col = 1; col <= cols; col++) {
grid += "<td></td>";
}
grid += "</tr>";
}
return grid;
}
$("#tableContainer").append(generateGrid(10, 10));
$("td").click(function() {
$(this).css('cursor', 'default');
var index = $("td").index(this);
var row = Math.floor((index) / 10) + 1;
var col = (index % 10) + 1;
var $td = $(this);
if ($td.data('clicked'))
return;
if (white === true) {
whi.push([row, col]);
} else {
bla.push([row, col]);
}
$td.data('clicked', true);
$td.css('background-color', white ? 'white' : 'black');
white = !white;
});
$('#getarr').click(function(){
console.log("white arr: ", whi);
console.log("black arr: ", bla);
});
html {
background-color: #7189ea;
}
td {
border: 1px solid;
width: 25px;
height: 25px;
border-radius: 100%;
}
table {
border-collapse: collapse;
}
<link type="text/css" rel="stylesheet" href="stylesheet.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<div id="tableContainer"></div>
<button id="getarr">Get array</button>

selecting multiple table row using shift key and control key is not working

hi i have a editable table which is created by using java script.here i use some code for selection process .i want select table row using control key and shift key . i get the code from
[1]: http://jsfiddle.net/g8Rpe/ here. this example shown for html table .but my table is daynamic one
the code is here:
/******for table**************/
$(function () {
function tableCreate() {
var body = document.body,
tbl = document.createElement('table');
tbl.style.width = '100%';
tbl.style.borderCollapse = 'collapse';
for (var i = 0; i < 30; i++) {
var tr = tbl.insertRow();
tr.setAttribute("data-id", i, 0);
for (var j = 0; j < 3; j++) {
var td = tr.insertCell();
td.appendChild(document.createTextNode(''));
}
}
$("body").append(tbl);
$("td").addClass("mainheading4")
$("tr").on("onmousedown=RowClick(this,false)")
}
tableCreate();
//******************for editable table*************************//
$('td').click(function () {
$('td').attr('contenteditable', 'true');
})
//************for multiple selection*****************//
var lastSelectedRow;
var trs = document.getElementById('table').tBodies[0].getElementsByTagName('tr');
// disable text selection
document.onselectstart = function () {
return false;
}
function RowClick(currenttr, lock) {
if (window.event.ctrlKey) {
toggleRow(currenttr);
}
if (window.event.button === 0) {
if (!window.event.ctrlKey && !window.event.shiftKey) {
clearAll();
toggleRow(currenttr);
}
if (window.event.shiftKey) {
selectRowsBetweenIndexes([lastSelectedRow.rowIndex, currenttr.rowIndex])
}
}
}
function toggleRow(row) {
row.className = row.className == 'selected' ? '' : 'selected';
lastSelectedRow = row;
}
function selectRowsBetweenIndexes(indexes) {
indexes.sort(function (a, b) {
return a - b;
});
for (var i = indexes[0]; i <= indexes[1]; i++) {
trs[i - 1].className = 'selected';
}
}
function clearAll() {
for (var i = 0; i < trs.length; i++) {
trs[i].className = '';
}
}
});
body{font-size:62.5%;}
td { padding: 0.2em 0.4em; }
.selected { background: lightBlue }
.mainheading4{
border: 1px solid;
border-color: lightgray;
width:33.3%;
height:17px;
font-size:15px;
padding-left: -5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
i use
$("tr").on("mousedown=RowClick(this,false)") <
for getting mouse event.
but its not taken.
There are couple of wrong doings.
1) Assign id to table without which you will not get table rows as in below line
var trs = document.getElementById('table').tBodies[0].getElementsByTagName('tr');
E.g. In your tableCreate method add below lines of code.
var body = document.body,
tbl = document.createElement('table'),
tableId = document.createAttribute('id');
tableId.value = "table";
tbl.setAttributeNode(tableId);
2) Second register mouse down event like suggested by feela,
$(document).on('click', 'tr', function () {
RowClick(this, false);
});
Hope it will resolve your issue.
This is not a valid syntax for on. See: http://api.jquery.com/on/
What you probably meant was:
$("tr").on("mousedown", function(event) {
RowClick(event.target, false);
});

Categories