Jquery Search - Case insensitive - javascript

I have had some help on a Jquery script which creates a searchable, toggleable FAQ. The code can be seen here:
http://jsfiddle.net/pT6dB/62/
The trouble is, if there is the word “How” with an upper case “H” and I search “h”, it wont find it. How can I make this script case insensitive?

Update
Alternatively, you could reduce the amount of code significantly using regular expression. jsFiddle demo
$('#search').keyup(function(e) {
// create the regular expression
var regEx = new RegExp($.map($(this).val().trim().split(' '), function(v) {
return '(?=.*?' + v + ')';
}).join(''), 'i');
// select all list items, hide and filter by the regex then show
$('#result li').hide().filter(function() {
return regEx.exec($(this).text());
}).show();
});​
Original
Based on your current algorithm for determining relative elements, you could use the jQuery filter method to filter your results based on the keywords array. Here's a rough idea:
// select the keywords as an array of lower case strings
var keywords = $(this).val().trim().toLowerCase().split(' ');
// select all list items, hide and filter then show
$('#result li').hide().filter(function() {
// get the lower case text for the list element
var text = $(this).text().toLowerCase();
// determine if any keyword matches, return true on first success
for (var i = 0; i < keywords.length; i++) {
if (text.indexOf(keywords[i]) >= 0) {
return true;
}
}
}).show();

Change this line
$('#result LI:not(:contains('+keywords[i]+'))').hide();
to
$('#result LI').each(function()
{
if(this.innerHTML.toLowerCase().indexOf(keywords[i].toLowerCase()) === -1)
{
$(this).hide();
}
});

// split the search into words
var keywords = s.toLowerCase().split(' ');
// loop over the keywords and if it's not in a LI, hide it
for(var i=0; i<keywords.length; i++) {
$('#result LI').each(function (index, element) {
if ($(element).text().toLowerCase().indexOf(keywords) != -1) {
$(element).show();
} else {
$(element).hide();
}
});
}

Related

jQuery if div contains multiple text strings

I had a quick script to search for some text (a unique code) in a div and hide a different element if it exists:
var itemCode = ["000001"];
if( $(".itemCode").text().indexOf(itemCode) >= 0) {
$(".codeBox").addClass("hideElement");
}
however I wanted to expand this so it finds one of multiple texts (codes) and if any of them exist then hide the element:
var itemCode = ["000001", "000003", "000008"];
if( $(".itemCode").text().indexOf(itemCode) >= 0) {
$(".codeBox").addClass("hideElement");
}
and this isn't working. I'm sure It's probably something simple and I'm supposed to add a .each() somewhere but I'm just not getting it working when I experiment trying things, what am I missing?
Might be slighty quicker if you have a few item codes in your array
var itemCode = ["000001", "000003", "000008"];
var regExpPattern = itemCode.join('|');
if($(".itemCode").text().match(new RegExp(regExpPattern, 'i'))) {
$(".codeBox").addClass("hideElement");
}
});
indexOf takes only one (mandatory) argument, so you'll have to iterate over your list to find element(s) matching your condition :
var itemCode = ["000001", "000003", "000008"];
var contains = itemCode.some(function(code) {
return $(".itemCode").text().indexOf(code) >= 0;
});
if (contains) {
$(".codeBox").addClass("hideElement");
}

jQuery/Javascript - Connecting two filters - showing only tr's with td's matching an array

