Getting a row from a data attribute in datatables.js - javascript

I am struggling trying to find the right method to do this. Basically, I have an array of id values that correspond to which rows have been selected in my table. To construct this list, I use the following code. this.options.ajaxId is the key that accesses my Id value in the data object passed to the table.
this.getRowData(target)[this.options.ajaxId]
where my getRowData function is:
getRowData: function (HTMLrow) {
return this.dataTable.row(HTMLrow).data();
},
This works great, but then I am stumped on my next step which is re-selecting the correct rows when the table is re-drawn via paging, sorting, or searching. My plan was to cycle through the ID's and find which table row corresponded to that ID value, but I cannot find a function to input a key value search pair and return the html row. Something like the following is what I was thinking,
this.dataTable.findRow( key, value );
// then my usage would be the following:
var that = this;
_.each(this.selectedList, function (id) {
var row = that.dataTable.findRow( that.options.ajaxId, id );
// code to select the row
});
I haven't written it yet, but I know I can cycle through each of the rows, get the data for that row, and check it against what I am looking for, but in cases where the user is viewing 100 rows and has only one selection I would like to avoid that.
Any insight?
Thanks

SOLUTION #1
You can use the following code to locate and highlight rows based on row IDs if row ID is stored in one of the fields.
// Index of column containing IDs
var colIdIndex = 0;
// List of row IDs
var rowIds = ['2', '4', '6'];
// Find indexes of rows which have IDs in the desired column
var rowIndexes = table.rows().eq(0).filter( function (rowIdx) {
return ($.inArray(table.cell( rowIdx, colIdIndex ).data(), rowIds) !== -1)
? true
: false;
});
// Select rows based on array of found row indexes
table.rows(rowIndexes)
.nodes()
.to$()
.addClass('selected');
See filter() API method for more details.
Please note that this method will work for client-side processing mode only.
DEMO
See this jsFiddle for code and demonstration.
SOLUTION #2
Alternative approach that would work both in client-side and server-side processing modes would be to use createdRow callback.
For example:
// Index of column containing IDs
var colIdIndex = 0;
// List of row IDs
var rowIds = ['2', '4', '6'];
var table = $('#example').DataTable({
createdRow: function( row, data, dataIndex ) {
if ( $.inArray(data[colIdIndex], rowIds) !== -1) {
$(row).addClass('selected');
}
}
});
DEMO
See this jsFiddle for code and demonstration.

Related

Cypress - Working with div tables - Validating text on each row

I want to check if the first column of each row's text starts with "AA", "BB" or "CC". But I couldn't manage it on div table. I can only select and check the first row (code below). But I also tried with selecting the whole column and tried with using cy.each & cy.wrap and got errors too.
How can I check the first column for each row's text? (Table has 40-45 rows.)
The table looks like this:
Right now I can only check the first row with the code below. How can I check all the rows like this? Is the code below clear to you by the way?
cy.get('div[row-index="0"]')
.eq(1)
.invoke('text')
.then(text => {
const productID = text.trim();
let correctProductIDPrefix = false;
['AA', 'BB', 'CC'].forEach(possibleProductIDPrefix => {
if (!correctProductIDPrefix) {
correctProductIDPrefix = productID.startsWith(possibleProductIDPrefix);
}
});
expect(correctProductIDPrefix).to.be.true;
});
Thanks in advance!
To perform the same test on all rows
select all the rows (change [row-index="0"] to [row-index])
use .each() to run test on all rows
sub-select just the column you want, in case some other column also has the prefix and gives you a false-positive result
use Array.some() method to check at least one prefix matches
const possibleProductPrefixes = ['AA', 'BB', 'CC'] // define once outside test
cy.get('div[row-index]') // selects every row
.each($row => {
const $col = $row.find('[col-id="orderNumber"]') // pick out the column
const productId = $col.text().trim()
const correctProductIDPrefix = possibleProductPrefixes.some(prefix => {
return productId.startsWith(prefix)
})
expect(correctProductIDPrefix).to.be.true;
});
Ref Array.prototype.some()
The some() method tests whether at least one element in the array passes the test implemented by the provided function. It returns true if, in the array, it finds an element for which the provided function returns true; otherwise it returns false. It doesn't modify the array.
You can do something like this:
let prefix = ['AA', 'BB', 'CC']
cy.get('.ag-cell-value').each(($ele, index) => {
expect($ele.text().trim().startsWith(prefix[index])).to.be.true
})

How to delete a specific dataset from Chart.js?

