how to unselect a row on keydown in datatables - javascript

I am using datatables. Trying to use select and keytable features together. Please see this jsfiddle.
$(document).ready(function() {
$('#data-table')
.DataTable({
"select": {
"style": "os"
},
"keys": true
}).on('key-focus', function() {
$('#data-table').DataTable().row(getRowIdx()).select();
})
.on('click', 'tbody td', function() {
var rowIdx = $('#data-table').DataTable().cell(this).index().row;
$('#data-table').DataTable().row(rowIdx).select();
}).on('key', function(e, datatable, key, cell, originalEvent) {
if (key === 13) {
var data = $('#data-table').DataTable().row(getRowIdx()).data();
$("#output").html("Code: " + data[0] + ". Description: " + data[1]);
}
});
});
function getRowIdx() {
return $('#data-table').DataTable().cell({
focused: true
}).index().row;
}
It almost works perfect except when press key down it doesn't unselect the first row that I clicked. It acts like as if I have pressed the shift key.
My second problem that when I press enter it shows the first column data but I need to show the row id.
I would appreciate a lot if you could help me to solve these two problems

you need to use deselect() all rows before select()
also keep a reference of $('#data-table').DataTable() as table instead of calling it everytime.
$(document).ready(function() {
var shiftKey, ctrlKey, table = $('#data-table').DataTable({
select: { style: 'os' },
keys: true
}).on('key-focus', function() {
if(!shiftKey && !ctrlKey) table.rows().deselect();
table.row(getRowIdx()).select();
})
.on('key', function(e, datatable, key, cell, originalEvent) {
if (key === 13) {
var data = table.row(getRowIdx()).data();
$('#output').html('Code: ' + data[0] + '. Description: ' + data[1]);
}
});
function getRowIdx() {
return table.cell({ focused: true }).index().row;
}
$(document).on('keyup keydown', function(e){
shiftKey = e.shiftKey;
ctrlKey = e.ctrlKey;
return true;
});
});
table.dataTable th.focus,
table.dataTable td.focus {
outline: none !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://cdn.datatables.net/1.10.11/css/jquery.dataTables.min.css" rel="stylesheet" />
<script src="https://cdn.datatables.net/1.10.11/js/jquery.dataTables.min.js"></script>
<link href="https://cdn.datatables.net/select/1.1.2/css/select.dataTables.min.css" rel="stylesheet" />
<script src="https://cdn.datatables.net/select/1.1.2/js/dataTables.select.min.js"></script>
<link href="https://cdn.datatables.net/keytable/2.1.1/css/keyTable.dataTables.css" rel="stylesheet" />
<script src="https://cdn.datatables.net/keytable/2.1.1/js/dataTables.keyTable.min.js"></script>
<div>Result: <span id="output"></span></div><br/>
<table id="data-table" class="display compact articulos table0">
<thead><tr><th>Code</th><th>Description</th></tr></thead>
<tbody>
<tr id="1001"><td>1</td><td>Description 1</td></tr>
<tr id="1002"><td>2</td><td>Description 2</td></tr>
<tr id="1003"><td>3</td><td>Description 3</td></tr>
<tr id="1004"><td>4</td><td>Description 4</td></tr>
<tr id="1005"><td>5</td><td>Description 5</td></tr>
</tbody>
</table>

Related

DataTable Column Filtering Not Pulling in Values

I am working in Modern SharePoint and have a web-part installed that allows me to inject code directly into the page. I have built this code to allow me to use a DataTable to pull information from a List I have on that site.
I am having trouble with the filters for the columns as they appear to not be pulling in any values at all. I believe this is due to me calling the data for the table after the DataTable has been created. But I also reference the table in the code to get the data for the table after it is declared. Can someone please take a look at my code and see if there is a way for this to be done?
Any help would be appreciated!
<table id="example" class="display" cellspacing="0" width="100%">
<thead>
<tr>
<th>Image</th>
<th>Title</th>
<th>Industry</th>
<th>Market</th>
<th>Description</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Image</th>
<th>Title</th>
<th>Industry</th>
<th>Market</th>
<th>Description</th>
</tr>
</tfoot>
</table>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script src="https://cdn.datatables.net/1.10.21/js/jquery.dataTables.min.js"></script>
<link
rel="stylesheet"
type="text/css"
href="https://cdn.datatables.net/1.10.21/css/jquery.dataTables.min.css"
/>
<script>
var dataTable;
$(document).ready(function () {
dataTable = $('#example').DataTable({
initComplete: function () {
this.api()
.columns([2, 3])
.every(function () {
var column = this;
var select = $('<select><option value=""></option></select>')
.appendTo($(column.header()).empty())
.on('change', function () {
var val = $.fn.dataTable.util.escapeRegex($(this).val());
column.search(val ? '^' + val + '$' : '', true, false).draw();
});
column
.data()
.unique()
.sort()
.each(function (d, j) {
select.append('<option value="' + d + '">' + d + '</option>');
});
});
}
});
$.ajax({
url:
"https://ewscripps.sharepoint.com/sites/lighthouseideas/_api/web/lists/getbytitle('Site%20Pages')/items?$select=FileLeafRef,Title,Industry,Market,Description,PageType&$filter=TaxCatchAll/Term eq 'Station Initiatives'",
headers: {
accept: 'application/json;odata=verbose',
'content-type': 'application/json;odata=verbose',
'X-RequestDigest': jQuery('#__REQUESTDIGEST').val()
},
success: function (data) {
console.log('issued URL Request');
//Get Success Stories
for (var i = 0; i < data.d.results.length; i++) {
console.log('Found: ' + data.d.results[i].Title);
dataTable.row
.add([
"<img src='https://ewscripps.sharepoint.com/sites/lighthouseideas/_layouts/15/getpreview.ashx?path=SitePages/" +
data.d.results[i].FileLeafRef +
"'>",
data.d.results[i].Title,
data.d.results[i].Industry.results,
data.d.results[i].Market.results,
data.d.results[i].Description
])
.draw(false);
}
console.log(data.d.results[4]);
console.log(data.d.results[9]);
dataTable.draw(true);
}
});
});
</script>
This should be related to databind after DataTable init, try to update the init with data, in your case, it's success function.
You could check my previous tested thread here.

HTML table with qrcode as column; loading issues on tablet

I have a HTML table with QRcode as one of its column values; I use QRcode.min js library to convert the string to QRcode;
json = $.parseJSON(JSON.stringify(res.d));
// console.log('data ' , json);
$.each(json, function (i, item) {
// console.log(item.medicine);console.log(item.Medicine);
if (item.QrImg1 == null) {
td1 = $('<td>').text(' ');
} else {
td1 = $('<td>').qrcode({ width: 100, height: 100, text: item.QrImg1 })
}
if (item.QrImg2 == null) {
td2 = $('<td>').text(' ');
} else {
td2 = $('<td>').qrcode({ width: 100, height: 100, text: item.QrImg2 })
}
var $tr = $('<tr>').append(
$('<td style="width:30%">').text(item.Medicine),
$('<td>').text(item.BatchCode),
td1,
td2
).appendTo('#meds');
}
This is a pharmacy app, where in all the medicines along with their batch code(as QRCode) is displayed. They will have to do quick filter search on the medicine name so pagination wont help.
The issue is that I have around 6000+ row so while loading it takes time specially on a tablet. Is there some way I can get this loaded faster.
if you get the data one time from the server and you do search on client side from table then jquery.DataTables will help you filter rows https://datatables.net/
it has many options customize the view of table & functionality like sort / search / group
<html>
<head>
<link rel="stylesheet" type="text/css" href="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/css/jquery.dataTables.css">
</head>
<body>
<table id="example">
<thead>
<tr><th class="site_name">Name</th><th>Url </th><th>Type</th><th>Last modified</th></tr>
</thead>
<tbody>
</tbody>
</table>
<script type="text/javascript" charset="utf8" src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.2.min.js"></script>
<script type="text/javascript" charset="utf8" src="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/jquery.dataTables.min.js"></script>
<script>
$("#example").dataTable({
"aaData":[
["Sitepoint","http://sitepoint.com","Blog","2013-10-15 10:30:00"],
["Flippa","http://flippa.com","Marketplace","null"],
["99designs","http://99designs.com","Marketplace","null"],
["Learnable","http://learnable.com","Online courses","null"],
["Rubysource","http://rubysource.com","Blog","2013-01-10 12:00:00"]
],
"aoColumnDefs":[{
"sTitle":"Site name"
, "aTargets": [ "site_name" ]
},{
"aTargets": [ 1 ]
, "bSortable": false
, "mRender": function ( url, type, full ) {
return '' + url + '';
}
},{
"aTargets":[ 3 ]
, "sType": "date"
, "mRender": function(date, type, full) {
return (full[2] == "Blog")
? new Date(date).toDateString()
: "N/A" ;
}
}]
});
</script>
</body>
</html>

jQuery Datatables: Combining column visibility with individual column filters (text inputs)?

I am using basic column visibility and individual column searching (text inputs).
The problem is that when the user adds a previously-hidden column to the table, the text field box for that column does not appear. Thus, the user cannot filter that column.
Does anyone know how to enable filters for hidden columns as well? Ideally, this would not cause a byproduct of clearing the text in the other filters (if the user did enter text in the other filters).
Here is my filtering code:
<script type="text/javascript">
$(document).ready(function() {
// Setup - add a text input to each footer cell
$('#tableID tfoot th').each( function () {
var title = $(this).text();
if ((title != '') && !(title.includes("$"))) {
// Then the current column is *not* the Action column.
$(this).html( '<span style="color: #515151; font-size:15px;"><i>Filter</i></span> <br> <input type="text" style="margin-top:10px;" placeholder="'+title+'" /> ' );
}
} );
var table = $('#tableID').DataTable();
// Apply the search
table.columns().every( function () {
var that = this;
$( 'input', this.footer() ).on( 'keyup change', function () {
if ( that.search() !== this.value ) {
that
.search( this.value )
.draw();
}
});
} );
} );
</script>
I am using this line to hide the columns that I want to be hidden from view by default:
(table.column('.hideCol')).visible(false);
There's a custom column-visibility event in DataTables. So, you may revise your <input> elements visibility based on current status of the column.
E.g. you have <input> rendering function, like that:
//function to render input elements
const renderTfootInputs = () => {
//grab previous inputs into array
const prevInputs = [];
dataTable.columns().every(function(){
prevInputs.splice(this.index(), 1, $(`#example tfoot [colindex="${this.index()}"]`).val());
});
//purge <tfoot> row contents
$('#example tfoot tr').empty()
//iterate through table columns
dataTable.columns().every(function(){
//if the column is visible
this.visible() ?
//append corresponding footer <input>
$('#example tfoot tr').append(`<th><input colindex="${this.index()}" placeholder="${$(this.header()).text()}" value="${prevInputs[this.index()] || ''}"></input></th>`) :
true;
});
};
Than, you may call it upon column visibility changes:
$('#example').on('column-visibility.dt', renderTfootInputs);
Complete demo of this approach might look as follows:
//sample data source
const dataSrc = [
{id: 1, title: 'apple', cat: 'fruit'},
{id: 2, title: 'pear', cat: 'fruit'},
{id: 3, title: 'banana', cat: 'fruit'},
{id: 4, title: 'carrot', cat: 'vegie'},
{id: 5, title: 'eggplant', cat: 'vegie'}
];
//datatables initialization
const dataTable = $('#example').DataTable({
data: dataSrc,
dom: 'Bfrtip',
buttons: ['colvis'],
columns: ['id','title','cat'].map(header => ({title: header, data: header})),
columnDefs: [
{targets: 0, visible: false}
]
});
//append blank footer to the table
$('#example').append('<tfoot><tr></tr></tfoot>');
//function to render input elements
const renderTfootInputs = () => {
//grab previous inputs into array
const prevInputs = [];
dataTable.columns().every(function(){
prevInputs.splice(this.index(), 1, $(`#example tfoot [colindex="${this.index()}"]`).val());
});
//purge <tfoot> row contents
$('#example tfoot tr').empty()
//iterate through table columns
dataTable.columns().every(function(){
//if the column is visible
this.visible() ?
//append corresponding footer <input>
$('#example tfoot tr').append(`<th><input colindex="${this.index()}" placeholder="${$(this.header()).text()}" value="${prevInputs[this.index()] || ''}"></input></th>`) :
true;
});
};
//initial call of above function
renderTfootInputs();
//call that function each time upon column visibility changes
$('#example').on('column-visibility.dt', renderTfootInputs);
//individual search
$('#example').on('keyup', 'tfoot input', function(event){
dataTable.column($(event.target).attr('colindex')).search($(event.target).val()).draw();
});
tfoot input {
display: block;
}
tfoot th {
padding-left: 10px !important;
}
<!doctype html>
<html>
<head>
<script type="application/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="application/javascript" src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
<script type="application/javascript" src="https://cdn.datatables.net/buttons/1.5.6/js/dataTables.buttons.min.js"></script>
<script type="application/javascript" src="https://cdn.datatables.net/buttons/1.5.6/js/buttons.colVis.min.js"></script>
<script type="application/javascript" src="test.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css">
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/buttons/1.5.6/css/buttons.dataTables.min.css">
</head>
<body>
<table id="example"></table>
</body>
</html>
I have worked with this small snippet to hide/Unhide the Individual Column Search, Integrated with Column Visibility Event of Datatables.
$('#table').on( 'column-visibility.dt', function ( e, settings, column, state ) {
columnv = settings.aoColumns[column].bVisible;
if(columnv === false){
$('#table').find("tr.filters th:eq('"+column+"')").hide();
}else{
$('#table').find("tr.filters th:eq('"+column+"')").show();
}
});

Typeahead and first cell selector

I have this table
<table id="vehicleParamTable" class="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
When a click on a link, I add a row. That work fine.
In the first column of the row, I add an jquery-typehead
Selector is not working, also would like to avoid it for first row (th header)
$('#vehicleParamTable tr td:first-child').typeahead({
minLength: 2,
display: "name",
mustSelectItem: true,
emptyTemplate: function(query) {
//must reset current element here
return 'No result for "' + query + '"';
},
source: {
vehicleParam: {
ajax: {
url: "/rest/vehicleparam",
path: "content"
}
}
},
callback: {
onEnter: function(node, a, item, event) {
//must assign item.id to current current element id
},
onResult: function(node, query, result, resultCount, resultCountPerGroup) {
if (resultCount < 1) {
//must reset current element here
}
}
}
});
Edit
$('#vehicleParamTable tr td:first-child')
seem good, but with the rest(typeahead init..) that return undefined
Edit 2 because I add dynamicly row, need to refresh typehead...
I am assuming you are using this https://github.com/running-coder/jquery-typeahead?
This plugin needs to be initialized on an input field.
So, given that your input field is in the first column of the first row after the header, the selector would be
$('#vehicleParamTable tbody tr td:first-child input').typeahead({ ...options })

How to make excel like cell in javascript or Angularjs dynamically?

I want to make excel like cell system but dynamically, Where i have to select every cell individually.
My desired output:
If i have 2 and 10, the output will be like that(above image). 2 means 2 row and 10 means 10 columns. the 2 and 10 is from database then javascript/angularjs should make the table according to those values. The second thing is that i have to select every individual cell using javascript. For example, i want to select B7 and if i click on that cell, an alert box will be shown with the selected cell number.
In real i want to store some values regarding that cell. How can i make every cell clickable? Any suggestion? I prefer angularjs.
Edit:
Acually i want to make Yard graphical view. Staff will select cell and input goods weight(in bootstrap modal). Then save. Next time if a cell/slot has weight before, it will be in different color(red-means the cell/slot is already filled with goods) and if he click on that cell , all details will be shown regarding to that cell like weight. Database table will store yard_id,cell_id,weiight. How can make query to get details from database to have my cell filled with color and show details if the cell has details before?
Edit 2:
You make an object in factory to set value in cell :
database[createKey({
row: 'A',
column: 1
})] = 12;
Here row A and column 1 is red colored by default. But in real app, i will have data for some cells like:
[{"row":"A","column":1,"weight":100},
{"row":"A","column":2,"weight":200}
].
Then how can i set those value on specific cells and have different bg color?
I want to use this method( loadData() ) to set color(like the one you set-red color) in the cell those have value stored in database when page load for the first time :
function loadData() {
fakeHttp.get('api/weights').then(function (result) {
$scope.weights = result.data;
console.log(result.data)
});
};
I will pass json data in result.data parameter(given above).
...in real app, i will have data for some cells like:... how can i set those value on specific cells and have different bg color?
You can keep loadData the same and change $scope.getWeight to accommodate the format of the data. This takes a dependency on lodash's find, since that makes things more concise. If you don't want to do that you can replace _.find with your own find method that does the same thing - I'll leave that as an exercise for you :)
http://plnkr.co/edit/b0q4qTyNjQp7J2IB7ayf?p=preview
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.0.1/lodash.js"></script>
JavaScript
$scope.getWeight = function (row, column) {
if ($scope.weights) {
// See if there's a record with the row and column.
var record = _.find($scope.weights, {
row: row,
column: column
});
// Was a record found with the row and column?
if (record) {
// If so return its weight.
return record.weight;
}
}
};
Staff will select cell and input goods weight(in bootstrap modal). Then save. Next time if a cell/slot has weight before, it will be in different color(red-means the cell/slot is already filled with goods) and if he click on that cell , all details will be shown regarding to that cell like weight...How can make query to get details from database to have my cell filled with color and show details if the cell has details before?
I didn't completely understand, but here's roughly what you could do for the parts I did understand. This assumes you have 3 endpoints - GET api/weights to get the weights; GET api/weight to get the weight for a single cell and POST api/weight to update a weight. You'll need to replace fakeHttp with $http and the actual url's. I don't know what Yard or Yard_id is.
http://plnkr.co/edit/aAiYbChTqmAwgky0WOJ3?p=preview
// TODO: Replace fakeHttp with $http
var module = angular.module('myApp', ['ui.bootstrap']);
module.controller('MainCtrl', function ($scope, $uibModal, fakeHttp) {
$scope.rows = [
'A',
'B'
];
$scope.columns = [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10
];
$scope.select = function (row, column) {
var modalInstance = $uibModal.open({
templateUrl: 'myModal.html',
controller: 'ModalInstanceCtrl',
resolve: {
row: function () {
return row;
},
column: function () {
return column;
}
}
});
modalInstance.result.then(loadData);
};
$scope.getWeight = function (row, column) {
if ($scope.weights) {
var key = createKey({
row: row,
column: column
});
return $scope.weights[key];
}
};
loadData();
function loadData() {
fakeHttp.get('api/weights').then(function (result) {
$scope.weights = result.data;
});
};
function createKey(data) {
var key = {
row: data.row,
column: data.column
};
return JSON.stringify(key);
}
});
module.controller('ModalInstanceCtrl', function ($scope, row, column, fakeHttp, $uibModalInstance) {
$scope.row = row;
$scope.column = column;
fakeHttp.get('api/weight', {
row: row,
column: column
}).then(function (result) {
$scope.weight = result.data;
});
$scope.save = function () {
fakeHttp.post('api/weight', {
row: row,
column: column,
weight: $scope.weight
}).then(function () {
$uibModalInstance.close();
});
};
});
module.factory('fakeHttp', function ($q) {
var fakeHttp = {};
var database = {};
database[createKey({
row: 'A',
column: 1
})] = 12;
fakeHttp.get = function (url, data) {
if (url === 'api/weight') {
var key = createKey(data);
return $q.when({ data:
database[key]
});
} else if (url === 'api/weights') {
return $q.when({ data:
database
});
} else {
alert('invalid url: ' + url);
}
};
fakeHttp.post = function (url, data) {
if (url === 'api/weight') {
var key = createKey(data);
database[key] = data.weight;
return $q.when({});
} else {
alert('invalid url: ' + url);
}
};
return fakeHttp;
function createKey(data) {
var key = {
row: data.row,
column: data.column
};
return JSON.stringify(key);
}
});
index.html
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<link data-require="bootstrap#3.3.7" data-semver="3.3.7" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
<script data-require="angular.js#1.6.2" data-semver="1.6.2" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.js"></script>
<script data-require="angular.js#1.6.2" data-semver="1.6.2" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular-route.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/1.3.3/ui-bootstrap-tpls.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="MainCtrl">
<table border="1" cellspacing="0">
<tbody>
<tr ng-repeat="row in rows">
<td ng-repeat="column in columns" style="width: 100px; cursor: pointer"
ng-style="{ background: getWeight(row, column) ? 'red' : '' }"
ng-click="select(row, column)">
{{row}}{{column}}
</td>
</tr>
</tbody>
</table>
</body>
</html>
myModal.html
<div class="modal-body">
Please enter weight for {{ row }}{{ column }}
<input type="text" class="form-control"
ng-model="weight" />
<button class="btn btn-primary"
ng-click="save()">Save</button>
</div>
How can i make every cell clickable?
Here's how to make every cell clickable in AngularJS.
http://plnkr.co/edit/XKa5WwjyYTugDZ744iWB?p=preview
Your question was very unclear. I couldn't tell what you wanted, exactly.
JavaScript:
module.controller('MainCtrl', function($scope) {
$scope.rows = [
'A',
'B'
];
$scope.columns = [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10
];
$scope.select = function(row, column) {
if ($scope.selectedRow === row && $scope.selectedColumn === column) {
$scope.selectedRow = undefined;
$scope.selectedColumn = undefined;
} else {
$scope.selectedRow = row;
$scope.selectedColumn = column;
}
};
});
HTML:
<body ng-controller="MainCtrl">
<table border="1" cellspacing="0">
<tbody>
<tr ng-repeat="row in rows">
<td ng-repeat="column in columns" style="width: 100px; cursor: pointer"
ng-click="select(row, column)"
ng-style="{ background: row == selectedRow && column == selectedColumn ? 'yellow' : 'none' }">
{{row}}{{column}}
</td>
</tr>
</tbody>
</table>
<br>
Selected (row, column):
<br>
({{selectedRow || 'undefined'}}, {{selectedColumn || 'undefined'}})
</body>

Categories