Skip to content

Instantly share code, notes, and snippets.

@estrattonbailey
Created November 20, 2015 20:45
Show Gist options
  • Save estrattonbailey/8b56e705af1c05b533d0 to your computer and use it in GitHub Desktop.
Save estrattonbailey/8b56e705af1c05b533d0 to your computer and use it in GitHub Desktop.
{% unless filter_options %}
{% capture _filter_options %}
{% for tag in collection.all_tags %}{% if tag contains 'filter-' %}{{ tag | remove: 'filter-' | strip }} {%endif%}{%endfor%}
{% endcapture %}
{% assign filter_options = _filter_options | split: ' ' %}
{% endunless %}
{% assign current_option = 'none' %}
{% capture _filters %}
{% for tag in filter_options %}
{% assign _filter_partials = tag | split: '-' %}
{% assign partial = _filter_partials | first | strip %}
{% if partial != current_option %}{{ partial }} {% endif %}
{% assign current_option = partial %}
{% endfor %}
{% endcapture %}
{% assign filters = _filters | split: ' ' %}
{% for filter in filters %}
{% if filter == 'type' %}
{% unless collection.handle == 'accessories' or collection.handle == 'shirts' %}
{% continue %}
{% endunless %}
{% capture filter_tags %}
{% for option in filter_options %}{% if option contains filter %}{{ option | strip }} {%endif%}{%endfor%}
{% endcapture %}
{% assign filter_tags_array = filter_tags | split: ' ' %}
{% comment %} The following for-loop blocks are duplicated so that the "type" filter is always listed first (if existent) {% endcomment %}
{% comment %}Individual select{% endcomment %}
<div class="collection__filter inline-block align-m">
<div class="js-select-wrapper select-wrapper">
<select class="js-dropdown is-resizeable inline-block h7 font-t-u" placeholder="{{ filter | capitalize }}">
<option disabled selected>{{ filter | capitalize }}</option>
<option>All</option>
{%for tag in filter_tags_array %}
{% comment %}Create default selection (label){% endcomment %}
{% if forloop.first %}
{% assign title_partials = tag | split: '-' %}
{% for partial in title_partials %}
{% if forloop.first %}
{% assign filter_title = partial %}
{% endif %}
{% endfor %}
{% endif %}
{% comment %}Parse out each option{% endcomment %}
{% if tag contains '-' %}
{% assign tag_partial = tag | remove: filter_title | split: '-' %}
{% capture output_tag %}
{% for partial in tag_partial %}{{ partial | capitalize }} {% endfor %}
{% endcapture %}
<option value="{{ output_tag | handleize }}">{{ output_tag }}</option>
{% else %}
{% assign output_tag = tag | remove: filter_title | capitalize %}
<option value="{{ output_tag | handleize }}">{{ output_tag }}</option>
{% endif %}
{%endfor%}
</select>
</div>
</div>
{% endif %}
{% endfor %}
{% for filter in filters limit: 5 %}
{% if filter != 'type' %}
{% capture filter_tags %}
{% for option in filter_options %}{% if option contains filter %}{{ option | strip }} {%endif%}{%endfor%}
{% endcapture %}
{% assign filter_tags_array = filter_tags | split: ' ' %}
{% comment %}Individual select{% endcomment %}
<div class="collection__filter inline-block align-m">
<div class="js-select-wrapper select-wrapper">
<select class="js-dropdown is-resizeable inline-block h7 font-t-u" placeholder="{{ filter | capitalize }}">
<option disabled selected>{{ filter | capitalize }}</option>
<option>All</option>
{%for tag in filter_tags_array %}
{% comment %}Create default selection (label){% endcomment %}
{% if forloop.first %}
{% assign title_partials = tag | split: '-' %}
{% for partial in title_partials %}
{% if forloop.first %}
{% assign filter_title = partial %}
{% endif %}
{% endfor %}
{% endif %}
{% comment %}Parse out each option{% endcomment %}
{% if tag contains '-' %}
{% assign tag_partial = tag | remove: filter_title | split: '-' %}
{% capture output_tag %}
{% for partial in tag_partial %}{{ partial | capitalize }} {% endfor %}
{% endcapture %}
<option value="{{ output_tag | handleize }}">{{ output_tag }}</option>
{% else %}
{% assign output_tag = tag | remove: filter_title | capitalize %}
<option value="{{ output_tag | handleize }}">{{ output_tag }}</option>
{% endif %}
{%endfor%}
</select>
</div>
</div>
{% endif %}
{% endfor %}
@estrattonbailey
Copy link
Author

