Looping through table cell ids in Javascript - javascript

I have created table cells in html that have ids that increment by 1 for example: cell1, cell2, cell3, ......, cell100.
What I would like to do is loop through and get reference to each of these cells using a for loop because referencing them one by one won't be good pratice and will require alot of codes of line, instead of this;
var cell1 = document.getElementById('cell1');
var cell2 = document.getElementById('cell2');
var cell3 = document.getElementById('cell3');
......
var cell100 = document.getElementById('cell100');
Is it possible to do something like this?
for (i = 0; i<=100; i++) {
var cell+i = document.getElementById("cell"+i);
// then I can call individual cells and assign tasks to them something along the lines of;
cell1.addEventListener('input',function(){}
cell5.background = '#f5f5f5'
cell55.innerHTML = 'I am cell 55'
etc..
}
EDITED:
Incase it might be useful, I have 1 table that contains many cells of which some have ids and some don't. I would only like to reference the ones that do have ids.

you can use document.querySelectorAll with a wildcard
var slice = Array.prorotype.slice;
var selection = document.querySelectorAll("[id^=cell]");
slice.call(selection).forEach(function(item, index){
// here item is the table row and index is the iteration number of forEach
// to get the id
var id = item.id;
//to get the numerical value in id
var number_in_id = item.id.match(/\d+/g)[0];
})
document.querySelectorAll("[id^=cell]") selectects all elements that their id starts with the string cell if you want to make it specific for table td's you add document.querySelectorAll("td[id^=cell]")

may be you are looking for this
var grid = document.getElementById("grid");//grid is the id of the table
for (var i = 1, row; row = grid.rows[i]; i++)
row.cells[0].textContent = "";//content of the starts with row 1..2..3 and so one than cell[0] or cell[1] and so on.

It'd be good pratice to use classes, though;
In base of your loop, you can do it so to get the current element, but if you have an loop more longer than the amount of the elements id numbers sequence, then it will be returning errors.
var Cell=document.getElementById("cell"+i)
//you've your DOM element in the variable called Cell now
//the one error you did is in the variable name
//you used the + operator in the variable name;
That's equivalent to element with id "cell0" when it's the first execution time of the loop. Not too elegant, you've many other ways to do the same.

Yes, it is quite easy, see below.
var cells = [];
for (var i = 0; i <= 100; i++) {
cells[i] = document.getElementById("cell"+i);
// do stuff....
if( cells[55] ) {
cells[55].innerHTML = 'I am cell 55';
}
}

Consider you have a table with an ID as myTable.
Get the table with,,
var theTable = document.getElementById('myTable');
To get all <td>s you could do,
var cells = theTable.querySelectorAll('td');
Then do the looping part,
for(var i = 0; i < cells.length; i++){
if(cells[i].id && cells[i].id.indexOf('cell') != -1){ //added to get only the significant cells
//do your stuff
cells[i].addEventListener(function(){});
cells[i].innerHTML = 'Something';
}
}

I'm lazy and didn't want to hand code any table, so I made Demo 2:
A form that'll accept a number of rows and columns
Can create <tr> and append to a table (0 to 100 rows)
Can create <td> and append to a <tr>(0 to 100 columns)
Assigns a unique id to every <tr> and <td>
The id pattern allows a human reader to locate <tr>s and <td>s
Each id for the <td> are displayed in each cell.
There's also two arrays, one for the <tr>(rowX) and one for the <td>(colY). There's many powerful methods for Array and having those 2 arrays you could even make a two-dimensional array.
Concerning the OP's request specifically about an id for cells on a table (complete or partial), I am aware that you have a pre-made table, so I'll take the key lines that make it possible in Demo 2 to assign ids:
row.setAttribute('id', 'r' + r);// Each row will have a numbered id (ex. r0 is row 1)
col.setAttribute('id', 'r' + r + 'c' + c);// Each cell will have a numbered id representing it's location (ex. r3c0 is located on row 4 column 1)
Demo 1
This snippet is an adaptation of the code previously mentioned:
function oddRows() {
var rows = document.querySelectorAll('tr');
// rows is a NodeList (an array-like object).
// We can covert this NodeList into an Array.
var rowArray = Array.prototype.slice.call(rows);
//Either way, NodeList or Array should be iterated through a for loop (most common way to reiterate)
for (var i = 0; i < rowArray.length; i++) {
if (i % 2 === 1) {
console.log(i);
var odd = rowArray[i];
odd.style.display = "none";
//This filters and removes all odd numbered rows
}
}
return false;
}
function evenCols() {
var cols = document.querySelectorAll('td');
var colArray = Array.prototype.slice.call(cols);
for (var j = 0; j < colArray.length; j++) {
if (j % 2 === 0) {
console.log(j);
var even = colArray[j];
even.style.backgroundColor = "red";
//This filters even numbered <td> and colors the background red.
}
}
return false;
}
td {
border: 2px inset #777;
}
button {
margin: 20px 5px 10px;
}
<button id="btn1" onclick="oddRows();">Remove Odd Rows</button>
<button id="btn2" onclick="evenCols();">Mark Even Cols</button>
<table id="t1">
<tr id="r0" class="row">
<td id="r0c0" class="col">r0c0</td>
<td id="r0c1" class="col">r0c1</td>
<td id="r0c2" class="col">r0c2</td>
<td id="r0c3" class="col">r0c3</td>
<td id="r0c4" class="col">r0c4</td>
<td id="r0c5" class="col">r0c5</td>
<td id="r0c6" class="col">r0c6</td>
<td id="r0c7" class="col">r0c7</td>
<td id="r0c8" class="col">r0c8</td>
<td id="r0c9" class="col">r0c9</td>
</tr>
<tr id="r1" class="row">
<td id="r1c0" class="col">r1c0</td>
<td id="r1c1" class="col">r1c1</td>
<td id="r1c2" class="col">r1c2</td>
<td id="r1c3" class="col">r1c3</td>
<td id="r1c4" class="col">r1c4</td>
<td id="r1c5" class="col">r1c5</td>
<td id="r1c6" class="col">r1c6</td>
<td id="r1c7" class="col">r1c7</td>
<td id="r1c8" class="col">r1c8</td>
<td id="r1c9" class="col">r1c9</td>
</tr>
<tr id="r2" class="row">
<td id="r2c0" class="col">r2c0</td>
<td id="r2c1" class="col">r2c1</td>
<td id="r2c2" class="col">r2c2</td>
<td id="r2c3" class="col">r2c3</td>
<td id="r2c4" class="col">r2c4</td>
<td id="r2c5" class="col">r2c5</td>
<td id="r2c6" class="col">r2c6</td>
<td id="r2c7" class="col">r2c7</td>
<td id="r2c8" class="col">r2c8</td>
<td id="r2c9" class="col">r2c9</td>
</tr>
<tr id="r3" class="row">
<td id="r3c0" class="col">r3c0</td>
<td id="r3c1" class="col">r3c1</td>
<td id="r3c2" class="col">r3c2</td>
<td id="r3c3" class="col">r3c3</td>
<td id="r3c4" class="col">r3c4</td>
<td id="r3c5" class="col">r3c5</td>
<td id="r3c6" class="col">r3c6</td>
<td id="r3c7" class="col">r3c7</td>
<td id="r3c8" class="col">r3c8</td>
<td id="r3c9" class="col">r3c9</td>
</tr>
<tr id="r4" class="row">
<td id="r4c0" class="col">r4c0</td>
<td id="r4c1" class="col">r4c1</td>
<td id="r4c2" class="col">r4c2</td>
<td id="r4c3" class="col">r4c3</td>
<td id="r4c4" class="col">r4c4</td>
<td id="r4c5" class="col">r4c5</td>
<td id="r4c6" class="col">r4c6</td>
<td id="r4c7" class="col">r4c7</td>
<td id="r4c8" class="col">r4c8</td>
<td id="r4c9" class="col">r4c9</td>
</tr>
<tr id="r5" class="row">
<td id="r5c0" class="col">r5c0</td>
<td id="r5c1" class="col">r5c1</td>
<td id="r5c2" class="col">r5c2</td>
<td id="r5c3" class="col">r5c3</td>
<td id="r5c4" class="col">r5c4</td>
<td id="r5c5" class="col">r5c5</td>
<td id="r5c6" class="col">r5c6</td>
<td id="r5c7" class="col">r5c7</td>
<td id="r5c8" class="col">r5c8</td>
<td id="r5c9" class="col">r5c9</td>
</tr>
<tr id="r6" class="row">
<td id="r6c0" class="col">r6c0</td>
<td id="r6c1" class="col">r6c1</td>
<td id="r6c2" class="col">r6c2</td>
<td id="r6c3" class="col">r6c3</td>
<td id="r6c4" class="col">r6c4</td>
<td id="r6c5" class="col">r6c5</td>
<td id="r6c6" class="col">r6c6</td>
<td id="r6c7" class="col">r6c7</td>
<td id="r6c8" class="col">r6c8</td>
<td id="r6c9" class="col">r6c9</td>
</tr>
<tr id="r7" class="row">
<td id="r7c0" class="col">r7c0</td>
<td id="r7c1" class="col">r7c1</td>
<td id="r7c2" class="col">r7c2</td>
<td id="r7c3" class="col">r7c3</td>
<td id="r7c4" class="col">r7c4</td>
<td id="r7c5" class="col">r7c5</td>
<td id="r7c6" class="col">r7c6</td>
<td id="r7c7" class="col">r7c7</td>
<td id="r7c8" class="col">r7c8</td>
<td id="r7c9" class="col">r7c9</td>
</tr>
<tr id="r8" class="row">
<td id="r8c0" class="col">r8c0</td>
<td id="r8c1" class="col">r8c1</td>
<td id="r8c2" class="col">r8c2</td>
<td id="r8c3" class="col">r8c3</td>
<td id="r8c4" class="col">r8c4</td>
<td id="r8c5" class="col">r8c5</td>
<td id="r8c6" class="col">r8c6</td>
<td id="r8c7" class="col">r8c7</td>
<td id="r8c8" class="col">r8c8</td>
<td id="r8c9" class="col">r8c9</td>
</tr>
<tr id="r9" class="row">
<td id="r9c0" class="col">r9c0</td>
<td id="r9c1" class="col">r9c1</td>
<td id="r9c2" class="col">r9c2</td>
<td id="r9c3" class="col">r9c3</td>
<td id="r9c4" class="col">r9c4</td>
<td id="r9c5" class="col">r9c5</td>
<td id="r9c6" class="col">r9c6</td>
<td id="r9c7" class="col">r9c7</td>
<td id="r9c8" class="col">r9c8</td>
<td id="r9c9" class="col">r9c9</td>
</tr>
</table>
If ids seem too heavy and cumbersome, you can select any cell on a table by using the pseudo-selectors nth-child and nth-of-type.
Example:
Target:* You want the 3rd <td> on the 5th row to have red text.
CSS:
table tbody tr:nth-of-type(5) td:nth-of-type(3) { color: red; }
jQuery:
$("table tbody tr:nth-of-type(5) td:nth-of-type(3)").css('color', 'red');
JavaScript:
var tgt = document.querySelector("table tbody tr:nth-of-type(5) td:nth-of-type(3)");
tgt.style.color = "red";
*Assuming that the target element has a table with a <tbody>
Demo 2
fieldset {
width: 50vw;
height: 55px;
margin: 10px auto;
padding: 3px;
}
input {
width: 40px;
height: 20px;
margin: 5px 10px;
}
table {
table-layout: fixed;
border-collapse: collapse;
border: 3px ridge #666;
width: 50vw;
height: 50vh;
margin: 20px auto;
}
td {
height: 20px;
width: 20px;
border: 1px inset grey;
font-size: 8px;
}
<fieldset>
<legend>Rows & Columns</legend>
<input id="rows" type="number" min="0" max="100" />
<input id="cols" type="number" min="0" max="100" />
<button id="btn1">Build</button>
</fieldset>
<table id="t1"></table>
<script>
var t1 = document.getElementById('t1');
var rows = document.getElementById('rows');
var cols = document.getElementById('cols');
var btn1 = document.getElementById('btn1');
btn1.addEventListener('click', function(e) {
var R = rows.value;
var C = cols.value;
var rowX = [];
var colY = [];
for (var r = 0; r < R; r++) {
var row = document.createElement('tr');
row.setAttribute('id', 'r' + r);// Each row will have a numbered id (ex. r0 is row 1)
row.classList.add('row');
rowX.push(row);
t1.appendChild(row)
for (var c = 0; c < C; c++) {
var col = document.createElement('td');
col.setAttribute('id', 'r' + r + 'c' + c);// Each cell will have a numbered id representing it's location (ex. r3c0 is located on row 4 column 1)
col.innerHTML = col.id;
col.classList.add('col');
colY.push(col);
row.appendChild(col);
}
}
}, false);
</script>

Related

Function name is not defined at HTMLTableCellElement.onclick

I want to make X and O game , So the first function i did it has loop and condition that when i click on any cell(td) in the table and if all cells in the table are empty wrote X in the cell which I clicked it , but I have here 2 problem ,
First one The console wrote (Sample1.html:53 Uncaught SyntaxError: Unexpected token '<') it refers to for loop, so I don't know what is the problem there.
the second problem console wrote also that my function name is not define , although the function name is correct so can anyone help me.
the JS codes is
<script >
/*var lastGame;*/
var TR=0;
var table = document.getElementById('tb');
function CheckAllEmpty(idClicked){
for(var x=0, x < table.rows.length; x++){
if(!table.rows[x])
{
TR++;
}
else{}
}
if(TR==9)
{
document.getElementById(idClicked).innerHTML="X";
}
else {}
}
</script>
And the HTML :
<table id="tb">
<tr>
<td id="td1" onclick="CheckAllEmpty(this.id);"></td>
<td id="td2"></td>
<td id="td3"></td>
</tr>
<tr>
<td id="td4"></td>
<td id="td5"></td>
<td id="td6"></td>
</tr>
<tr>
<td id="td7"></td>
<td id="td8"></td>
<td id="td9"></td>
</tr>
</table>
There seems to be other problems with your code, but your two specific problems should be fixed. Also I don't see why you need to check if every cell is empty, but then again I can't see the rest of your code. Feel free to ask any questions in the comments.
var TR = 0;
var table = document.getElementById('tb');
function CheckAllEmpty(idClicked) {
for (var x = 0; x < table.rows.length; x++) {
if (!(table.rows[x].value == "")) {
TR++;
console.log(TR);
}
}
if (TR == 3) {
document.getElementById(idClicked).innerHTML = "X";
}
}
CheckAllEmpty('td1');
<table id="tb">
<tr>
<td id="td1" onclick="CheckAllEmpty(this.id)"></td>
<td id="td2"></td>
<td id="td3"></td>
</tr>
<tr>
<td id="td4"></td>
<td id="td5"></td>
<td id="td6"></td>
</tr>
<tr>
<td id="td7"></td>
<td id="td8"></td>
<td id="td9"></td>
</tr>
</table>

Border around specific set of cells

I have done the component with table like this.
The problem is, when user chooses a range of cell like this, how can i put the border around that groups( the border likes the first one in group of cells) ?
I tried to use different class for each cell's border style, but it seems imposible, because i dont know which cell user will pick, how big the group of cell's size will be
Thank a lot and sorry about my English
Had the same task this week and sadly the question did not hold any answer, except for external libraries. So here is my approach.
In the following example I am using the class Marked to mark the cells as being selected and the dataset to flag which cells define which outer bound(s).
;window.onload = (event) => {
//REM: Assign mousedown event
document.querySelector('table').addEventListener('mousedown',_onMouseDownTable, false)
};
/***
* MouseDown event for the table, handles cells
*/
function _onMouseDownTable(event){
//REM: Checking for 'td'...
if(
event.target &&
event.target.tagName.toLowerCase() === 'td'
){
const tObject = {Down: event.target};
//REM: ...add event for marking cells
this.onmousemove = ((object, event) => {
if(
event.target &&
event.target.tagName.toLowerCase() === 'td'
){
object.Move = event.target
}
else{
delete object.Move
};
_markCells(object.Down, object.Move)
}).bind(null, tObject);
//REM: ...add event for finish marking cells
this.onmouseleave = this.onmouseup = ((object, event) => {
this.onmouseleave = this.onmousemove = this.onmouseup = null;
}).bind(null, tObject)
}
};
/***
* Marks cells between cell a and cell b
*/
function _markCells(a, b){
if(a && b){
//REM: Table of a (thus usually b)
const tTable = a.closest('table');
//REM: Remove existing marks and border data
tTable.querySelectorAll('td.Marked, td[data-bounds-left], td[data-bounds-right], td[data-bounds-top], td[data-bounds-bottom]').forEach((td) => {
td.classList.remove('Marked');
delete td.dataset.boundsLeft;
delete td.dataset.boundsRight;
delete td.dataset.boundsTop;
delete td.dataset.boundsBottom
});
//REM: The lowest (top to bottom / left to right) and the largest coordinate
const
tMaxColumn = Math.max(Number(a.dataset.columnIndex), Number(b.dataset.columnIndex)),
tMaxRow = Math.max(Number(a.dataset.rowIndex), Number(b.dataset.rowIndex)),
tMinColumn = Math.min(Number(a.dataset.columnIndex), Number(b.dataset.columnIndex)),
tMinRow = Math.min(Number(a.dataset.rowIndex), Number(b.dataset.rowIndex));
//REM: Mark all cells between Min and Max
for(let row = tMinRow; row <= tMaxRow; row++){
for(let column = tMinColumn; column <= tMaxColumn; column++){
const tCell = tTable.querySelector(`td[data-row-index='${row}'][data-column-index='${column}']`);
if(tCell){
//REM: If outer left bound...
if(column === tMinColumn){
tCell.dataset.boundsLeft = true
};
//REM: If outer right bound...
if(column === tMaxColumn){
tCell.dataset.boundsRight = true
};
//REM: If outer top bound...
if(row === tMinRow){
tCell.dataset.boundsTop = true
};
//REM: If outer bottom bound...
if(row === tMaxRow){
tCell.dataset.boundsBottom = true
};
//REM: Set cell as marked
tCell.classList.add('Marked')
}
}
}
}
};
td{
border: 2px solid #000;
background-color: grey;
height: 25px;
width: 200px;
}
td.Marked{
background-color: #1e90ff
}
td.Marked[data-bounds-left]{
border-left-color: red
}
td.Marked[data-bounds-right]{
border-right-color: red
}
td.Marked[data-bounds-top]{
border-top-color: red
}
td.Marked[data-bounds-bottom]{
border-bottom-color: red
}
<table>
<tbody>
<tr>
<td data-column-index="0" data-row-index="0"></td>
<td data-column-index="1" data-row-index="0"></td>
<td data-column-index="2" data-row-index="0"></td>
<td data-column-index="3" data-row-index="0"></td>
<td data-column-index="4" data-row-index="0"></td>
</tr>
<tr>
<td data-column-index="0" data-row-index="1"></td>
<td data-column-index="1" data-row-index="1"></td>
<td data-column-index="2" data-row-index="1"></td>
<td data-column-index="3" data-row-index="1"></td>
<td data-column-index="4" data-row-index="1"></td>
</tr>
<tr>
<td data-column-index="0" data-row-index="2"></td>
<td data-column-index="1" data-row-index="2"></td>
<td data-column-index="2" data-row-index="2"></td>
<td data-column-index="3" data-row-index="2"></td>
<td data-column-index="4" data-row-index="2"></td>
</tr>
<tr>
<td data-column-index="0" data-row-index="3"></td>
<td data-column-index="1" data-row-index="3"></td>
<td data-column-index="2" data-row-index="3"></td>
<td data-column-index="3" data-row-index="3"></td>
<td data-column-index="4" data-row-index="3"></td>
</tr>
<tr>
<td data-column-index="0" data-row-index="4"></td>
<td data-column-index="1" data-row-index="4"></td>
<td data-column-index="2" data-row-index="4"></td>
<td data-column-index="3" data-row-index="4"></td>
<td data-column-index="4" data-row-index="4"></td>
</tr>
</tbody>
</table>
Note that this is just a draft and not a finished solution, since it depends heavily on the already existing implementation and use-case.

Grabbing data from an array using for loop to populate a table

Problem
I'm trying to iterate over an array of objects using a for loop, but instead of getting all the items in the array that I actually see when I console.log(arr[i].Sand) I get the same number eleven times in my HTML.
script.js
$(function(){
$.ajax({
url: "https://sheetsu.com/apis/fef35fba",
method: "GET",
dataType: "json",
}).then(function(spreadsheet){
// Array of objects
var arr = spreadsheet.result;
for (i = 1; i < arr.length; i++) {
console.log(arr[i].Sand); // Just the volume of sand in tonnes
var sand = arr[i].Sand // Volume of Sand in tonnes
var salt = arr[i].Salt // Volume of Salt in tonnes
var snow = arr[i].Snow // Snow Removal total in dollars
// Changes the numbers in the table
$(".sand").html(sand);
}
})
});
spreadsheet.result
index.html
<table>
<thead>
<tr>
<th class="year"></th>
<th>
<img src="img/sand-2.png" alt="" class="icons">
<p>Volume of Sand</p>
<p class="paren">(in tonnes)</p>
</th>
<th>
<img src="img/salt-3.png" alt="" class="icons">
<p>Volume of Salt</p>
<p class="paren">(in tonnes)</p>
</th>
<th>
<img src="img/snow-3.png" alt="" class="icons">
<p>Snow Removal</p>
<p class="paren">(total in dollars)</p>
</th>
</tr>
</thead>
<tbody>
<tr>
<td class="year">2016</th>
<td class="sand">-<span class="asterisk">*</span></td>
<td class="salt">-<span class="asterisk">*</span></td>
<td class="snow">-<span class="asterisk">*</span></td>
</tr>
<tr>
<td class="year">2015</th>
<td class="sand">-</td>
<td class="salt">-</td>
<td class="snow">-</td>
</tr>
<tr>
<td class="year">2014</th>
<td class="sand">-</td>
<td class="salt">-</td>
<td class="snow">-</td>
</tr>
<tr>
<td class="year">2013</th>
<td class="sand">-</td>
<td class="salt">-</td>
<td class="snow">-</td>
</tr>
<tr>
<td class="year">2012</th>
<td class="sand">-</td>
<td class="salt">-</td>
<td class="snow">-</td>
</tr>
<tr>
<td class="year">2011</th>
<td class="sand">-</td>
<td class="salt">-</td>
<td class="snow">-</td>
</tr>
<tr>
<td class="year">2010</th>
<td class="sand">-</td>
<td class="salt">-</td>
<td class="snow">-</td>
</tr>
<tr>
<td class="year">2009</th>
<td class="sand">-</td>
<td class="salt">-</td>
<td class="snow">-</td>
</tr>
<tr>
<td class="year">2008</th>
<td class="sand">-</td>
<td class="salt">-</td>
<td class="snow">-</td>
</tr>
<tr>
<td class="year">2007</th>
<td class="sand">-</td>
<td class="salt">-</td>
<td class="snow">-</td>
</tr>
<tr class="last">
<td class="year">2006</th>
<td class="sand">-</td>
<td class="salt">-</td>
<td class="snow">-</td>
</tr>
</tbody>
</table>
while I was generating the code to answer this, someone changed your ajax call.
Here's the code reworked so it should help.
$(function(){
$.ajax({
url: "https://sheetsu.com/apis/fef35fba",
method: "GET",
dataType: "json",
}).then(function(spreadsheet){
// Array of objects
var arr = spreadsheet.result;
for (i =0; i < arr.length; i++) {
console.log(arr[i].Sand); // Just the volume of sand in tonnes
sand = arr[i].Sand // Volume of Sand in tonnes
salt = arr[i].Salt // Volume of Salt in tonnes
snow = arr[i].Snow // Snow Removal total in dollars
year = arr[i].Year; //We need the year to find the right row
// Changes the numbers in the table
$("tr").each(function(){
//We need to find the correct TR object.
//Remove Any spacing outside the html to make sure we don't get anything extra.
// We need to locate the ROW that has the right year so we can populate ONLY it's columns. an id or class based off year would have made this easier and less resource expensive.
if($(this).find(".year").html().trim() == year){
$(this).find(".sand").html(sand);
$(this).find(".salt").html(salt);
$(this).find(".snow").html(snow);
}
});
}
})
});
Here is a JSFiddle to show it:
https://jsfiddle.net/g6vn4Lf6/
This line:
$(".sand").html(sand);
Finds all elements with class="sand" and then sets the inner html of all of them to the value of sand. Instead you need to label each row of the table with html (eg <tr class="year-2015">), then you can select the right td element by using something like $(".year-2015 .sand").
First, you should change the key of the year in your json response to "year" instead of ""
Then you should associate that year with the tr's in some way, such as
<tr year='2016'>
Then in your for loop you can select just the .sand element that is a child of the correct tr.
$("tr[year='" + arr[i].year + "'] .sand").html(sand)
perhaps you should dynamically add a row for each of the results you receive from your ajax call like shown below:
$(document).ready(function() {
var arrayResults = [
{ Year: '2016', Sand: '123', Salt: '234', Snow: '345' },
{ Year: '2015', Sand: '222', Salt: '333', Snow: '444' },
{ Year: '2014', Sand: '555', Salt: '111', Snow: '888' },
{ Year: '2013', Sand: '121', Salt: '232', Snow: '343' },
{ Year: '2012', Sand: '454', Salt: '565', Snow: '676' }
];
for(var i = 0; i < arrayResults.length; i++) {
var newRow = '<tr>';
newRow += '<td class="year">' + arrayResults[i].Year + '</td>';
newRow += '<td class="sand">' + arrayResults[i].Sand + '</td>';
newRow += '<td class="salt">' + arrayResults[i].Salt + '</td>';
newRow += '<td class="snow">' + arrayResults[i].Snow + '</td>';
newRow += '</tr>';
$('tbody').append(newRow);
}
});
th, td {
border: 1px solid black;
padding: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<thead>
<tr><th>year</th><th>sand</th><th>salt</th><th>snow</th></tr>
</thead>
<tbody>
</tbody>
</table>

merging <td> rows in one column of html table

I have a requirement, if i have same data in column1 of 's with same id then i need to merge those cells and show their respective values in column2.
i.e., in fiddle http://jsfiddle.net/7t9qkLc0/12/ the key column have 3rows with data 1 as row value with same id and has corresponding different values in Value column i.e., AA,BB,CC. I want to merge the 3 rows in key Column and display data 1 only once and show their corresponding values in separate rows in value column.
Similarly for data4 and data5 the values are same i.e.,FF and keys are different, i want to merge last 2 rows in Value column and dispaly FF only one time and show corresponding keys in key column. All data i'm getting would be the dynamic data. Please suggest.
Please find the fiddle http://jsfiddle.net/7t9qkLc0/12/
Sample html code:
<table width="300px" height="150px" border="1">
<tr><th>Key</th><th>Value</th></tr>
<tr>
<td id="1">data 1</td>
<td id="aa">AA</td>
</tr>
<tr>
<td id="1">data 1</td>
<td id="bb">BB</td>
</tr>
<tr>
<td id="1">data 1</td>
<td id="cc">CC</td>
</tr>
<tr>
<td id="2">data 2</td>
<td id="dd">DD</td>
</tr>
<tr>
<td id="2">data 2</td>
<td id="ee">EE</td>
</tr>
<tr>
<td id="3">data 3</td>
<td id="ff">FF</td>
</tr>
<tr>
<td id="4">data 4</td>
<td id="ff">FF</td>
</tr>
<tr>
<td id="5">data 5</td>
<td id="ff">FF</td>
</tr>
</table>
</td>
</tr>
<tr>
<td colspan="3" style="padding-left: 0px; padding-right: 0px; padding-bottom: 0px">
</td>
</tr>
</table>
Building on tkounenis' answer using Rowspan:
One option to implement what you need would be to read all the values in your table after being populated, then use a JS object literal as a data structure to figure out what rows/columns are unique.
A JS object literal requires a unique key which you can map values to. After figuring out what rows/columns should be grouped, you can either edit the original table, or hide the original table and create a new table (I'm creating new tables in this example).
I've created an example for you to create a new table either grouped by key or grouped by value. Try to edit the examples provided to introduce both requirements.
Let me know if you need more help. Best of luck.
JSFiddle: http://jsfiddle.net/biz79/x417905v/
JS (uses jQuery):
sortByCol(0);
sortByCol(1);
function sortByCol(keyCol) {
// keyCol = 0 for first col, 1 for 2nd col
var valCol = (keyCol === 0) ? 1 : 0;
var $rows = $('#presort tr');
var dict = {};
var col1name = $('th').eq(keyCol).html();
var col2name = $('th').eq(valCol).html();
for (var i = 0; i < $rows.length; i++) {
if ($rows.eq(i).children('td').length > 0) {
var key = $rows.eq(i).children('td').eq(keyCol).html();
var val = $rows.eq(i).children('td').eq(valCol).html();
if (key in dict) {
dict[key].push(val);
} else {
dict[key] = [val];
}
}
}
redrawTable(dict,col1name,col2name);
}
function redrawTable(dict,col1name,col2name) {
var $table = $('<table>').attr("border",1);
$table.css( {"width":"300px" } );
$table.append($('<tr><th>' +col1name+ '</th><th>' +col2name+ '</th>'));
for (var prop in dict) {
for (var i = 0, len = dict[prop].length; i< len; i++) {
var $row = $('<tr>');
if ( i == 0) {
$row.append( $("<td>").attr('rowspan',len).html( prop ) );
$row.append( $("<td>").html( dict[prop][i] ) );
}
else {
$row.append( $("<td>").html( dict[prop][i] ) );
}
$table.append($row);
}
}
$('div').after($table);
}
Use the rowspan attribute like so:
<table width="300px" height="150px" border="1">
<tr>
<th>Key</th>
<th>Value</th>
</tr>
<tr>
<td id="1" rowspan="3">data 1</td>
<td id="aa">AA</td>
</tr>
<tr>
<td id="bb">BB</td>
</tr>
<tr>
<td id="cc">CC</td>
</tr>
<tr>
<td id="2" rowspan="2">data 2</td>
<td id="dd">DD</td>
</tr>
<tr>
<td id="ee">EE</td>
</tr>
<tr>
<td id="3">data 3</td>
<td id="ff">FF</td>
</tr>
<tr>
<td id="4">data 4</td>
<td id="ff">FF</td>
</tr>
<tr>
<td id="5">data 5</td>
<td id="ff">FF</td>
</tr>
</table>
http://jsfiddle.net/37b793pz/4/
Can not be used more than once the same id. For that use data-id attribute
HTML:
<table width="300px" height="150px" border="1">
<tr>
<th>Key</th>
<th>Value</th>
</tr>
<tr>
<td data-id="key1">data 1</td>
<td data-id="valaa">AA</td>
</tr>
<tr>
<td data-id="key1">data 1</td>
<td data-id="valbb">BB</td>
</tr>
<tr>
<td data-id="key1">data 1</td>
<td data-id="valcc">CC</td>
</tr>
<tr>
<td data-id="key2">data 2</td>
<td data-id="valdd">DD</td>
</tr>
<tr>
<td data-id="key2">data 2</td>
<td data-id="valee">EE</td>
</tr>
<tr>
<td data-id="key3">data 3</td>
<td data-id="valff">FF</td>
</tr>
<tr>
<td data-id="key4">data 4</td>
<td data-id="valff">FF</td>
</tr>
<tr>
<td data-id="key5">data 5</td>
<td data-id="valff">FF</td>
</tr>
</table>
</td>
</tr>
<tr>
<td colspan="3" style="padding-left: 0px; padding-right: 0px; padding-bottom: 0px"></td>
</tr>
</table>
JQ:
//merge cells in key column
function mergerKey() {
// prevents the same attribute is used more than once Ip
var idA = [];
// finds all cells id column Key
$('td[data-id^="key"]').each(function () {
var id = $(this).attr('data-id');
// prevents the same attribute is used more than once IIp
if ($.inArray(id, idA) == -1) {
idA.push(id);
// finds all cells that have the same data-id attribute
var $td = $('td[data-id="' + id + '"]');
//counts the number of cells with the same data-id
var count = $td.size();
if (count > 1) {
//If there is more than one
//then merging
$td.not(":eq(0)").remove();
$td.attr('rowspan', count);
}
}
})
}
//similar logic as for mergerKey()
function mergerVal() {
var idA = [];
$('td[data-id^="val"]').each(function () {
var id = $(this).attr('data-id');
if ($.inArray(id, idA) == -1) {
idA.push(id);
var $td = $('td[data-id="' + id + '"]');
var count = $td.size();
if (count > 1) {
$td.not(":eq(0)").remove();
$td.attr('rowspan', count);
}
}
})
}
mergerKey();
mergerVal();
Use below snippet of javascript. It should work fine for what you are looking.
<script type="text/javascript">
function mergeCommonCells(table, columnIndexToMerge){
previous = null;
cellToExtend = null;
table.find("td:nth-child("+columnIndexToMerge+")").each(function(){
jthis = $(this);
content = jthis.text();
if(previous == content){
jthis.remove();
if(cellToExtend.attr("rowspan") == undefined){
cellToExtend.attr("rowspan", 2);
}
else{
currentrowspan = parseInt(cellToExtend.attr("rowspan"));
cellToExtend.attr("rowspan", currentrowspan+1);
}
}
else{
previous = content;
cellToExtend = jthis;
}
});
};
mergeCommonCells($("#tableId"), 1);
</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>

How Do I wrap only selected elements in jQuery

In a badly designed table like this:
<table id="bow-me">
<td class="show-me">Pet is Great</td>
<td class="show-me">Pete is Greate</td>
<td class="go-me">Met is Great</td>
<td class="go-me">Mete is Greate</td>
<td class="show-me">Latte is Great</td>
<td class="show-me">Lattus is Greate</td>
<td class="low-me">Bet is Great</td>
<td class="low-me">Bette is Greate</td>
<td class="go-me">Rat is Great</td>
<td class="go-me">Rate is Greate</td>
</table>
I need to add the <tr> tag after every 2 <td> tags using jQuery. To make things clear, I have separated 2 <td>s in above question.
At first I did:
$('.show-me').wrapAll('<tr class="know-me"> </tr>');
$('.go-me').wrapAll('<tr class="know-me"> </tr>');
$('.low-me').wrapAll('<tr class="know-me"> </tr>');
But the messes up the structure.
Then I tried wrap('<tr></tr>'), which wraps every td with tr.
I also tried with before() and after() methods, but wasn't successful with it too.
My ideal output should be:
<table id="bow-me">
<tr class="know-me">
<td class="show-me">Pet is Great</td>
<td class="show-me">Pete is Greate</td>
</tr>
<tr class="know-me">
<td class="go-me">Met is Great</td>
<td class="go-me">Mete is Greate</td>
</tr>
<tr class="know-me">
<td class="show-me">Latte is Great</td>
<td class="show-me">Lattus is Greate</td>
</tr>
<tr class="know-me">
<td class="low-me">Bet is Great</td>
<td class="low-me">Bette is Greate</td>
</tr>
<tr class="know-me">
<td class="go-me">Rat is Great</td>
<td class="go-me">Rate is Greate</td>
</tr>
</table>
Is there anyway I can do this with jQuery?
The JSFiddle
You can do:
var tds = $('#bow-me td');
for (var i = 0; i < tds.length; i += 2) {
tds.slice(i, i + 2).wrapAll('<tr class="know-me"></tr>');
}
Updated Fiddle
As #Blazemonger suggestion, you can use unwrap() to remove the auto-generated tr here:
$('.know-me').unwrap();
Updated Fiddle
HTML (the original source code) is not the same as the DOM (the page as your browser and jQuery understand it). When your browser reads the original HTML, it considers it invalid and automatically adds <tr> tags around all the table cells.
You ought to alter your original HTML, or else use div elements and CSS to add display: table-cell as needed. HTML:
<div id="bow-me">
<div class="show-me">Pet is Great</div>
<div class="show-me">Pete is Greate</div>
<div class="go-me">Met is Great</div>
<div class="go-me">Mete is Greate</div>
<div class="show-me">Latte is Great</div>
<div class="show-me">Lattus is Greate</div>
<div class="low-me">Bet is Great</div>
<div class="low-me">Bette is Greate</div>
<div class="go-me">Rat is Great</div>
<div class="go-me">Rate is Greate</div>
</div>
CSS:
#bow-me {
display: table;
}
.know-me {
display: table-row;
}
.show-me, .go-me, .low-me {
display: table-cell;
}
And now this slightly unorthodox jQuery will do what you want:
$('.show-me,.go-me,.low-me').each(function() {
var klass = $(this).attr('class');
if (!$(this).closest('.know-me').length) { // not already wrapped in a row
$(this).nextUntil(':not(".'+klass+'")').addBack()
.wrapAll('<div class="know-me">');
};
});
http://jsfiddle.net/mblase75/QhKP7/
I don't think you can wrap 2 dom nodes...
I suspect you will have to do something like:
$('#bow-me').find('td:nth-child(2n+1),td:nth-child(2n+2)').wrapAll('<tr class="know-me"></tr>');
Hope someone improves and finds a better way but for now thats all I got
You can use following code;
var length = $("#bow-me td").length;
for (var i = 0; i <= length; i += 2) {
$("#bow-me td:eq(" + i + "), #bow-me td:eq(" + (i+1) + ")").wrapAll('<tr class="know-me"></tr>');
}
Here is a working fiddle: http://jsfiddle.net/cubuzoa/WNQ3d/4/
You could do something like this:
var els = $('td'),
trow;
for (var i = 0; i < els.length; i++) {
if (i%2 === 0) {
trow = $('<tr class="know-me" />');
$(els[i]).before(trow);
trow.append(els[i]);
trow.append(els[i + 1]);
}
}
Code snippet:
var els = $('td'),
trow;
for (var i = 0; i < els.length; i++) {
if (i % 2 === 0) {
trow = $('<tr class="know-me" />');
$(els[i]).before(trow);
trow.append(els[i]);
trow.append(els[i + 1]);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="bow-me">
<td class="show-me">Pet is Great</td>
<td class="show-me">Pete is Greate</td>
<td class="go-me">Met is Great</td>
<td class="go-me">Mete is Greate</td>
<td class="show-me">Latte is Great</td>
<td class="show-me">Lattus is Greate</td>
<td class="low-me">Bet is Great</td>
<td class="low-me">Bette is Greate</td>
<td class="go-me">Rat is Great</td>
<td class="go-me">Rate is Greate</td>
</table>

Categories

Resources