Select all rows programmatically and keep selection - javascript

How do I select all rows in my Bootgrid table programmatically with JavaScript?
I've added a button in the action bar and i have a function which is looping through all the rows in the JQuery Bootgrid table.
so far, I'm getting all the rows id (data-row-id) in the table, even on other pages in the bootgrid table.
How do i select all the rows from here and keep the selection programmatically?
Thanks
Code Below:
// JS
<script>
$(document).ready(function () {
var count = 0;
var dt = $("#table1").bootgrid({
selection: true,
multiSelect: true,
keepSelection: true,
rowSelect: true
}).on("selected.rs.jquery.bootgrid", function (e, rows) {
var rowIds = [];
for (var i = 0; i < rows.length; i++) {
count++;
}
$('#NumSelected').html(count);
console.log(count);
}).on("deselected.rs.jquery.bootgrid", function (e, rows) {
var rowIds = [];
for (var i = 0; i < rows.length; i++) {
count--;
}
$('#NumSelected').html(count);
console.log(count);
});
var rows = dt.data('.rs.jquery.bootgrid').rows;
// Get all Ids in the table and log
for(var i = 0; i < rows.length; i++)
{
console.log(rows[i].ID);
}
// append button in action bar
$(".bootgrid-header .actionBar").find('.actions.btn-group').append('<button id="selectAll" class="btn btn-default" type="button" title="Select All Clients Listed"><span class="icon glyphicon glyphicon-saved"></span></button>');
// Select all rows in table
// This is not working, I have data paginated in 8 pages (80 rows)
// and the code below only select the data in the first page
// I want to select all rows in the table and keep the selection by using jquery bootgrid
$("#selectAll").click(function () {
$('#table1 tbody > tr').each(function() {
$(this).addClass('active').attr('aria-selected', true);
$(this).find(":checkbox").prop('checked', true);
});
// get all selected rows id in array
var selectedRowsId = $("#table1").bootgrid('getSelectedRows');
console.log(selectedRowsId);
});
});
</script>
// html
<table id="table1">
<thead>
<tr>
<th data-column-id="ID" data-identifier="true" data-type="numeric">ID</th>
<th data-column-id="Name" data-type="string">Name</th>
<th data-column-id="OtherDetails" data-type="string">Other Details</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>#item.ID</td>
<td>#item.Name</td>
<td>#item.OtherDetails</td>
</tr>
}
</tbody>
</table>

First, it's important to set the values for the grid init (as you have already done correctly)
var dt = $("#table1").bootgrid({
selection: true,
multiSelect: true,
keepSelection: true,
rowSelect: true
...
Second, as of bootgrid Version 1.1.0 you can call the "select" method for selecting all items:
$("#yourGridName").bootgrid("select");
In your case:
$("#table1").bootgrid("select");
(in server-side scenario only the loaded items are selectable.)
So for this, you could generate a JS-function and a HTML-Button:
<button onclick="selectAllItems();">Select all loaded Items</button>
function selectAllItems()
{
$("#table1").bootgrid("select");
}
I've tested it with several pages. All loaded items will be selected and the selection is kept after going forward and backward to several pages.
I'm using the current version of bootgrid: V 1.3.1
In my case, after turning over to a new page I'm loading the new page via AJAX. So only the loaded items could get checked. But the checked checkboxes are kept after loading a new page.
If you want to check certain items, you could select the items with an array of ids:
$("#table1").bootgrid("select", [rowIdsArray]);
For example:
$("#table1").bootgrid("select", [1,3,5,8,9]);
In the bootgrid documentation, it's not very clear, what is meant with "row ids".
I think, it's the "data-row-id" attribute, because the input-tags don't have an id. There is only a class.

Related

How to add condition and change the color of table row

I have a javascript which will read the value from the JSON and creates a table dynamically in the HTML page.
<div style="width:700px;padding:20px;S">
<h1 style="text-align:center"><i style="color:#ccc">ALM Server Availability</i></h1>
<table id="records_table" class="table">
<tr>
<th>Server Name</th>
<th>Availability %</th>
</tr>
</table>
</div>
JQUERY :
function availshow(series) {
// 1. remove all existing rows
$("tr:has(td)").remove();
$.each(series.data.hostgroup.hosts, function (index, test) {
$('<tr>').append(
$('<td>').text(test.name),
$('<td>').text(parseInt((test.time_up/86400)*100)),
).appendTo('#records_table');
});
}
Now i need to check the condition if value of (test.time_up/86400)*100) < 100 , then i need to make that particular row into red color. How can I achieve it.
You can do this, looping through each tr then looking for 2nd td value
$('#records_table tr').each(function() {
var $td = $(this).find('td:eq(1)');
var value = $td.text();
if (parseInt(value) < 100) {
$td.css('background-color', 'red');
}
});
Your JQuery fucntion should be something like this:
var i=0
function availshow(series) {
// 1. remove all existing rows
$("tr:has(td)").remove();
$.each(series.data.hostgroup.hosts, function (index, test) {
i=(test.time_up/86400)*100);
$("<tr"+(i < 100 ? "class:'redBlock'": "")+">").append(
$('<td>').text(test.name),
$('<td>').text(parseInt((test.time_up/86400)*100)),
).appendTo('#records_table');
});
}
And then create that said class in .css file with all the style you want:
.redBlock{
background-color:red;
}
Hope I could help.
Happy Coding :)

