Intersection of two collections of nodes with jQuery

Asked

Viewed 66 times

2

I was trying to create a pseudo-search function by filtering the results of Hugo’s taxonomy that nay recursion for all nodes or, rather, related terms with each other, more or less like this:

|-\ Category 1
  |-\ Subcategory 1
    |-\ Item 1
    |-\ Item 2
    |-\ Item 3
|-\ Category 2
  |-\ Item 1
    |-\ Category 1
      |-\ Subcategory
  |-\ Item 2
    |-\ Category 1
      |-\ Subcategory
  |-\ Item 3
    |-\ Category 1
      |-\ Subcategory

In fact, it returns something more or less like this:

|-\ Category 1
  |-\ Subcategory 1
    |-\ Item 1
    |-\ Item 2
    |-\ Item 3
|-\ Category 2
  |-\ Subcategory 2
    |-\ Item 1
    |-\ Item 2
  |-\ Subcategory 3
    |-\ Item 3

With that in mind, I added data Attributes in all the <li> so I could get nodes to marry with each condition chosen in a set of menus dropdown individually:

$( document ).ready( function() {
  
  /**
   * Aqui seria, na verdade, jQuery.val() sobre os menus dropdwn existentes
   */
  var c1   = 'category 1';
  var c2   = 'category 2';

  var nodes = $( '#taxonomy' );
  
  var terms  = [];

  $.each( nodes.find( 'ul li' ), function() {
      
    var term = $( this ).attr( 'data-term' );

    // Filtrando termos desnecessários
    
    if( $.inArray( term, [ 'category 1', 'category 2', 'subcategory 1', 'subcategory 2', 'subcategory 3' ] ) == -1 ) {
      terms.push( term );
    }
    
  });

  /**
   * As linhas a seguir, na verdade, estão condicionadas ao valor do dropdown
   * manualmente setado acima não ser o valor padrão, caso no qual não haveria filtragem
   */
  var category1 = [];

  $.each( nodes.find( 'li[data-term="' + c1 + '"] ul li' ), function() {
    category1.push( $( this ).attr( 'data-term' ) );
  });
  
  terms = $( terms ).filter( category1 );
  
  /**
   * Assim como acima
   */
  var category2 = [];

  $.each( nodes.find( 'li[data-term="' + c2 + '"] ul li' ), function() {
    category2.push( $( this ).attr( 'data-term' ) );
  });
  
  terms = $( terms ).filter( category2 );
  
  /**
   * Separado porque a linha acima estaria dentro de um IF
   */
  terms = jQuery.unique( terms );
  
  // Fazendo a interseção

  nodes = nodes.find( 'li' ).filter( function() {
    return ( $.inArray( $( this ).attr( 'data-term' ), terms ) != -1 );
  });
  
  console.log( terms );
  console.log( nodes )
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="taxonomy">

  <li data-term="category 1">
    Categoria 1

    <ul>


      <li data-term="subcategory 1">

        Subcategoria 1

        <ul>

          <li data-term="Item #1">
            <a href="#">Item #1</a>
          </li>

          <li data-term="Item #2">
            <a href="#">Item #2</a>
          </li>

        </ul>

      </li>

      <li data-term="subcategory 2">

        Subcategoria 2


        <ul>

          <li data-term="Item #3">
            <a href="#">Item #3</a>
          </li>

          <li data-term="Item #4">
            <a href="#">Item #4</a>
          </li>

          <li data-term="Item #5">
            <a href="#">Item #5</a>
          </li>

        </ul>

      </li>

    </ul>
  </li>


  <li data-term="category 2">
    Categoria 2

    <ul>


      <li data-term="subcategory 3">

        Subcategoria 3


        <ul>

          <li data-term="Item #4">
            <a href="#">Item #4</a>
          </li>
          
          <li data-term="Item #6">
            <a href="#">Item #6</a>
          </li>

          <li data-term="Item #7">
            <a href="#">Item #7</a>
          </li>

        </ul>

      </li>

    </ul>
  </li>

</ul>

For some reason the code generates (a lot of) script error(s) in the editor inline, then I’ll leave a Fiddle.

I modified a lot based on the previous review, well against taste, and now compare with jQuery.inArray(), verbatim.

Opening the browser console you can see that first I filter for the first category and then for the second and this returns only the Item #4.

It works, it’s not ideal, but it works.

However, because it is a taxonomy, eventually the terms will repeat. I managed to reproduce a single repetition in this code fragment.

Same as the array terms is clean, without repetitions, the collection nodes keeps both <li> of Item #4 because they both have data-Attributes valid in the scope of filtration.

And I can’t remove that duplicate knot, even with that approach that I found.

Any idea?

  • I guess now it will ^_^

No answers

Browser other questions tagged

You are not signed in. Login or sign up in order to post.