Check if the element has text, if not add one - javascript

I have a simple table and I want to add specific text if an element is empty, so far my code looks like this:
$("table").each(function (index, tableID) {
$(tableID)
.find("thead tr th")
.each(function (index) {
index += 1;
$(tableID)
.find("tbody tr td:nth-child(" + index + ")")
.attr("data-title", $(this).text());
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<th>By Year</th>
<th>TEAM</th>
<th>GP</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td>GSW</td>
<td>6.1</td>
</tr>
<tr>
<th>2016-17</th>
<td>GSW</td>
<td>6.1</td>
</tr>
<tr>
<th>2015-16</th>
<td>GSW</td>
<td>6.1</td>
</tr>
</tbody>
</table>
With this code am adding data-title and everything works fine, what am trying to achieve to add - when there is no data: so I modify my code:
$( "table" ).each( function( index, tableID ) {
$( tableID ).find( "thead tr th" ).each( function( index ) {
index += 1;
$( tableID ).find( "tbody tr td:nth-child(" + index + ")" ).attr( "data-title", $(this).text() );
if ($("tbody tr td:nth-child(" + index + ")" ).is(':empty')).append( "-" );
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<th>By Year</th>
<th>TEAM</th>
<th>GP</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td>GSW</td>
<td>6.1</td>
</tr>
<tr>
<th>2016-17</th>
<td>GSW</td>
<td>6.1</td>
</tr>
<tr>
<th>2015-16</th>
<td>GSW</td>
<td>6.1</td>
</tr>
</tbody>
</table>
This part of code where am adding - when table element is empty doesn't work, can anybody try to help me with this?

Your if statement is not using valid syntax. You need the expression body after the if which contains the code to be executed. You cannot call a method from the if statement itself.
Try this:
$("table").each(function(_, table) {
$(table).find("thead tr th").each(function(i) {
let $th = $(this);
let $td = $(table).find("tbody tr td:nth-child(" + (i + 1) + ")");
$td.attr("data-title", $th.text());
if ($td.is(':empty')) {
$td.append("-");
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<th>By Year</th>
<th>TEAM</th>
<th>GP</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td>GSW</td>
<td>6.1</td>
</tr>
<tr>
<th>2016-17</th>
<td>GSW</td>
<td>6.1</td>
</tr>
<tr>
<th>2015-16</th>
<td>GSW</td>
<td>6.1</td>
</tr>
</tbody>
</table>
However, it's worth noting that this code can be made more succinct with a single line of code:
$('tbody td:empty').text('-');
The code you're using to loop through the th/td and add the data attribute seems almost entirely redundant as the th value can be read at the point of use.

I simplified the code a little. I found it easier to make the header data-title values an array i could reference each iteration. The '-' for empty values was just a ternary expression tacked on to the end of the jQuery chain:
$(this).attr("data-title", h[i]).text($(this).text() || "-");
$("table").each(function() {
let h = [], i = 0
$("thead tr th").each(function() {
h.push($(this).text());
})
$(this).find("tbody tr>*").each(function() {
$(this).attr("data-title", h[i]).text($(this).text() || "-");
i++;
if (i >= h.length) i = 0
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<th>By Year</th>
<th>TEAM</th>
<th>GP</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td>GSW</td>
<td>6.1</td>
</tr>
<tr>
<th>2016-17</th>
<td>GSW</td>
<td>6.1</td>
</tr>
<tr>
<th>2015-16</th>
<td>GSW</td>
<td>6.1</td>
</tr>
</tbody>
</table>

Related

Hide elements without knowing complete id

I have a table like below
<table id="categoriesTable">
<tr id=row_id1_dynamicdata>
<td>...</td>
<td>..</td>
</tr>
<tr id=row_id2_dynamicdata>
<td>...</td>
<td>..</td>
</tr>
<tr id=row_id3_dynamicdata>
<td>...</td>
<td>..</td>
</tr>
<tr id=row_id4_dynamicdata>
<td>...</td>
<td>..</td>
</tr>
</table>
I want to hide all rows except row whose id contains id4. I won't have full id.
I came up with below jQuery code, but as I don't have full id, it doesn't work.
var idValue = document.getElementById(someElement);
$('#categoreisTable').find('tr').not($('#row_' +idValue)).hide();
How to filter with only half the id?
You can use the "Attribute starts with" selector to find the rows which don't match the one with the specified idValue. For example:
$('#someElement').on('change', function() {
var idValue = this.value;
$('#categoriesTable')
.find('tr')
.show() // not needed if you only want to hide
.not('[id^="row_id' + idValue + '_"]')
.hide();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="categoriesTable">
<tr id=row_id1_dynamicdata>
<td>.1..</td>
<td>..</td>
</tr>
<tr id=row_id2_dynamicdata>
<td>.2..</td>
<td>..</td>
</tr>
<tr id=row_id3_dynamicdata>
<td>.3..</td>
<td>..</td>
</tr>
<tr id=row_id4_dynamicdata>
<td>.4..</td>
<td>..</td>
</tr>
</table>
<input type="text" id="someElement" />
You can use querySelectorall on the tr element and then run a loop to only show rows that include id4 in their id.
Run the snippet below:
var idValue = document.querySelectorAll('tr');
for (i = 0; i < idValue.length; i++) {
if (idValue[i].id.includes("id4")) {
idValue[i].style.display = "block";
} else {
idValue[i].style.display = "none"
}
}
<table id="categoriesTable">
<tr id=row_id1_dynamicdata>
<td>row1</td>
<td>..</td>
</tr>
<tr id=row_id2_dynamicdata>
<td>row2</td>
<td>..</td>
</tr>
<tr id=row_id3_dynamicdata>
<td>row3</td>
<td>..</td>
</tr>
<tr id=row_id4_dynamicdata>
<td>row 4</td>
<td>..</td>
</tr>
<tr id=anotherrow_id4_dynamicdata>
<td>another row with id4</td>
<td>..</td>
</tr>
</table>
You can use document.getElementsByTagName to get all id contain id4.
Then, just to hide them.
let ElementArray = Array.prototype.filter.call(document.getElementsByTagName('tr'), element => element.id.match('id4'));
let idArray = ElementArray.forEach(element => document.getElementById(element.id).style.display="none");
You can simply use:
$('#categoriesTable tr').not('[id^="row_id4_"]').hide();

jquery - for every row that contains string disabled button

table:
<table id=tblList>
<thead>
<th>Firstname</th>
<th>Lastname</th>
<th>Status</th>
<th>Action</th>
</thead>
<tbody>
<tr>
<td>Jane</td>
<td>Doe</td>
<td>Pending</td>
<td><button class="cancelThis">Cancel</button></td>
</tr>
<tr>
<td>John</td>
<td>Doe</td>
<td>Cancelled</td>
<td><button class="cancelThis">Cancel</button></td>
</tr>
</tbody>
</table>
and script
var search = 'Cancelled';
$('#tblAppointment tr td').filter(function () {
return $(this).text() == search;
}).parent('tr').css('color', 'red');
with code above, i've managed to changed the color of the row that contains "Cancelled" to red
and with this:
$('#tblAppointment tr td').filter(function () {
return $(this).text() == search;
}).find(".cancelThis").prop("disabled", true);
is not working.
should be: for every row that contains string "Cancelled" cancel button will be disabled. rows that doesn't contain string "Cancelled" will remain unaffected.
TIA.
You can just add the same logic as the one that is working, Add .parent('tr') before .find(".cancelThis").prop("disabled", true);
$('#tblAppointment tr td').filter(function() {
return $(this).text() == search;
}).parent('tr').find(".cancelThis").prop("disabled", true);
You can cut down you code a bit,
var search = 'Cancelled';
var t = $('#tblAppointment tr td').filter(function() {
return $(this).text() == search;
}).parent('tr');
t.css('color', 'red');
t.find(".cancelThis").prop("disabled", true);
Demo
var search = 'Cancelled';
$('#tblAppointment tr td').filter(function() {
return $(this).text() == search;
}).parent('tr').css('color', 'red');
$('#tblAppointment tr td').filter(function() {
return $(this).text() == search;
}).parent('tr').find(".cancelThis").prop("disabled", true);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id=tblAppointment>
<thead>
<th>Firstname</th>
<th>Lastname</th>
<th>Status</th>
<th>Action</th>
</thead>
<tbody>
<tr>
<td>Jane</td>
<td>Doe</td>
<td>Pending</td>
<td><button class="cancelThis">Cancel</button></td>
</tr>
<tr>
<td>John</td>
<td>Doe</td>
<td>Cancelled</td>
<td><button class="cancelThis">Cancel</button></td>
</tr>
</tbody>
</table>
Your initial query is getting a list of <td> elements. So when you call find on that, you're only searching inside the <td> (which doesn't have a .cancelThis) element. You'd have to do something like this:
$('#tblAppointment tr td').filter(function () {
return $(this).text() == search;
}).parent('tr').find(".cancelThis").prop("disabled", true);
However, I can think of one issue you might want to resolve. What if First or Last named is "Cancelled"? Your query would match that too. If you add a class to the status <td>, you can search for it specifically:
<table id='tblAppointment'>
<thead>
<th>Firstname</th>
<th>Lastname</th>
<th>Status</th>
<th>Action</th>
</thead>
<tbody>
<tr>
<td>Jane</td>
<td>Doe</td>
<td class='status'>Pending</td>
<td><button class="cancelThis">Cancel</button></td>
</tr>
<tr>
<td>John</td>
<td>Doe</td>
<td class='status'>Cancelled</td>
<td><button class="cancelThis">Cancel</button></td>
</tr>
</tbody>
</table>
$('#tblAppointment tr td.status').filter(function () {
return $(this).text() == search;
}).parent('tr').find(".cancelThis").prop("disabled", true);
This will only look at the text of the td.status elements, and not the other elements (like first and last name).

jQuery - Create an array from a 2-column table

I have a 2-column table and I would like to convert the cells into an array using jQuery. I currently have that working, but I would like the array to be "2-column" as well, not sure if that's the right terminology. But basically I want the 2 cells from each row to be part of the same "row" in the array. Currently I have this:
$(function() {
var arr = [];
$('tbody tr').each(function() {
var $this = $(this),
cell = $this.find('td');
if (cell.length > 0) {
cell.each(function() {
arr.push($(this).text());
});
}
});
console.log(arr);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<td>Table heading</td>
</tr>
</thead>
<tbody>
<tr>
<td>Apples</td>
<td>Red</td>
</tr>
<tr>
<td>Bananas</td>
<td>Yellow</td>
</tr>
<tr>
<td>Oranges</td>
<td>Orange</td>
</tr>
<tr>
<td>Cucumbers</td>
<td>Green</td>
</tr>
</table>
How do I make it so that 0 would be Apples, Red and so on?
You can do something like this
$(function() {
var arr = $('tbody tr').get()//convert jquery object to array
.map(function(row) {
return $(row).find('td').get()
.map(function(cell) {
return cell.innerHTML;
}).join(',');
});
console.log(arr);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<td>Table heading</td>
</tr>
</thead>
<tbody>
<tr>
<td>Apples</td>
<td>Red</td>
</tr>
<tr>
<td>Bananas</td>
<td>Yellow</td>
</tr>
<tr>
<td>Oranges</td>
<td>Orange</td>
</tr>
<tr>
<td>Cucumbers</td>
<td>Green</td>
</tr>
</table>
ok you can also do this.
$(function() {
var arr = [];
flag = 0;
$('tbody tr td').each(function() {
if(flag == 0){
arr1 = [];
arr1.push($(this).text());
arr.push(arr1);
flag = 1;
}else{
let arr1 = arr[arr.length-1];
arr1.push($(this).text());
arr[arr.length-1] = arr1;
flag = 0;
}
});
console.log(arr);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<td>Table heading</td>
</tr>
</thead>
<tbody>
<tr>
<td>Apples</td>
<td>Red</td>
</tr>
<tr>
<td>Bananas</td>
<td>Yellow</td>
</tr>
<tr>
<td>Oranges</td>
<td>Orange</td>
</tr>
<tr>
<td>Cucumbers</td>
<td>Green</td>
</tr>
</table>
I'd suggest:
// using Array.from() to convert the Array-like NodeList returned
// from document.querySelectorAll() into an Array, in order to use
// Array.prototype.map():
let array = Array.from(document.querySelectorAll('tbody tr')).map(
// tr: a reference to the current array-element of the Array over
// which we're iterating; using Arrow function syntax:
(tr) => {
// here we return the result of the following expression;
// again using Array.from() to convert the NodeList of
// the <tr> element's children into an Array, again in order
// to utilise Array.prototype.map():
return Array.from(tr.children).map(
// cell is a reference to the current Node of the Array
// of Nodes over which we're iterating; here we implicitly
// return the textContent of each <td> ('cell') Node; after
// using String.prototype.trim() to remove leading/trailing
// white-space:
(cell) => cell.textContent.trim()
);
});
let array = Array.from(document.querySelectorAll('tbody tr')).map(
(tr) => {
return Array.from(tr.children).map(
(cell) => cell.textContent.trim()
);
});
console.log(array);
<table>
<thead>
<tr>
<td>Table heading</td>
</tr>
</thead>
<tbody>
<tr>
<td>Apples</td>
<td>Red</td>
</tr>
<tr>
<td>Bananas</td>
<td>Yellow</td>
</tr>
<tr>
<td>Oranges</td>
<td>Orange</td>
</tr>
<tr>
<td>Cucumbers</td>
<td>Green</td>
</tr>
</table>
References:
Array.from().
Array.prototype.map().
Arrow functions.
document.querySelectorAll().
ParentNode.children.
String.prototype.trim().

percentage two numbers and show final result in another td

I have a table that consists of tr and tds and I show the percentage of sold ticket in third td. the problem of this code is it generate a zero after each percentage, i think it is for br tag .
what should i do ?
here is my snippet :
$('table tbody tr').each(function() {
var $this = this,
td2Value = $('td:nth-child(2)', $this)
.html()
.trim()
.split(/\D+/);
$('span.result', $this).html(
$('td:nth-child(1)', $this)
.html()
.trim()
.split(/\D+/)
.map(function(v, i) {
return Math.round((td2Value[i] * 100 / v) || 0);
})
.join('<br>'));
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table border="1">
<thead>
<tr>
<th>Avalable</th>
<!--available-->
<th>Sold</th>
<!--used-->
<th>Result</th>
</tr>
</thead>
<tr>
<td>30 <br/></td>
<!--available-->
<td>4 <br/></td>
<!--used-->
<td><span class="result"></span></td>
</tr>
<tr>
<td>20 <br/> 20 <br/></td>
<!--available-->
<td>6 <br/> 5 <br/></td>
<!--used-->
<td><span class="result"></span></td>
</tr>
</table>
The issue is because you're using html(), so there's an extra line added to the output which then gets evaluated in the calculation. Use text() instead:
$('table tbody tr').each(function() {
var $this = $(this),
td1Value = $this.find('td:nth-child(1)').text().trim().split(/\D+/),
td2Value = $this.find('td:nth-child(2)').text().trim().split(/\D+/);
$this.find('span.result').html(td1Value.map(function(v, i) {
return Math.round((td2Value[i] * 100 / v) || 0) + '%';
}).join('<br>'));
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table border="1">
<thead>
<tr>
<th>Avalable</th>
<th>Sold</th>
<th>Result</th>
</tr>
</thead>
<tr>
<td>30 <br/></td>
<td>4 <br/></td>
<td><span class="result"></span></td>
</tr>
<tr>
<td>20 <br/> 20 <br/></td>
<td>6 <br/> 5 <br/></td>
<td><span class="result"></span></td>
</tr>
</table>
Note that I tidied up your logic a little too.
you are looping on content inside for first 2 you have numbers but for 3rd td, if you will debug you can see loop is doing one extra iteration.
Just put below line in map function before return statement :
console.log('>>>', td2Value[i],v,i);

How to iterate through each data in a table

<table class="table_style" id="table">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
</tr>
</thead>
<tbody>
<tr >
<td>1</td>
<td>ACDB</td>
<td>agaeg#aegrg.com</td>
<td>98900000</td>
</tr>
<tr>
<td>2</td>
<td>DEFG</td>
<td>defg#defg.com</td>
<td>11111112</td>
</tr>
<tr>
<td>3</td>
<td>IJKL</td>
<td>ijkl#ijkl.com</td>
<td>1234323432</td>
</tr>
</tbody>
</table>
I am a bit confused about how to get all the data from the table using a single button. When the user click on the button i should get all the table data. I tried with the below code. I need to get all the data in a array format. So that i can save all the data to my database.
$("#saveButton").click(function(event) {
var table = document.getElementById("table");
var dataArray = [];
var data = table.find('td');
for (var i = 0; i <= data.size() - 1; i = i + 4) {
data.push(data[i].textContent, data[i + 1].textContent, data[i + 2].textContent);
}
});
Try this code.
$("#saveButton").click(function(event) {
var data = [];
$("#table tr").each(function(i){
if(i != 0){
data.push({
id: $(this).find("td:eq(0)").html(),
name: $(this).find("td:eq(1)").html(),
email: $(this).find("td:eq(2)").html(),
phone: $(this).find("td:eq(3)")}).html()
});
}
});
//do something with data
});
If you want to use jquery, have a look at https://jsfiddle.net/qg6xpy39/
HTML:
<table class="table_style" id="table">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
</tr>
</thead>
<tbody>
<tr >
<td>1</td>
<td>ACDB</td>
<td>agaeg#aegrg.com</td>
<td>98900000</td>
</tr>
<tr>
<td>2</td>
<td>DEFG</td>
<td>defg#defg.com</td>
<td>11111112</td>
</tr>
<tr>
<td>3</td>
<td>IJKL</td>
<td>ijkl#ijkl.com</td>
<td>1234323432</td>
</tr>
</tbody>
</table>
<button id="saveButton">
click
</button>
JS:
$("#saveButton").click(function(event) {
var rows = $('#table td'); // retrieve the rows of your table
var dataArray = [];
$.each(rows, function(idx, elt) {
dataArray.push($(elt).text()); // add cell text content to the data array
});
console.log(dataArray); // so you can check what's in the array ;-)
});
As said in comments, in plain JavaScirpt.
use querySelectorAll to select all trs. Then iterate in each of them and get it's td's innerHTML and push it in an array.
Then use Array.shift() to remove the th elements. That is, the titles.
The code
function save(){
var arr=[];
var tr=document.querySelectorAll('tr');
tr.forEach(function(x,y){
arr[y]=[];
x.querySelectorAll("td").forEach(function(z){
arr[y].push(z.innerHTML);
});
});
arr.shift();
console.log(arr);
}
Check the below snippet.
function save(){
var arr=[];
var tr=document.querySelectorAll('tr');
tr.forEach(function(x,y){
arr[y]=[];
x.querySelectorAll("td").forEach(function(z){
arr[y].push(z.innerHTML);
});
});
arr.shift();
console.log(arr);
}
<table class="table_style" id="table">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
</tr>
</thead>
<tbody>
<tr >
<td>1</td>
<td>ACDB</td>
<td>agaeg#aegrg.com</td>
<td>98900000</td>
</tr>
<tr>
<td>2</td>
<td>DEFG</td>
<td>defg#defg.com</td>
<td>11111112</td>
</tr>
<tr>
<td>3</td>
<td>IJKL</td>
<td>ijkl#ijkl.com</td>
<td>1234323432</td>
</tr>
</tbody>
</table>
<button onclick="save();">Save</button>
Another possible approach, again using pure javascript rather than jQuery would be to use the DOM NodeIterator in conjunction with an XPath via Document.evaluate()
<!doctype html>
<html>
<head>
<meta charset='utf-8' />
<title>Javascript DOM Processing</title>
<script type='text/javascript'>
document.addEventListener('DOMContentLoaded',function(e){
var query='/html/body/table[#id="table"]/tbody/tr/td';
var xpr = document.evaluate( query, document, null, XPathResult.ANY_TYPE, null );
var td = xpr.iterateNext();
var dataTbl=[];
while( td ){
try{
dataTbl.push( td.textContent );
td=xpr.iterateNext();
}catch( err ){
alert( 'Error'+err );
}
}
/* The data from all table cells is now in the array */
alert( dataTbl.join(String.fromCharCode(10)) );
},false);
</script>
</head>
<body>
<!-- content -->
<table class="table_style" id="table">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
</tr>
</thead>
<tbody>
<tr >
<td>1</td>
<td>ACDB</td>
<td>agaeg#aegrg.com</td>
<td>98900000</td>
</tr>
<tr>
<td>2</td>
<td>DEFG</td>
<td>defg#defg.com</td>
<td>11111112</td>
</tr>
<tr>
<td>3</td>
<td>IJKL</td>
<td>ijkl#ijkl.com</td>
<td>1234323432</td>
</tr>
</tbody>
</table>
</body>
</html>
Simplest approach would be
var data_arr = [];
$('#table tr').each(function() {
data_arr.push(this.cells[0].innerHTML);
data_arr.push(this.cells[1].innerHTML);
data_arr.push(this.cells[2].innerHTML);
data_arr.push(this.cells[3].innerHTML);
});

Categories

Resources