Overriding datatables.js search behavior [duplicate] - javascript

This question already has an answer here:
Odd behavior of datatables.search function after modifying it
(1 answer)
Closed 4 years ago.
There are already several questions here on SO on this subject, however none is about my exact situation.
I have a datatable with 2 columns, one contains text input field and the other a select. The current behavior of datatables' search functionality is to search in the entire select HTML. The behvior I want is search only the chosen option.
I'm aware we can override/intercept the search/filter events, ie
$('#mapping-table_filter input', data_table.table().container())
.off('.DT')
.on('keyup.DT cut.DT paste.DT input.DT search.DT', function (e) {
data_table.search(...).draw();
});
// or
data_table.on('search.dt', function () {
});
But this does not help since .search does not accept a callback.
JSFiddle
https://jsfiddle.net/0oabx2mr/
If you search for any of "first", "second" or "third" both rows are still visible. I want to be able to search for "second" and "third" and only get the relevant row.

With slight architecture changes, your example may look like that:
var srcData = [
['firstOption', 'secondOption', 'thirdOption'],
['firstOption', 'secondOption', 'thirdOption'],
['firstOption', 'secondOption', 'thirdOption'],
['firstOption', 'secondOption', 'thirdOption']
];
var dataTable = $('#mytable').DataTable({
sDom: 't',
data: srcData,
columns: [{
title: 'Options',
render: (data, type, row) => '<select>'+row.reduce((options, option) => options += `<option value="${option}">${option}</option>`,'')+'</select>'
}]
});
var needle = null;
$.fn.DataTable.ext.search.push(
(settings, row, index) => $(dataTable.cell(`:eq(${index})`,':eq(0)').node()).find('select').val().match(needle) || !needle
);
$('#search').on('keyup', event => {
needle = $(event.target).val();
dataTable.draw();
});
<!doctype html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script 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>
<input id="search"></input>
<table id="mytable"></table>
</body>
</html>

Related

Change a datatable cell value to an input text with YUI

