I am working on developing a multi-column multi-word filtering search and have difficulties with two problems:
I am only able to partially filter the first column; partial because typing apple it shows apple and oranges in the first column.
I am struggling with finding a way to make this a multi-word search over both columns.
I found a table filtering techniques on SO and adjusted them in this fiddle. But this code will only filter over all the columns with one word. Typing more than one word to narrow the result (find A and B) does not work.
The code below is my attempt to perform a multi-column multi-word search in a single box see my fiddle.
How can I achieve filtering over multiple columns that combines the search phrases?
Meaning show only rows where searchphrase-1 and searchphrase-2 are present.
JS
var $orig_rows1 = $('#table tbody tr td[class = "col1"]');
var $orig_rows2 = $('#table tbody tr td[class = "col2"]');
$('#search').keyup(function() {
var $rows1 = $orig_rows1;
var $rows2 = $orig_rows2;
var val = '^(?=.*\\b' + $.trim($(this).val()).split(/\s+/).join('\\b)(?=.*\\b') + ').*$',
reg = RegExp(val, 'i'),
text;
$("tr:hidden").show();
$rows1.show().filter(function() {
text = $(this).text().replace(/\s+/g, ' ');
return !reg.test(text);
}).parent("tr").hide();
});
HTML
<input type="text" id="search" placeholder="Type to search title 1">
<table class="table-striped" id="table">
<thead>
<th>Title 1</th>
<th>Title 2</th>
</thead>
<tbody>
<tr>
<td class="col1">Apple</td>
<td class="col2">Green</td>
</tr>
<tr>
<td class="col1">Grapes</td>
<td class="col2">Green</td>
</tr>
</tbody>
<tr>
<td>Orange</td>
<td>Orange</td>
</tr>
</table>
Any advice would be great.
Mistake in your code </tbody> is placed wrong, it must be
<tbody>
<tr>
<td class="col1">Apple</td>
<td class="col2">Green</td>
</tr>
<tr>
<td class="col1">Grapes</td>
<td class="col2">Green</td>
</tr>
<tr>
<td>Orange</td>
<td>Orange</td>
</tr>
</tbody>
Not a perfect solution, suggestions would be greatly appreciated
Try this Demo Fiddle it has multiple words search capability made using Tag-it! plugin.
Update search for both AND and OR
Demo Fiddle with a check box to perform both operations
Edit: pieces of linked fiddle added
This is a part of the code from the linked fiddle
var search = function () {
if ($('.tagit-label').length) {
$("#table tbody tr").hide();
var toShow = [];
$('.tagit-label').each(function () {
filter = $(this).text();
$("#table tbody tr").each(function () {
if ($(this).text().search(new RegExp(filter, "i")) > 0) {
toShow.push($("#table tbody tr").index(this));
}
});
});
if ($('#chkBoth').prop("checked") && $('.tagit-label').length > 1) {
var filterShow = [];
var outputArray = [];
$(toShow).each(function (i, value) {
if (($.inArray(value, outputArray)) == -1) {
outputArray.push(value);
}
});
$(outputArray).each(function (i, value) {
var index = toShow.indexOf(value);
toShow.splice(index, 1);
});
}
$(toShow).each(function (i, value) {
$("#table tbody tr").eq(value).fadeIn();
});
} else {
$("#table tbody tr").fadeIn();
}
}
This is the result of my linked fiddle below:
Hope it helps..!!
Related
I have a large table in WordPress, I need to change the order of the columns, but I have to do it manually every time, when I need. Is there any plugin out there, in which all table loads up and I drag and drop the whole column from there as my choice?
The website is here
Based on your question, i can give you a demo to show you how to move forward with your requirements.
Please check this UPDATED FIDDLE. As you requested we are using Dragtable js.
Once sorting is completed we checks each row of the table finds each column of the respective row and create a json tree structure.
Html
<table id="sort_table">
<thead>
<tr>
<th></th>
<th class="draggable">Col1</th>
<th class="draggable">Col2</th>
<th class="draggable">Col3</th>
<th class="draggable">Col4</th>
</tr>
</thead>
<tbody>
<tr>
<td>Row1</td>
<td>Data11</td>
<td>Data12</td>
<td>Data13</td>
<td>Data14</td>
</tr>
<tr>
<td>Row2</td>
<td>Data21</td>
<td>Data22</td>
<td>Data23</td>
<td>Data24</td>
</tr>
<tr>
<td>Row3</td>
<td>Data31</td>
<td>Data32</td>
<td>Data33</td>
<td>Data34</td>
</tr>
<tr>
<td>Row4</td>
<td>Data41</td>
<td>Data42</td>
<td>Data43</td>
<td>Data44</td>
</tr>
</tbody>
</table>
JS (UPDATED)
$(document).ready(function() {
$('#sort_table').dragtable({
dragaccept: '.draggable',
beforeStop: function() {
var tree = {};
var rows = [];
$('#sort_table tr').each(function() {
var col_count = 0;
var cols = [];
$(this).children().each(function() {
cols[col_count] = $(this).html();
col_count++;
});
rows.push(cols);
});
tree.data = rows;
var tree_json = JSON.stringify(tree); // use the variable to save to DB
console.log(tree_json);
}
});
});
You can save the variable tree_json to database (Call ajax to php and save to DB)
On each page load you could take the value from database to a variable and using json_decode to make the string a json object
$table_structure = ; // Code to take from db
$table_structure = json_decode($table_structure);
You can copy and paste json from console to check if its valid using JSONLint
I have a scenario to bind a html table using angular js. In my table i need to show an a tag based on another column value(Payment Status). If its fully paid no need to show the a tag, else need to show it for very next element. I am a new one in angular.
<table>
<thead>
<tr>
<th>Month</th>
<th>Installement</th>
<th>PaymentAmount</th>
<th>PaymentDate</th>
<th>Payment Status</th>
<th>Pay</th>
</tr>
</thead>
<tbody>
<tr dir-paginate="row in rowCollection|orderBy:type:reverse|filter:searchKeyword|itemsPerPage:maxsize">
<td>{{row.Month}}</td>
<td>{{row.MonthlyInstallement}}</td>
<td>{{row.PaymentAmount}}</td>
<td>{{row.PaymentDate}}</td>
<td>{{row.PaymentStatus}}</td>
<td ng-if="row.PaymentStatus == 'UNPAID'">
Pay Online
</td>
<td ng-if="row.PaymentStatus == 'FULLY_PAID'">
</td>
</tr>
</tbody>
</table>
function bindFinanceDetails() {
var finUrl = baseurl + 'api/FinancialStatement/GetCarFinanceInfo';
var req = {
method: 'post',
data: {
LoginID: LoginID,
ContractNumber: 11170200669,
CustomerId: 2355898046
},
url: finUrl,
headers: {
RequestedPlatform: "Web",
RequestedLanguage: cookiePreferredLanguage,
Logintoken: $cookieStore.get('LoginToken'),
LoginId: LoginID
}
};
$http(req).then(function(response) {
var getData = response.data.FinanceList;
$scope.rowCollection = getData;
}, function(error) {
toastr.error($filter('translate')('Error Occured'));
});
}
A quite hacky solution will be something like the following (just showing you the needed change in the unpaid td element):
<td ng-if="row.PaymentStatus === 'UNPAID'" ng-show="$index === data.payOnlineIndex"
ng-init="data.payOnlineIndex = (!data.payOnlineIndex || (data.payOnlineIndex > $index)) ? $index : data.payOnlineIndex">
Pay Online
</td>
This way ng-init will run for all unpaid elements, setting the smallest index to the payOnlineIndex variable. ng-show will make sure to only show that one element that has the smallest index.
I encapsulate payOnlineIndex with a data object to keep a stable reference to it. This also requires the following addition to the controller code:
$scope.data = { payOnlineIndex: null };
See a working jsFiddle example here: https://jsfiddle.net/t3vktv0r/
Another option is running your filter and orderBy in the controller, searching for the first occurrence of an "unpaid" row, and marking that element for the "pay online" feature with some flag you can test with ng-if in your view.
Is there any way to fill the empty <td></td>, if data does not exist in this?
<table><tr><td></td><td>1</td><td></td></tr></table>
Change it to:
<table><tr><td>Not Data</td><td>1</td><td>No Data</td></tr></table>
Not with HTML itself.
Usually you would do this by generating the HTML using a data in a programming language and a template, with template logic used to insert a default value if none came from the data.
A little bit hackish, because it changes only visual aspect. You can do that with CSS:
table, td {border: 1px solid black; padding: 4px; border-collapse: collapse}
td:empty::before {content: "No Data"}
<table>
<tr>
<td></td>
<td>Real data</td>
<td></td>
</tr>
</table>
Won't really work just with html.
it depends on how you build your HTML-DOM. If it is just a pure HTML-file (*.html ) you could check for value by adding some JavaScrit/JQuery.
But if you are trying to do this, make sure to give your table/tr or td to give element-ids.
<table>
<tr id="1">
<td id="1_1"></td>
<td id="1_2">1</td>
<td id="1_3"></td>
</tr>
</table>
<script type="text">
/* For the amount of rows */
for(var outeri = 1; outeri <= 1; outeri++)
{
/* For the amount of columns */
for(var ineri = 1; ineri <= 3; ineri)
{
var innertd = String(outeri + '_' + ineri);
if(document.getElementById(inntertd).innerHTML == '')
{
document.getElementById(inntertd).innerHTML = 'No Data';
}
else {continue;}
}
}
</script>
This example is not very realistic and more likely not to be done unless your table is just static.
you can add an empty space:
This can be achieved in many ways, here are 2 (c# and jquery)
Solutions:
c#:
Use razor as in the following:
<table>
<thead>
<tr>
<td>Name</td>
<td>Date</td>
</tr>
</thead>
<tbody>
<tr>
#{
if(data)
{
<td>#data.name</td>
<td>#data.date</td>
}
else
{
<td colspan="2">NO DATA</td>
}
}
</tr>
</tbody>
</table>
jQuery:
Select the table and change the html depending on if there is any data
$(document).ready(function()
{
var table = $("table-selector");
var isData = $("data-selector").length;
if(!isData){
table.html("customize HTML right here, considering 'colspan' in case
there is a headers row as well")
}
});
I have the below html table where the header on seperate table and content on another table. I have to sort the table when i click the header that are in another table.
I found so many javascript examples that are working only if the headers are in same table.Can any you guys give me with some examples related to my task?
<html>
<table >
<tr>
<th>Name</th>
<th>Salary</th>
</tr>
</table>
<table>
<tr>
<td>Fred</td>
<td>$12000.00</td>
</tr>
<tr>
<td>Kevin</td>
<td>$191200.00</td>
</tr>
</table>
</html>
If you add some classes to the columns so that the column cells and the associated header have the same class name, it's not too difficult to leverage those other existing JavaScript solutions.
As an example, I used this simple JQuery sorting function and created this JSFiddle demo.
I modified the HTML like this:
<html>
<table id="heading">
<tr>
<th class="name-col">Name</th>
<th class="salary-col">Salary</th>
</tr>
</table>
<table id="data">
<tr>
<td class="name-col">Fred</td>
<td class="salary-col">$12000.00</td>
</tr>
<tr>
<td class="name-col">Kevin</td>
<td class="salary-col">$191200.00</td>
</tr>
</table>
</html>
Notice that I game the header Name and all of the cells in that column the class name-col, and I did the same for the Salary header and cells with the class salary-col.
Then I used JQuery to add a click listener to the name-col header, which then triggered the sort function on the name-col cells:
$('th.name-col').click(function() {
$('td.name-col').sortElements(function(a, b){
return $(a).text() > $(b).text() ? 1 : -1;
}, function(){ return this.parentNode; });
});
$('th.salary-col').click(function() {
$('td.salary-col').sortElements(function(a, b){
return $(a).text() > $(b).text() ? 1 : -1;
}, function(){ return this.parentNode; });
});
In this example, sortElements is the function provided in the simple JQuery sorting function I linked above. I am not the author of it.
You will notice that this script will only sort once, however, since the direction of the comparator (>) is hard-coded. One quick-n-dirty way to implement logic to reverse this sort is like this:
var nameAsc = false;
var salaryAsc = false;
$('th.name-col').click(function() {
$('td.name-col').sortElements(function(a, b){
if (nameAsc) {
nameAsc = false;
return $(a).text() > $(b).text() ? 1 : -1;
} else {
nameAsc = true;
return $(a).text() < $(b).text() ? 1 : -1;
}
}, function(){ return this.parentNode; });
});
$('th.salary-col').click(function() {
$('td.salary-col').sortElements(function(a, b){
if(salaryAsc) {
salaryAsc = false;
return $(a).text() > $(b).text() ? 1 : -1;
} else {
salaryAsc = true;
return $(a).text() < $(b).text() ? 1 : -1;
}
}, function(){ return this.parentNode; });
});
Here the nameAsc and salaryAsc boolean variables are just a hackish way of allowing you to reverse the sort order. If it's ascending, it flips the boolean and the direction of the > in the comparator function. There's probably a more efficient way to do this, but I was just going for a quick-and-dirty example.
You're going to have a lot of problems with your two-table model, especially with sizing the columns. If you have longer data in the cells in the data table, your data columns will no longer line up with your header columns. I strongly suggest you use just a single table for both the header and the data.
use sorttable.js for sorting, it might give problem with column alignment while clicking on column head for sorting....
<script type="text/javascript" src="http://community.wikidot.com/local--files/howto:sortable-tables-js/sorttable.js"></script>
<style>
th, td{
padding: 3px;//important
}
</style>
<table class="sortable">
<tr><th>...</th></tr><tr><td>...</td</tr>
</table>
I'm trying to dynamically hide/unhide multiple table rows using Javascript to mimic collapse/expand. here are relevant code snippets:
function selectionFilter(check, filter){
var elem = document.getElementById('myScrollTable').rows;
for(i = 0; i < elem.length; i++){
var type = elem[i].getAttribute('type');
if(type== filter){
if(check == true){
elem[i].style.display='';
}else{
elem[i].style.display='none';
}
}
}
}
and here is the sample HTML:
<input type="checkbox" checked="true" value="t1" onclick="selectionFilter(this.checked, this.value);">some type 1</input >
<input type="checkbox" value="t2" onclick="selectionFilter(this.checked, this.value);">some type 2</input ><br><br>
<table cellspacing="1" cellpadding="2" class="" id="myScrollTable">
<thead>
<tr>
<th>Data1</th>
<th>Data2</th>
</tr>
</thead>
<tbody>
<tr type="t1">
<td rowspan="50">something1</td><td>something2</td>
</tr>
<tr type="t1">
<td>something2</td>
</tr>
.
.
<tr type="t2" style="display:none;">
<td rowspan="50">something1</td><td>something2</td>
</tr>
<tr type="t2" style="display:none;">
<td>something2</td>
</tr>
.
.
</tbody>
</table>
In Firefox everything is fine. However in IE, after the first time any row is hidden, when it is unhidden it has some extra space appending at the bottom. This does not happen when rowspan is not used. I tried many things but couldn't get rid of the extra space.
I would truly appreciate if anyone could give me some hint.
Did you try using block instead of an empty string?
you should try using
elem[i].style.display = 'block';
and if this fails you should try
elem[i].style.display = 'table-row';
and allways you should check the w3schools documentation, its really usefull
http://www.w3schools.com/css/pr_class_display.asp
tellme if this works for you