Selecting a row in table based on content and clicking link from selected row - Protractor

I have a page object that looks like this:
<table border>
<th>Email</th>
<th>action</th>
<tr current-page="adminUsers.meta.page">
<td>admin#example.com</td>
<td>Delete permanently</td>
</tr>
<tr current-page="adminUsers.meta.page">
<td>matilda#snape.com</td>
<td>Delete permamently</td>
</tr>
</table>
I want to create a method that will enable me to delete a user based on his email address.
This is what I came up with, basing on How to find and click a table element by text using Protractor?:
describe('Admin panel', function() {
it('admin deletes a user', function() {
var re = new RegExp("matilda#snape.com");
var users_list = element.all(by.xpath("//tr[#current-page='adminUsers.meta.page']"));
var delete_btn = element(by.xpath("//a[contains(text(), 'Delete permamently')]"));
users_list.filter(function(user_row, index) {
return user_row.getText().then(function(text) {
return re.test(text);
});
}).then(function(users) {
users[0].delete_btn.click();
});
// some assertion, not relevant right now
});
});
First I'm trying to filter the row in which there's a user I want delete (array with all rows fitting my filter, then selecting the first row - should be one row anyway) and then click corresponding Delete button.
However, from my debugging I know that the method ignores the filtering and clicks the first Delete button available in the table and not the first from filtered elements.
What am I doing wrong?
In this particular case, I would use an XPath and its following-sibling axis:
function deleteUser(email) {
element(by.xpath("//td[. = '" + email + "']/following-sibling::td/a")).click();
}
I agree with #alexce's short & elegant answer but #anks, why don't you delete inside your filter??
describe('Admin panel', function() {
it('admin deletes a user', function() {
var re = new RegExp("matilda#snape.com");
var users_list = element.all(by.xpath("//tr[#current-page='adminUsers.meta.page']"));
var delete_btn = element(by.xpath("//a[contains(text(), 'Delete permamently')]"));
users_list.filter(function(user_row, index) {
return user_row.getText().then(function(text) {
return if(re.test(text)) { //assuming this checks the match with email id
user_row.delete_btn.click();
}
});
})
// some assertion, not relevant right now
});
});

DataTables issue: VM9075 dataTables.min.js:24Uncaught TypeError: Cannot set property '_DT_CellIndex' of undefined