I'm working on a project with a javascript library YUI and JSP.
I'm trying to manipulate a YUI datatable, some cells of the table are select options and input text:
What I'm trying to do is to manipulate the options of the select options input dynamically at runtime:
First, this is the declaration of the datatable:
var CustomSelectCellEditor = Y.Component.create({
NAME: 'CustomSelectCellEditor',
ATTRS: {
multiple: {
value: false,
validator: Y.Lang.isBoolean
},
strings: {
value: {
edit: 'Edit',
save: 'OK',
cancel: 'Annuler'
}
}
},
EXTENDS: Y.BaseOptionsCellEditor,
UI_ATTRS: ['multiple'],
prototype: {
ELEMENT_TEMPLATE: '<select class="celleditor-element error-field"></select>',...
var ruleTypeCreateColumns = [{editor: new CustomSelectCellEditor({editable: false,options: types}), ...
var newRulesTable = new Y.DataTable({
columns : ruleTypeCreateColumns,
width: "80%",
editable: true,
editEvent: 'click'
});
the datatable will look like, a datatable with input cells, the input editor appears in a click event:
At runtime, I tried to change the editor, for example from select options to input text, according to the input of the first column:
newRulesTable.after('*:criteriaTypeChange', function(o){
for(var i=0; i<newRulesTable.data.size();i++) {
if(newRulesTable.data.item(i).get('criteriaType') == getTypes().date) {
// TODO HERE
}
}
});
After many attempts, I couldn't reach my goal, so I need to know which object should I change?
manipulating data in runtime is a hinder when using native JavaScript, unlike famous libraries like angular , react that updates automatically your view when your data change ( two ways binding) , in native JavaScript you should implement this logic manually via listeners and pure code:
Here a simple example
we want to update our select option when we click on the button
<!DOCTYPE html>
<html lang="en" xml:lang="en">
<head>
<title>an example </title>
<meta content="text/html; charset=utf-8" />
</head>
</div>
<body>
<h1>
This is a dynamic select
</h1>
<div id="select-container">
<button id="button">Change Select Dynamiclly</button>
<select id="select" name="pets" id="pet-select">
<option value="dog">Dog</option>
<option value="cat">Cat</option>
</select>
</div>
<script>
const button = document.querySelector("#button");
button.addEventListener("click", event => {
window.alert('Content has been changed !')
changeContent();
});
var changeContent = function () {
var animals = ["Fish","Horse","Pig"]
const select = document.querySelector("#select");
for (var i = 0; i < animals.length; i++) {
var opt = document.createElement('option');
opt.value = animals[i];
opt.innerHTML = animals[i];
select.appendChild(opt);
}
}
</script>
</body>
</html>
idon't really know how YUI library work but i hope this will help you a little.

jQuery DataTable add row first position

var clientTable = $("#table").DataTable();
clientTable.row.add([1,1,1,1]).draw(false);
I add new row in my datatable with this code but I need to add row in first position of the table.
How can I do this ?
According to the documentation "The rows that are added are subjected to the ordering and search criteria that are applied to the table, which will determine the new row's position and visibility in the table" - so, the new row's position in the table is dependent on the data. If you apply a sort ordering to the table, the new row may be added first - depending on the data. If you don't have a column that would fit for that, you can add a hidden column with a counter and sort by that (see the below snippet for example).
Alternately, you can consider using the RowReorder extension
$(document).ready(function() {
var t = $('#example').dataTable( {
'columns': [
{'title': 'id', 'visible': false},
{'title': 'data'}
],
'order' : [[1,'desc']]
} );
var counter = 1;
$('#addRow').on( 'click', function () {
t.api().row.add( [
counter,
'data for id: ' + counter
] ).draw( false );
counter++;
} );
// Automatically add a first row of data
$('#addRow').click();
} );
<html>
<head>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<link rel="stylesheet" type="text/css" href="//cdn.datatables.net/1.10.16/css/jquery.dataTables.css">
<script type="text/javascript" charset="utf8" src="//cdn.datatables.net/1.10.16/js/jquery.dataTables.js"></script>
</head>
<button id="addRow">Add New Row</button>
<table id="example" class="display" width="100%" cellspacing="0" />
</html>
Actualy, is not possible with DataTable default function.
Do it with jQuery :
$('#tableName tr:first').after("<tr role="row"><td></td><td>Your Row</td></tr>");

Making URLs Clickable within JS in single HTML Table column? (CSV Parsing to HTML Table)

I'm using PapaParse to parse data from a CSV and display the results in a HTML table. The HTML table contains a column with URL's. Currently my parser is parsing them in TEXT format. I want these URLs to be clickable, however they are in text format.
The HTML:
<html>
<head>
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="http://papaparse.com/resources/js/papaparse.js"></script>
<script src="test.js"></script>
<link rel="stylesheet" href="main.css">
<meta charset="utf-8">
<meta http-equiv="refresh" content="120"><!-- REFRESH EVERY 2 minutes -->
<title>JS Bin</title>
</head>
<body>
<table id="results">
<tbody>
</tbody>
</table>
</body>
</html>
The JavaScript:
$(function() {
Papa.parse("data/file.csv", {
download: true,
complete: function(results) {
console.log("Remote file parsed!", results.data);
$.each(results.data, function(i, el) {
var row = $("<tr/>");
row.append($("<td/>").text("")); /**List Number**/
$.each(el, function(j, cell) {
if (cell !== "")
row.append($("<td/>").text(cell));
});
$("#results tbody").append(row);
});
}
});
});
file.csv
1, search, www.google.com
2, car, www.autotrader.com
3, news, www.bbc.co.uk/news
The current output will be all the above fields, but all in text format. I would like the all the last fields (the URLs) to be clickable. Is this possible, using my above method?
This is not a duplicate of: How to replace plain URLs with links? - It has nothing to do with parsing CSV files and the regexp principles maybe over complicated for this use case. There must a much simpliar solution
You are experiencing troubles while creating the table rows. The correct way is:
row.append($("", {text: cell})); // if it is not the last cell or URL
row.append($("").append($('', {href: cell, text: cell})));
The snippet:
//Papa.parse("data/file.csv", {
Papa.parse('1, search, www.google.com\n\
2, car, www.autotrader.com\n\
3, news, www.bbc.co.uk/news\n', {
//download: true,
complete: function(results) {
//console.log("Remote file parsed!", results.data);
$.each(results.data, function(i, el) {
var row = $("<tr/>");
$.each(el, function(j, cell) {
if (cell !== "") {
if (j != 2) {
row.append($("<td/>", {text: cell}));
} else {
row.append($("<td/>").append($('<a/>', {href: cell, text: cell})));
}
}
});
$("#results tbody").append(row);
});
}
});
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/4.1.2/papaparse.js"></script>
<table id="results">
<tbody>
</tbody>
</table>

Get data from Materialize CSS chips

I need to get data from Materialize CSS chips, but I don't know, how.
$('.chips-placeholder').material_chip({
placeholder: 'Stanici přidíte stisknutím klávesy enter',
secondaryPlaceholder: '+Přidat',
});
function Show(){
var data = $('.chips-placeholder').material_chip('data');
document.write(data);
}
<!-- Added external styles and scripts -->
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.7/js/materialize.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.7/css/materialize.min.css">
<link href="http://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<!-- HTML body -->
<div class="chips chips-placeholder"></div>
<button onclick="Show()" type="button">Show</button>
So, to access to the data's chip you just have to do this:
var data = $('#id of your chips div').material_chip('data');
alert(data[0].tag);`
'0' is the index of your data (0, 1, 2 , 3, ...).
'tag' is the chip content. You can also get the id of your data with '.id'.
To get data from Materialize CSS chips, use the below code.
$('#button').click(function(){
alert(JSON.stringify(M.Chips.getInstance($('.chips')).chipsData));
});
They appear to have changed the method available in the latest version.
The documentation suggests that you should be able to access the values as properties of the object, but I’ve spent an hour looking, not getting anywhere.
Until the following happened
$('.chips-placeholder').chips({
placeholder: 'Enter a tag',
secondaryPlaceholder: '+Tag',
onChipAdd: (event, chip) => {
console.log(event[0].M_Chips.chipsData);
},
During the onChipAdd event I was able to access the event. Within this object was an array of tags.
I know this isn't the documented way, however there is only so much time a client will accept when it comes billing and I must move on.
This worked great for me
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() {
var elems = document.querySelectorAll('.chips');
var instances = M.Chips.init(elems, {
placeholder: "Ajouter des Tags",
secondaryPlaceholder: "+tag",
onChipAdd: chips2Input,
onChipDelete: chips2Input,
Limit: 10,
minLength: 1
});
function chips2Input(){
var instance = M.Chips.getInstance(document.getElementById('chip1')), inpt = document.getElementById('myInputField');
inpt.value = null;
for(var i=0; i<instance.chipsData.length; i++){
if(inpt.value == null)
inpt.value = instance.chipsData[i].tag;
else{
inpt.value += ','+instance.chipsData[i].tag; //csv
}
}
console.log('new value: ', inpt.value);
}
});
</script>

jqGrid - Multiple grids on same page shows only one pager

I am writing a page with multiple jqGrids. My code follows a JavaScript MVC pattern which is going to provide an API for my HTML elements (including jqGrids). So, in the end of the day, I can create grids by calling my API. Something like:
var grid1 = new grid();
grid1.init();
var grid2 = new grid();
grid2.init();
I have done it with other javascript components and it worked great. However, when I create multiple jqGrid instances on the same page there is only one jqPager on the page attached to the last grid. Does anybody have an idea why?
Here is my code (Note that this is a simplified version, in reality I keep it separated in different .js files and also follow many other design patterns):
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/themes/redmond/jquery-ui.css" />
<link rel="stylesheet" type="text/css" href="http://www.ok-soft-gmbh.com/jqGrid/jquery.jqGrid-4.1.2/css/ui.jqgrid.css" />
</head><body>
<!-- IMPORT JS -->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
<script type="text/javascript" src="http://www.ok-soft-gmbh.com/jqGrid/jquery.jqGrid-4.1.2/js/i18n/grid.locale-en.js"></script>
<script type="text/javascript" src="http://www.ok-soft-gmbh.com/jqGrid/jquery.jqGrid-4.1.2/js/jquery.jqGrid.min.js"></script>
<script>
$(document).ready(function() {
function grid() {
//=== LOCA VARIABLES ===//
var myGrid = $('<table>').attr( "id", "useraccount-search-datagrid");
var myPager = $("<div>").attr("id", "useraccount-search-datagrid-pager");
var localData1 = {
"page" : 1,
"totalRecords" : 5,
"pageSize" : 3,
"rows" : [
{ Name : "Name 1"},
{ Name : "Name 3"},
{ Name : "Name 2"}
]
};
function publicInit(){
$("body").append(myGrid, myPager);
myGrid.jqGrid({
pager : myPager,
data: localData1.rows,
datatype : "local",
colModel : [
{ name : 'Name', index : 'Name', width : "500"}
],
localReader: {
repeatitems: false
},
rowNum : 3,
viewrecords : true,
height : "auto",
ignoreCase : true
});
}
//=== REVEALING PATTERN===//
return {
init: publicInit
}
};
var grid1 = new grid();
grid1.init();
$("body").append("<br><br>"); //Add some spacing to distinguish between both grids
var grid2 = new grid();
grid2.init();
});
</script>
</body>
</html>
Any help would be highly appreciated.
It seems to me that your code produce <table> and <div> elements with the same id attributes. So the second grid var grid2 = new grid(); just add <table> and <div> elements which already exist on the page. It's a bug. All id attributes of all element on one HTML page must be unique. So the lines myGrid = $('<table>').attr( "id", "useraccount-search-datagrid"); and var myPager = $("<div>").attr("id", "useraccount-search-datagrid-pager"); must be changed.
If you need just to assign some unique ids you can use $.jgrid.randId() method used in jqGrid internally. The code could be
var myGrid = $("<table>").attr("id", $.jgrid.randId());
var myPager = $("<div>").attr("id", $.jgrid.randId());
Moreover I strictly recommend you to use name conversion used in JavaScript. If you need to use new operator to create an object you should rename the function grid to Grid.

Categories

Resources