Datatables: column search with stripped HTML - javascript

Referencing to the Datatables API.
I implemented individual column searching and need to extend it:
There is a column which is displaying a button with HTML-Attributes/Classes applied. The Problem: I need to strip HTML in order to search the button's caption only. Any ideas how can I do that?
Here's my code:
table().every(function () {
var that = this;
$('input', this.footer()).on('keyup change', function (e) {
if (e.which == 27) {
$(this).val('');
}
if (that.search() !== this.value) {
that.search(this.value).draw();
}
});
});

I believe, you may need to employ external (custom) search function $.fn.DataTable.ext.search in order to look for button texts only (if that's what you're trying to achieve).
You may find the demo below:
//Sample source data
const srcData=[
{title:'apple',cat:'fruit',score:'good'},
{title:'strawberry',cat:'berry',score:'good'},
{title:'broccoli',cat:'vegie',score:'bad'},
{title:'durian',cat:'fruit',score:'bad'}
];
//Global variable for button text custom search
var buttonText = '';
//DataTables initialization
const dataTable = $('#mytable').DataTable({
dom: 't',
data: srcData,
columns: [
{title: 'title', data: 'title'},
{title: 'category', data: 'cat'},
//render score property as a button
{title: 'score', data: 'score', render: (data, type, row, meta) => `<button>${data == 'good' ? 'Love it!' : 'Hate it!'}</button>`}
],
});
//Append <tfoot> and searchbars
$('#mytable').append('<tfoot><tr></tr></tfoot>');
dataTable.columns().every(function () {
$('#mytable tfoot tr').append(`<td><input colindex="${this.index()}"></input></td>`);
});
//Custom search function across button text only
$.fn.DataTable.ext.search.push((settings, row, rowIndex, rowData, counter) => $(dataTable.row(rowIndex).node()).find('td:eq(2) button').text().toLowerCase().includes(buttonText) || buttonText == '');
//Listen for 'keyup' in <tfoot> searchbars
$('#mytable').on('keyup', 'tfoot td input', function () {
const colindex = $(this).attr('colindex');
//If it's input in 3-rd column (colindex==2)
//simply assign global variabl and re-draw
//table to apply custom search
if (colindex == 2) buttonText = $(this).val().toLowerCase();
//Otherwise search by corresponding column
else dataTable.column(colindex).search($(this).val());
dataTable.draw();
});
tfoot td {
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>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css">
</head>
<body>
<table id="mytable"></table>
</body>
</html>

Related

How to display column headers in Y axis for a Datatable using HighCharts?

I am using Datatables and HighCharts. Please see my code below. I am not sure how to display this bar chart where Years are displayed in Y axis. I have added an image below to show how it looks like.
I am new to HighCharts, so I am not sure of all the functions. Thanks.
How can I get graph to show like this? I want years in Y axis. Thanks.
http://live.datatables.net/febayaxa/1/edit
$(document).ready(function() {
var table = $("#example1").DataTable();
var salary = getSalaries(table);
// Declare axis for the column graph
var axis = {
id: "salary",
min: 0,
title: {
text: "Number"
}
};
// Declare inital series with the values from the getSalaries function
var series = {
name: "Overall",
data: Object.values(salary)
};
var myChart = Highcharts.chart("container", {
chart: {
type: "column"
},
title: {
text: "Test Data"
},
xAxis: {
categories: Object.keys(salary)
},
yAxis: axis,
series: [series]
});
// On draw, get updated salaries and refresh axis and series
table.on("draw", function() {
salary = getSalaries(table);
myChart.axes[0].categories = Object.keys(salary);
myChart.series[0].setData(Object.values(salary));
});
});
function getSalaries(table) {
var salaryCounts = {};
var salary = {};
// Get the row indexes for the rows displayed under the current search
var indexes = table
.rows({ search: "applied" })
.indexes()
.toArray();
// For each row, extract the office and add the salary to the array
for (var i = 0; i < indexes.length; i++) {
var office = table.cell(indexes[i], 0).data();
if (salaryCounts[office] === undefined) {
salaryCounts[office] = [+table.cell(indexes[i], 1).data().replace(/[^0-9.]/g, "")];
}
else {
salaryCounts[office].push(+table.cell(indexes[i], 1).data().replace(/[^0-9.]/g, ""));
}
}
// Extract the office names that are present in the table
var keys = Object.keys(salaryCounts);
// For each office work out the average salary
for (var i = 0; i < keys.length; i++) {
var length = salaryCounts[keys[i]].length;
var total = salaryCounts[keys[i]].reduce((a, b) => a + b, 0);
salary[keys[i]] = total / length;
}
return salary;
};
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<link href="https://nightly.datatables.net/css/jquery.dataTables.css" rel="stylesheet" type="text/css" />
<script src="https://nightly.datatables.net/js/jquery.dataTables.js"></script>
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<link href="https://nightly.datatables.net/css/jquery.dataTables.css" rel="stylesheet" type="text/css" />
<script src="https://nightly.datatables.net/js/jquery.dataTables.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<meta charset=utf-8 />
</head>
<body>
<div id="container" style=" width: 100%; height: 400px;"></div>
<div class="container">
<table id="example1" class="display nowrap" width="100%"><thead>
<tr><th>Year</th><th>2012</th><th>2013</th><th>2014</th><th>2015</th><th>2016</th><th>2017</th><th>2018</th><th>2019</th><th>2020</th><th>2021</th></tr></thead>
<tr ><td> Data</td><td>3,823</td><td>3,823</td><td>3,954</td><td>3,959</td><td>3,955</td><td>3,956</td><td>3,843</td><td>3,699</td><td>3,472</td><td>3,551</td></tr></tbody>
</tbody></table>
I am going to assume you mean the x-axis (the horizontal axis) when you say that you want to use the years (from the table headings) from your DataTable for each bar's label in the chart.
You can access these table headings using the DataTables API and some jQuery.
Use this to get an array of table heading elements:
api.columns().header()
And then use $(element).html() to get the label (the year) from each heading.
There is a lot of code in your example in the question which does not appear to be relevant to the chart you want to create, so in the following example, I removed all of that. If it is needed, you can put it back.
$(document).ready(function() {
var tableData = [];
var tableCategories = []
var table = $("#example1").DataTable({
initComplete: function(settings, json) {
let api = new $.fn.dataTable.Api(settings);
// get the seris data as an array of numbers from the table row data:
api.rows().data().toArray()[0].forEach(function(element, index) {
if (index > 0) {
tableData.push(parseFloat(element.replace(/,/g, '')));
}
});
// get the x-axis caregories from the table headings:
api.columns().header().toArray().forEach(function(element, index) {
if (index > 0) {
tableCategories.push($(element).html());
}
});
  
}
});
var myChart = Highcharts.chart("container", {
chart: {
type: "column"
},
title: {
text: "Test Data"
},
xAxis: {
categories: tableCategories
},
series: [{
data: tableData
}]
});
});
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<link href="https://nightly.datatables.net/css/jquery.dataTables.css" rel="stylesheet" type="text/css" />
<script src="https://nightly.datatables.net/js/jquery.dataTables.js"></script>
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<link href="https://nightly.datatables.net/css/jquery.dataTables.css" rel="stylesheet" type="text/css" />
<script src="https://nightly.datatables.net/js/jquery.dataTables.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<meta charset=utf-8 />
</head>
<body>
<div id="container" style=" width: 100%; height: 400px;"></div>
<div class="container">
<table id="example1" class="display nowrap" width="100%">
<thead>
<tr>
<th>Year</th>
<th>2012</th>
<th>2013</th>
<th>2014</th>
<th>2015</th>
<th>2016</th>
<th>2017</th>
<th>2018</th>
<th>2019</th>
<th>2020</th>
<th>2021</th>
</tr>
</thead>
<tr>
<td> Data</td>
<td>3,823</td>
<td>3,823</td>
<td>3,954</td>
<td>3,959</td>
<td>3,955</td>
<td>3,956</td>
<td>3,843</td>
<td>3,699</td>
<td>3,472</td>
<td>3,551</td>
</tr>
</tbody>
</tbody>
</table>
The output looks like this:
If you do actually want the years labels to be displayed on the y-axis (with horizontal bars, instead of vertical bars) then you can change the chart type by changing this part of the chart...
chart: { type: "column" },
to this:
chart: { type: "bar" },

Datatable : How to jump to the first empty cell

I'm using datatable to display predictions about future events. Among my columns I have "Day" "Hour" "Prediction" "Reality".
Prediction is always filled, but reality is only filled when the event happens.
I want to jump to the page corresponding to the current time. So I used jumpToData() on the date. With that, I have quick access to the last events of the current day but I still need to turn 4 or 5 pages if it's 9AM for example.
I think the easiest way to solve the problem is to jump to the first empty cell in the "Reality" column.
Have you any elements to do that ?
Thanks in advance for any help,
Thomas
Is that what you were trying to achieve?:
//Make up random chronological data to fill DataTable
var srcData = [...Array(300)].map((value, index) => {
let obj = {};
let today = new Date()
let randomDate = new Date(today.getFullYear(), today.getMonth(), today.getDate()-10, index);
obj.date = randomDate.toLocaleDateString();
obj.hour = index%24;
obj.prediction = Math.floor(Math.random()*1000);
obj.reality = randomDate < Date.now() ? obj.prediction+(3-Math.floor(Math.random()*6)) : '';
return obj;
});
//Define DataTables object
var dataTable = $('#forecasts').DataTable({
sDom: 'tp',
orderFixed: [[0, 'asc'],[1, 'asc']],
ordering: false,
data: srcData,
columns: [
{title: 'date', data: 'date'},
{title: 'hour', data: 'hour'},
{title: 'prediction', data: 'prediction'},
{title: 'reality', data: 'reality'},
]
});
$('#jumptoblank').on('click', () => {
//Search for empty cell
var emptyRowIndex = dataTable.rows().data().toArray().findIndex(row => row.reality == '');
//Go to the page, where necessary row is located
dataTable.page(Math.floor(emptyRowIndex/dataTable.page.info().length)).draw(false)
});
.dataTables_wrapper {width: 600px}
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css">
<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>
</head>
<body>
<button id="jumptoblank">Jump to blank reality</button>
<table id="forecasts"></table>
</body>
</html>

KendoDropdown with disabled default option

I`m filling a kendo dropdown with a function but I would like for the default value to be "Select Option" which you wont be able to select it back once you select another one.
function FillInDropDown(dataSet,ddID) {
var dropDown = $(ddID);
if (!dataSet.error) {
var i;
var values = [];
// Apppend the other options on dataSet
for (i = 0; i < dataSet.dropdownData.length; i++) {
values.push(dataSet.dropdownData[i]);
}
// Clearing Values
$(ddID).empty();
$(ddID).kendoDropDownList({
dataSource: [],
animation: false
});
$(ddID).data("kendoDropDownList").dataSource.data(values);
$(ddID).data("kendoDropDownList").value(values[0]);
}
else {
simpleDialog.info(dataSet.ErrorMessage);
}
};
Here are two alternatives that you can pursue:
After the user picks a value, remove the optionLabel item from the list and refresh it.
After the user picks a value, prevent the selection of the optionLabel item via the select event.
You will need a one-time handler for the change event of the DropDownList.
Here is an example for both options:
<!DOCTYPE html>
<html>
<head>
<base href="http://demos.telerik.com/kendo-ui/dropdownlist/remotedatasource">
<style>html { font-size: 14px; font-family: Arial, Helvetica, sans-serif; }</style>
<title></title>
<link rel="stylesheet" href="//kendo.cdn.telerik.com/2016.3.914/styles/kendo.common.min.css" />
<link rel="stylesheet" href="//kendo.cdn.telerik.com/2016.3.914/styles/kendo.default.min.css" />
<script src="//kendo.cdn.telerik.com/2016.3.914/js/jquery.min.js"></script>
<script src="//kendo.cdn.telerik.com/2016.3.914/js/kendo.all.min.js"></script>
</head>
<body>
<p>The optionLabel will be removed:</p>
<input id="products1" />
<p>The optionLabel selection will be prevented:</p>
<input id="products2" />
<script>
$(function() {
var settings = {
optionLabel: "Select a product",
dataTextField: "ProductName",
dataValueField: "ProductID",
dataSource: {
transport: {
read: {
dataType: "jsonp",
url: "//demos.telerik.com/kendo-ui/service/Products",
}
}
}
};
$("#products1").kendoDropDownList(settings);
$("#products2").kendoDropDownList(settings);
$("#products1").data("kendoDropDownList").one("change", function(e) {
e.sender.list.find(".k-list-optionlabel").remove();
e.sender.refresh();
});
$("#products2").data("kendoDropDownList").one("change", function(e) {
e.sender.bind("select", function(j){
if (j.dataItem.ProductID == "") {
j.preventDefault();
}
});
});
});
</script>
</body>
</html>

jQuery blur event not fired for table cell

I'm loading a table dynamically using jQuery ajax, the rows of the table has "contenteditable=true", I'm trying to listen on blur event for every cell, so that it triggers a function to update that cell dynamically.
The problem is that the event blur isn't fired at all, I've tried different selectors(table,tbody, and finally the whole document), but all in vain.
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript" src='jquery-1.8.3.js'></script>
<link rel="stylesheet" href='jquery-ui-1.8.7.custom.css' type="text/css">
<?php
include './datatable_include.php';
?>
<script type="text/javascript">
$(function () {
$.ajax({//create an ajax request to load_page.php
type: "GET",
url: "load_table.php",
dataType: "html", //expect html to be returned
success: function (response) {
$('#dataTable').find('tbody').html(response);
initDataTable('#dataTable', null);
}
});
});
$(document).bind("blur", "td", (function () {
// this code isn't reached
alert("ahoo");
var id = $(this).attr("id");
var name = $(this).attr("name");
var message_status = $("#status");
var value = $(this).text();
$.post('update_table.php', "id=" + id + "&" + name + "=" + value, function (data) {
if (data != '')
{
message_status.show();
message_status.text(data);
//hide the message
setTimeout(function () {
message_status.hide()
}, 3000);
}
});
}));
</script>
</head>
<body>
<table id="dataTable" width="700px" >
<thead>
<tr>
<th>Name</th>
<th>ID</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</body>
</html>
try
$(document).bind("td").blur(function()
{
});
seems that table td isn't a standard focusable element so you can't blur it.
try to add the tabsindex property to each td
<td tabindex="1">focus on me</td>
the definition of bind function is as follows:
.bind( eventType [, eventData ], handler )
so, you should do:
$('td').bind('blur', function(){
//event handler statement goes here
});
And as mentioned by #paul roub in the comments above, you should be using live() function, as you are creating the td elements dynamically.
$('td').live('blur', function(){
//event handler statement goes here
});

Javascript return me object Object

I have this code to create datatable with datatables.net plugin:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
<script type='text/javascript' src='//netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.min.js'></script>
<link rel="stylesheet" type="text/css" href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css">
<link type="text/css" href="https://cdn.datatables.net/1.10.3/css/jquery.dataTables.css" />
<link type="text/css" href="https://cdn.datatables.net/plug-ins/380cb78f450/integration/bootstrap/3/dataTables.bootstrap.css" />
<script src="https://cdn.datatables.net/1.10.3/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/plug-ins/380cb78f450/integration/bootstrap/3/dataTables.bootstrap.js"></script>
<script type='text/javascript' src="https://datatables.net/release-datatables/extensions/KeyTable/js/dataTables.keyTable.js"></script>
</head>
<body>
<script type="text/javascript">
// function day2Date( day, year ) {
// return new Date(year,0,day);
//}
$(document).ready(function() {
$('#example').dataTable({
"ajax": "table1.php",
"columns": [{
"data": "ID"
}, {
"data": "naziv"
}, {
"data": "vrsta"
},
],
"columnDefs": [{
"targets": 2,
"data": "download_link",
"render": function(data, type, full, meta) {
// return data;
return '<button class="btn btn-success">' + data + '</button>';
}
}]
});
});
var table = $('#example').DataTable();
$(document).ready(function() {
$('#example tbody').on('click', 'td', function() {
console.log('Data:' + $(this).html().trim() + 'Row:' + $(this).parent().find('td').html().trim() + 'Column:' + $('#example thead tr th').eq($(this).index()).html().trim());
// alert('Row:'+$(this).parent().find('td').html().trim());
//alert('Column:'+$('#example thead tr th').eq($(this).index()).html().trim());
});
$('#example tbody').on('click', 'tr', function() {
console.log('Row index: ', table.row(this).index());
});
});
</script>
<div class="container">
<table id="example" class="table table-striped table-bordered table-responsitive" cellspacing="0" width="100%">
<thead>
<tr>
<th>ID</th>
<th>Naziv</th>
<th>Vrsta</th>
</tr>
</thead>
<tfoot>
<tr>
<th>ID</th>
<th>Naziv</th>
<th>Vrsta</th>
</tr>
</tfoot>
</table>
</div>
</body>
</html>
I need to get row index so I write as you can see from code above:
$('#example tbody').on( 'click', 'tr', function () {
console.log( 'Row index: '+table.row( this ).index() );
like I see on documentation on datatables web site but this code return me only [object Object]
example:
Data:12Row:2Column:Naziv
Row index: [object Object]
Why? Sombody have explanation?
You have included one key line of code outside any DOM ready handler, but before the element to which it occurs. That means that $('#example') is not returning a match:
Put this line in the DOM ready handler:
var table = $('#example').DataTable();
e.g
$(document).ready(function () {
var table = $('#example').DataTable();
$('#example tbody').on('click', 'td', function () {
console.log('Data:' + $(this).html().trim() + 'Row:' + $(this).parent().find('td').html().trim() + 'Column:' + $('#example thead tr th').eq($(this).index()).html().trim());
// alert('Row:'+$(this).parent().find('td').html().trim());
//alert('Column:'+$('#example thead tr th').eq($(this).index()).html().trim());
});
$('#example tbody').on('click', 'tr', function () {
console.log('Row index: ', table.row(this).index());
});
});
When you do a String concatenation on a JavaScript Object it will implicitly call toString() on the Object.
The default Object.toString() simply returns [object Object].
To print out the contents of the Object use console.log with two arguments:
console.log( 'Row index:', table.row( this ).index() );
If I test on the DataTable example website then it appears to work as expected, and the result is a Number, so I think there must be some information missing from your question...
var table = $('#example').DataTable()
> []
table.row(1).index()
> 1

Categories

Resources