CMS Development

Aaaaandrei
Participante

Filtering HubDB elements with HTML Checkboxes

resolver

Hi,

 

I'm working on creating a video directory, using HubDB to store the details for each video.

I'm looking for a way where a user can filter the results iterated from HubDB by interacting with HTML checkboxes like this:

Capture.PNG

The issue I'm having at the moment is that I don't see a straightforward way to connect the user interacting with checkboxes and the HubDB filter queries.

I tried using javascript for if conditionals and use HubL code inside, but it seems that the HubL code regardless if it passes the logic test or not.  I have since removed that and I am a little stuck. 

Would greatly appreciate some help. Thanks!

I've included the HTML+HubL code below:

 

{% set nofilter = hubdb_table_rows(1036506)%}
<div class="hubdb-outer-wrapper">Level-of-interest
  <div class="hubdb-content-wrapper">
  <div class="hubdb-left-column">
    Level of Study
    <div class="checkboxes">
     <input id="emba-box" type="checkbox" name="Level-of-interest-emba" value="Executive+MBA">EMBA
     <input id="mba-box" type="checkbox" name="Level-of-interest-mba" value="MBA" onclick="mbaFilter()">MBA<br>
     <input id="masters-box" type="checkbox" name="Level-of-interest-masters" value="Masters" checked>Masters<br>
    </div>
    Region of Study
    <div class="checkboxes">
     <input id="china-box" type="checkbox" name="region-study-china" value="China">China
     <input id="india-box" type="checkbox" name="region0study-india" value="India">India<br>
     <input id="africa-box" type="checkbox" name="region-study-africa" value="Africa">Africa<br>
      </div>
   </div>
   <div class="hubdb-right-column">
  {% for row in nofilter %}
      <div class="hubdb-box">
       <div class="hubdb-image">
          <img src="{{ row.thumbnail.url }}">
        </div>
        <div class="hubdb-title">
          {{ row.name }}
        </div>
        <div class="hubdb-description">
          {{ row.description }}
        </div>
     </div>
     {% endfor %}
   </div>
  </div>
</div>
0 Me gusta
1 Soluciones aceptada
Kevin-C
Solución
Experto reconocido | Partner
Experto reconocido | Partner

Filtering HubDB elements with HTML Checkboxes

resolver

Hey @Aaaaandrei 

 

Thanks for the reminder message.

Below I've dropped in a basic template code that I built for a POC and learning experience for myself. You'' have to excuse the mess haha.

 

This is purely a JS solution, I might have a HUBL excusive solution that I will continue to look for.

 

I have clarified any comments I had left in the code to help understand what is going on / the thought process.

 

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <title>{{ content.html_title }}</title>
    <meta name="description" content="{{ content.meta_description }}">
    {{ standard_header_includes }}
    
    <style>
      img {
        max-width: 200px;
      }

      .grid {
        display: grid;
        grid-gap: 0;
        grid-template-columns: repeat(auto-fill,minmax(220px,1fr));
      }

      ul {
        padding: 0px;
      }
    </style>
    
  </head>
  <body>
    <form name="filters-form"></form>

    {% if dynamic_page_route_level == 0 %}
    <h1>Gallery - 0</h1><!-- For tracking purpose - remove for production -->
    <div class="grid">

      {% set rows = hubdb_table_rows(1056514) %}
      {% for row in rows %}
      <a class="gallery-1 gallery-card" href="{{ request.path }}/{{ row.hs_path }}" data-filter="{{row.tags}}">
        <img src="{{row.image.url}}" alt="" />
        <h2>{{ row.hs_name }}</h2>
        <p>{{row.tags}}</p>
      </a>
      {% endfor %}
    </div>
    {% endif %}

    {% if dynamic_page_route_level == 1 %}
    <h1>Gallery - 1</h1><!-- For tracking purpose - remove for production -->
    <h2>{{dynamic_page_hubdb_row.hs_name}}</h2>
    {% set rows = hubdb_table_rows(dynamic_page_hubdb_row.hs_child_table_id) %}
    <ul class="grid">
      {% for row in rows %}
      <a class="gallery-1 gallery-card" href="{{ request.path }}/{{ row.hs_path }}" data-filter="{{row.tags}}">
        <img src="{{row.image.url}}" alt="" />
        <h2>{{ row.hs_name }}</h2>
        <p>{{row.tags}}</p>
      </a>
      {% endfor %}
    </ul>
    {% endif %}

    <script>
      $(document).ready(function() {
        var filterValues = [];

        // Get all filters and place into an array
        function getAllFilters() {
          var returnArray = [];
          $('.gallery-card').each( function() {
            var c = $(this).data('filter').split(' ');
            console.log(c);
            returnArray = returnArray.concat(c).unique(); ;
          });
          return returnArray;
        }
        // Prevent duplicates in the filters
        Array.prototype.unique = function() {
          var a = this.concat();
          for(var i=0; i<a.length; ++i) {
            for(var j=i+1; j<a.length; ++j) {
              if(a[i] === a[j])
                a.splice(j--, 1);
            }
          }
          return a;
        };

        // Populate the filters in to the form
        function popFilters(filArray) {
          for (i=0; i<filArray.length; i++) {
            var checkbox = '<label><input type="checkbox" value="' + filArray[i] + '">' + filArray[i] + '</label>';
            $('[name="filters-form"]').append(checkbox);
          }
        }

        // Initialize the filters
        popFilters(getAllFilters());

        // Watch the filters form for changes
        $('form[name="filters-form"]').change(function () {
          // collect array of all "checked" checkboxes
          //var appliedFilters = getFiltersForm();
          // pass array into  filter function
          // function hides and shwos based on arry
          updateUi( getFiltersForm() );
        });

        // Collect the checked filters
        function getFiltersForm() {
          var filters = [];
          $('form[name="filters-form"] input[type="checkbox"]:checked').each( function() {
            var value =$(this).val();
            filters.push(value);
            console.log('filters = ' + filters);
          });
          return filters;
        }

        // Check if values are in an array
        function isInArray(needles, haystack){ 
          for(var i = 0 , len = needles.length; i < len; i++){
            if($.inArray(needles[i], haystack) == -1) return false;
          }
          return true;
        }

        // Update the gallery the UI
        function updateUi(b) {
          if (b.length <=0) {
            $('.gallery-card').show();
          } else {
            $('.gallery-card').each( function() {
              var a = $(this).data('filter').split(' ');
              console.log(isInArray(b,a));
              if ( isInArray(b,a) != true ) {
                $(this).hide();
              } else if ( isInArray(b,a) == true ) {
                $(this).show();
              }
            });
          }
        }

        // NEXT STEPS
        // Add querystring recognition and history API states

      });
    </script>

    {{ standard_footer_includes }}
  </body>