I just started using DataTables and everything works fine when creating the table.
When I display 5, 24, 47 rows in my table, DataTables behaves as I would expect.
But I have this table that has around 700 rows and I get the error in Google Chrome,
"VM9075 dataTables.min.js:24Uncaught TypeError: Cannot set property '_DT_CellIndex' of undefined "
and in IE 9,
"SCRIPT5007: Unable to set value of the property '_DT_CellIndex': object is null or undefined
jquery-1.10.2.min.js, line 4 character 2367"
I don't have jQuery included twice btw.
I'm not sure how to proceed from here.
I tried to use the unminified version of the .js file to debug it more myself but i kept getting an "ext" method or property is undefined and couldn't fix that either.
Any help is appreciated!
I figured it out
The biggest issue was not knowing exactly what this error actually meant.
In my case it meant "the number of every <td> element in your table that is a child of a <tr> element doesn't match the number of <th> elements that are a child of the <thead> element."
My table was being generated by the server, and some of the <tr> elements had 27 <td> children (which was filling the whole width of the table up, but some of the <tr> elements only had 3, 4, or 5, ... <td> child elements which isn't a valid table.
I solved it by adding empty <td> elements in my table for the <tr> elements that lacked the correct number of <td> elements
var makeTableValidObject = {
thisWasCalled: 0,
makeTableValid: function() {
var tableToWorkOn = document.getElementById("table1");
//check the number of columns in the <thead> tag
//thead //tr //th elements
var numberOfColumnsInHeadTag = tableToWorkOn.children[1].children[0].children.length;
var numberOf_trElementsToValidate = tableToWorkOn.children[2].children.length;
//now go through each <tr> in the <tbody> and see if they all match the length of the thead columns
//tbody //all trs//all tds elements
//tableToWorkOn.children[2].children.children);
for(var i = 0; i < numberOf_trElementsToValidate; i++) {
//row my row make sure the columns have the correct number of elements
var tdColumnArray = tableToWorkOn.children[2].children[i].children
var trElementToAppendToIfNeeded = tableToWorkOn.children[2].children[i];
if(tdColumnArray.length != numberOfColumnsInHeadTag) {
//since they don't match up, make them valid
if(tdColumnArray.length < numberOfColumnsInHeadTag) {
//add the necessary number of blank <td> tags to the <tr> element to make this <tr> valid
var tdColumnArrayLength = tdColumnArray.length;
for(var j = 0; j < (numberOfColumnsInHeadTag - tdColumnArrayLength); j++) {
var blank_tdElement = document.createElement("td");
blank_tdElement.id = "validating_tdId" + i + "_" + j;
trElementToAppendToIfNeeded.appendChild(blank_tdElement);
}
}
else {
//TODO: remove <td> tags to make this <tr> valid if necessary
}
}
}
}
};
Edit 1:
It has been awhile and this question is still getting a bunch of views. I have since updated the code.
I replaced the first line of code with the second line to be more general
var numberOfColumnsInHeadTag = tableToWorkOn.children[1].children[0].children.length;
var numberOfColumnsInHeadTag = tableToWorkOn.querySelectorAll('thead')[0].querySelectorAll('th');
Pretty much where ever in the prior code you see the children.children I replaced that with the querySelectorAll(...) Function.
It uses css selectors which makes it amazingly powerful.
stay blessed
Ran into this same issue and implemented this same solution (essentially) in jquery based on Coty's. Hope this helps someone. :)
$( '.table' ).each(function( i ) {
var worktable = $(this);
var num_head_columns = worktable.find('thead tr th').length;
var rows_to_validate = worktable.find('tbody tr');
rows_to_validate.each( function (i) {
var row_columns = $(this).find('td').length;
for (i = $(this).find('td').length; i < num_head_columns; i++) {
$(this).append('<td class="hidden"></td>');
}
});
});
As answered by Coty, the problem lies in the mismatch of td elements generated in the header and body of table.
I'd like to highlight one of the reasons why it can occur (For .Net Users).
If Page numbers are being displayed at the end of gridview, they can disrupt table structure.
Remove AllowPaging="true" from your gridview to solve this.
And no worries because Datatable handles Paging.
you always keep four column but sometimes you will receive or append null td or only one td, td count always match with total column so when you does not have record then make td as following.
<th>No</th>
<th>Name</th>
<th>place</th>
<th>Price</th>
----------------------------------------
<td colspan="4">Data not found.</td>
<td style="display: none;"></td>
<td style="display: none;"></td>
<td style="display: none;"></td>
this error can also be triggered if you try to set options for the responsive extension for more columns than you have.
$( '.table' ).each(function( i ) {
var worktable = $(this);
var num_head_columns = worktable.find('thead tr th').length;
var rows_to_validate = worktable.find('tbody tr');
rows_to_validate.each( function (i) {
var row_columns = $(this).find('td').length;
for (i = $(this).find('td').length; i < num_head_columns; i++) {
$(this).append('<td class="hidden"></td>');
}
});
});

jQuery sort custom table

I'm working on a small userscript to sort a table, the structure of the table is really weird however. What i'm trying to do is to add an extra sort feature so I can sort on the ranking (#) of the persons.
Table data looks like this:
<table id="outer">
<tr>
<td><div id="bgn"></div></td>
<td>User 1</td>
<td>
<table id="inner">
<tbody>
<tr>
<td>Rank</td>
<td id="tdp">#28</td>
</tr>
</tbody>
</table>
</td>
</tr>
<!-- more rows -->
</table>
There are some additional <td>'s but they are not important right now. There are about 52 rows, but these could vary, of course.
Current jQuery code I have:
jQuery( document ).ready(function() {
var rankings = [];
$(document).on('click', '#tdr', function() {
// skipping first line because it's the header
$('tr:not(:first-child').each(function () {
var rank = $(this).find('#tdp').text();
var rank2 = rank.substring(1, rank.length)
rankings.push(rank2);
});
console.log(rankings.sort(sortNumber));
});
function sortNumber(num1, num2) {
return num1 - num2;
}
});
JS Bin Example
The output in the console is a correctly sorted array with all the rankings, I just don't have any idea how to also swap the corresponding <tr>'s so that the table get's rebuild the right way. Looking for any tips or pointers!
This suggestion is not really into "sorting" the rows, but re-constructing the table with the sorted rows. But this should do the job:
rankings = rankings.sort(sortNumber);
var table = $('<table></table>');
for (var i = 0; i < rankings.length; i++) {
var row = $('tr').filter(function() {
var rank = $(this).find('#tdp').text();
return rank.substring(1, rank.length) == i;
});
table.append(row);
}
$('#originalTable').html(table.html());

JavaScript Table Manipulation

I have a table with one column and about ten rows. The first column has rows with text as row headers, "header 1", "header 2". The second column contains fields for the user to type data (textboxes and checkboxes).
I want to have a button at the top labelled "Add New...", and have it create a third column, with the same fields as the first column. If the user clicks it again, it will create another blank column with fields (as in the second column).
Does anyone know of an effective way to manipulate the DOM to achieve this?
I'm experimenting with div's and TABLES but i'm on my third day of doing this, and it feels harder than it should be.
Amusing exercise. Thanks to AviewAnew's hint, I could do it.
function AddColumn(tableId)
{
var table = document.getElementById(tableId);
if (table == undefined) return;
var rowNb = table.rows.length;
// Take care of header
var bAddNames = (table.tHead.rows[0].cells.length % 2 == 1);
var newcell = table.rows[0].cells[bAddNames ? 1 : 0].cloneNode(true);
table.rows[0].appendChild(newcell);
// Add the remainder of the column
for(var i = 1; i < rowNb; i++)
{
newcell = table.rows[i].cells[0].cloneNode(bAddNames);
table.rows[i].appendChild(newcell);
}
}
with following HTML:
<input type="button" id="BSO" value="Add" onclick="javascript:AddColumn('TSO')"/>
<table border="1" id="TSO">
<thead>
<tr><th>Fields</th><th>Data</th></tr>
</thead>
<tbody>
<tr><td>Doh</td><td>10</td></tr>
<tr><td>Toh</td><td>20</td></tr>
<tr><td>Foo</td><td>30</td></tr>
<tr><td>Bar</td><td>42</td></tr>
<tr><td>Ga</td><td>50</td></tr>
<tr><td>Bu</td><td>666</td></tr>
<tr><td>Zo</td><td>70</td></tr>
<tr><td>Meu</td><td>80</td></tr>
</tbody>
</table>
Something along the lines of
function(table)
{
for(var i=0;i<table.rows.length;i++)
{
newcell = table.rows[i].cells[0].cloneNode(true);
table.rows[i].appendChild(newcell);
}
}

Categories