I'm trying to use jquery to to create a live filter to hide divs on realtime text input. So far I have the following:
<input type="text" class="form-control" id="filter" name="filter" class="filter">
<div class="media">
<div class="media-body>
<h4>Apples</h4>
...
</div>
</div>
<div class="media">
<div class="media-body>
<h4>Oranges</h4>
...
</div>
</div>
<script>
$('#filter').keyup(function () {
var filter = $("#filter").val();
$('.media').each(function(i, obj) {
if ($('this > .media-body > h4:contains(filter)').length === 0) {
$(this).css("display","none");
}
});
});
</script>
I want this to work so that as soon as someone types an 'o' the apples div is hidden but currently it hides all the divs as soon as anything is typed.
Also how can I make it case insensitive?
I'm trying to use jquery to to create a live filter to hide divs on realtime text input. So far I have the following:
<input type="text" class="form-control" id="filter" name="filter" class="filter">
<div class="media">
<div class="media-body>
<h4>Apples</h4>
...
</div>
</div>
<div class="media">
<div class="media-body>
<h4>Oranges</h4>
...
</div>
</div>
<script>
$('#filter').keyup(function () {
var filter = $("#filter").val();
$('.media').each(function(i, obj) {
if ($('this > .media-body > h4:contains(filter)').length === 0) {
$(this).css("display","none");
}
});
});
</script>
I want this to work so that as soon as someone types an 'o' the apples div is hidden but currently it hides all the divs as soon as anything is typed.
Also how can I make it case insensitive?
Share Improve this question edited Apr 1, 2014 at 12:04 Evgeniy 2,9213 gold badges22 silver badges35 bronze badges asked Apr 1, 2014 at 11:58 RayZorRayZor 6651 gold badge13 silver badges25 bronze badges 3- see jsfiddle.net/arunpjohny/LXEDE/1 – Arun P Johny Commented Apr 1, 2014 at 12:05
- I suppose items should be shown again when someone clears the filter? :) – Ja͢ck Commented Apr 1, 2014 at 12:18
- Wow! I pop out for lunch and come back to a flurry of answers! Thank-you every one! =D – RayZor Commented Apr 1, 2014 at 13:09
10 Answers
Reset to default 8Big thanks to everyone who responded to this question - in the end I went with the solution Fabrizio Calderan provided, but have made a few modifications to it that allow for the text filter to search a string for words in any order and to redisplay previously hidden divs if the user deletes what they've typed, I thought I would share this modified solution with you:
$('#filter').keyup(function () {
var filter_array = new Array();
var filter = this.value.toLowerCase(); // no need to call jQuery here
filter_array = filter.split(' '); // split the user input at the spaces
var arrayLength = filter_array.length; // Get the length of the filter array
$('.media').each(function() {
/* cache a reference to the current .media (you're using it twice) */
var _this = $(this);
var title = _this.find('h4').text().toLowerCase();
/*
title and filter are normalized in lowerCase letters
for a case insensitive search
*/
var hidden = 0; // Set a flag to see if a div was hidden
// Loop through all the words in the array and hide the div if found
for (var i = 0; i < arrayLength; i++) {
if (title.indexOf(filter_array[i]) < 0) {
_this.hide();
hidden = 1;
}
}
// If the flag hasn't been tripped show the div
if (hidden == 0) {
_this.show();
}
});
});
You need to properly interpolate the selector string with the actual value of filter
.
You also have a typo in $('this > ...
.
Try this code (with some improvements)
$('#filter').keyup(function () {
var filter = this.value.toLowerCase(); // no need to call jQuery here
$('.media').each(function() {
/* cache a reference to the current .media (you're using it twice) */
var _this = $(this);
var title = _this.find('h4').text().toLowerCase();
/*
title and filter are normalized in lowerCase letters
for a case insensitive search
*/
if (title.indexOf(filter) < 0) {
_this.hide();
}
});
});
Try
if (!RegExp.escape) {
RegExp.escape = function (value) {
return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&")
};
}
var $medias = $('.media'),
$h4s = $medias.find('> .media-body > h4');
$('#filter').keyup(function () {
var filter = this.value,
regex;
if (filter) {
regex = new RegExp(RegExp.escape(this.value), 'i')
var $found = $h4s.filter(function () {
return regex.test($(this).text())
}).closest('.media').show();
$medias.not($found).hide()
} else {
$medias.show();
}
});
Demo: Fiddle
Modified the answer to this
var filter = this.value.toLowerCase(); // no need to call jQuery here
$('.device').each(function() {
/* cache a reference to the current .device (you're using it twice) */
var _this = $(this);
var title = _this.find('h3').text().toLowerCase();
/*
title and filter are normalized in lowerCase letters
for a case insensitive search
*/
if (title.indexOf(filter) < 0) {
_this.hide();
}
else if(filter == ""){
_this.show();
}
else{
_this.show();
}
});
});
Try this -
if ($('.media-body > h4:contains('+filter+')',this).length === 0) {
$(this).css("display","none");
}
This is wrong:
if ($('this > .media-body > h4:contains(filter)').length === 0) {
You should do like this:
if ($(this).find(' > .media-body > h4:contains('+filter+')').length === 0) {
Or like this:
if ($(' > .media-body > h4:contains('+filter+')', this).length === 0) {
You need to use .children() as well as concatenate your filter
variable using +
, so use:
if ($(this).children('.media-body > h4:contains(' + filter +')').length === 0) {
$(this).css("display","none");
}
instead of:
if ($('this > .media-body > h4:contains(filter)').length === 0) {
$(this).css("display","none");
}
example here
$('#filter').keyup(function () {
var filter = $("#filter").val();
$('.media').each(function() {
$(this).find("h4:not(:contains('" + filter + "'))").hide();
$(this).find("h4:contains('" + filter + "')").show();
});
});
You can simplify this code to:
$('#filter').keyup(function () {
// create a pattern to match against, in this one
// we're only matching words which start with the
// value in #filter, case-insensitive
var pattern = new RegExp('^' + this.value.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1"), 'i');
// hide all h4's within div.media, then filter
$('div.media h4').hide().filter(function() {
// only return h4's which match our pattern
return !!$(this).text().match(pattern);
}).show(); // show h4's which matched the pattern
});
Here's a fiddle
Credit to this answer for the expression to escape special characters in the value.
You can use this code.
$('#filter').keyup(function () {
var filter = this.value.toLowerCase();
$('.media').each(function () {
var _this = $(this);
var title = _this.find('h1').text().toLowerCase();
if (title.indexOf(filter) < 0) {
_this.hide();
}
if (title.indexOf(filter) == 0) {
_this.show();
}
});
});