My code currently has 2 separate filters, that filter the table based on their own criteria.
I've created a dumbed down jsfiddle of this specific part of the code.
What I am trying to do is to connect these 2 filters together. So, if, for example, Students is selected, then the button submit filters out only the Students with corresponding to the array numbers, but doesn't touch any other types of drivers.
And likewise, if the table is already filtered, selecting a driver type only works with the rows that are already filtered out.
Here is the code:
$('body').on('click', 'button', function() {
var array = [123, 124, 125, 126];
var filter = function() {
var match = false;
$(this).find('td').each(function() {
var currentText = $(this).text();
var filtered = array.filter(function(value) {
return value == currentText;
});
if (filtered.length > 0) {
match = true;
}
});
return match;
};
$('tr').hide().filter(filter).show();
});
$('#driverTypes').change(function () {
var val = parseInt($(this).val(), 10);
switch (val) {
case 777:
$('tr').show();
break;
case 19:
$('tr').hide();
$('tr').filter(function() {
return $(this).data('filtercriteria') == "Lease Purchase";
}).show();
break;
case 20:
$('tr').hide();
$('tr').filter(function() {
return $(this).data('filtercriteria') == "Company Driver Team";
}).show();
break;
case 21:
$('tr').hide();
$('tr').filter(function() {
return $(this).data('filtercriteria') == "Student";
}).show();
break;
case 22:
$('tr').hide();
$('tr').filter(function() {
return $(this).data('filtercriteria') == "Company Driver";
}).show();
break;
}
});
http://jsfiddle.net/m4orLpd3/12/
Thanks
Here is code that will do what you want. It retains the current filter in a global object. A separate filter is stored per column, and the two are combined when the filter is executed:
// List of zip codes of interest
var zipFinal2 = [123, 124, 125, 126];
// Variable to retain currently applied filter:
// An array with a filter per column.
var columnFilters = [{}, {}, {}, {}]; // add as many as you have columns
var zipColumnNo = 0;
var driverColumnNo = 1;
function applyFilter(filter) {
$('tr').each(function() {
$(this).toggle( // show when no TD has mismatching content
!$(this).find('td').filter(function(idx) {
// return true when content does not match the filter on this column
return filter[idx] && Object.keys(filter[idx]).length &&
!filter[idx].hasOwnProperty($(this).text());
}).length
);
});
}
$('#zipButton').click(function() {
// toggle first-column filter:
var newFilter = {};
if (!Object.keys(columnFilters[zipColumnNo]).length) {
// turn zipFinal2[] into object with values as properties for faster lookup
zipFinal2.forEach(function(zip) {
newFilter[zip] = 1;
});
}
columnFilters[zipColumnNo] = newFilter;
applyFilter(columnFilters);
});
$('#driverTypes').change(function () {
columnFilters[driverColumnNo] = {}; // no filter
if (this.selectedIndex) {
// filter second column on text in selected option
columnFilters[driverColumnNo][$(this.options[this.selectedIndex]).text()] = 1;
}
applyFilter(columnFilters);
});
// reset filter on page load:
$(function() {
$('#driverTypes').val(777);
});
Check out the fiddle.
As a bonus, this code also treats the "Submit" button (strange name) as a toggle: the filter on that column will be removed when you click it again.
Some browsers retain the last selected value in a drop-down list box when you refresh the page. So I have added at the end the code needed to reset that. Otherwise the situation is inconsistent: all entries of the table become visible, yet a filter is selected in the drop-down.
The code calls the applyFilter method whenever one of the two controls is used, and then the toggle method is called on all tr elements. The argument determines the visibility. Visibility is only set when none of the td elements mismatches with the filter. A td mismatches if and only when a filter is defined for that column (different from the empty object), and the value in the td is not a property of that filter object.
If you expect to run only in ECMAScript 6 compatible browsers, you could make the code nicer by using Set instead of object properties to store the filter values.
Also, if you expect to use more tables for filtering, you could make this more generic by passing the table tag to the applyFilter function, and storing the columnFilters array in the table tag's data property.
Modified your filter method. Use $('tr:visible') instead of $('tr').
jQuery hide() equivalent to css( "display", "none" ) which is considered as visible, since they still consume space in the layout.
var filter = function() {
var text = $(this).text();
var result = array.filter(function(id){
return ((text.indexOf(id) >= 0) ? true : false);
});
return !result.length;
};
$('tr:visible').filter(filter).hide();
http://jsfiddle.net/m4orLpd3/13/

loop through array to find matches and return every possible solution

