table multiple word search in jquery - javascript

I have a jquery function that search a word in a table. e.g.
TABLE
<table>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Band Name</th>
</tr>
<tr>
<td>John</td>
<td>Lennon</td>
<td>Beatles</td>
</tr>
<tr>
<td>Paul</td>
<td>McCartney</td>
<td>Beatles</td>
</tr>
<tr>
<td>George</td>
<td>Harrison</td>
<td>Beatles</td>
</tr>
<tr>
<td>Ringo</td>
<td>Starr</td>
<td>Beatles</td>
</tr>
now. i have an input text box that if you put any word in there based on the table e.g Paul
the result will be a table that has only paul mccartney . and all the other td elements will be hidden.
$(document).ready(function(){
if (!RegExp.escape) {
RegExp.escape = function (s) {
return s.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&")
};
}
///search this table
jQuery(function ($) {
///search this table
$(' #search ').click(function () {
var searchthis = new RegExp($(' #emp_search ').val().replace(/\s+/, '|'), 'i');
$("table").find("tr").slice(1).each(function (index) {
var text = $.trim($(this).text());
$(this).toggle(searchthis.test(text));
});
Now, what i want to happen is..
what if i input a text containg "Paul Harrison", the result should be paul mccartney and george harrison.. is that possible? like inputting a multiple words and displaying a possible result? Im just new in jquery. and the codes above is not mine.. thanks in advance. :)
here is the demo
http://jsfiddle.net/wind_chime18/D6nzC/7/

I think a regex based search will be the best fit for this
if (!RegExp.escape) {
RegExp.escape = function (s) {
return s.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&")
};
}
jQuery(function ($) {
var $table = $("table");
var bands = [];
$table.find('td:nth-child(3)').each(function () {
var text = $.trim($(this).text()).toLowerCase();
if ($.inArray(text, bands) == -1) {
bands.push(text);
}
}).get();
///search this table
$(' #search ').click(function () {
var parts = $(' #emp_search ').val().split(/\s+/);
var bns = [],
i = 0,
idx;
while (i < parts.length) {
idx = $.inArray(parts[i].toLowerCase(), bands);
if (idx >= 0) {
bns.push(parts.splice(i, 1)[0]);
} else {
i++;
}
}
var nameexp = parts.length ? new RegExp(parts.join('|'), 'im') : false;
var bnexp = bns.length ? new RegExp(bns.join('|'), 'im') : false;
$("table").find("tr").slice(1).each(function (index) {
var $this = $(this);
var name = $.trim($this.children().not(':nth-child(3)').text());
var band = $.trim($this.children(':nth-child(3)').text());
$(this).toggle((!nameexp || nameexp.test(name)) && (!bnexp || bnexp.test(band)));
});
});
});
Demo: Fiddle

You could first collapse all the rows, then split the searchthis string on space and finally add visible to rows that match one of the rows... something like this for example.
$(document).ready(function(){
///search this table
$('#search').click(function() {
var searchthis = $('#emp_search').val();
$("table").find("tr").each(function(index) {
if (index === 0) return;
$(this).css('visibility', 'collapse');
});
var searchArray = [searchthis];
if (searchthis.indexOf(' ') > -1) {
searchArray = searchthis.split(' ');
}
$("table").find("tr").each(function(index) {
if (index === 0) return;
var id = $(this).find("td").text().toLowerCase().trim();
for (var i = 0; i < searchArray.length; i++) {
var txt = searchArray[i].toLowerCase().trim();
if (id.indexOf(txt) !== -1) {
$(this).css('visibility', 'visible');
}
}
});
});
});

Related

How to query an AJAX imported table (instead of a local table) using javascript

Currently, I have a script that searches column 1 of a locally-stored table, and returns the result from column 2 from the same row. Based on that result, it logs something to the console.
Here it is action. It searches the table for "dragon" in column 1, returns "2" from Column 2, then the script logs "The result is two." to the console.
var username = 'dragon'
const searchDataSetByKey = (dataSet, key) => {
return dataSet.find((data) => data[0] === key)
}
document.addEventListener('DOMContentLoaded', () => {
var tableToArray = Array
.from(document.querySelectorAll('tr'))
.reduce((_tableToArray, tableRow, tableRowIndex) => {
if(tableRowIndex !== 0) {
var tableData = tableRow.querySelectorAll('td')
var key = tableData.item(0).innerText
var value = tableData.item(1).innerText
_tableToArray.push([key, value])
}
return _tableToArray
}, [])
var searchString = searchDataSetByKey(tableToArray,username).toString()
var oneSearch = searchString.indexOf("1")
var twoSearch = searchString.indexOf("2")
var threeSearch = searchString.indexOf("3")
if (oneSearch >= 0) {
console.log('The result is one!');}
else if (twoSearch >= 0) {
console.log('This result is two.');}
else if (threeSearch >= 0) {
console.log('The answer is three! :)');}
})
<html>
<script src="script.js"></script>
<body>
<table>
<tr>
<th>Username</th>
<th>1/2/3</th>
</tr>
<tr>
<td>wisp</td>
<td>1</td>
</tr>
<tr>
<td>husky</td>
<td>2</td>
</tr>
<tr>
<td>dragon</td>
<td>2</td>
</tr>
<tr>
<td>woop</td>
<td>3</td>
</tr>
<tr>
<td>e6</td>
<td>1</td>
</tr>
</table>
</body>
</html>
This is great for locally-stored tables. The issue is, I'd like to get the same result from a Google Sheet. I've found a way to store the info from a Google Sheet into a HTML table using AJAX. The code for this can be seen here:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript">
var spData = null;
function doData(json) {
spData = json.feed.entry;
}
function drawCell(tr, val) {
var td = $("<td/>");
tr.append(td);
td.append(val);
return td;
}
function drawRow(table, rowData) {
if (rowData == null) return null;
if (rowData.length == 0) return null;
var tr = $("<tr/>");
table.append(tr);
for(var c=0; c<rowData.length; c++) {
drawCell(tr, rowData[c]);
}
return tr;
}
function drawTable(parent) {
var table = $("<table/>");
parent.append(table);
return table;
}
function readData(parent) {
var data = spData;
var table = drawTable(parent);
var rowData = [];
for(var r=0; r<data.length; r++) {
var cell = data[r]["gs$cell"];
var val = cell["$t"];
if (cell.col == 1) {
drawRow(table, rowData);
rowData = [];
}
rowData.push(val);
}
drawRow(table, rowData);
}
$(document).ready(function(){
readData($("#data"));
});
</script>
<script src="https://spreadsheets.google.com/feeds/cells/1P9DhWOHcl14Y7-P5wCxTm-sUceckGquPoOobO75XhvM/1/public/values?alt=json-in-script&callback=doData"></script>
<style type="text/css" media="print">
form {display: none;}
</style>
</head>
<body>
<div id="data"/>
</body>
</html>
I was wondering if there was any way of achieving what was done in the local HTML table, with this AJAX imported HTML table?
Thanks!
It's exactly the same work that you need to do, albeit at a different time - i.e in response to a different event. Do it straight after you've loaded the table, instead of straight after you've received the DOMContentLoaded event from the document. Here's an alternate way to go looking.
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript">
var spData = null;
function doData(json) {
spData = json.feed.entry;
}
function drawCell(tr, val) {
var td = $("<td/>");
tr.append(td);
td.append(val);
return td;
}
function drawRow(table, rowData) {
if (rowData == null) return null;
if (rowData.length == 0) return null;
var tr = $("<tr/>");
table.append(tr);
for(var c=0; c<rowData.length; c++) {
drawCell(tr, rowData[c]);
}
return tr;
}
function drawTable(parent) {
var table = $("<table/>");
parent.append(table);
return table;
}
function readData(parent) {
var data = spData;
var table = drawTable(parent);
var rowData = [];
for(var r=0; r<data.length; r++) {
var cell = data[r]["gs$cell"];
var val = cell["$t"];
if (cell.col == 1) {
drawRow(table, rowData);
rowData = [];
}
rowData.push(val);
}
drawRow(table, rowData);
}
$(document).ready(function(){
readData($("#data"));
searchTable( 'dragon', document.querySelector('table') );
});
function searchTable(searchStr, target)
{
let rows = Array.from( target.querySelectorAll('tr') );
rows.forEach( (row,idx,col) => {
let firstCell = row.querySelector('td').textContent;
if (firstCell == searchStr)
{
let cell2 = row.querySelectorAll('td')[1].textContent;
console.log(`${searchStr} found in row ${idx}`);
console.log(`col 2 of row #${idx} is: ${cell2}`);
}
}
);
}
</script>
<script src="https://spreadsheets.google.com/feeds/cells/1P9DhWOHcl14Y7-P5wCxTm-sUceckGquPoOobO75XhvM/1/public/values?alt=json-in-script&callback=doData"></script>
<style type="text/css" media="print">
form {display: none;}
</style>
</head>
<body>
<div id="data"/>
</body>
</html>

How to display multiple cells in Table Search

I'm wondering if there is a way for this search bar that I'm using to display multiple elements. As it is right now if I search for "123" in a pool with "321" "1234" "123" "12345" The only displayed value would be the first one: "1234". I'd like for all values that match my search to be displayed, therefore this would be the correct search result: "1234" "123" "12345".
Any answer is appreciated.
Here's the current code that I have:
var cells = document.querySelectorAll("#myTable td");
var search = document.getElementById("myInput");
search.addEventListener("keyup", function() {
if (search.value.length > 0 && search.value != '') {
for (var i = 0; i < cells.length; ++i) {
if (cells[i].textContent.toLowerCase().indexOf(search.value.toLowerCase()) === 0) {
cells.forEach(function(element) {
element.style.display = "none";
});
cells[i].style.display = "table-cell";
break;
} else {
cells.forEach(function(element) {
if (cells[i] !== element) {
element.style.display = "table-cell";
}
});
}
}
} else {
cells.forEach(function(element) {
if (cells[i] !== element) {
element.style.display = "table-cell";
}
});
}
});
<input id="myInput">
<table id="myTable">
<tr>
<td>321</td>
<td>123</td>
</tr>
<tr>
<td>1234</td>
<td>abc</td>
</tr>
<tr>
<td>12345</td>
<td>abcde</td>
</tr>
</table>
Your cells selector returns a nodelist this is an arrayish object. That doesn't have the forEach function.
However we can borrow from the Array object:
Array.prototype.forEach
What I did to solve the other problem is create an indexArray as a lookup array. that keeps track of the indices that contained the search string. Then when we loop all the cells we can turn the ones of that don't show up in the lookup array
var cells = document.querySelectorAll("#myTable td");
var search = document.getElementById("myInput");
search.addEventListener("keyup", function() {
var indexArray = []; //look up array
for (var i = 0; i < cells.length; ++i) {
//restore the cells:
cells[i].style.display = "table-cell";
//if search value is found the value will be 0 if it starts a the beginning
if (cells[i].textContent.toLowerCase().indexOf(search.value.toLowerCase()) === 0) {
indexArray.push(i); //push index into lookup
}
}
//loop over all cells
Array.prototype.forEach.call(cells, function(element, index) {
if (indexArray.indexOf(index) === -1) //if index is not present in look up, set display to none
element.style.display = "none";
});
});
<input id="myInput">
<table id="myTable">
<tr>
<td>321</td>
<td>123</td>
</tr>
<tr>
<td>1234</td>
<td>abc</td>
</tr>
<tr>
<td>12345</td>
<td>abcde</td>
</tr>
</table>
below code is enough if you want to show which cell has contain that search; also you can test on jsfiddle https://jsfiddle.net/bzcdomjs/
var cells = document.querySelectorAll("#myTable td");
var search = document.getElementById("myInput");
search.addEventListener("keyup", function() {
for (var i = 0; i < cells.length; ++i) {
cells[i].style.display = "table-cell";
if (search.value.length > 0 && search.value != '') {
if(cells[i].textContent.toLowerCase().indexOf(search.value.toLowerCase()) === -1) {
cells[i].style.display = "none";
}
}
});

Case insensitive search in bootstrap table data

I am trying to find and highlight the matching text in a bootstrap table.
Here is the fiddler: https://jsfiddle.net/99x50s2s/74/
HTML
<table class='table table-bordered'>
<thead>
<tr><th>ID</th><th>Name</th></tr>
</thead>
<tbody id='UserInfoTableBody'>
<tr><td>1</td><td>UserName 1</td></tr>
<tr><td>2</td><td>UserName 2</td></tr>
<tr><td>3</td><td>UserName 1</td></tr>
<tr><td>4</td><td>UserName 3</td></tr>
<tr><td>5</td><td>UserName 2</td></tr>
<tr><td>6</td><td>UserName 2</td></tr>
<tr><td>7</td><td>UserName 1</td></tr>
<tr><td>8</td><td>UserName 1</td></tr>
<tr><td>9</td><td>username 2</td></tr>
</tbody>
</table>
JS
HighlightMatches();
function HighlightMatches(){
var textToMatch = 'UserName 2';
$('.match').replaceWith(function () {
return this.innerText;
});
$('#UserInfoTableBody td').each(function (i, tdContent) {
var $td = $(tdContent);
$td.html($td.html().
split(textToMatch).
join('<span class="match">' + textToMatch + '</span>'));
});
}
CSS
.match{background-color:yellow;}
Problem:
The current search is case-sensitive and I want it to be case-insensitive. In the code above, I am trying to search 'UserName 2' but it is missing the value in last row (username 2).
I tried to use contains but in that case, I am not sure how to highlight the text. Any help is appreciated.
Expectation
Highlight only the matching text.
Should work for,
var textToMatch = '2';
var textToMatch = 'User';
var textToMatch = 'user';
You can do it like this:
HighlightMatches();
function HighlightMatches(){
var textToMatch = 'username';
$('.match').replaceWith(function () {
return this.innerText;
});
$('#UserInfoTableBody td:odd').each(function (i, tdContent) {
var $td = $(tdContent);
var pos = $td.html().toLowerCase().search(textToMatch);
var len = textToMatch.length;
if(pos != -1 ){
var match = $td.html().substring(pos, len+pos);
var splitted = $td.html().split(match);
$td.html(splitted[0] + '<span class="match">' + match + '</span>' + splitted[1]);
}
});
}
Fiddle: https://jsfiddle.net/99x50s2s/87/
You can use the function toLowerCase().
this function characters converted to lowercase. use this function for textToMatch and td
Good luck
$.extend($.expr[":"], {
"containsIN": function(elem, i, match, array) {
return (elem.textContent || elem.innerText || "").toLowerCase().indexOf((match[3] || "").toLowerCase()) >= 0;
}
});
HighlightMatches();
function HighlightMatches(){
var textToMatch = 'UserName 2';
$('.match').replaceWith(function () {
return this.innerText;
});
$('#UserInfoTableBody td').each(function (i, tdContent) {
$('td:containsIN("'+textToMatch+'")').html('<span class="match">' + textToMatch + '</span>');
});
}
you can try this.
https://jsfiddle.net/99x50s2s/85/

Javascript 'onclick' not working in Google Chrome

I am using datatables to dynamically create a table and populate it with data. So far so good. Then I try to use onclick() to make certain td elements clickable so they redirect me to another page.
The problem is: clicking on the td's does absolutely nothing in Chrome. It works fine in IE though.
Here's the html code.
<body id="dt_example">
<form>
<input type="hidden" name="currency_numberOfRows" id="currency_numberOfRows" value="<%=currency_numberOfRows %>"></input>
<input type="hidden" name="currency_numberOfColumns" id="currency_numberOfColumns" value="<%=currency_numberOfColumns %>"></input>
<div id="demo">
<table cellpadding="0" cellspacing="0" border="0" class="display" id="currency_example" tableType="currency_clickableTDs">
<thead><tr>
<th class="heading"></th>
<th class="heading"><%=header_data%></th>
<th>% of Total</th>
<th>Total</th>
</tr></thead>
<tbody>
<tr class="odd">
<th class="heading">*Dynamically Added Heading*</th>
<td valign=middle class="underline">***Clickable Cell***</td>
<td valign=middle>*Dynamically Added Data*</td>
<td valign=middle>*Dynamically Added Data*</td>
</tr>
</tbody>
</table>
</div>
The javascript code is
<script type="text/javascript" charset="utf-8">
$(document).ready(function() {
var counter=(document.getElementById("currency_numberOfColumns").value)*2+1;
var tempaoColumns = [];
for(i=0;i<=counter;i++){
if(i==0)
{tempaoColumns[i] = null;}
else
{ tempaoColumns[i] = { "sType": "numeric-comma" };}
}
$('table.display').dataTable({
"aoColumns": tempaoColumns,
"sDom": 'T<"clear">lfrtip',
"aaSorting": [[ 1, "desc" ]]
});
} );
</script>
and
function setTDOnclickEvents(val){
var pageFrom = val;
var colHeaders = [];
var rowHeaders = [];
var numberOfColumns = document.getElementById("currency_numberOfColumns").value;
var numberOfRows = document.getElementById("currency_numberOfRows").value;
var table=document.getElementById("currency_example");
for (var h=0; h <= numberOfColumns*2; h++) {
//find every TR in a "clickableTDs" type table
colHeaders[h]= (table.rows[0].cells[h].innerHTML);
//alert(h)
//alert(table.rows[0].cells[h].innerHTML)
}
for (var h=0; h < numberOfRows/2; h++) {
//find every TR in a "clickableTDs" type table
if(h==0)
rowHeaders[h]= (table.rows[h].cells[0].innerHTML);
else if(h==1){
rowHeaders[h]= (table.rows[numberOfRows/2].cells[0].innerHTML);}
Uncaught TypeError: Cannot read property 'cells' of undefined in the above line
else
rowHeaders[h]= (table.rows[h-1].cells[0].innerHTML);
}
var allTRs = new Array();
//go through all elements
if(document.forms[0].tab.value=="Currency"){
for (var h=0; h < document.all.length; h++) {
//find every TR in a "clickableTDs" type table
if (document.all[h].tagName == "TR" &&
document.all[h].parentElement.parentElement.tableType == "currency_clickableTDs") {
allTRs.push(document.all[h]);
}
}
}
else if(document.forms[0].tab.value=="Service"){
for (var h=0; h < document.all.length; h++) {
//find every TR in a "clickableTDs" type table
if (document.all[h].tagName == "TR" &&
document.all[h].parentElement.parentElement.tableType == "service_clickableTDs") {
allTRs.push(document.all[h]);
}
}
}
else if(document.forms[0].tab.value=="Project"){
for (var h=0; h < document.all.length; h++) {
//find every TR in a "clickableTDs" type table
if (document.all[h].tagName == "TR" &&
document.all[h].parentElement.parentElement.tableType == "project_clickableTDs") {
allTRs.push(document.all[h]);
}
}
}
else if(document.forms[0].tab.value=="Location"){
for (var h=0; h < document.all.length; h++) {
//find every TR in a "clickableTDs" type table
if (document.all[h].tagName == "TR" &&
document.all[h].parentElement.parentElement.tableType == "location_clickableTDs") {
allTRs.push(document.all[h]);
}
}
}
for (var i=1; i < allTRs.length; i++) {
for (var j=1; j < allTRs[i].cells.length; j++) {
allTRs[i].cells[j].colHeader = colHeaders[j];
allTRs[i].cells[j].rowHeader = rowHeaders[i];
allTRs[i].cells[j].onclick = function (){
if(this.innerHTML == "0.00" || this.innerHTML == "0"){
alert("No data to represent!!!");
}else{
if((pageFrom == "GrossRevenueLevel") && (this.colHeader != "% of Total")&&(this.colHeader != "TOTAL")){
goMyController(this.colHeader,this.rowHeader);
}
}}
} } }
Could someone please help me? Thanks in advance and sorry for the painfully long code.
P.S. I didn't put the entire html code as it would be too lengthy
I found a solution. I replaced the javascript code with
function setTDOnclickEvents(val){
var pageFrom = val;
var bhal=$("#tab").val();
if(bhal=="Currency"){
var $tables = $("#currency_example tr");
}
else if(bhal=="Service"){
var $tables = $("#service_example tr");
}
else if(bhal=="Project"){
var $tables = $("#project_example tr");
}
else if(bhal=="Location"){
var $tables = $("#location_example tr");
}
$tables.each(function (i, el) {
var $tds = $(this).find('td.underline');
$tds.click(function(){
var hetch = $(this).html();
var hindex = $(this).index();
var colHeada= $tds.closest('table').find('th').eq(hindex).html();
var rowHeada= $tds.closest('tr').find('th').html();
if(hetch == "0.00" || hetch == "0"){
alert("No data available for this selection.");
}else{
if((pageFrom == "GrossRevenueLevel") && (colHeada != "% of Total")&&(colHeada != "TOTAL")){
alert(colHeada);
alert(rowHeada);
}
}
});
});
}
and it's working now.

Finding column index using jQuery when table contains column-spanning cells

Using jQuery, how can I find the column index of an arbitrary table cell in the example table below, such that cells spanning multiple columns have multiple indexes?
HTML
<table>
<tbody>
<tr>
<td>One</td>
<td>Two</td>
<td id="example1">Three</td>
<td>Four</td>
<td>Five</td>
<td>Six</td>
</tr>
<tr>
<td colspan="2">One</td>
<td colspan="2">Two</td>
<td colspan="2" id="example2">Three</td>
</tr>
<tr>
<td>One</td>
<td>Two</td>
<td>Three</td>
<td>Four</td>
<td>Five</td>
<td>Six</td>
</tr>
</tbody>
</table>
jQuery
var cell = $("#example1");
var example1ColIndex = cell.parent("tr").children().index(cell);
// == 2. This is fine.
cell = $("#example2");
var example2ColumnIndex = cell.parent("tr").children().index(cell);
// == 2. It should be 4 (or 5, but I only need the lowest). How can I do this?
Here's a plugin which can calculate the 'noncolspan' index.
$(document).ready(
function()
{
console.log($('#example2').getNonColSpanIndex()); //logs 4
console.log($('#example1').getNonColSpanIndex()); //logs 2
}
);
$.fn.getNonColSpanIndex = function() {
if(! $(this).is('td') && ! $(this).is('th'))
return -1;
var allCells = this.parent('tr').children();
var normalIndex = allCells.index(this);
var nonColSpanIndex = 0;
allCells.each(
function(i, item)
{
if(i == normalIndex)
return false;
var colspan = $(this).attr('colspan');
colspan = colspan ? parseInt(colspan) : 1;
nonColSpanIndex += colspan;
}
);
return nonColSpanIndex;
};
Mine is quite similar to SolutionYogi's, minus the creation of a plugin. It took me a bit longer... but I'm still proud of it so here it is :)
cell = $("#example2");
var example2ColumnIndex2 = 0;
cell.parent("tr").children().each(function () {
if(cell.get(0) != this){
var colIncrementor = $(this).attr("colspan");
colIncrementor = colIncrementor ? colIncrementor : 1;
example2ColumnIndex2 += parseInt(colIncrementor);
}
});
console.log(example2ColumnIndex2);
There is a more concise answer here: Get Index of a td considering the colspan using jquery
In short:
var index = 0;
$("#example2").prevAll("td").each(function() {
index += this.colSpan;
});
console.log(index);
You could do something like this:
var index = 0;
cell.parent('tr').children().each(
function(idx,node) {
if ($(node).attr('colspan')) {
index+=parseInt($(node).attr('colspan'),10);
} else {
index++;
}
return !(node === cell[0]);
}
);
console.log(index);
It'd probably make sense to do it as a plugin or via extend.
Slightly modified version is here: http://jsfiddle.net/Lijo/uGKHB/13/
//INDEX
alert ( GetNonColSpanIndex ('Type'));
function GetNonColSpanIndex(referenceHeaderCellValue) {
var selectedCell = $("th").filter(function (i) {
return ($.trim($(this).html() )) == referenceHeaderCellValue;
});
alert(selectedCell.html());
var allCells = $(selectedCell).parent('tr').children();
var normalIndex = allCells.index($(selectedCell));
var nonColSpanIndex = 0;
allCells.each(
function (i, item) {
if (i == normalIndex)
return false;
var colspan = $(selectedCell).attr('colspan');
colspan = colspan ? parseInt(colspan) : 1;
nonColSpanIndex += colspan;
}
);
return nonColSpanIndex;
};
​

Categories

Resources