<section class="panel theme--white 
    panel--no-padding-top h-margin-top-2">
    <div class="panel__inner">
        <div class="filters js-filters js-loader-overlay-holder" aria-controls="filter-documents-list">

            <div class="h-margin-bottom-2">
                <div class="row h-margin-bottom-1 js-dropdowns-holder h-margin-top-2">
                    <div class="col col--span-12 col--span-xs-6 col--span-m-3">
                        <div class="form-item form-item--select ">
                            <select id="categorySelect1" class="select__select js-filter" name="Country" aria-controls="filter-partners-cards-grid" data-type="select">
                                <option class="select__option" value="" disabled selected>Country</option>
                                <option class="select__option" value="1">Option 1</option>
                                <option class="select__option" value="2">Option 2</option>
                            </select>
                        </div>

                    </div>
                    <div class="col col--span-12 col--span-xs-6 col--span-m-3">
                        <div class="form-item form-item--select ">
                            <select id="categorySelect2" class="select__select js-filter" name="Product area" aria-controls="filter-partners-cards-grid" data-type="select">
                                <option class="select__option" value="" disabled selected>Product area</option>
                                <option class="select__option" value="2">Option 2</option>
                                <option class="select__option" value="3">Option 3</option>
                            </select>
                        </div>

                    </div>
                </div>

                <div class="js-clear-filters-holder h-hidden-from-view row h-margin-top-1 h-margin-bottom-1 h-margin-top-2">
                    <div class="col">
                        <a href="#" class="js-clear-filters">Clear filters</a>
                    </div>
                </div>
            </div>

            <div class="h-margin-top-3">
                <div class="row row--justify-between row--align-center">
                    <div class="col col--auto-width">
                        <p class="search-result-count"></p>
                    </div>
                    <div class="col col--auto-width">
                    </div>
                </div>
            </div>

            <div class="row" id="">
            </div>
            <script type="text/template" id="card-data-tmpl">
                <% forEach(results, function(result) { %>
    <div class="col col--bottom-gutter col--span-12 col--span-s-6 col--span-xl-3">
        <div class="card card--fluid-layout">
            <a href="<%= result.url %>" class="card__cta">
                <figure class="card__figure">
                    <img src="<%= result.imageSrc %>" alt="<%= result.imageAlt %>" class="card__image">
                </figure>
                <div class="card__body">
                    <span class="card__follow-link">
                        <svg class="icon " focusable="false">
                            <use xlink:href="#icon-chevron-right"></use>
                        </svg>
                    </span>
                    <h4 class="card__title"><%= result.title %></h4>
                    <p class="card__date"><%= result.date %></p>
                    <p class="card__description"><%= result.description %></p>
                </div>
            </a>
        </div>
    </div>
    <% }); %>