I want to add & delete datasets from chart.js using checkboxes.
Right now I am adding using this:
var ds1 = {
label: ..
data: .. etc
};
data.datasets.push(ds1);
When I uncheck any of the checkboxes, it's always deleting the last dataset added, which is not necessary the one of the checkbox.
I'm using data.datasets.pop(ds1); to remove the when a checkbox is clicked.
If you're removing using data.datasets.pop(ds1) you'll never get the result you're looking for. The dataset property is an array, so let's just focus on arrays and ignore Chart.js.
First issue is that the pop() method of the Arrays type does not take an argument, so providing which element you want to remove is irrelevant. Pop() will always remove the last element from an array.
To remove a specific element from the array you need to use the splice() function.
Let's say that ds1 is the element you want to remove.
let removalIndex = data.datasets.indexOf(ds1); //Locate index of ds1
if(removalIndex >= 0) { //make sure this element exists in the array
data.datasets.splice(removalIndex, 1);
}
This will delete the 1 record in the array starting at the index we located ds1.
If you look at ChartJS' internal object chart.data.datasets, the datasets are distinguishable by the label you gave when initially adding the datasets (it's weird that there's no ID):
So it's really just a matter of filtering out an object from the array by that Label, and calling chart.update();.
// Filter out and set back into chart.data.datasets
chart.data.datasets = chart.data.datasets.filter(function(obj) {
return (obj.label != targetLabel);
});
// Repaint
chart.update();
Thank you JNYRanger!
It got like this:
...
$(document).ready(function() {
$('#ind4').change(function(){
if (this.checked) {
graph.data.datasets.push(ds4);
graph.update();
} else {
let removalIndex = graph.data.datasets.indexOf(ds4);
graph.data.datasets.splice(removalIndex, 1);
graph.update();
}
});
});
$(document).ready(function() {
$('#ind5').change(function(){
if (this.checked) {
graph.data.datasets.push(ds5);
graph.update();
} else {
let removalIndex = graph.data.datasets.indexOf(ds5);
graph.data.datasets.splice(removalIndex, 1);
graph.update();
}
});
I just added graph.data.... (when graph is the var of my chart) and graph.update() by the end of every action.
Actually you can add an ID in your dataset :
var ds1 = {
label: ..
data: ..
id : 'myId'
};
data.datasets.push(ds1);
It will not affect your dataset or your chart in anyway
Then you can find and delete (or update) :
data.datasets.find((dataset, index) => {
if (dataset.id === 'myId') {
data.datasets.splice(index, 1);
return true; // stop searching
}
});
myChart.update();

SlickGrid javascript get current row data

I would like to remove a row when I press the Delete key. But I can't get any data from the source below:
var selectedrows = grid.getSelectedRows();
grid.onKeyDown.subscribe(function(event) {
var item = data[selectedrows.cell];
if (event.keyCode == 46) {
alert(item.hostname);
}
});
First, the getSelectedRows() function returns an Array of the selected column numbers. The way you are trying will return undefined, since that Array doesn't contain any property called cells.
Open this official SlickGrid example demo and try the following:
Select the first row in grid.
Try issuing the following command in your JS debugger console:
grid.getSelectedRows()
Will return you an Array with the selected row number as:
Array [ 0 ]
The returned Array'sfirst element is the row number that you have just selected.
Now that we know the selected row number issue this:
data[grid.getSelectedRows()[0]]
Will return you the selected Object as:
Object { name: "Make a list", complete: true }
If you want to reach a property of the returned Object you could do it as:
var selectedRow = data[grid.getSelectedRows()[0]];
console.log(selectedRow.name);
Will return the property name's value as:
Make a list
Hope this clears up your confusion.

JS check if an array is embedded in another array

I have a two dimensional JS array in which some rows are useless and needs to be deleted;
In particular I need to delete the rows that are embedded in other rows (by saying that row B is embedded in row A I mean not just that A is a superset of B, but that A contains all the elements in B, in sequence and in the same order)
EX. I have:
var matrix = [
["User","Shop","Offer","Product","File"],
["User","Shop","File"],
["User","Shop","Map"],
["User","Shop","Promotion"],
["User","Shop","Offer","Product","Reservation"],
["User","Group","Accesslevel"],
["User","Group"],
["User","Reservation"],
["User","Shop"],
["User","Shop","Offer","Product","Markers"]
];
In this example the second row (["User","Shop","File"]) should NOT be deleted (all its elements are in the first row, but not consecutive);
Row 7 (["User","Group"]) should be deleted because is embedded in the 6th (["User","Group","Accesslevel"]) and also row 9 (["User","Shop"]) because is embedded in many others..
I'm looking for a possible efficient algorithm to check if an array is embedded in another one;
I will use this in nodejs.
This should do the trick.
// Is row2 "embedded" in row1?
function embedded(row1, row2) {
return row2.length < row1.length &&
row2.every(function(elt, i) { return elt === row1[i]; });
}
//filter out rows in matrix which are "embedded" in other rows
matrix.filter(function(row) {
return !matrix.some(function(row2) { return embedded(row2, row); });
});
here is a solution which I used few days ago for the same purpose but on the client side, This would also work on node server.
http://jsfiddle.net/8wLst3qr/
I have changed the program according to your needs,
What I have done here is,
some initialisation,
var matrix = [
["User","Shop","Offer","Product","File"],
["User","Shop","File"],
["User","Shop","Map"],
["User","Shop","Promotion"],
["User","Shop","Offer","Product","Reservation"],
["User","Group","Accesslevel"],
["User","Group"],
["User","Reservation"],
["User","Shop"],
["User","Shop","Offer","Product","Markers"]
];
var tempArr=matrix;
here are the steps
convert the array of arrays to an array of strings-(this is because you need to clear the redundant data only if it is in the same order), code as follows.
var json=[];
for(k=0;k<tempArr.length;k++)
{
json[k]=tempArr[k].toString();
}
and then match the index of each string in other strings in the array, if matches, check the string whose length is less and delete
it.
for(k=0;k<json.length;k++)
{
for(l=0;l<json.length;l++)
{
console.log("val l="+json[l]+"val k="+json[k]+"value="+json[l].indexOf(json[k]));
console.log("k="+k+";l="+l);
if(k!=l && (json[k].indexOf(json[l]) !=-1))
{
console.log("removing");
console.log("removing");
if(json[k].length>json[l].length)
{
json.splice(l, 1);
}
else
{
json.splice(k, 1);
}
}
}
}
hope it helps,
edit-sorry you would require to check the console.log for the output on fiddle

Bring selected rows to the top from the Jqgrid

I am using jqgrid in 'multiselect' mode and without pagination. When the user selects individual records by using mouse click, is there any way that I can bring those selected records to the top of the grid?
Thanks in advance for your help.
After small discussion with you in comments I could reformulate your question so: "how one can implement sorting by multiselect column?"
The question find is very interesting so I invested some time and could suggest a solution in case of jqGrid which hold local data (datatype which is not 'xml' or 'json' or which has 'loadonce: true' option).
First of all the working demo which demonstrate my suggestion you can find here:
The implementation consist from two parts:
Making selection as part of local data. As the bonus of the selection will be hold during paging of local data. This feature is interesting independent on the sorting by multiselect column.
The implementation of sorting by multiselect column.
To implement of holding selection I suggest to extend local data parameter, which hold local data with the new boolean property cb (exactly the same name like the name of the multiselect column). Below you find the implementation:
multiselect: true,
onSelectRow: function (id) {
var p = this.p, item = p.data[p._index[id]];
if (typeof (item.cb) === "undefined") {
item.cb = true;
} else {
item.cb = !item.cb;
}
},
loadComplete: function () {
var p = this.p, data = p.data, item, $this = $(this), index = p._index, rowid;
for (rowid in index) {
if (index.hasOwnProperty(rowid)) {
item = data[index[rowid]];
if (typeof (item.cb) === "boolean" && item.cb) {
$this.jqGrid('setSelection', rowid, false);
}
}
}
}
To make 'cb' column (multiselect column) sortable I suggest to do following:
var $grid = $("#list");
// ... create the grid
$("#cb_" + $grid[0].id).hide();
$("#jqgh_" + $grid[0].id + "_cb").addClass("ui-jqgrid-sortable");
cbColModel = $grid.jqGrid('getColProp', 'cb');
cbColModel.sortable = true;
cbColModel.sorttype = function (value, item) {
return typeof (item.cb) === "boolean" && item.cb ? 1 : 0;
};
UPDATED: The demo contain a little improved code based on the same idea.
If you have the IDs of the row(s) you can do a special sort on server side by using following command for e.g. MySQL:
Select a,b,c
FROM t
ORDER BY FIND_IN_SET(yourColumnName, "5,10,44,29") DESC
or
ORDER BY FIELD(yourColumnName, "5") DESC

Categories