Džuris
Džuris

Reputation: 2234

Filter nested div's with jquery

This is the html structure I have:

<div class="day">
    <div class="date">
        ...
    </div>
    <div class="event-container">
        <div class="event">...</div>
        <div class="event">...</div>
        ...
        <div class="event">...</div>
    </div>
</div>

I want to filter this structure by contents of .event. If any of the words in search query are not present in .event element, it must be hidden. If all .events in an .event-container are hidden, whole .day must be hidden.

Here is my attempt:

var terms = query.split(" ");

$('.day').each(function() {           //iterate over days
    var matches = false;              //does the day contain a valid event?

    $(this).find('.event').each(function() {   //iterate over events of this day
        var evMatches = true;         //does this event contain all terms?

        $.each(terms, function (index, term) {  //iterate over terms
            if ($(this).text().search(new RegExp(term, "i")) < 0)
                evMatches = false;    //if any term isn't found, element is invalid
        });

        if (evMatches)   //if event contained query
        {
            matches = true;  //day contains valid event
            $(this).show();
        }
        else
            $(this).hide();

    });

    if (matches)  //if day contains valid event
        $(this).show();
    else
        $(this).hide();
});

I am getting "Uncaught RangeError: Maximum call stack size exceeded".

I believe I am doing something wrong in $.each(terms, ...) or $(this).find('event-entry').each(...) because I don't understand those statements well enough, just trying to put this together from examples and jquery docs.

Upvotes: 0

Views: 295

Answers (1)

charlietfl
charlietfl

Reputation: 171669

this isn't what you think it is inside the loop of terms. It has a new context from the each that iterates elements

You can't use this within an each loop that iterates an array of strings.

When you have nested loops store any this references so you know which this you are dealing with.

Also try to store values that don't change so you don't have to look the same thing up many many times

$('.day').each(function() {          
    var matches = false;             

   var $day = $(this); // store `$(this)` reference

    $day.find('.event').each(function() {   
        var evMatches = true;         

        var $event = $(this), eventText = $event.text();

        $.each(terms, function (index, term) {  
             // use stored text value instead of looking it up each time
            if (eventText.search(new RegExp(term, "i")) < 0)
                evMatches = false;    
        });

        if (evMatches)   //if event contained query
        {
            matches = true;  //day contains valid event
            $event.show();
        }
        else
            $event.hide();

    });

    if (matches)  //if day contains valid event
        $day.show();
    else
       $day.hide();
});

Upvotes: 1

Related Questions