<link media="all" rel="stylesheet" href="/assets/themes/default/css/search-listings.css?cb=">
    <link media="all" rel="stylesheet" href="/assets/themes/default/css/list-card.css?cb=">
    <link media="all" rel="stylesheet" href="/assets/themes/default/css/listing.css?cb=">
    <link media="all" rel="stylesheet" href="/assets/themes/default/css/property-list-card.css?cb=">
    <link media="all" rel="stylesheet" href="/assets/themes/default/css/gallery.css?cb=">

    <div class="listing search-listing grid-container" data-module="searchListings" data-page-size="2" data-endpoint="/components/preview/search-results-api-result--{0}?category&#x3D;{0}" data-initialcategory="properties">
        <div>
            <div id="top"></div>
            <div class="grid-x category-listing__filters">
                <div class="cell">
                    <div class="grid_container listing-filter listing-filter--4-buttons">
                        <div class="listing-filter__button">
                            <button class="listing-filter__cta js-apply-filter-btn selected" data-category=default>All</button>
                        </div>
                        <div class="listing-filter__button">
                            <button class="listing-filter__cta js-apply-filter-btn " data-category=properties>Properties</button>
                        </div>
                        <div class="listing-filter__button">
                            <button class="listing-filter__cta js-apply-filter-btn " data-category=news>News And Media</button>
                        </div>
                        <div class="listing-filter__button">
                            <button class="listing-filter__cta js-apply-filter-btn " data-category=pages>Pages</button>
                        </div>
                    </div>
                </div>
            </div>
            <div class="listing__lazy-loader-content grid-x js-results-container">
                <!-- content is generated by JavaScript -->
            </div>
            <div class="grid-container">
                <div class="grid-x align-center">
                    <link rel="stylesheet" href="/assets/themes/default/css/pagination.css?cb=" />

                    <div class="pagination js-pagination">
                        <a href="#top" class="pagination__previous js-previous"><span>Previous</span></a>
                        <a href="#top" class="pagination__page js-page js-first selected" data-page="1">1</a>
                        <span class="pagination__dots js-dots-left">&#8230;</span>
                        <a href="#top" class="pagination__page js-page js-second-page" data-page="2">2</a>
                        <a href="#top" class="pagination__page js-page js-third-page" data-page="3">3</a>
                        <a href="#top" class="pagination__page js-page js-fourth-page" data-page="4">4</a>
                        <span class="pagination__dots js-dots-right">&#8230;</span>
                        <a href="#top" class="pagination__page js-page js-last-page" data-page="5">5</a>
                        <a href="#top" class="pagination__next js-next"><span>Next</span></a>
                    </div>
                </div>
            </div>
        </div>
    </div>
{{#if firstInstance}}
    <link media="all" rel="stylesheet" href="/assets/themes/{{theme}}/css/search-listings.css?cb={{cacheBuster}}">
    <link media="all" rel="stylesheet" href="/assets/themes/{{theme}}/css/list-card.css?cb={{cacheBuster}}">
    <link media="all" rel="stylesheet" href="/assets/themes/{{theme}}/css/listing.css?cb={{cacheBuster}}">
    <link media="all" rel="stylesheet" href="/assets/themes/{{theme}}/css/property-list-card.css?cb={{cacheBuster}}">
    <link media="all" rel="stylesheet" href="/assets/themes/{{theme}}/css/gallery.css?cb={{cacheBuster}}">
{{/if}}

<div class="listing search-listing grid-container" data-module="searchListings" data-page-size="{{pageSize}}" data-endpoint="{{endpoint}}" data-initialcategory="{{initialCategory}}">
    <div>
        <div id="top"></div>
        <div class="grid-x category-listing__filters">
            <div class="cell">
                {{> @listing-filter filter}}
            </div>
        </div>
        <div class="listing__lazy-loader-content grid-x js-results-container">
            <!-- content is generated by JavaScript -->
        </div>
        <div class="grid-container">
            <div class="grid-x align-center">
                {{> @pagination }}
            </div>
        </div>
    </div>
</div>
{
  "theme": "default",
  "firstInstance": true,
  "endpoint": "/components/preview/search-results-api-result--{0}?category={0}",
  "pageSize": "2",
  "loadMoreText": "Load more",
  "initialCategory": "properties",
  "filter": {
    "listingFilterButtons": [
      {
        "category": "default",
        "text": "All"
      },
      {
        "category": "properties",
        "text": "Properties"
      },
      {
        "category": "news",
        "text": "News And Media"
      },
      {
        "category": "pages",
        "text": "Pages"
      }
    ]
  }
}
  • Content:
    import LazyLoader from '../../../../js/utils/lazy-loader';
    import Pagination from '../pagination/pagination';
    import { getQueryStringParameter, setQueryParams } from '../../../../js/utils/routing';
    import format from '../../../../js/utils/string';
    import { PropertyListCard } from '../../cards/property-list-card/property-list-card';
    
    const pageQueryStringParameterName = 'page';
    
    export class SearchListings {
        constructor(container) {
            this.container = container;
    
            this.resultsContainer = this.container.querySelector('.js-results-container');
            this.filterButtons = this.container.querySelectorAll('.js-apply-filter-btn');
            this.selectOptions = this.container.querySelector('.js-filter-select-options');
            this.categoryQueryStringParameterName = 'category';
    
            this.init();
        }
    
        init() {
            this.parseQueryParams();
            this.setUpLazyLoader();
            this.addEventListener();
        }
    
        parseQueryParams() {
            let currentCategory = getQueryStringParameter(this.categoryQueryStringParameterName);
    
            if (!currentCategory) {
                currentCategory = this.container.dataset.initialcategory;
            }
    
            if (currentCategory) {
                const filterButton = this.container.querySelector(`.js-apply-filter-btn[data-category='${currentCategory}']`);
                if (filterButton) {
                    this.resetButtons();
                    filterButton.classList.add('selected');
                }
            }
        }
    
        setUpLazyLoader() {
            const loadMoreButton = this.container.querySelector('.js-load-more-button');
            const paginationElement = this.container.querySelector('.js-pagination');
    
            const pageNumberParamValue = getQueryStringParameter(pageQueryStringParameterName);
            let pageNumber = 1;
            if (pageNumberParamValue) {
                pageNumber = parseInt(pageNumberParamValue, 10);
            }
    
            if (paginationElement) {
                this.pagination = new Pagination(this.container.querySelector('.js-pagination'), () => { this.onPaginationChange(); });
            }
    
            this.lazyLoader = new LazyLoader(
                this.container.dataset.endpoint,
                this.container.dataset.pageSize,
                loadMoreButton,
                this.resultsContainer,
                () => this.onApiSuccess(),
                'get',
            );
    
            const { endpoint } = this.container.dataset;
            const { category } = this.container.querySelector('.js-apply-filter-btn.selected').dataset;
            this.endpoint = endpoint;
            this.updatedEndPoint = format(this.endpoint, category);
            this.lazyLoader.setPage(pageNumber);
            this.lazyLoader.setEndPoint(this.updatedEndPoint);
            this.lazyLoader.load();
        }
    
        addEventListener() {
            const that = this;
            function updateCategory(category) {
                that.updatedEndPoint = format(that.endpoint, category);
                that.lazyLoader.reset();
                that.lazyLoader.setEndPoint(that.updatedEndPoint);
                that.lazyLoader.load();
                setQueryParams(that.categoryQueryStringParameterName, category);
            }
    
            this.filterButtons.forEach((btn) => {
                btn.addEventListener('click', (event) => {
                    event.preventDefault();
                    const button = event.target;
                    this.resetButtons();
                    button.classList.add('selected');
                    const { category } = button.dataset;
    
                    updateCategory(category);
                });
            });
    
            if (this.selectOptions) {
                this.selectOptions.addEventListener('change', () => {
                    const selectedOption = this.selectOptions.options[this.selectOptions.selectedIndex];
                    const { category } = selectedOption.dataset;
    
                    updateCategory(category);
                });
            }
        }
    
        onApiSuccess() {
            const propertyCards = this.resultsContainer.querySelectorAll('[data-module="propertyListCard"]');
            propertyCards.forEach((propertyCardElement) => {
                new PropertyListCard(propertyCardElement);
            });
    
            if (this.pagination) {
                this.pagination.setNumberOfPages(this.lazyLoader.totalPages);
            }
        }
    
        resetButtons() {
            this.filterButtons.forEach((btn) => {
                btn.classList.remove('selected');
            });
        }
    
        onPaginationChange() {
            setQueryParams(pageQueryStringParameterName, this.pagination.currentPage);
            if (this.pagination) {
                this.lazyLoader.reset();
            }
    
            this.lazyLoader.setPage(this.pagination.currentPage);
            this.lazyLoader.load();
        }
    }
    
    export default (module) => new SearchListings(module);
    
  • URL: /components/raw/search-listings/search-listings.js
  • Filesystem Path: source/patterns/03-components/listings/search-listings/search-listings.js
  • Size: 4.7 KB
  • Content:
    @import 'source/scss/01-settings/_import';
    @import 'source/scss/02-tools/_import';
    
    .search-listing {
        @extend %spacer-large;
    
        .listing__lazy-loader-content {
            &.loading {
                @extend %lazy-loader;
            }
        }
    }
    
  • URL: /components/raw/search-listings/search-listings.scss
  • Filesystem Path: source/patterns/03-components/listings/search-listings/search-listings.scss
  • Size: 238 Bytes

No notes defined.