</script>

            <div class="row filters-result-container" id="filter-partners-cards-grid">
                <div class="col col--bottom-gutter col--span-12 col--span-s-6 col--span-xl-3">
                    <div class="contact-card contact-card--no-icon ">

                        <div class="contact-card__body">
                            <strong class="contact-card__label">Partner, Country</strong>
                        </div>

                        <div id="" class="show-info js-show-info ">
                            <div class="show-info__wrapper js-show-info-wrapper">
                                <div class="show-info__content">

                                    <ul class="contact-list">
                                        <li class="contact-list__item">
                                            <span href=>
                                                <svg class="icon contact-list__icon" focusable="false">
                                                    <use xlink:href="#icon-map-pin"></use>
                                                </svg>
                                                City name
                                            </span>
                                        </li>
                                        <li class="contact-list__item">
                                            <span href=>
                                                <svg class="icon contact-list__icon" focusable="false">
                                                    <use xlink:href="#icon-fan"></use>
                                                </svg>
                                                Product area
                                            </span>
                                        </li>
                                        <li class="contact-list__item">
                                            <a href=https://int.swegon.com/sv/kontaktsidor/#product-area-tab>
                                                <svg class="icon contact-list__icon" focusable="false">
                                                    <use xlink:href="#icon-globe"></use>
                                                </svg>
                                                Visit website
                                            </a>
                                        </li>
                                    </ul>
                                </div>
                            </div>

                            <div class="show-info__btn-holder js-show-info-btn-holder">
                                <button class="show-info__btn js-show-info-btn">
                                    <span class="show-info__btn-opened-text">
                                        More info
                                    </span>
                                    <span class="show-info__btn-closed-text">
                                        Hide info
                                    </span>
                                    <svg class="icon show-info__btn-icon" focusable="false">
                                        <use xlink:href="#icon-close"></use>
                                    </svg>
                                </button>
                            </div>
                        </div>
                    </div>
                </div>
                <div class="col col--bottom-gutter col--span-12 col--span-s-6 col--span-xl-3">
                    <div class="contact-card contact-card--no-icon ">

                        <div class="contact-card__body">
                            <strong class="contact-card__label">Partner, Country</strong>
                        </div>

                        <div id="" class="show-info js-show-info ">
                            <div class="show-info__wrapper js-show-info-wrapper">
                                <div class="show-info__content">

                                    <ul class="contact-list">
                                        <li class="contact-list__item">
                                            <span href=>
                                                <svg class="icon contact-list__icon" focusable="false">
                                                    <use xlink:href="#icon-map-pin"></use>
                                                </svg>
                                                City name
                                            </span>
                                        </li>
                                        <li class="contact-list__item">
                                            <span href=>
                                                <svg class="icon contact-list__icon" focusable="false">
                                                    <use xlink:href="#icon-fan"></use>
                                                </svg>
                                                Product area
                                            </span>
                                        </li>
                                        <li class="contact-list__item">
                                            <a href=https://int.swegon.com/sv/kontaktsidor/#product-area-tab>
                                                <svg class="icon contact-list__icon" focusable="false">
                                                    <use xlink:href="#icon-globe"></use>
                                                </svg>
                                                Visit website
                                            </a>
                                        </li>
                                    </ul>
                                </div>
                            </div>

                            <div class="show-info__btn-holder js-show-info-btn-holder">
                                <button class="show-info__btn js-show-info-btn">
                                    <span class="show-info__btn-opened-text">
                                        More info
                                    </span>
                                    <span class="show-info__btn-closed-text">
                                        Hide info
                                    </span>
                                    <svg class="icon show-info__btn-icon" focusable="false">
                                        <use xlink:href="#icon-close"></use>
                                    </svg>
                                </button>
                            </div>
                        </div>
                    </div>
                </div>
                <div class="col col--bottom-gutter col--span-12 col--span-s-6 col--span-xl-3">
                    <div class="contact-card contact-card--no-icon ">

                        <div class="contact-card__body">
                            <strong class="contact-card__label">Partner, Country</strong>
                        </div>

                        <div id="" class="show-info js-show-info ">
                            <div class="show-info__wrapper js-show-info-wrapper">
                                <div class="show-info__content">

                                    <ul class="contact-list">
                                        <li class="contact-list__item">
                                            <span href=>
                                                <svg class="icon contact-list__icon" focusable="false">
                                                    <use xlink:href="#icon-map-pin"></use>
                                                </svg>
                                                City name
                                            </span>
                                        </li>
                                        <li class="contact-list__item">
                                            <span href=>
                                                <svg class="icon contact-list__icon" focusable="false">
                                                    <use xlink:href="#icon-fan"></use>
                                                </svg>
                                                Product area
                                            </span>
                                        </li>
                                        <li class="contact-list__item">
                                            <a href=https://int.swegon.com/sv/kontaktsidor/#product-area-tab>
                                                <svg class="icon contact-list__icon" focusable="false">
                                                    <use xlink:href="#icon-globe"></use>
                                                </svg>
                                                Visit website
                                            </a>
                                        </li>
                                    </ul>
                                </div>
                            </div>

                            <div class="show-info__btn-holder js-show-info-btn-holder">
                                <button class="show-info__btn js-show-info-btn">
                                    <span class="show-info__btn-opened-text">
                                        More info
                                    </span>
                                    <span class="show-info__btn-closed-text">
                                        Hide info
                                    </span>
                                    <svg class="icon show-info__btn-icon" focusable="false">
                                        <use xlink:href="#icon-close"></use>
                                    </svg>
                                </button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <script type="text/template" id="partner-card-data-tmpl">
                <% forEach(results, function(result) { %>
    <div class="col col--bottom-gutter col--span-12 col--span-s-6 col--span-xl-3">
        <div class="contact-card contact-card--no-icon">
            <div class="contact-card__body">
                <strong class="contact-card__label"><%= result.label %></strong>
            </div>

            <div class="show-info js-show-info">
                <div class="show-info__wrapper js-show-info-wrapper" style="max-height: 0px;">
                    <div class="show-info__content">
                        <ul class="contact-list">
                            <% forEach(result.contactLinks, function(link) { %>
                                <li class="contact-list__item">
                                    <% if (link.tag === 'a') { %>
                                        <a 
                                            href="<%= link.href %>" 
                                            <%=  Object.entries(link.attributes || {}).map(function(item) {
                                                return item[0] + "='" + item[1] + "'"
                                            }).join(" ") %>
                                        >
                                            <svg class="icon contact-list__icon" focusable="false">
                                                <use xlink:href="#icon-<%= link.icon %>"></use>
                                            </svg>
                                            <%= link.description %>
                                        </a>
                                     <% } else { %>
                                        <span>
                                            <svg class="icon contact-list__icon" focusable="false">
                                                <use xlink:href="#icon-<%= link.icon %>"></use>
                                            </svg>
                                            <%= link.description %>
                                        </span>
                                     <% } %>
                                </li>
                            <% }); %>
                        </ul>        
                    </div>
                </div>
            
                <div class="show-info__btn-holder js-show-info-btn-holder">
                    <button class="show-info__btn js-show-info-btn">
                        <span class="show-info__btn-opened-text">
                            More info
                        </span>
                        <span class="show-info__btn-closed-text" style="display: none;">
                            Hide info
                        </span>
                        <svg class="icon show-info__btn-icon" focusable="false">
                            <use xlink:href="#icon-close"></use>
                        </svg>
                    </button>
                </div>
            </div>
        </div>
    </div>
    <% }); %>