I have a small input field where this code gets activated everytime a key is pressed inside it. But it now only prints "found something" when the name exacly matches what you type in the input field.
How can change a part that when I type something like "b" it already removes the matches where there is no "b" in the name is and print every possible matches that still have a "b".
My small code to find the match.
Info is my json big array where I can loop through all the names with info[i].name
var textInput = $findperson.find('input').val();
console.log(textInput);
for (i = 1; i < info.length; i++) {
if (textInput === info[i].name) {
console.log('found something');
}
}
Set Flag if found any match and print them, otherwise print found nothing,
for gi g mean search globally and i mean ignore case sothat A will match a and vise verse.
var textInput = $findperson.find('input').val();
console.log(textInput);
found = false
for (i = 1; i < info.length; i++) {
if (info[i].name.match(new RegExp(textInput,"gi")) ) {
console.log(info[i].name);
found = true
}
}
if(!found){
console.log("found nothing")
}
I would use regex like this:
var textInput = $findperson.find('input').val();
var regex = new Regexp(".*("+textInput+").*","i");
var filtered = info.filter(function (current) {
return current.name.match(regex);
});
console.log(filtered);
Just use indexOf to search for one String within another:
if(info[i].name.indexOf(textInput) != -1) {
indexOf will return -1 if String isn't found within the other.
You can try searching for some letters in one of the results 'balloon', 'ball', 'apple' in the example below:
var results = ['balloon', 'ball', 'apple'];
function filterResults() {
var input = document.getElementById('input').value;
var resultsFiltered = results.filter(function(a) {
return a.indexOf(input) != -1;
});
var result = ''; resultsFiltered.map(function(a) {
result += a + '<br/>';
}); document.getElementById('result').innerHTML = result;
}
<input id='input' onkeyup='filterResults();'/>
<div id='result'></div>

How to remove all jQuery validation engine classes from element?

I have a plugin that is cloning an input that may or may not have the jQuery validation engine bound to it.
so, it's classes may contain e.g. validate[required,custom[number],min[0.00],max[99999.99]] or any combination of the jQuery validation engine validators.
The only for sure thing is that the class begins with validate[ and ends with ], but to make it more complicated as in the example above, there can be nested sets of [].
So, my question is, how can I remove these classes (without knowing the full class) using jQuery?
Here is my implementation, It's not using regex, but meh, who said it had too?
//'first validate[ required, custom[number], min[0.00], max[99999.99] ] other another';
var testString = $('#test')[0].className;
function removeValidateClasses(classNames) {
var startPosition = classNames.indexOf("validate["),
openCount = 0,
closeCount = 0,
endPosition = 0;
if (startPosition === -1) {
return;
}
var stringStart = classNames.substring(0, startPosition),
remainingString = classNames.substring(startPosition),
remainingSplit = remainingString.split('');
for (var i = 0; i < remainingString.length; i++) {
endPosition++;
if (remainingString[i] === '[') {
openCount++;
} else if (remainingString[i] === ']') {
closeCount++;
if (openCount === closeCount) {
break;
}
}
}
//concat the strings, without the validation part
//replace any multi-spaces with a single space
//trim any start and end spaces
return (stringStart + remainingString.substring(endPosition))
.replace(/\s\s+/g, ' ')
.replace(/^\s+|\s+$/g, '');
}
$('#test')[0].className = removeValidateClasses(testString);
It might actually be simpler to do that without JQuery. Using the className attribute, you can then get the list of classes using split(), and check whether the class contains "validate[".
var classes = $('#test')[0].className.split(' ');
var newClasses = "";
for(var i = 0; i < classes.length; i++){
if(classes[i].indexOf('validate[') === -1){
newClasses += classes[i];
}
}
$('#test')[0].className = newClasses
I think this solution is even more simple. You just have to replace field_id with the id of that element and if the element has classes like some_class different_class validate[...] it will only remove the class with validate, leaving the others behind.
var that ='#"+field_id+"';
var classes = $(that).attr('class').split(' ');
$.each(classes, function(index, thisClass){
if (thisClass.indexOf('validate') !== -1) {
$(that).removeClass(classes[index])
}
});

use variable in regular expression in jquery

May be it will be a very easy question some of expert but seems difficult to me. I want to use a variable in pattern of regular expression.
$("#srcbtn .btnPage").live("click",function(){
var filter = $(this).val(), count = 0;
$(".checkpoint").each(function () {
if ($(this).find(".chpdetails .chkpname").text().search(new RegExp(/\b filter /i)) < 0) {
$(this).hide();
} else {
$(this).show();
count++;
}
});
});
but the filter variable doesn't work in if condition. the purpose of this code is to search a word which is start with filter variable's value i.e. A, B etc. How can i do this?
Thanks in advance.
Use this :
new RegExp("\\b" + filter, 'i')
See the documentation on RegExp
If you have many checkpoints, you should probably build the regexp object before entering the loop instead of building it at each iteration :
var r = new RegExp("\\b" + filter, 'i');
$(".checkpoint").each(function () {
if ($(this).find(".chpdetails .chkpname").text().search(r) < 0) {
$(this).hide();
} else {
$(this).show();
count++;
}
});
Using the constructor allows this for RegExp
$("#srcbtn .btnPage").live("click",function(){
var filter = $(this).val(), count = 0;
$(".checkpoint").each(function () {
if ($(this).find(".chpdetails .chkpname").text().search(new RegExp("\\b" + filter, "i")) < 0) {
$(this).hide();
} else {
$(this).show();
count++;
}
});
});

Categories

Resources