So I already have a search filter in place but now I want it to have the ability to combine
search phrases. Below is the code that generates a list on page.
<div class="sortable2">
<ul class="connectedSortable links loadfiles" id="loadfiles">
<?php
foreach ($result as $value) {
list($classname, $origin, $name) = explode('_', $value);
$classname = trim($classname, '[]');
$origin = trim($origin, '[]');
$name = pathinfo($name, PATHINFO_FILENAME);
echo "<li class='audiofile " . $name . " " . $classname . "' id='" . $value . "'>".
"<a class='btn_clone fa fa-clone' aria-hidden='true' id='' onclick='repeat(event)' title='Clone'> </a>".
"<a class='btn_addto fa fa-arrow-up' aria-hidden='true' id='' onclick='addto(event)' title='Add to playlist'> </a>".
"<a class='btn_removefrom fa fa-trash' aria-hidden='true' id='' onclick='removefrom(event)' title='Remove element'> </a>".
"<span class='audioclass'>" . $classname . "</span>".
"<a href='" . $directoryname . "/" . $value . "' target='_blank'>".
"<img src='images/avatars/" . $classname . ".jpg'>".
"<div class='audiotext'>".
"<span class='audiotitle'>" . $name . "</span>".
"<span class='audioorigin'>" . $origin . "</span>".
"</div>".
"</a>".
"</li>";
}
?>
</ul>
</div>
This list basically generates blocks like:
frank
hello how are you
link to audio file
william
i am fine
link to audio file
frank
what?
link to audio file
The filtering is done by this code
$('#global_filter').keyup(function() {
var col_name = $(this).attr('class');
var search_val = $(this).val().toLowerCase();
$('.' + col_name).closest('#loadfiles > li').css('display', 'none');
$('.' + col_name).each(function() {
var val = $(this).text();
console.log($(this).text(), 'text');
if(val.toLowerCase().indexOf(search_val) >= 0) {
$(this).closest('#loadfiles > li').css('display', 'block');
}
});
});
which works together with
<div class="input">
<h4>Search field</h4>
<div class="all_all" id="filter_global">
<div align="left"><input type="text" name="global_filter" id="global_filter" class="audiofile"></div>
<div align="left"><input type="checkbox" name="global_regex" id="global_regex" ></div>
<div align="left"><input type="checkbox" name="global_smart" id="global_smart" checked></div>
</div>
</div>
How can I change the filter to allow for multiple search phrases with [AND]
and maybe also [OR]
if possible. So the user can type in for instance:
frank [and] hello
and this will then return
frank
hello how are you
link to audio file
Although this project appears to have not been updated in quite some time, you can probably utilize parts of it to work for your needs: https://github.com/bloomtime/boolean-expression-js
$('#global_filter').keyup(function() {
// Init
var col_name = $(this).attr('class');
var search_val = $(this).val().toLowerCase();
// Setup boolean expression
var parsed = new Expression(search_val);
$('.' + col_name).closest('#loadfiles > li').css('display', 'none');
$('.' + col_name).each(function() {
var val = $(this).text();
if(parsed.test(val) == true) {
$(this).closest('#loadfiles > li').css('display', 'block');
}
});
});
It utilizes ReParse behind the scenes to be able to split your search on pre-defined grammar and then test for matching.
If you are really trying to keep it super simple, it may not be extremely flexible, but you could try this approach. This basically gives the ability to search using [AND]
or using [OR]
but not both. Could probably use some refactoring as I just quickly whipped it up.
$('#global_filter').keyup(function() {
// Init
var col_name = $(this).attr('class');
var search_val = $(this).val().toLowerCase();
var columns = $('.' + col_name);
// If doing a boolean AND
if (search_val.toLowerCase().indexOf('[and]') >= 0) {
// Get search parts
var parts = search_val.split('[and]');
$(columns).each(function(columnIndex, column) {
var val = $(column).text();
var matched = true;
$(parts).each(function(partIndex, part) {
// Since AND is inclusive, failing to match should assume this column is a non-match
if (val.toLowerCase().indexOf(part.toLowerCase()) < 0) {
matched = false;
// Break early
return false;
}
});
if (matched) {
$(column).closest('#loadfiles > li').css('display', 'block');
}
});
}
// If doing a boolean OR
else if (search_val.toLowerCase().indexOf('[or]') >= 0) {
// Get search parts
var parts = search_val.split('[or]');
$(columns).each(function(columnIndex, column) {
var val = $(column).text();
var matched = false;
$(parts).each(function(partIndex, part) {
// With OR, if ANY of the parts match then it is a match
if (val.toLowerCase().indexOf(part.toLowerCase()) >= 0) {
matched = true;
// Break early
return false;
}
});
if (matched) {
$(column).closest('#loadfiles > li').css('display', 'block');
}
});
} else {
var val = $(this).text();
if(val.toLowerCase().indexOf(search_val) >= 0) {
$(column).closest('#loadfiles > li').css('display', 'block');
}
}
});