</script>

            <div class="h-text-align-center">

                <a class="button  js-load-more h-hidden-from-view " href="/mocks/api/partnerCards.json" aria-controls="filter-partners-cards-grid" data-template-id="partner-card-data-tmpl">
                    <span class="button__label">Ladda fler</span>
                </a>
            </div>
        </div>
    </div>
</section>
<script type="text/template" id="no-results-data-tmpl">
    <div class="row row--justify-around h-text-align-center-m">
    <div class="col col--span-12 col--span-s-8 h-text-align-center">No results message</div>
</div>

</script>
{{#> @panel theme=panel.theme modifiers=panel.modifiers }}
    <div class="filters js-filters js-loader-overlay-holder" {{{getattributes filtersAttributes}}}>
        {{#if filtersTitle}}
            <div class="row">
                <div class="col h-margin-top-4 h-margin-bottom-1">
                    <div class="headline-5">{{filtersTitle}}</div>
                </div>
            </div>
        {{/if}}

        <div class="h-margin-bottom-2">
            {{#if displayDropdowns}}
                <div class="row h-margin-bottom-1 js-dropdowns-holder {{additionalClasses}}">
                    {{#each filters.dropdowns}}
                        <div class="col col--span-12 col--span-xs-6 col--span-m-3">
                            {{#if multi}}
                                {{render "@select-multiple" this merge=true}}
                            {{else}}
                                {{render "@select--default" this merge=true}}
                            {{/if}}
                        </div>
                    {{/each}}
                </div>
            {{/if}}

            {{#each filters.checkboxes}}
                {{#if label}}
                    <div class="row">
                        <div class="col">
                            <div class="headline-7">{{label}}</div>
                        </div>
                    </div>
                {{/if}}
                <div class="row row--justify-between h-margin-bottom-1">
                    <div class="col col--auto-width">
                        {{#each items}}
                            <div class="h-display-inline-block h-margin-right-3 h-margin-bottom-2">
                                {{render "@checkbox--default" this merge=true}}
                            </div>
                        {{/each}}
                    </div>
                    <div class="col col--auto-width">
                        {{#each switchers}}
                            {{render "@switch" this merge=true}}
                        {{/each}}
                    </div>
                </div>
            {{/each}}

            {{#if displaySearch}}
                <div class="row h-margin-top-3 h-margin-bottom-1 js-search-field-holder">
                    <div class="col col--span-12 col--span-l-7 col--span-xl-5">
                         {{render "@search" searchField}}
                    </div>
                </div>
            {{/if}}
            {{#if resetButton}}
                <div class="js-clear-filters-holder h-hidden-from-view row h-margin-top-1 h-margin-bottom-1 {{additionalClasses}}">
                    <div class="col">
                         <a href="#" class="js-clear-filters">Clear filters</a>
                    </div>
                </div>
            {{/if}}
        </div>

        <div class="h-margin-top-3">
            <div class="row row--justify-between row--align-center">
                <div class="col col--auto-width">
                    {{>@search-result-count searchResultCount}}
                </div>
                <div class="col col--auto-width">
                    {{#if displaySort}}
                        {{render "@select--ghost" filters.sort merge=true}}
                    {{/if}}
                </div>
            </div>
        </div>

        {{#if cards}}
            <div class="row" id="{{cards.id}}">
                {{#each cards.items}}
                <div class="col col--bottom-gutter col--span-12 col--span-s-6 col--span-xl-3">
                    {{>@card this}}
                </div>
                {{/each}}
            </div>
            {{render "@card-data-tmpl"}}
        {{/if}}

        {{#if officeCards}}
            <div class="row" id="{{officeCards.id}}">
                {{#each officeCards.items}}
                    <div class="col col--bottom-gutter col--span-12 col--span-s-6 col--span-xl-3">
                        {{>@contact-card this}}
                    </div>
                {{/each}}
            </div>

            {{render "@office-card-data-tmpl"}}

            {{#> @modal messageSelectorModal modifiers="form"}}
                <div class="h-padding-bottom-4">
                    <h2>New message</h2>
                    <div id="form_40600">
                        <script>
                            document.addEventListener('DOMContentLoaded', function () {
                                hbspt.forms.create({
                                    css: '',
                                    portalId: "3433011",
                                    formId: "cee49fbd-acb1-4054-9a44-74ea6ec39adc",
                                    target: "#form_40600",
                                    onFormSubmit: function ($form) {
                                        dataLayer.push({
                                            'event': 'hubspot form submitted',
                                            'hubspot form name': 'Technical support',
                                            'hubspot form id': $form[0].id,
                                        });
                                    },
                                    onFormReady: function ($form) {
                                        let event;

                                        try {
                                            event = new CustomEvent('onDynamicContentAdded');
                                        } catch (e) {
                                            event = document.createEvent('Event');
                                            event.initEvent('onDynamicContentAdded', true, true);
                                        };
                                        window.dispatchEvent(event);
                                    }
                                });
                            });
                        </script>
                    </div>
                </div>
            {{/@modal}}
        {{/if}}
        
        {{#if personCards}}
            <div class="row filters-result-container" id="{{personCards.id}}">
                {{#each personCards.items}}
                    <div class="col col--bottom-gutter col--span-12 col--span-s-6 col--span-xl-3">
                        {{>@contact-card this}}
                    </div>
                {{/each}}
                <div class="row h-margin-top-3">
                    {{render "@no-results"}}
                </div>
            </div>

            {{render "@person-card-data-tmpl"}}
        {{/if}}

        {{#if partnerCards}}
            <div class="row filters-result-container" id="{{partnerCards.id}}">
                {{#each partnerCards.items}}
                    <div class="col col--bottom-gutter col--span-12 col--span-s-6 col--span-xl-3">
                        {{>@contact-card this}}
                    </div>
                {{/each}}
            </div>

            {{render "@partner-card-data-tmpl"}}
        {{/if}}

        {{#if table}}
            {{#> @horizontal-scroller showScrollIcon="true" contentContainer="filter-documents"}}
                <table id="{{table.id}}" class="table table--inverted-zebra {{ tableAdditionalClasses }}">
                    {{#with ../table}}
                        <thead>
                            {{#each headerRows}}
                                <tr>
                                    {{#each cols}}
                                        <td>{{{ this }}}</td>
                                    {{/each}}
                                </tr>
                            {{/each}}
                        </thead>
                        <tbody id="filter-documents-list">
                            {{#each rows}}
                                <tr 
                                    data-extension="{{this.extension}}"
                                    data-filename="{{this.fileName}}"
                                    data-document-category="{{this.type}}"
                                    class="js-document-tracking-row"
                                >
                                    {{#each cols}}
                                        <td>{{{this}}}</td>
                                    {{/each}}
                                </tr>
                            {{/each}}
                        </tbody>
                    {{/with}}
                </table>
            {{/@horizontal-scroller}}
            {{render "@document-data-tmpl"}}
        {{/if}}

        <div class="h-text-align-center">
            {{#if searchResultCount}}
                {{> @search-result-count}}
            {{/if}}

            {{#if loadMore}}
                {{#if loadMore.visuallyHidden}}
                    {{> @button loadMore additionalClasses="js-load-more h-hidden-from-view"}}
                {{else}}
                    {{> @button loadMore additionalClasses="js-load-more"}}
                {{/if}}
            {{/if}}
        </div>
    </div>
{{/@panel}}

{{render "@no-results-data-tmpl"}}
{
  "panel": {
    "theme": "white",
    "modifiers": "no-padding-top"
  },
  "filtersTitle": false,
  "filtersAttributes": {
    "aria-controls": "filter-documents-list"
  },
  "displayDropdowns": true,
  "displaySearch": false,
  "resetButton": true,
  "displaySort": false,
  "searchField": {
    "name": "Search",
    "value": "",
    "type": "text",
    "placeholder": "text",
    "disabled": false,
    "additionalClasses": "js-filter",
    "attr": {
      "aria-controls": "filter-documents-list",
      "data-type": "search"
    }
  },
  "searchResultCount": null,
  "filters": {
    "checkboxes": [],
    "dropdowns": [
      {
        "name": "Country",
        "label": "",
        "id": "categorySelect1",
        "additionalClasses": "js-filter",
        "options": [
          {
            "name": "Country",
            "value": "",
            "disabled": true,
            "selected": true
          },
          {
            "name": "Option 1",
            "value": 1
          },
          {
            "name": "Option 2",
            "value": 2
          }
        ],
        "attr": {
          "aria-controls": "filter-partners-cards-grid",
          "data-type": "select"
        }
      },
      {
        "name": "Product area",
        "label": "",
        "id": "categorySelect2",
        "additionalClasses": "js-filter",
        "options": [
          {
            "name": "Product area",
            "value": "",
            "disabled": true,
            "selected": true
          },
          {
            "name": "Option 2",
            "value": 2
          },
          {
            "name": "Option 3",
            "value": 3
          }
        ],
        "attr": {
          "aria-controls": "filter-partners-cards-grid",
          "data-type": "select"
        }
      }
    ],
    "sort": {
      "name": "Sort",
      "label": "Sortera:",
      "modifiers": "horizontal",
      "id": "categorySelectSort",
      "additionalClasses": "js-filter select__select--ghost",
      "options": [
        {
          "name": "Senaste",
          "value": "",
          "selected": true
        },
        {
          "name": "A-Z",
          "value": "a-z"
        },
        {
          "name": "Z-A",
          "value": "z-a"
        }
      ],
      "attr": {
        "aria-controls": "filter-documents-list",
        "data-type": "select"
      }
    },
    "switchers": []
  },
  "table": [],
  "loadMore": {
    "tag": "a",
    "label": "Ladda fler",
    "href": "/mocks/api/partnerCards.json",
    "attributes": {
      "aria-controls": "filter-partners-cards-grid",
      "data-template-id": "partner-card-data-tmpl"
    },
    "additionalClasses": "js-load-more",
    "visuallyHidden": true
  },
  "additionalClasses": "h-margin-top-2",
  "cards": {},
  "partnerCards": {
    "id": "filter-partners-cards-grid",
    "items": [
      {
        "showMoreText": "More info",
        "hideText": "Hide info",
        "cardType": "as-partner",
        "label": "Partner, Country",
        "additionalClasses": "contact-card--no-icon",
        "contactLinks": [
          {
            "description": "City name",
            "icon": "map-pin"
          },
          {
            "description": "Product area",
            "icon": "fan"
          },
          {
            "description": "Visit website",
            "href": "https://int.swegon.com/sv/kontaktsidor/#product-area-tab",
            "icon": "globe",
            "tag": "a"
          }
        ]
      },
      {
        "showMoreText": "More info",
        "hideText": "Hide info",
        "cardType": "as-partner",
        "label": "Partner, Country",
        "additionalClasses": "contact-card--no-icon",
        "contactLinks": [
          {
            "description": "City name",
            "icon": "map-pin"
          },
          {
            "description": "Product area",
            "icon": "fan"
          },
          {
            "description": "Visit website",
            "href": "https://int.swegon.com/sv/kontaktsidor/#product-area-tab",
            "icon": "globe",
            "tag": "a"
          }
        ]
      },
      {
        "showMoreText": "More info",
        "hideText": "Hide info",
        "cardType": "as-partner",
        "label": "Partner, Country",
        "additionalClasses": "contact-card--no-icon",
        "contactLinks": [
          {
            "description": "City name",
            "icon": "map-pin"
          },
          {
            "description": "Product area",
            "icon": "fan"
          },
          {
            "description": "Visit website",
            "href": "https://int.swegon.com/sv/kontaktsidor/#product-area-tab",
            "icon": "globe",
            "tag": "a"
          }
        ]
      }
    ]
  }
}
  • Content:
    import getEvent from '../../functions/getEvent';
    import ShowInfo from '../show-info/ShowInfo';
    import OptionsLimiter from '../options-limiter/OptionsLimiter';
    import Modal from '../modal/Modal';
    import { debounce } from 'lodash';
    
    class Filters {
        constructor(el) {
            this.el = el;
            this.filterDropdownsSelector = '.js-filter[data-type="select"]';
            this.searchFieldSelector = '.js-filter[data-type="search"]';
            this.filterDropdownsMultipleSelector = '.js-filter[data-type="select-multiple"]';
            this.notFilterDropdownsSelector = '.js-filter:not([data-type="select"]):not([data-type="search"]):not([data-type="checkbox"])';
            this.filterCheckboxSelector = '.js-filter[data-type="checkbox"]';
            this.filterRangeSlider = '.js-filter[data-type="range-slider"]';
            this.filters = el.querySelectorAll('.js-filter');
            this.dropdownsMultiple = el.querySelectorAll(this.filterDropdownsMultipleSelector);
            this.dropdownsHolder = el.querySelector('.js-dropdowns-holder');
            this.sortableCells = el.querySelectorAll('.js-sortable-cell');
            this.loadMoreBtn = el.querySelector('.js-load-more');
            this.clearFiltersBtn = el.querySelector('.js-clear-filters');
            this.searchField = el.querySelector(this.searchFieldSelector);
            this.searchButton = this.searchField ? this.searchField.nextElementSibling : null;
            this.updateFilters = this.updateFilters.bind(this);
            this.triggerUpdate = this.triggerUpdate.bind(this);
            const savedFiltersArray = sessionStorage.getItem('filters array');
            const savedFiltersDictionary = sessionStorage.getItem('filters dictionary');
            this.filtersArray = savedFiltersArray ? JSON.parse(savedFiltersArray) : [];
            this.filtersDictionary = savedFiltersDictionary ? JSON.parse(savedFiltersDictionary) : {};
            this.sortOrder = '';
            this.sortBy = '';
    
            this.init();
        }
    
        init() {
            this.attachListeners(true);
        }
    
        attachListeners() {
            const self = this;
    
            if (this.clearFiltersBtn) {
                this.clearFiltersBtn.addEventListener('click', (e) => {
                    e.preventDefault();
                    this.clearFilters();
                });
            };
            this.el.addEventListener('change', function (e) {
                const target = e.target;
                if (target.matches
                    ? target.matches(self.filterDropdownsSelector)
                    : target.msMatchesSelector(self.filterDropdownsSelector)
                ) {
                    self.updateFilter(target, true);
                }
            }, false);
            this.el.addEventListener('change', function (e) {
                const target = e.target;
                const shouldUpdateFromData = target.dataset.shouldUpdateFilters;
                const shouldUpdate = typeof shouldUpdateFromData !== 'undefined' ? shouldUpdateFromData === 'true' : true;
                if (target.matches
                    ? target.matches(self.filterCheckboxSelector)
                    : target.msMatchesSelector(self.filterCheckboxSelector)
                ) {
                    self.updateFilter(target, shouldUpdate);
                }
            }, false);
            this.el.addEventListener('change', function (e) {
                const target = e.target.closest(self.filterRangeSlider);
    
                if (target) {
                    const shouldUpdateFromData = target.dataset.shouldUpdateFilters;
                    const shouldUpdate = typeof shouldUpdateFromData !== 'undefined' ? shouldUpdateFromData === 'true' : true;
                    self.updateFilter(target, shouldUpdate);
                }
            }, false);
    
            this.el.addEventListener('click', function (e) {
                const target = e.target;
                if (target.matches
                    ? target.matches(self.notFilterDropdownsSelector)
                    : target.msMatchesSelector(self.notFilterDropdownsSelector)
                ) {
                    self.updateFilter(target, true);
                }
            }, false);
    
            for (let i = 0; this.dropdownsMultiple.length > i; i++) {
                this.dropdownsMultiple[i].addEventListener('change', (e) => {
                    const target = e.target;
                    if (target.matches
                        ? target.matches(this.filterDropdownsMultipleSelector)
                        : target.msMatchesSelector(this.filterDropdownsMultipleSelector)
                    ) {
                        this.updateFilter(target, true);
                    }
                });
            }
    
            for (let i = 0; i < this.sortableCells.length; i++) {
                const cell = this.sortableCells[i];
                cell.addEventListener('click', e => this.sortTable(e, cell));
            }
    
            if (this.searchField) {
                this.searchField.addEventListener('input', (e) => {
                    const target = e.target;
                    this.updateFilterDebounced(target, true);
                });
            }
    
            if (this.searchButton) {
                this.searchButton.addEventListener('click', (e) => {
                    this.updateFilter(this.searchField, true);
                });
            }
    
            window.addEventListener('loadMoreUpdate', (e) => {
                if (e && e.data) {
                    const showInfoEls = this.el.querySelectorAll('.js-show-info');
    
                    // Re-initialize modals
                    const els = document.querySelectorAll('.modal');
    
                    for (let el of els) {
                        new Modal(el);
                    }
                    // Re-initialize showInfo component
                    for (let el of showInfoEls) {
                        ShowInfo(el);
                    }
    
                    // Re-initialize Options limiter component
                    const optionsLimiter = this.el.querySelectorAll('.js-options-limiter');
    
                    for (let el of optionsLimiter) {
                        new OptionsLimiter(el);
                    }
                }
            });
    
            // Listener if Filter history is enabled
            window.addEventListener('popstate', this.applyFiltersFromUrl.bind(this));
    
            this.loadMoreBtn && this.loadMoreBtn.addEventListener('updateFilterDropdowns', this.updateFilters);
        }
    
        sortTable(e, cell) {
            const newSortBy = cell.id;
            if (newSortBy === this.sortBy) {
                if (this.sortOrder === 'asc') {
                    this.sortOrder = 'desc';
                } else {
                    this.sortOrder = 'asc';
                }
            } else {
                this.sortOrder = 'asc';
            }
            this.sortBy = newSortBy;
            this.triggerUpdateDebounced(cell.getAttribute('aria-controls'));
            e.preventDefault();
        }
    
        groupFilters(filters) {
            let a = [];
    
            for (let filter of filters) {
                const existingIndex = a.findIndex((obj) => obj.name === filter.name);
    
                if (existingIndex > -1) {
                    a[existingIndex].value = a[existingIndex].value.concat(filter.value);
                } else {
                    filter.value = [filter.value];
                    a.push(filter);
                }
            }
    
            return a;
        }
    
        updateFilters(e) {
            const { subcategoriesMarkup } = e.data;
            if (this.dropdownsHolder) {
                this.dropdownsHolder.innerHTML = subcategoriesMarkup;
            }
        }
    
        triggerUpdate(ariaControls) {
            const event = getEvent('filterApplied');
            const data = {
                ariaControls,
                filtersArray: this.groupFilters(this.filtersArray),
                filtersDictionary: this.filtersDictionary,
                sortData: {}
            };
            if (this.sortBy) {
                data.sortData.sortOrder = this.sortOrder;
                data.sortData.sortBy = this.sortBy;
            }
            event['data'] = data;
    
            if (this.loadMoreBtn) {
                this.loadMoreBtn.dispatchEvent(event);
            }
        }
    
        triggerUpdateDebounced = debounce(this.triggerUpdate, 100, false);
    
        clearFilters() {
            const filters = this.el.querySelectorAll('.js-filter');
            let ariaControls = '';
    
            for (let i = 0; i < filters.length; i++) {
                const filter = filters[i];
                const filterType = filter.getAttribute('data-type-variant') || filter.getAttribute('data-type');
    
                switch (filterType) {
                    case 'switch':
                        filter.checked = false;
                        break;
                    case 'select-multiple': {
                        const checked = filter.querySelectorAll('option:checked');
                        [...checked].forEach(option => { option.selected = false; });
                        filter.value = '';
                        filter.dispatchEvent(new Event('change'));
                        break;
                    }
                    case 'select-with-relation':
                        filter.value = '';
                        break;
                    case 'select':
                        filter.value = '';
                        break;
                    case 'checkbox':
                        filter.checked = false;
                        filter.dispatchEvent(new Event('change'));
                        break;
                    case 'search':
                        filter.value = '';
                        break;
                    case 'range-slider':
                        filter.dispatchEvent(new Event('reset'));
                        filter.dispatchEvent(new Event('change'));
                        break;
                    default:
                        break;
                }
                ariaControls = filter.getAttribute('aria-controls');
            }
    
            this.updateFilter(null, false);
            sessionStorage.removeItem('filters array');
            sessionStorage.removeItem('filters dictionary');
            this.triggerUpdateDebounced(ariaControls);
        }
    
        updateUrlWithQueryParams(filtersArray, filtersDictionary) {
            // Generate query parameters from filtersArray and filtersDictionary
            const queryParams = new URLSearchParams();
    
            // Add matched filters for filtersArray to the URL parameters
            const groupedFilters = {};
            filtersArray.forEach(filter => {
                if (filter.name && filter.value) {
                    const values = Array.isArray(filter.value) ? filter.value : [filter.value]; // Supports both array or string.
    
                    // Concat filter type name if it exists - or create new key.
                    if (groupedFilters[filter.name]) {
                        groupedFilters[filter.name] = groupedFilters[filter.name].concat(values);
                    } else {
                        groupedFilters[filter.name] = values;
                    }
                }
            });
    
            // Add matched filters for filtersDictionary to the URL parameters
            for (const [key, value] of Object.entries(filtersDictionary)) {
                if (value) {
                    queryParams.append(key, value);
                }
            }
    
            // Add filters to queryParams
            for (const [key, values] of Object.entries(groupedFilters)) {
                queryParams.append(key, values.join('|'));
            }
    
            const newUrl = `${window.location.pathname}?${queryParams.toString()}`;
    
            // Update URL with new queryparams
            window.history.pushState(null, '', newUrl);
        }
    
        applyFiltersFromUrl() {
            const urlParams = new URLSearchParams(window.location.search);
    
            // Update filters state from URL and queryparams.
            this.el.querySelectorAll('.js-filter').forEach(filter => {
                const filterName = filter.getAttribute('name');
                const filterType = filter.getAttribute('data-type-variant') || filter.getAttribute('data-type');
                const paramValue = urlParams.get(filterName);
    
                if (paramValue) {
                    switch (filterType) {
                        case 'checkbox':
                            filter.checked = paramValue.split('|').includes(filter.value);
                            break;
                        case 'select-multiple':
                            [...filter.options].forEach(option => {
                                const value = option.value;
                                const selectedValues = paramValue.split('|');
                                const dropdownOption = option.parentNode.parentNode.querySelector('.select-multiple__options a[data-value="' + value + '"]');
                                const button = option.parentNode.parentNode.querySelector('.select-multiple__wrapper a[data-value="' + value + '"]');
    
                                option.selected = selectedValues.includes(option.value);
    
                                if (dropdownOption) {
                                    selectedValues.includes(option.value)
                                        ? dropdownOption.setAttribute('data-checked', true)
                                        : dropdownOption.removeAttribute('data-checked');
                                }
    
                                if (button) {
                                    button.style.display = selectedValues.includes(option.value) ? 'block' : 'none';
                                }
                            });
                            break;
                        case 'select':
                        case 'search':
                            filter.value = paramValue;
                            break;
                        default:
                            break;
                    }
    
                    this.updateFilter(filter, false);
                } else {
                    // Reset filters if no match with queryParams.
                    if (filter.type === 'checkbox') {
                        filter.checked = false;
                    } else {
                        filter.value = '';
                    }
    
                    this.updateFilter(filter, false);
                }
            });
    
            // Update filter result
            this.triggerUpdateDebounced(this.el.getAttribute('aria-controls'));
        }
    
        updateFilter(filter, shouldUpdate) {
            this.filtersArray = [];
            this.filtersDictionary = {};
    
            const filters = this.el.querySelectorAll('.js-filter');
            const dropdownFilters = this.el.querySelectorAll('.js-filter[data-type="select"]');
            const changedDropdownIndex = Array.prototype.indexOf.call(dropdownFilters, filter);
            const isFilterHistoryEnabled = filter && filter.getAttribute('data-enable-history') === 'true';
    
            let currentDropdownIndex = 0;
    
            for (let i = 0; i < filters.length; i++) {
                const filter = filters[i];
                const filterType = filter.getAttribute('data-type-variant') || filter.getAttribute('data-type');
    
                switch (filterType) {
                    case 'switch':
                        this.filtersDictionary[filter.value] = filter.checked;
                        break;
                    case 'select-multiple': {
                        const checked = filter.querySelectorAll('option:checked');
                        const checkedValues = [...checked].map(option => option.value);
    
                        if (checkedValues.length) {
                            this.filtersDictionary[filter.name] = checkedValues.join('|');
                        }
                        break;
                    }
                    case 'select-with-relation':
                        if (currentDropdownIndex > changedDropdownIndex && changedDropdownIndex > -1) {
                            break;
                        }
    
                        this.filtersDictionary[filter.name] = filter.value;
                        currentDropdownIndex++;
                        break;
                    case 'select':
                        this.filtersDictionary[filter.name] = filter.value;
                        break;
                    case 'checkbox':
                        let newFilters = [];
    
                        if (filter.checked) {
                            newFilters = [...this.filtersArray, { 'name': filter.name, 'value': filter.value }];
                        } else {
                            newFilters = this.filtersArray.filter(item => item !== filter.value);
                        }
                        this.filtersArray = newFilters;
                        break;
                    case 'search':
                        this.filtersDictionary[filter.name] = filter.value;
                        break;
                    case 'range-slider':
                        const input = filter.querySelector('.input');
                        const paramName = filter && filter.querySelector('input:checked') && filter.querySelector('input:checked').value;
    
                        if (input.getAttribute('isDirty') === 'false') {
                            break;
                        }
    
                        let value = input.dataset.realValue;
    
                        this.filtersDictionary[paramName] = value;
                        break;
                    default:
                        break;
    
                }
            }
    
            if (shouldUpdate) {
                sessionStorage.setItem('filters array', JSON.stringify(this.filtersArray));
                sessionStorage.setItem('filters dictionary', JSON.stringify(this.filtersDictionary));
                // Update URL with query params.
                if (isFilterHistoryEnabled) {
                    this.updateUrlWithQueryParams(this.filtersArray, this.filtersDictionary);
                }
                this.triggerUpdateDebounced(filter.getAttribute('aria-controls'));
            }
        }
    
        updateFilterDebounced = debounce(this.updateFilter, 500, false);
    }
    
    export default Filters;
    
  • URL: /components/raw/filters/Filters.js
  • Filesystem Path: src/components/filters/Filters.js
  • Size: 17.3 KB
  • Content:
    .filters {
        th, td {
    
            &:last-child {
                text-align: center;
            }
    
            @include breakpoint-down($l) {
                min-width: 0;
                &:first-child {
                    min-width: size(25);
                }
            }
        }
    }
    
    .js-clear-filters {
        color: $color-black;
    }
  • URL: /components/raw/filters/filters.scss
  • Filesystem Path: src/components/filters/filters.scss
  • Size: 300 Bytes
  • Content:
    import Filters from './Filters';
    
    const els = document.querySelectorAll('.js-filters');
    
    for (let el of els) {
        new Filters(el);
    }
    
  • URL: /components/raw/filters/index.js
  • Filesystem Path: src/components/filters/index.js
  • Size: 134 Bytes

No notes defined.