Hey Barry,
I had a look at your fiddle yesterday - the code is a little bit busy, so I thought I’d have a go at refactoring it to get it working and to make it a little easier to maintain/work with.
Here’s my fiddle: http://jsfiddle.net/3pefkgm8/1/
I’ll briefly step through what the code is doing:
$(".hit").click(updateEventList);
I’ve moved the click handler code to a separate function (I’ll explain why in a minute):
function updateEventList() {
var cats = getSelectedCategories();
renderSelectedCategories(cats);
showEvents(cats);
}
This function basically gets the selected categories (as an array) from the checkboxes, and passes them to renderSelectedCategories()
, which adds the category name and close button to the UL, and showEvents()
, which is responsible for updating the events that get displayed.
function getSelectedCategories() {
return $('.checkit:checked').map(function(checkbox) {
return this.id;
}).get();
}
This function gets all the checked checkboxes, and then loops over them with map()
.
If you’re not familiar with map, it allows you to loop over a collection and return a value for each item - those values are then returned as a new collection. Here I’m using it to get an array of checkbox IDs from the array of checkbox DOM elements.
It’s necessary to call get()
on the result to transform it from a jQuery collection back to a regular JS array.
function renderSelectedCategories(categories) {
$list.empty();
categories.forEach(function(cat) {
$list.append(
'<li><a href="#">' +
cat + '</a><button class="closebutton" value="' +
cat + '">X</button></li>'
);
});
}
This function is similar to the code you had before, but it’s no longer necessary to check for checked values, as we’re already passing in an array of the categories we want to be displayed.
function showEvents(categories) {
$('.event-spot').hide();
categories.forEach(function(cat){
$('.'+cat).show();
});
}
This is pretty straightforward - it just hides all of the events, then loops over the selected categories, calling show()
on each one.
Finally, we just need to modify the close button handler slightly:
$list.on('click', '.closebutton', function () {
var b = this.value;
$("#filtered-tags div:contains('" + b + "')").remove();
$('label:contains("' + b + '")').find('.checkit').prop('checked', false);
updateEventList();
});
The important thing here is that I’ve added a call to updateEventList()
(hence why it’s a separate function) to trigger re-rendering when a category is removed.
On a separate note, is there any reason why you’re having users click a submit button and close buttons to update the selected categories? You could just have the whole thing react to checkbox changes, which I think would give you a cleaner interface.
I’ve made a quick fiddle to show you what I mean: http://jsfiddle.net/n6vLc29t/1/
Doing it that way allows you to remove about half the code.