Reputation: 11207
http://jsfiddle.net/nicktheandroid/QhL2M/ (type "bye" into the input box")
Purpose of the script: Each li
contains tag words in it. When the user types one of these tag words in the input
box, it will hide all of the li
's that do not contain that tag word. Multiple words may be typed into the input
, if more than 1 li
's tag words matches any of the words in the input
, then they are shown. So it's basically a filtered list that allows for multiple words, and shows all matching li
's that contain any of the words typed into the input
. It only matches whole words, not partial words, and it should only update the list of matches when another whole word has been matched(when multiple words). This is the goal.
My problem is that it's incorrectly reporting that there's a match in this piece of code:
if (matches == true) {
alert('matched true') //incorrectly reports
} else {
alert('matched false') //incorrectly reports
}
while this piece of code is reporting correctly:
if (regex.test($(this).text()) === true) {
matches = true;
// alert('tis true') //correctly reports
} else {
matches = false;
// alert('tis false') //correctly reports
}
Why is it not reporting correctly? (correctly, as in: what I want it to report)
If anyone is good enough at Javascript to see what i'm trying to do and knows how to help me, that'd be fantastic. I'm trying to work my way through this because there's just a few things left to change.
Upvotes: 2
Views: 83
Reputation: 150040
I think the problem is that you are looping through all of the list items with:
$("#list li").each(function() {
and then within each iteration you loop through the list of words with:
$.each(inputWords, function(i, a_filter) {
and then in the inner loop you again process all li elements with:
var containing = $('#list li').filter(function () {
So then in the inner part you're getting confused about just what you're dealing with. I think what you need to do is loop through each element, testing if it has any matches to the input word list, and then hide or show that element as appropriate. Something like this:
var inputWords = inputValue.toLowerCase().split(/[\s,]+/);
$("#list li").each(function() {
var matches = false,
$currentElement = $(this);
$.each(inputWords, function(i, a_filter) {
if ($.trim(a_filter)==="") return; // skip blank items
var regex = new RegExp('\\b(' + a_filter + ')(s|es|\'s)?\\b', 'i');
if (regex.test($currentElement.text())) {
matches = true;
return false; // return false breaks out of the $.each
// (no need to continue once a match is found)
}
});
if (matches)
$currentElement.slideDown(400);
else
$currentElement.slideUp();
});
Working demo: http://jsfiddle.net/QhL2M/19/
EDIT: also the way you were splitting the input word list didn't work for me:
var inputWords = $('.filterinput').text().toLowerCase().split(/[\s,]+/);
// I've changed that to
var inputWords = inputValue.toLowerCase().split(/[\s,]+/);
You don't want to use .text()
on an input, and in any case inputValue
was already initialised earlier to hold the text of that input. My code above and demo have been updated.
Upvotes: 2
Reputation: 8482
Let me know if this is what you try to accomplish (jsFiddle example):
(function($) {
function fiKeyup() {
var inputValue = $(this).val();
if (inputValue.length > 2) {
var inputWords = inputValue.split(/[\s,]+/ig);
var containing = $('#list li').filter(function () {
var ret = false;
var text = $(this).text().toLowerCase();
$.each(inputWords, function(i, a_filter) {
var regex = new RegExp('\\b(' + a_filter + ')(s|es|\'s)?\\b');
if(regex.test(text)) {
return !(ret = true);
}
});
return ret;
});
$('#list li').not(containing).slideUp();
} else {
$('#list li').slideDown();
}
return false;
};
var timeout;
$('.filterInput').keyup(function() {
var that = this;
clearTimeout(timeout);
timeout = setTimeout(function() {
fiKeyup.call(that);
}, 500);
});
}(jQuery));
Upvotes: 0