I am currently using the list.js plugin along with it's filter extension to produce a search results page that allows the user to filter down the end results to make it easier for them to find exactly what they are looking for.
I have been using their API to try and come up with a solution but in all honesty it is a little dated and not sure when it was last updated.
http://www.listjs.com/docs/list-api
My code is as follows:
HTML
<div id="search-results">
<div class="col-md-3">
<div class="panel panel-warning">
<div class="panel-heading">Filters</div>
<div class="panel-body">
<div class="search-filter">
<ul class="list-group">
<li class="list-group-item">
<div class="list-group-item-heading">
<h4>Filter Options</h4>
</div>
</li>
<li class="list-group-item">
<div class="nameContainer">
<h5 class="list-group-item-heading">Name</h5>
</div>
</li>
<li class="list-group-item">
<div class="typeContainer">
<h5 class="list-group-item-heading">Type</h5>
</div>
</li>
<li class="list-group-item">
<div class="difficultyContainer">
<h5 class="list-group-item-heading">Difficulty</h5>
</div>
</li>
<li class="list-group-item">
<label>Tour contains</label>
<input class="search form-control" placeholder="Search" />
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="col-md-9">
<div class="panel panel-primary">
<div class="panel-heading">Results</div>
<div class="list panel-body">
<div class="package well">
<div class="name">Niagra Falls</div>
<div class="type hidden">Boat Trip</div>
<div class="difficulty">Relaxed</div>
</div>
<div class="package well">
<div class="name">Pyramids</div>
<div class="type hidden">History Holiday</div>
<div class="difficulty">Relaxed</div>
</div>
<div class="package well">
<div class="name">Great Barrier Reef</div>
<div class="type hidden">Snorkling Holiday</div>
<div class="difficulty">Dangerous</div>
</div>
<div class="package well">
<div class="name">Boar Hunting</div>
<div class="type hidden">Hunting Trip</div>
<div class="difficulty">Active</div>
</div>
<div class="package well">
<div class="name">Thames Cruise</div>
<div class="type hidden">Cruise</div>
<div class="difficulty">Easy</div>
</div>
</div>
<ul class="pagination"></ul>
</div>
</div>
</div>
Javascript
var options = {
valueNames: ['name', 'type', 'difficulty'],
page: 3,
plugins: [
ListPagination({})
]
};
var userList = new List('search-results', options);
var updateList = function () {
var name = new Array();
var type = new Array();
var difficulty = new Array();
$("input:checkbox[name=name]:checked").each(function () {
name.push($(this).val());
});
$("input:checkbox[name=type]:checked").each(function () {
type.push($(this).val());
});
$("input:checkbox[name=difficulty]:checked").each(function () {
difficulty.push($(this).val());
});
var values_type = type.length > 0 ? type : null;
var values_name = name.length > 0 ? name : null;
var values_difficulty = difficulty.length > 0 ? difficulty : null;
userList.filter(function (item) {
return (_(values_type).contains(item.values().type) || !values_type)
&& (_(values_name).contains(item.values().name) || !values_name)
&& (_(values_difficulty).contains(item.values().difficulty) || !values_difficulty)
});
}
userList.on("updated", function () {
$('.sort').each(function () {
if ($(this).hasClass("asc")) {
$(this).find(".fa").addClass("fa-sort-alpha-asc").removeClass("fa-sort-alpha-desc").show();
} else if ($(this).hasClass("desc")) {
$(this).find(".fa").addClass("fa-sort-alpha-desc").removeClass("fa-sort-alpha-asc").show();
} else {
$(this).find(".fa").hide();
}
});
});
var all_type = [];
var all_name = [];
var all_difficulty = [];
updateList();
_(userList.items).each(function (item) {
all_type.push(item.values().type)
all_name.push(item.values().name)
all_difficulty.push(item.values().difficulty)
});
_(all_type).uniq().each(function (item) {
$(".typeContainer").append('<label><input type="checkbox" name="type" value="' + item + '">' + item + '</label>')
});
_(all_name).uniq().each(function (item) {
$(".nameContainer").append('<label><input type="checkbox" name="name" value="' + item + '">' + item + '</label>')
});
_(all_difficulty).uniq().each(function (item) {
$(".difficultyContainer").append('<label><input type="checkbox" name="difficulty" value="' + item + '">' + item + '</label>')
});
$(document).off("change", "input:checkbox[name=type]");
$(document).on("change", "input:checkbox[name=type]", updateList);
$(document).off("change", "input:checkbox[name=name]");
$(document).on("change", "input:checkbox[name=name]", updateList);
$(document).off("change", "input:checkbox[name=difficulty]");
$(document).on("change", "input:checkbox[name=difficulty]", updateList);
I've also created a working example on Codepen.
http://codepen.io/JasonEspin/pen/bdajKo
What I wish to achieve is for some packages, they may have multiple type values such as:
<div class="package well">
<div class="name">Niagra Falls</div>
<div class="type hidden">Boat Trip</div>
<div class="type hidden">Other trip type</div>
<div class="difficulty">Relaxed</div>
</div>
So in this situation, I would expect my filter to detect that there is a type of Boat Trip and Other trip type and display these options as a filter option. If either is selected, this package is then returned. However, it seems to ignore the second type.
I have even tried it like this as I expected it to act like an array but this was not the case. It just mashed the two items together to create a random option.
<div class="package well">
<div class="name">Niagra Falls</div>
<div class="type hidden"><div>Boat Trip</div><div>Other Trip Type</div> </div>
<div class="difficulty">Relaxed</div>
</div>
So, does anyone have any ideas how I can adapt my code to accept multiple options? My ideal scenario would be for me to attach a number of departure dates to each package and enable the user to filter by these departure dates.
Any help would be greatly appreciated as I believe the issue may be with my Lodash code but as it is my first time using Lodash i'm a little bit unsure of what it is actually doing due to its unusual syntax.
This was actually fairly straightforward to implement using a combination of string.split() definitions and array concatenations.
HTML
<div id="search-results">
<div class="col-md-3">
<div class="panel panel-warning">
<div class="panel-heading">Filters</div>
<div class="panel-body">
<div class="search-filter">
<ul class="list-group">
<li class="list-group-item">
<div class="list-group-item-heading">
<h4>Filter Options</h4>
</div>
</li>
<li class="list-group-item">
<div class="nameContainer">
<h5 class="list-group-item-heading">Name</h5>
</div>
</li>
<li class="list-group-item">
<div class="typeContainer">
<h5 class="list-group-item-heading">Type</h5>
</div>
</li>
<li class="list-group-item">
<div class="difficultyContainer">
<h5 class="list-group-item-heading">Difficulty</h5>
</div>
</li>
<li class="list-group-item">
<label>Tour contains</label>
<input class="search form-control" placeholder="Search" />
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="col-md-9">
<div class="panel panel-primary">
<div class="panel-heading">Results</div>
<div class="list panel-body">
<div class="package well">
<div class="name">Niagra Falls</div>
<div class="type hidden">Boat Trip|Other Trip|My Trip</div>
<div class="difficulty">Relaxed</div>
</div>
<div class="package well">
<div class="name">Pyramids</div>
<div class="type hidden">History Holiday</div>
<div class="difficulty">Relaxed</div>
</div>
<div class="package well">
<div class="name">Great Barrier Reef</div>
<div class="type hidden">Snorkling Holiday</div>
<div class="difficulty">Dangerous</div>
</div>
<div class="package well">
<div class="name">Boar Hunting</div>
<div class="type hidden">Hunting Trip</div>
<div class="difficulty">Active</div>
</div>
<div class="package well">
<div class="name">Thames Cruise</div>
<div class="type hidden">Cruise</div>
<div class="difficulty">Easy</div>
</div>
</div>
<ul class="pagination"></ul>
</div>
</div>
</div>
JAVASCRIPT
var options = {
valueNames: ['name', 'type', 'difficulty'],
page: 3,
plugins: [
ListPagination({})
]
};
var userList = new List('search-results', options);
var updateList = function () {
var name = new Array();
var type = new Array();
var difficulty = new Array();
$("input:checkbox[name=name]:checked").each(function () {
name.push($(this).val());
});
$("input:checkbox[name=type]:checked").each(function () {
if($(this).val().indexOf('|') > 0){
var arr = $(this).val().split('|');
var arrayLength = arr.length;
type = type.concat(arr);
console.log('Multiple values:' + arr);
}else{
type.push($(this).val());
console.log('Single values:' + arr);
}
});
$("input:checkbox[name=difficulty]:checked").each(function () {
difficulty.push($(this).val());
});
var values_type = type.length > 0 ? type : null;
var values_name = name.length > 0 ? name : null;
var values_difficulty = difficulty.length > 0 ? difficulty : null;
userList.filter(function (item) {
var typeTest;
var nameTest;
var difficultyTest;
if(item.values().type.indexOf('|') > 0){
var typeArr = item.values().type.split('|');
for(var i = 0; i < typeArr.length; i++){
if(_(values_type).contains(typeArr[i])){
typeTest = true;
}
}
}
return (_(values_type).contains(item.values().type) || !values_type || typeTest)
&& (_(values_name).contains(item.values().name) || !values_name)
&& (_(values_difficulty).contains(item.values().difficulty) || !values_difficulty)
});
}
userList.on("updated", function () {
$('.sort').each(function () {
if ($(this).hasClass("asc")) {
$(this).find(".fa").addClass("fa-sort-alpha-asc").removeClass("fa-sort-alpha-desc").show();
} else if ($(this).hasClass("desc")) {
$(this).find(".fa").addClass("fa-sort-alpha-desc").removeClass("fa-sort-alpha-asc").show();
} else {
$(this).find(".fa").hide();
}
});
});
var all_type = [];
var all_name = [];
var all_difficulty = [];
updateList();
_(userList.items).each(function (item) {
if(item.values().type.indexOf('|') > 0){
var arr = item.values().type.split('|');
all_type = all_type.concat(arr);
}else{
all_type.push(item.values().type)
}
all_name.push(item.values().name)
all_difficulty.push(item.values().difficulty)
});
_(all_type).uniq().each(function (item) {
$(".typeContainer").append('<label><input type="checkbox" name="type" value="' + item + '">' + item + '</label>')
});
_(all_name).uniq().each(function (item) {
$(".nameContainer").append('<label><input type="checkbox" name="name" value="' + item + '">' + item + '</label>')
});
_(all_difficulty).uniq().each(function (item) {
$(".difficultyContainer").append('<label><input type="checkbox" name="difficulty" value="' + item + '">' + item + '</label>')
});
$(document).off("change", "input:checkbox[name=type]");
$(document).on("change", "input:checkbox[name=type]", updateList);
$(document).off("change", "input:checkbox[name=name]");
$(document).on("change", "input:checkbox[name=name]", updateList);
$(document).off("change", "input:checkbox[name=difficulty]");
$(document).on("change", "input:checkbox[name=difficulty]", updateList);
Codepen