Collection Filtering Liquid Logic

Shopify collections are filterable by tags. We're taking this one step further by creating categories using the same tags we then use to filter the collection. The syntax looks like this:

filter-<category>-<option>

# e.g.
# filter-collar-button-down

Process

To parse these filters into dropdowns, we're using three steps.

1. Get every tag within the collection

We're only looking for tags that are prefixed with filter-. We grab one at a time, remove the filter- prefix, and capture the resulting tag as a string along with the other collection tags.

{% unless filter_options %}
  {% capture _filter_options %}
    {% for tag in collection.all_tags %}{% if tag contains 'filter-' %}{{ tag | remove: 'filter-' | strip }} {%endif%}{%endfor%}
  {% endcapture %}
  {% assign filter_options = _filter_options | split: ' ' %}
{% endunless %}

2. Split tags into array and remove duplicates

In this snippet, current_option refers to the current tag, so that if a tag is repeated, we only use one instance of it. This process assumes that if two tags are the same, they are listed consecutively. Luckily, this is the case.

{% assign current_option = 'none' %}
{% capture _filters %}
  {% for tag in filter_options %}
    {% assign _filter_partials = tag | split: '-' %}
    {% assign partial = _filter_partials | first | strip %}
    {% if partial != current_option %}{{ partial }} {% endif %}
    {% assign current_option = partial %}
  {% endfor %}
{% endcapture %}

3. Iterate over tags array and create each dropdown

Each dropdown corresponds to the <category> part of the filter-<category>-<option> tag. We've limited the number of dropdowns to six, total.

Note: the type dropdown only appears on "top level" collections, like Shirts and Accessories, where types correspond to the product sub-types like "dress shirts, sport shirts, bow ties" etc.

{% assign filters = _filters | split: ' ' %}
{% for filter in filters %}
  {% if filter == 'type' %}
    ... we want to output the "Type" dropdown first, if present ...
  {% endif %}
{% endfor %}
{% for filter in filters limit: 5 %}
  {% if filter != 'type' %}
    ... then, the other dropdowns needed ...
  {% endif %}
{% endfor %}

4. Generate the dropdown options

Each dropdown option corresponds to the <option> part of the filter tag. Tags that share a <category> are grouped together and output within the same dropdown. Options that contain more than one word, i.e. filter-type-button-down are split a third time into yet another array, and each word capitalized before being dumped into an option.

{% capture filter_tags %}
  {% for option in filter_options %}{% if option contains filter %}{{ option | strip }} {%endif%}{%endfor%}
{% endcapture %}
{% assign filter_tags_array = filter_tags | split: ' ' %}

{% comment %}Individual select{% endcomment %}
<div class="collection__filter inline-block align-m">
  <div class="js-select-wrapper select-wrapper">
    <select class="js-dropdown is-resizeable inline-block h7 font-t-u" placeholder="{{ filter | capitalize }}">
      <option disabled selected>{{ filter | capitalize }}</option>
      <option>All</option>
      {%for tag in filter_tags_array %}
        {% comment %}Remove <category>{% endcomment %}
        {% if forloop.first %}
          {% assign title_partials = tag | split: '-' %}
          {% for partial in title_partials %}
            {% if forloop.first %}
              {% assign filter_title = partial %}
            {% endif %}
          {% endfor %}
        {% endif %}
        {% comment %}Parse out each option and remove the <category>{% endcomment %}
        {% if tag contains '-' %}
          {% assign tag_partial = tag | remove: filter_title | split: '-' %}
          {% capture output_tag %}
            {% for partial in tag_partial %}{{ partial | capitalize }} {% endfor %}
          {% endcapture %}
          <option value="{{ output_tag | handleize }}">{{ output_tag }}</option>
        {% else %}
          {% assign output_tag = tag | remove: filter_title | capitalize %}
          <option value="{{ output_tag | handleize }}">{{ output_tag }}</option>
        {% endif %}
      {%endfor%}
    </select>
  </div>
</div>

Final Code (above)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment