I'm new to jQuery and need help on searching for user-typed element within a table. I wrote this in JS, but have a problem writing in using jQuery.
When the element is found, the other rows in the table with the same class name should be visible and other rows should be hidden:
$(document).ready(function()
{
search(".site-table", "#recordInput");
console.log("Document is ready");
}
);
function search(search_table, search_field)
{
// Searching for an item specified in search_field within a table
$(search_field).on("keyup", function()
{
var target_text = $(this).val().toLowerCase();
//Hide everything first
$(search_table).find('tr').addClass(".hidden");
$(search_table).find('tr').each(function(index, element){
// For each row, find out if the row has the target_text in it
$element:contains($target_text).each(function(index, element){
$(element).removeClass(".hidden");
});
// for each row with the target text in it, find other rows with this rows class name in their class name and show them. Any other row should be hidden
});
Any help is appreciated.
EDIT 1:
So, here is the editted code after the comments. I still cannot get it working:
$(document).ready(function()
{
search(".site-table", "#recordInput");
console.log("Document is ready");
}
);
function search($search_table, $search_field)
{
console.log("Starting to search...");
$($search_field).on("keyup", function()
{
// Heighlight the search field
$(this).css('border', '1px solid red');
$search_text = $(this).val().toLowerCase();
// 1st method:
$search_result = $($search_table).find('tbody tr').text().toLowerCase().indexOf($search_text > -1); // Does not work! Nothing is found when there is a match
console.log("Search Result: ", $search_result);
// 2nd method:
$($search_table).find('tr').each(function(index, element){
// For each row, toggle the hidden class if the row contains the search text
$(this).toggleClass('hidden', $(this).text().toLowerCase().indexOf($search_text > -1));
});
// 3rd method:
var found = $($search_table).find('tbody tr').filter(function() {
return $(this).text().toLowerCase() == $search_text;
});
console.log("found: ", found);
});
}
None of these methods works! What am I doing wrong in each method?
Your problem is about using the indexOf. What you must put between the parentheses is only the searching text and > -1 must be out. See this sample:
var its_ok = $('div').first().html().indexOf('b') > -1
console.log('first one: ', its_ok)
var its_not_ok = $('div').first().html().indexOf('b' > -1)
console.log('second one: ', its_not_ok)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>abcd</div>
What you have done is the second one that is not true way of using the indexOf.
Related
I have the following code below... It takes a search field, and quickly searches the table for matching items, and hides all the other results. Right now this code works for a single search field (with class .search), and a single table (with id #SearchableTbl).
$(document).ready(function(){
$('.search').on('keyup',function(){
var searchTerm = $(this).val().toLowerCase();
$('#SearchableTbl tbody tr').each(function(){
var lineStr = $(this).text().toLowerCase();
if(lineStr.indexOf(searchTerm) === -1){
$(this).hide();
}else{
$(this).show();
}
});
});
});
I don't know javascript, so I'm not sure how to make this function work for multiple tables. So, if the first search field was .search1 (and not just .search), and the second was .search2. And, the tables being searched were #SearchableTbl1 and #SearchableTbl2 (respectively).
Can someone help me modify the code so this works with many (not just 2) tables? As I said, I don't know javascript (but I do know a little PHP), so I'm trying to do something like this (below is a mish-mash of PHP and Javascript, which definitely wont work, but should get my point across) ....
$(document).ready(function(){
for($var=1; $var<10; $var++;) {
$('.search($var)').on('keyup',function(){
var searchTerm = $(this).val().toLowerCase();
$('#SearchableTbl($var) tbody tr').each(function(){
var lineStr = $(this).text().toLowerCase();
if(lineStr.indexOf(searchTerm) === -1){
$(this).hide();
}else{
$(this).show();
}
});
});
}
});
Thanks!
With jQuery it depends on your dom structure, so wrap the table and search input (or anything else for that "data table" component) in a div, then the simple fact you're inputting into a specific input you can use that to find the parent element then find() the table.
$(document).ready(function(){
$('.data-table input').on('keyup',function(){
// find the parent
var parent = $(this).closest('.data-table')
var searchTerm = $(this).val().toLowerCase();
$(parent).find('table tbody tr').each(function(){
var lineStr = $(this).text().toLowerCase();
if(lineStr.indexOf(searchTerm) === -1){
$(this).hide();
}else{
$(this).show();
}
});
});
});
<div class="data-table">
<input type="text"/>
<table>
...
<table>
</div>
I have an Asp gridview that I am hiding elements in using a css class. When a row on the grid is selected I have a jQuery function that adds a selected_row class and changes the color. I am trying to find the data for the rows that are selected, and hidden. My function looks like this
$(function() {
$("[id*=MainContent_grvAccounts] td").bind("click", function() {
var row = $(this).parent();
$("[id*=MainContent_grvAccounts] tr").each(function() {
if ($(this)[0] != row[0]) {
$("td", this).removeClass("selected_row");
} else {
var hiddenElements = $("body").find(".hidden-field").not("script");
console.log(hiddenElements);
var myElements = Array.from(hiddenElements, element => element.innerHTML);
console.log(myElements);
}
});
$("td", row).each(function() {
if (!$(this).hasClass("selected_row")) {
$(this).addClass("selected_row");
} else {
$(this).removeClass("selected_row");
}
});
});
In the DOM I can see that they have a class name of "hidden-field selected_row".
When I try to filter using jQuery grep my data returns empty.
I need the var hiddenElements to only contain elements with class name hidden-field selected_row
I ended up using
var hiddenElements = row.find(".hidden-field");
To get my data.
I am using DataTables and the validationEngine plugin.
My issue is that I am only able to know which rows are selected on a particular page in the pagination. So, if I have rows selected on the second page of the pagination and no rows selected on the 1st page, it will show me an error 'Please select a row'.
I have read posts about it but not specific to my code, so that's the reason I am asking this question.
So in addition to the validation code I have, I should add the following code,
CODE
$("#mSelector").on("click", "button[name='next'],button[name='finish']",
function() {
var $stepSelector = $(".WizardStep:visible"); // get current step
var anyError = false;
$stepSelector .find("input,textarea,select").each(function () {
if (!$(this).validationEngine('validate')) {// validate every input element inside this step
anyError = true;
}
});
if (anyError)
return false; // exit if any error found
});
});
CODE
$(function () {
var singleSelect = $('.single-select').DataTable({
'lengthMenu': ['300']
});
// Single row select
$('.single-select tbody').on('click', 'tr', function () {
if ($(this).hasClass('selected')) {
$(this).removeClass('selected');
$('#hId').val('');
} else {
singleSelect.$('tr.selected').removeClass('selected');
$(this).addClass('selected');
$('#Id').val($(this).attr('id'));
}
});
var cId = $('#hdId').val();
if (cId > 0) {
$("#grid1.single-select")
.find("[id='" + currentId + "']")
.addClass('selected');
}
//selection
var mGrid = $("#mSelector").DataTable({
'lengthMenu': ['300']
});
$('#mSelector tbody').on('click', 'tr', function () {
if ($(this).hasClass('selected')) {
$(this).removeClass('selected');
$('#mId').val('');
} else {
mGrid.$('tr.selected').removeClass('selected');
$(this).addClass('selected');
$('#mId').val($(this).attr('id'));
}
});
CODE
$("button[name='next'],button[name='finish']").click(function() {
var $step = $(".Step:visible"); // get current step
var ifError = false;
$step.find("input,textarea,select").each(function() {
if (!$(this).validationEngine('validate')) { // validate
ifError = false;
}
});
if (ifError)
return false; // exit if there is an error
});
CAUSE
DataTables removes non-visible rows from DOM for various reasons so when you attach an event handler it works for currently visible elements only.
SOLUTION
You need to use event delegation by providing selector as a second argument in on() call.
Replace this code:
$("button[name='next'],button[name='finish']").click(function() {
// ... skipped ...
});
with
$("#mSelector").on("click", "button[name='next'],button[name='finish']", function() {
// ... skipped ...
});
where mSelector is your table ID.
From jQuery on() method documentation:
Delegated events have the advantage that they can process events from
descendant elements that are added to the document at a later time.
See "Direct and delegated events" in jQuery on() method documentation and jQuery DataTables – Why click event handler does not work for more information.
I have a list view in html which has headers and child elements. I have implemented jquery script to filter the header and child elements, but the problem is when I search the child elements, I get that specific child element with other elements in it also. The actual result should be (suppose I search "xxx" in the searchbox, the output should be the header element and the child-xxx element only which is not happening). I get the xxx result with other child element-aaa also. Please help. I have attached the jsfiddle link "My Test Fiddle"
$("#search").keyup(function(){
var SEARCHWORD = this.value;
$("#list li").each(function(){
if($(this).
text().toUpperCase().
indexOf(SEARCHWORD.toUpperCase()) >=0)
$(this).show();
else
$(this).hide();
});
});
I've modified your fiddle to include a combination of CSS and JS to accomplish what you want. One of your complications is that you want the header to show if any of the siblings match. So you cannot hide the header based on a non-match because there may be a different sibling match.
Second is that multiple siblings could potentially match. This means you can't just show/hide siblings based on a match. If both siblings match you need to show both, and any code that hides siblings could potentially hide a previous match.
I've added CSS code to do the showing/hiding based on matches and the event that the user is searching something (so clearing the box will reshow everything). Then the JS just sets or removes the 'hit' class.
#list.searching h3, #list.searching li > p { display: none }
#list.searching li > p.hit, #list.searching li.hit h3 { display: block }
The JS
var theList = $('#list');
$("#search").keyup(function(){
var SEARCHWORD = this.value;
// remove all hits each time
theList.find('.hit').removeClass('hit');
if (SEARCHWORD) {
// if a search term make sure the list is marked
theList.addClass('searching');
} else {
// remove searching mark
theList.removeClass('searching');
}
$("#list li p").each(function() {
// case-insensitive matching
if (this.innerText.toLowerCase().indexOf(SEARCHWORD.toLowerCase()) > -1) {
$(this).addClass('hit').parent().addClass('hit');
} else {
$(this).removeClass('hit');
}
})
});
Here is the updated fiddle http://jsfiddle.net/gS4AS/4/
Try this:
$("#search").keyup(function () {
var SEARCHWORD = this.value;
$("#list li").each(function () {
$(this).hide();
$('p:contains(' + SEARCHWORD + ')').closest('li').show();
$('p:contains(' + SEARCHWORD + ')').show().siblings('p').hide();
if (SEARCHWORD == "") {
$('#list').find('p:hidden').show();
}
});
});
Fiddle
You have to add this condition to show back the hidden elems:
if (SEARCHWORD == "") {
$('#list').find('p:hidden').show();
}
Updated Fiddle
As per your latest dom structure with tables and tds update to this code:
$("#search").keyup(function () {
var SEARCHWORD = this.value;
$("#list tr").each(function () {
$(this).hide();
$('td:contains(' + SEARCHWORD + ')').closest('tr').show();
if (SEARCHWORD == "") {
$('#list').find('tr:hidden').show();
}
});
});
Updated Fiddle with table structure.
I'm trying to make a filter on screen, by just hiding what doesn't meet the requirements.
This what I've come up with so far. I'm not sure what I am doing wrong.
jQuery :
jQuery('#searchBox').on('keyup change', function() {
var search = $('#searchBox').val();
//for each h4
$('h4').each(function(){
var h4id = $(this).attr('id');
if ($(h4id).contains(search))
$(this).show();
else
$(this).hide
});
HTML :
<input type="search" name="search" id="searchBox"/>
<h4 id="Adminstrator">Administrator</h4>
<h4 id="John,Smith">John Smith</h4>
<h4 id="Jane,Smith">Jane Smith</h4>
(I'm using jQuery 1.9.1)
(So, if I start typing Smith, "Administrator" h4 should disappear.
.contains will not give you the text content of the selector. It will only search for elements inside the selector.
Try this approach .. This can be lot more optimized
jQuery('#searchBox').on('keyup change', function () {
var search = $('#searchBox').val().toLowerCase();
$('h4').hide();
$('h4').each(function () {
var h4id = $(this).attr('id'),
$text = $('#'+ h4id).text().toLowerCase();
if($text.indexOf(search) > -1)
$(this).show();
});
});
Make sure your id's are unique.
Next is your id's should not contain , in them
JSFIDDLE
Try this:-
Simple one, but case sensitive though
Demo
jQuery('#searchBox').on('keyup change', function() {
var search = $('#searchBox').val();
$('h4').hide();
$('h4[id*='+ search + ']').show();
});
See if this helps. I won't use id for storing the string comparison since name can be same for multiple people and you might end up having multiple h4s with same id. SO i am using data-attribute and jquery data here.
Demo
jQuery('#searchBox').on('keyup change', function() {
var search = $('#searchBox').val();
$('h4').hide().filter(function(_,oj){
return $(oj).data('key').toLowerCase().indexOf(search.toLowerCase()) > -1;
//if your are trying to match the text() then do
//return $(oj).text().toLowerCase().indexOf(search.toLowerCase()) > -1;
}).show();
});
Fixing your code would mean this. There is no contains function and couple of other typos.
Demo
jQuery('#searchBox').on('keyup change', function() {
var search = $('#searchBox').val();
//for each h4
$('h4').each(function(){
var h4id = this.id;
if (h4id.indexOf(search) > -1)
//if your are trying to match the text() then do
//if ($('#'+h4id).text().indexOf(search) > -1)
$(this).show();
else
$(this).hide();
});
});
Try a regex based solution
jQuery('#searchBox').on('keyup change', function() {
var search = $(this).val();
var regex = new RegExp(search, 'i');
//for each h4
$('h4').hide().filter(function(){
return regex.test(this.id)
}).show();
});
Demo: Fiddle
Just using jQuery attribute selector,see here,just two line code will be enough.
Demo:
//for each h4
var h4id = $(this).attr('id');
$("h4").hide().filter("[id*=" + h4id + "]").show();