</html>

A few things to note:

- I'm pretty sure this POC uses an Additive Filtering model, it's been some time since I've been in it.

- This was also built for a multi level UI (terminology?), meaning it used nested database tables.

- This uses the html markup as the data source…slaps self on the wrist. This would ideally use JSON produced by HUBL and opperate more like a true micro SPA.

- My POC did not have filter categories as your UI shows, but I'm positive with a little logic this can be solved easily.

- The plan for this piece when in production was to do 2 additional things that aren't included here: 1) Use the history api so the user can use the back and forward  buttons. 2) Use a query string to allow deep linking.

 

 

 

EDIT:

After rereading the initiasl post I'm not positive this was a solution for you, but I hope it at least gets you going in the right direction.

Kevin Cornett - Sr. Solutions Architect @ BridgeRev

Ver la solución en mensaje original publicado

4 Respuestas 4
Kevin-C
Experto reconocido | Partner
Experto reconocido | Partner

Filtering HubDB elements with HTML Checkboxes

resolver

Hey @Aaaaandrei 

 

I did something similar recently! I will have to get back to the code and follow up with the solutions I had come up with.

If in the unlikely scenary you don't hear from me in the nexty few days please message me!

Kevin Cornett - Sr. Solutions Architect @ BridgeRev
Aaaaandrei
Participante

Filtering HubDB elements with HTML Checkboxes

resolver

Thank you Kevin, looking forward to hearing from you!

Cheers,

Andrei

0 Me gusta
Kevin-C
Solución
Experto reconocido | Partner
Experto reconocido | Partner

Filtering HubDB elements with HTML Checkboxes

resolver

Hey @Aaaaandrei 

 

Thanks for the reminder message.

Below I've dropped in a basic template code that I built for a POC and learning experience for myself. You'' have to excuse the mess haha.

 

This is purely a JS solution, I might have a HUBL excusive solution that I will continue to look for.

 

I have clarified any comments I had left in the code to help understand what is going on / the thought process.

 

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <title>{{ content.html_title }}</title>
    <meta name="description" content="{{ content.meta_description }}">
    {{ standard_header_includes }}
    
    <style>
      img {
        max-width: 200px;
      }

      .grid {
        display: grid;
        grid-gap: 0;
        grid-template-columns: repeat(auto-fill,minmax(220px,1fr));
      }

      ul {
        padding: 0px;
      }
    </style>
    
  </head>
  <body>
    <form name="filters-form"></form>

    {% if dynamic_page_route_level == 0 %}
    <h1>Gallery - 0</h1><!-- For tracking purpose - remove for production -->
    <div class="grid">

      {% set rows = hubdb_table_rows(1056514) %}
      {% for row in rows %}
      <a class="gallery-1 gallery-card" href="{{ request.path }}/{{ row.hs_path }}" data-filter="{{row.tags}}">
        <img src="{{row.image.url}}" alt="" />
        <h2>{{ row.hs_name }}</h2>
        <p>{{row.tags}}</p>
      </a>
      {% endfor %}
    </div>
    {% endif %}

    {% if dynamic_page_route_level == 1 %}
    <h1>Gallery - 1</h1><!-- For tracking purpose - remove for production -->
    <h2>{{dynamic_page_hubdb_row.hs_name}}</h2>
    {% set rows = hubdb_table_rows(dynamic_page_hubdb_row.hs_child_table_id) %}
    <ul class="grid">
      {% for row in rows %}
      <a class="gallery-1 gallery-card" href="{{ request.path }}/{{ row.hs_path }}" data-filter="{{row.tags}}">
        <img src="{{row.image.url}}" alt="" />
        <h2>{{ row.hs_name }}</h2>
        <p>{{row.tags}}</p>
      </a>
      {% endfor %}
    </ul>
    {% endif %}

    <script>
      $(document).ready(function() {
        var filterValues = [];

        // Get all filters and place into an array
        function getAllFilters() {
          var returnArray = [];
          $('.gallery-card').each( function() {
            var c = $(this).data('filter').split(' ');
            console.log(c);
            returnArray = returnArray.concat(c).unique(); ;
          });
          return returnArray;
        }
        // Prevent duplicates in the filters
        Array.prototype.unique = function() {
          var a = this.concat();
          for(var i=0; i<a.length; ++i) {
            for(var j=i+1; j<a.length; ++j) {
              if(a[i] === a[j])
                a.splice(j--, 1);
            }
          }
          return a;
        };

        // Populate the filters in to the form
        function popFilters(filArray) {
          for (i=0; i<filArray.length; i++) {
            var checkbox = '<label><input type="checkbox" value="' + filArray[i] + '">' + filArray[i] + '</label>';
            $('[name="filters-form"]').append(checkbox);
          }
        }

        // Initialize the filters
        popFilters(getAllFilters());

        // Watch the filters form for changes
        $('form[name="filters-form"]').change(function () {
          // collect array of all "checked" checkboxes
          //var appliedFilters = getFiltersForm();
          // pass array into  filter function
          // function hides and shwos based on arry
          updateUi( getFiltersForm() );
        });

        // Collect the checked filters
        function getFiltersForm() {
          var filters = [];
          $('form[name="filters-form"] input[type="checkbox"]:checked').each( function() {
            var value =$(this).val();
            filters.push(value);
            console.log('filters = ' + filters);
          });
          return filters;
        }

        // Check if values are in an array
        function isInArray(needles, haystack){ 
          for(var i = 0 , len = needles.length; i < len; i++){
            if($.inArray(needles[i], haystack) == -1) return false;
          }
          return true;
        }

        // Update the gallery the UI
        function updateUi(b) {
          if (b.length <=0) {
            $('.gallery-card').show();
          } else {
            $('.gallery-card').each( function() {
              var a = $(this).data('filter').split(' ');
              console.log(isInArray(b,a));
              if ( isInArray(b,a) != true ) {
                $(this).hide();
              } else if ( isInArray(b,a) == true ) {
                $(this).show();
              }
            });
          }
        }

        // NEXT STEPS
        // Add querystring recognition and history API states

      });
    </script>

    {{ standard_footer_includes }}
  </body>
</html>

A few things to note:

- I'm pretty sure this POC uses an Additive Filtering model, it's been some time since I've been in it.

- This was also built for a multi level UI (terminology?), meaning it used nested database tables.

- This uses the html markup as the data source…slaps self on the wrist. This would ideally use JSON produced by HUBL and opperate more like a true micro SPA.

- My POC did not have filter categories as your UI shows, but I'm positive with a little logic this can be solved easily.

- The plan for this piece when in production was to do 2 additional things that aren't included here: 1) Use the history api so the user can use the back and forward  buttons. 2) Use a query string to allow deep linking.

 

 

 

EDIT:

After rereading the initiasl post I'm not positive this was a solution for you, but I hope it at least gets you going in the right direction.

Kevin Cornett - Sr. Solutions Architect @ BridgeRev
Aaaaandrei
Participante

Filtering HubDB elements with HTML Checkboxes

resolver

Hi @Kevin-C ,

Thanks a lot for sharing this!

While I can't directly apply this, it's really useful to look at your logic and try to extrapolate from here.

Cheers,

Andrei