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();
Related
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).
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().
I want to hide all of the <tr> where td's text is 0. How can I do that? I have to mention that in reality i have more than 600 rows. But the example below is a demo. THX
<table id ="list2">
<tbody>
<tr>
<td>2</td>
<td>213</td>
<td id ="hideRow">0</td>
<tr>
<tr>
<td>vb</td>
<td>asf</td>
<td id ="hideRow">0</td>
<tr>
<tr>
<td>cxvb</td>
<td>xcvb</td>
<td id ="hideRow">2</td>
<tr>
<tr>
<td>cas</td>
<td>asdf</td>
<td id ="hideRow">45</td>
<tr>
</tbody>
</table>
This is my try :| . The event is loaded by onclick event
$('#list2').find("tr td #hideRow").each(function(){
var txt2 = $(this).text();
if (txt2 =="0"){
$('#list2').find("tr").each(function(){
$(this).hide();
});
}
})
First of all do not use id for duplicate names. Try doing it like following.
<table id ="list2">
<tbody>
<tr>
<td>2</td>
<td>213</td>
<td class="hideRow">0</td>
<tr>
<tr>
<td>vb</td>
<td>asf</td>
<td class="hideRow">0</td>
<tr>
<tr>
<td>cxvb</td>
<td>xcvb</td>
<td class="hideRow">2</td>
<tr>
<tr>
<td>cas</td>
<td>asdf</td>
<td class="hideRow">45</td>
<tr>
</tbody>
</table>
$('#list2').find(".hideRow").each(function(){
var txt2 = $(this).text();
if (txt2 =="0"){
$(this).parent().hide();
}
})
IDs on elements need to be unique, you can't have multiple <td id="hideRow"> elements and expect things to play nicely all of the time. I'd suggest changing it to a class. Then, select all elements:
var elems = $('span.hideRow');
Filter to those whose text is 0:
elems = elems.filter(function() {
return $(this).text() === "0";
});
Get their parent <tr> element:
elems = elems.closest('tr');
Then, finally, hide them:
elems.hide();
That can, obviously, all be done in one line:
$('span.hideRow').filter(function() {return $(this).text() === "0";}).closest('tr').hide();
I am not so good in English, to express myself, so I show it with examples to you!
Here is my HTML table with code:
<table border="1">
<tr id="tr1_1">
<td rowspan="2">1</td>
<td>tr1.1 td2</td>
<td>tr1.1 td3</td>
<td rowspan="2">
up/
down
</td>
</tr>
<tr id="tr1_2">
<td>tr1.2 td2</td>
<td>td1.2 td3</td>
</tr>
<tr id="tr2_1">
<td rowspan="2">2</td>
<td>tr2.1 td2</td>
<td>tr2.1 td3</td>
<td rowspan="2">
up/
down
</td>
</tr>
<tr id="tr2_2">
<td>tr2.2 td2</td>
<td>td2.2 td3</td>
</tr>
</table>
(You can see the result here)
For example, if I click on the second two rows' "up" link, the result should be this:
<table border="1">
<tr id="tr2_1">
<td rowspan="2">2</td>
<td>tr2.1 td2</td>
<td>tr2.1 td3</td>
<td rowspan="2">
up/
down
</td>
</tr>
<tr id="tr2_2">
<td>tr2.2 td2</td>
<td>td2.2 td3</td>
</tr>
<tr id="tr1_1">
<td rowspan="2">1</td>
<td>tr1.1 td2</td>
<td>tr1.1 td3</td>
<td rowspan="2">
up/
down
</td>
</tr>
<tr id="tr1_2">
<td>tr1.2 td2</td>
<td>td1.2 td3</td>
</tr>
</table>
(You can see the final result here)
So how could I do this? I know the prev() and before() methods in javascript, but it merge only 1 row with 1 row, but I want to merge 2 rows WITH 2 rows!
I hope, someone can help me! Thank you!
Try this jQuery code :
$('.up').click(function() {
tr = $('tr[id^="'+$(this).closest('tr').attr('id').slice(0, 3)+'"]')
tr.insertBefore(tr.eq(0).prev().prev())
return false;
})
$('.down').click(function() {
tr = $('tr[id^="'+$(this).closest('tr').attr('id').slice(0, 3)+'"]')
tr.insertAfter(tr.eq(1).next().next())
return false;
})
And have a look to your fiddle edited : http://jsfiddle.net/lulu3030/UQz8u/6/
Just some explanations :
closest('tr') method find the nearest parent which has a tr tag
slice(0, 3) get the first 3 characters of a string
=> variable tr selects all elements which has the same 3 first id characters
insertBefore and insertAfter methods allows to move selected elements
Could be done like that too:
DEMO
$(function () {
$('.up, .down').on('click', function () {
var $tr = $(this).closest('tr'),
$flag = $('<tr/>').insertBefore($tr),
$rows = $tr.add($tr.next('tr')).detach()
methods = $(this).is('.up') ? ['insertBefore', 'prevAll'] : ['insertAfter', 'nextAll'];
if ($flag[methods[1]]('tr').eq(1).length) {
$rows[methods[0]]($flag[methods[1]]('tr').eq(1));
$flag.remove();
} else $flag.replaceWith($rows);
});
});
http://jsfiddle.net/9sKwJ/66/
tr.spacer { height: 40px; }
$.tablesorter.addWidget({
id: 'spacer',
format: function(table) {
var c = table.config,
$t = $(table),
$r = $t.find('tbody').find('tr'),
i, l, last, col, rows, spacers = [];
if (c.sortList && c.sortList[0]) {
$t.find('tr.spacer').removeClass('spacer');
col = c.sortList[0][0]; // first sorted column
rows = table.config.cache.normalized;
last = rows[0][col]; // text from first row
l = rows.length;
for (i=0; i < l; i++) {
// if text from row doesn't match last row,
// save it to add a spacer
if (rows[i][col] !== last) {
spacers.push(i-1);
last = rows[i][col];
}
}
// add spacer class to the appropriate rows
for (i=0; i<spacers.length; i++){
$r.eq(spacers[i]).addClass('spacer');
}
}
}
});
$('table').tablesorter({
widgets : ['spacer']
});
<table id="test">
<thead>
<tr>
<th>Name</th>
<th>Number</th>
<th>Another Example</th>
</tr>
</thead>
<tbody>
<tr>
<td>Test4</td>
<td>4</td>
<td>Hello4</td>
</tr>
<tr>
<td colspan="3">Test4</td>
</tr>
<tr>
<td>Test3</td>
<td>3</td>
<td>Hello3</td>
</tr>
<tr>
<td colspan="3">Test3</td>
</tr>
<tr>
<td>Test2</td>
<td>2</td>
<td>Hello2</td>
</tr>
<tr>
<td colspan="3">Test2</td>
</tr>
<tr>
<td>Test1</td>
<td>1</td>
<td>Hello1</td>
</tr>
<tr>
<td colspan="3">Test1</td>
</tr>
</tbody>
</table>
This sorts just the way I want it if you sort it by the first column, but the other two columns don't maintain the same paired 'tr' sort im looking for.
Any help on this?
Use the expand-child class name on each duplicated row:
<tr>
<td>Test3</td>
<td>3</td>
<td>Hello3</td>
</tr>
<tr class="expand-child">
<td colspan="3">Test3</td>
</tr>
It's defined by the cssChildRow option:
$('table').tablesorter({
cssChildRow: "expand-child"
});
Here is a demo of it in action.