Skip to content
Advertisement

Hide a parent div when filtering

I have timeline with a filter that allows users to show/hide events. The way the CSS is formatted requires that the entire parent (“.timeline”) be hidden if no matches were made in the filter, otherwise there’s a border that remains visible:

JSFiddle to see example

<form>
  <p>Topics</p>
  <input type="checkbox" name="topic" value="topic1" id="topic1"><label for="topic1">Topic 1</label>
  <input type="checkbox" name="topic" value="topic2" id="topic2"><label for="topic2">Topic 2</label>
  <input type="checkbox" name="topic" value="topic3" id="topic3"><label for="topic3">Topic 3</label>
</form>

<form>
<p>
Format
</p>
  <input type="checkbox" name="format" value="format1" id="format1"><label for="format1">Format 1</label>
  <input type="checkbox" name="format" value="format2" id="format2"><label for="format2">Format 2</label>
</form>

<br>

<div class="timeline">
    <div class="event" data-id="event1"
        data-category="topic1 format1">
        Date &amp; Time<br>
        Content
    </div>
    <div class="event" data-id="event2"
        data-category="topic2 format2">
        Date &amp; Time<br>
        Content
    </div>
</div>
    var $filterCheckboxes = $('input[type="checkbox"]');
    $filterCheckboxes.on('change', function () {
        var selectedFilters = {};
        $filterCheckboxes.filter(':checked').each(function () {
            if (!selectedFilters.hasOwnProperty(this.name)) {
                selectedFilters[this.name] = [];
            }
            selectedFilters[this.name].push(this.value);
        });
        var $filteredResults = $('.event');
        $.each(selectedFilters, function (name, filterValues) {
            $filteredResults = $filteredResults.filter(function () {
                var matched = false,
                    currentFilterValues = $(this).data('category').split(' ');
                $.each(currentFilterValues, function (_, currentFilterValue) {
                    if ($.inArray(currentFilterValue, filterValues) != -1) {
                        matched = true;
                        return false;
                    }
                });
                return matched;
            });
        });
        $('.event').hide().filter($filteredResults).show();
    });

I tried including $('.timeline').hide().filter($filteredResults).show(); to the last line, which works at first, but then when you uncheck boxes none of the elements reappear.

Is there some sort of if/then statement I should be using? Like, if matched = false { document.getElementsByClassName("timeline").style.display = "none"; };

Advertisement

Answer

This is the Javascript you need

    var $filterCheckboxes = $('input[type="checkbox"]');
    $filterCheckboxes.on('change', function () {
        $('.timeline').show();
        var selectedFilters = {};
        $filterCheckboxes.filter(':checked').each(function () {
            if (!selectedFilters.hasOwnProperty(this.name)) {
                selectedFilters[this.name] = [];
            }
            selectedFilters[this.name].push(this.value);
        });
        var $filteredResults = $('.event');
        $.each(selectedFilters, function (name, filterValues) {
            $filteredResults = $filteredResults.filter(function () {
                var matched = false,
                    currentFilterValues = $(this).data('category').split(' ');
                $.each(currentFilterValues, function (_, currentFilterValue) {
                    if ($.inArray(currentFilterValue, filterValues) != -1) {
                        matched = true;
                        return false;
                    }
                });
                return matched;
            });
        });
        $('.event').hide().filter($filteredResults).show();
        var all_hidden = true;
        $('.event').each(function (index) {
                if ($(this).is(":visible")) {
                all_hidden = false;
            }
        });
        if (all_hidden) {
            $('.timeline').hide();
        }
    });

I added an if statement at the end to check if all events are hidden, by looping through all events and checking their visibility with if ($(this).is(":visible")). If they are all hidden it hides the timeline, if not the timeline stays put.

At the start of your function I added a line to make sure the timeline is visible before starting the visibility loop or else all events will be hidden and the code won’t work as $(this).is(":visible") will always return false.

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement