PageSourceSearch

https://www.visitblekinge.se/modules/custom/common/cbis_product_list/js/app.js?tlvkaq

js visitblekinge.se collected 2026-09-24 21:34:06 UTC 48,654 bytes, 1,321 lines download raw bytes

1/**
2 *
3 */
4(function ($, drupalSettings, Vue) {
5  'use strict';
6  const msInDay = 1000 * 60 * 60 * 24;
7  var d = new Date();
8  // Bucketed to bound route-cache key cardinality (~10^16 -> 100 distinct
9  // values); the seed is stripped from the module's own cache key anyway,
10  // so this only affects Drupal's route cache. See issue #390.
11  var random = Math.floor(Math.random() * 100) / 100;
12  Vue.config.devtools = true;
13
14  $('[data-cbis-product-list]').each(function () {
15    var $this = $(this);
16    var nodeId = $this.data('cbis-product-list');
17    var facilityGroupsOperatorBetweenGroups = $this.data('facility-groups-operator-between-groups') || 'AND';
18    var facilityGroupsOperatorBetweenFacilitiesInSameGroup = $this.data('facility-groups-operator-between-facilities-in-same-group') || 'AND';
19    var settings = drupalSettings.productList[nodeId];
20    var occasionsSelectType = $this.data('occasions-select-type') ?? null;
21    var oneValuePerCustomFacilititesFilter = $this.data('one-per-custom-facilities-filter') ?? null;
22    var occasionsDefaultValue = null;
23
24    switch ($this.data('occasions-default-value')) {
25      case 'today':
26        occasionsDefaultValue = new Date();
27        break;
28      case 'tomorrow':
29        occasionsDefaultValue = new Date(+new Date() + 86400000);
30        break;
31    }
32    if (settings.viewMode.substring(0, 4) !== 'list' && !settings.viewMode.includes('slideshow')) {
33      return;
34    }
35    new Vue({
36      el: this,
37      delimiters: ['<%', '%>'],
38      data: {
39        node: nodeId,
40        payload: null,
41        busy: false, // Prevent multiple simultaneous loads
42        allProductsLoaded: false,
43        page: -1,
44        pageSize: settings.viewMode.includes('slideshow') ? 20 : null, // Only set pageSize for slideshow modes
45        fail: false,
46        items: [],
47        order: settings.order,
48        flyingXhr: null,
49        categoryTree: settings.categoryTree,
50        unfilteredCategoryTree: settings.unfilteredCategoryTree || {children: []},
51        monthData: settings.monthData,
52        geoTree: settings.geoTree,
53        arenas: settings.arenas,
54        arenaFilter: settings.arenaFilter,
55        facilities: settings.facilities,
56        maxProducts: settings.maxProducts,
57        showOccasionChooser: settings.showOccasionChooser,
58        totalFilter: 0,
59        totalCount: 0,
60        occasionCount: 0,
61        isDesktop: false,
62        isExplorer: false,
63        linkTitle: settings.linkTitle || null,
64        linkUrl: settings.linkUrl || null,
65        filter: {
66          categories: [],
67          geos: [],
68          arenas: [],
69          facilities: [],
70          search: '',
71        },
72        showFilter: {
73          all: false,
74          categories: false,
75          geos: false,
76          arenas: false,
77          facilities: false,
78          facilityMonths: false,
79          occasions: false,
80          extraFilter1: false,
81          extraFilter2: false,
82          extraFilter3: false,
83          extraFilter4: false,
84          extraFilter5: false,
85          extraFilter6: false,
86          extraFilter7: false,
87        },
88        facilityMonths: [],
89        facilityWithoutMonths: [],
90        filteredFacilitySelection: [],
91        drag: null,
92        swiper: null, // Store swiper instance
93        isAutoplayPaused: false, // Track autoplay state for pause/play button
94        adItemAdded: false, // Track if ad item has been added
95        occasions: occasionsDefaultValue ?? null,
96        formats: {
97          input: 'D MMM',
98        },
99        occasionsSelectType: occasionsSelectType,
100        iticketAvailabilityDates: {},
101        occasionsDefaultValue: occasionsDefaultValue,
102        oneValuePerCustomFacilititesFilter: oneValuePerCustomFacilititesFilter,
103      },
104      created: function () {
105        this.handleWindowResize();
106        this.extractMonthsFromFacilitiesAndSort();
107        this.extractFacilitiesWithoutMonths();
108        if (this.detectBrowser()) {
109          this.isExplorer = true;
110        }
111      },
112      mounted: function () {
113        this.loadFilter();
114        this.loadMore();
115        window.addEventListener('resize', this.handleWindowResize);
116
117        if (settings.viewMode !== 'list') {
118          this.swiper11Init();
119        }
120      },
121      computed: {
122        daySpan: function () {
123          const days = this.getDaySpan(this.drag || this.occasions);
124          return days ? days + ' days' : '';
125        },
126        orderByCurrentMonth: function () {
127          var m = d.getMonth();
128          var currentYear = d.getFullYear();
129          var oneYearPlus = d.getFullYear() + 1;
130          var fromMonth = this.facilityMonths.splice(m);
131          for (var i = 0; i < fromMonth.length; i++) {
132            fromMonth[i]['year'] = currentYear;
133          }
134          for (var j = 0; j < this.facilityMonths.length; j++) {
135            this.facilityMonths[j]['year'] = oneYearPlus;
136          }
137          return fromMonth.concat(this.facilityMonths);
138        },
139        skeletonLoaderCount: function () {
140          // Determine how many skeleton loaders to show based on viewport and settings
141          if (this.isDesktop) {
142            // Desktop: use the configured itemsPerSlide or default to 4
143            return settings.itemsPerSlide ? parseInt(settings.itemsPerSlide) : 4;
144          } else if (document.documentElement.clientWidth >= 640) {
145            // Medium devices (tablets): use itemsPerSlideMediumDevice or fallback
146            return settings.itemsPerSlideMediumDevice ? parseInt(settings.itemsPerSlideMediumDevice) : settings.itemsPerSlide > 1 ? 2 : 1;
147          } else {
148            // Small devices (mobile): use itemsPerSlideSmallDevice or default to 1
149            return settings.itemsPerSlideSmallDevice ? parseInt(settings.itemsPerSlideSmallDevice) : 1;
150          }
151        },
152      },
153      watch: {
154        filter: {
155          handler: function () {
156            this.reset();
157            this.loadMore();
158            this.saveFilter();
159            this.totalFilter = this.filter.categories.length + this.filter.geos.length + this.filter.arenas.length + this.filter.facilities.length + this.occasionCount;
160          },
161          deep: true,
162        },
163        occasions: function () {
164          this.reset();
165          this.loadMore();
166          this.saveFilter();
167          if (this.occasions && !this.occasionCount) {
168            this.occasionCount = 1;
169          }
170          this.totalFilter = this.filter.categories.length + this.filter.geos.length + this.filter.arenas.length + this.filter.facilities.length + this.occasionCount;
171        },
172        iticketAvailabilityDates: function (newVal) {
173          this.reset();
174          this.loadMore();
175          this.saveFilter();
176        },
177        items: function () {
178          if (this.swiper && settings.viewMode !== 'list') {
179            this.$nextTick(() => {
180              // Update Swiper to recognize new slides
181              this.swiper.update();
182
183              if (settings.autoPlay) {
184                this.swiper.autoplay.start();
185              }
186            });
187
188            // Add pause/play button if autoplay is enabled and items are loaded (only once)
189            if (settings.autoPlay && this.items.length > 0 && !this.autoplayControlButton) {
190              this.addAutoplayControl();
191            }
192          }
193        },
194      },
195
196      methods: {
197        swiper11Init: function () {
198          // Target only the product list swiper using specific class
199          const swiperEl = this.$el.querySelector('.product-list-swiper');
200          if (!swiperEl) {
201            return;
202          }
203
204          const vue = this;
205
206          // Build Swiper configuration
207          const swiperConfig = {
208            draggable: true,
209            slidesPerView: settings.slidesPerViewAuto ? 'auto' : settings.itemsPerSlideSmallDevice ? parseFloat(settings.itemsPerSlideSmallDevice) : 1,
210            slidesPerColumn: 1,
211            spaceBetween: settings.spaceBetweenSmall ? parseInt(settings.spaceBetweenSmall) : settings.spaceBetween ? parseInt(settings.spaceBetween) : 0,
212            watchOverflow: true,
213            autoplay: settings.autoPlay
214              ? {
215                  delay: settings.autoPlayDuration || 3000,
216                  disableOnInteraction: false,
217                  pauseOnMouseEnter: true,
218                }
219              : false,
220            // Loop mode (Swiper 4.5.3) silently drops slideNext() calls made
221            // while a transition is still animating, so repeated clicks on
222            // the next arrow skip products instead of advancing one-by-one.
223            // Keep autoplay's own advancing, but don't wrap end-to-start.
224            loop: false,
225            breakpoints: {
226              1024: {
227                slidesPerView: settings.slidesPerViewAuto ? 'auto' : settings.itemsPerSlide ? parseFloat(settings.itemsPerSlide) : 3,
228                spaceBetween: settings.spaceBetween ? parseInt(settings.spaceBetween) : 0,
229                slidesPerColumn: settings.slidesPerColumn ? parseInt(settings.slidesPerColumn) : 1,
230              },
231              640: {
232                slidesPerView: settings.slidesPerViewAuto ? 'auto' : settings.itemsPerSlideMediumDevice ? parseFloat(settings.itemsPerSlideMediumDevice) : settings.itemsPerSlide > 1 ? 2 : 1,
233                spaceBetween: settings.spaceBetweenMedium ? parseInt(settings.spaceBetweenMedium) : settings.spaceBetween ? parseInt(settings.spaceBetween) : 0,
234              },
235            },
236            pagination: {
237              el: '.swiper-pagination',
238              dynamicBullets: true,
239              clickable: true,
240              type: settings.paginationType ? settings.paginationType : 'bullets',
241            },
242            navigation: {
243              nextEl: '.swiper-button-next',
244              prevEl: '.swiper-button-prev',
245            },
246            a11y: {
247              prevSlideMessage: Drupal.t('Previous slide'),
248              nextSlideMessage: Drupal.t('Next slide'),
249            },
250            on: {
251              slideChange: function () {
252                // Check if we've reached max products limit
253                if (settings.maxProducts && vue.items.length >= settings.maxProducts) {
254                  return;
255                }
256
257                // Check if already loading or all products loaded
258                if (vue.busy || vue.allProductsLoaded) {
259                  return;
260                }
261
262                // Get the number of slides currently visible
263                const slidesPerView = this.params.slidesPerView === 'auto' ? 1 : this.params.slidesPerView;
264
265                // In loop mode, realIndex gives us the actual slide position (not the duplicated ones)
266                const actualIndex = this.params.loop ? this.realIndex : this.activeIndex;
267
268                // Calculate how many actual items we have vs displayed slides
269                const actualItemCount = vue.items.length;
270                const slidesFromEnd = actualItemCount - (actualIndex + slidesPerView);
271
272                // Load more when we're within one full view of the end of actual items
273                if (slidesFromEnd <= slidesPerView && slidesFromEnd >= 0) {
274                  vue.loadMoreSlides(this);
275                }
276              },
277              reachEnd: function () {
278                // In loop mode, this event might not fire properly, rely on slideChange
279                if (!settings.autoPlay && !vue.busy) {
280                  vue.loadMoreSlides(this);
281                }
282              },
283            },
284          };
285
286          const swiper = new Swiper(swiperEl, swiperConfig);
287
288          vue.swiper = swiper;
289        },
290
291        loadMoreSlides: function (swiper) {
292          if (!swiper) {
293            return;
294          }
295
296          // Check if we've reached max products limit
297          if (this.maxProducts && this.items.length >= this.maxProducts) {
298            return;
299          }
300
301          if (this.busy || this.allProductsLoaded) {
302            return;
303          }
304
305          // Load more slides logic here
306          this.loadMore();
307        },
308
309        addAutoplayControl: function () {
310          const vue = this;
311          const swiperEl = this.$el.querySelector('.swiper') || this.$el.querySelector('.swiper-container');
312          if (!swiperEl) {
313            return;
314          }
315
316          // Create pause/play button
317          const controlButton = document.createElement('button');
318          controlButton.className = 'btn btn-primary swiper-autoplay-control-btn';
319          controlButton.setAttribute('aria-label', Drupal.t('Pause slideshow'));
320          controlButton.innerHTML =
321            '<span class="sr-only">' + Drupal.t('Pause slideshow') + '</span><svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/></svg>';
322
323          // Find pagination element to position button next to it
324          const paginationEl = swiperEl.querySelector('.swiper-pagination');
325          let buttonPosition = 'right: 15px;';
326
327          if (paginationEl) {
328            // Position button to the right of pagination
329            buttonPosition = 'left: calc(50% + 70px);'; // Adjust positioning relative to centered pagination
330          }
331
332          controlButton.style.cssText = `
333            ${buttonPosition}
334          `;
335
336          // Add click handler
337          controlButton.addEventListener('click', function () {
338            vue.toggleAutoplay();
339          });
340
341          // Append to swiper container
342          swiperEl.appendChild(controlButton);
343          vue.autoplayControlButton = controlButton;
344        },
345
346        toggleAutoplay: function () {
347          if (!this.swiper || !settings.autoPlay) {
348            return;
349          }
350
351          if (this.isAutoplayPaused) {
352            this.swiper.autoplay.start();
353            this.isAutoplayPaused = false;
354            this.updateAutoplayButton();
355          } else {
356            this.swiper.autoplay.stop();
357            this.isAutoplayPaused = true;
358            this.updateAutoplayButton();
359          }
360        },
361
362        updateAutoplayButton: function () {
363          if (!this.autoplayControlButton) {
364            return;
365          }
366
367          if (this.isAutoplayPaused) {
368            this.autoplayControlButton.setAttribute('aria-label', Drupal.t('Play slideshow'));
369            this.autoplayControlButton.innerHTML =
370              '<span class="sr-only">' + Drupal.t('Play slideshow') + '</span><svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7z"/></svg>';
371          } else {
372            this.autoplayControlButton.setAttribute('aria-label', Drupal.t('Pause slideshow'));
373            this.autoplayControlButton.innerHTML =
374              '<span class="sr-only">' + Drupal.t('Pause slideshow') + '</span><svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/></svg>';
375          }
376        },
377
378        extractMonthsFromFacilitiesAndSort: function () {
379          if (!this.monthData) {
380            this.facilityMonths = this.facilities
381              .filter(function (key) {
382                return key.id >= 100847 && key.id <= 100858;
383              })
384              .sort(function (a, b) {
385                return a.id - b.id;
386              });
387          } else {
388            this.facilityMonths = this.monthData;
389          }
390        },
391        extractFacilitiesWithoutMonths: function () {
392          this.facilityWithoutMonths = this.facilities.filter(function (key) {
393            return key.id < 100847 || key.id > 100858;
394          });
395        },
396        formatOccasionObject: function () {
397          let occasionObject = null;
398          let vue = this;
399          if (vue.occasionsSelectType == 'singleDate') {
400            occasionObject = {
401              from: vue.formatOccasionDate(vue.occasions) ?? '',
402              to: vue.formatOccasionDate(vue.occasions) ?? '',
403            };
404          } else {
405            occasionObject = {
406              from: vue.occasions ? vue.formatOccasionDate(vue.occasions.start) : '',
407              to: vue.occasions ? vue.formatOccasionDate(vue.occasions.end) : '',
408            };
409          }
410          return occasionObject;
411        },
412        loadMore: function () {
413          var vue = this;
414          if (this.maxProducts && this.items.length >= this.maxProducts) {
415            return;
416          }
417          if (vue.busy || vue.allProductsLoaded || vue.fail) {
418            return;
419          }
420          vue.busy = true;
421          if (vue.flyingXhr) {
422            vue.flyingXhr.abort();
423          }
424          var url = (settings.host || '').replace('http://', '//').replace('https://', '//') + '/' + drupalSettings.path.pathPrefix + 'api/cbis-product-list';
425
426          let occasionObject = vue.formatOccasionObject();
427
428          vue.payload = null;
429
430          vue.payload = {
431            nodeId: vue.node,
432            page: vue.page + 1,
433            facilityGroupsOperatorBetweenGroups: facilityGroupsOperatorBetweenGroups,
434            facilityGroupsOperatorBetweenFacilitiesInSameGroup: facilityGroupsOperatorBetweenFacilitiesInSameGroup,
435            categories: vue.filter.categories,
436            geos: vue.filter.geos,
437            arenas: vue.filter.arenas,
438            facilities: vue.filter.facilities,
439            search: vue.filter.search,
440            order: vue.order,
441            randomSeed: random,
442            occasion: occasionObject,
443            imagetag: settings.imagetag,
444            iticketAvailabilityDates: vue.iticketAvailabilityDates,
445          };
446
447          // Only include pageSize for slideshow view modes
448          if (vue.pageSize !== null) {
449            vue.payload.pageSize = vue.pageSize;
450          }
451
452          vue.flyingXhr = $.getJSON(url, vue.payload, function (data) {
453           // var items = data.items;
454            var totalCount = data.totalCount;
455            if (data.items.length) {
456              data.items.forEach(function (item, index) {
457                 // After 1 loop - go and create appendAdItem
458                if (index == 1 && settings.adItemNumber && !vue.adItemAdded) {
459                  vue.appendAdItem();
460                  vue.adItemAdded = true;
461                }
462
463                vue.items.push(item);
464              });
465              vue.page++;
466            } else {
467              vue.allProductsLoaded = true;
468            }
469            /* Add if all products loaded at once*/
470            if (vue.items.length === data.totalCount) {
471              vue.allProductsLoaded = true;
472            }
473            /* if (vue.linkTitle && vue.linkUrl && (vue.items.length === parseInt(vue.maxProducts)) && settings.viewMode === 'slideshow') {
474              vue.appendSlide(); // Append a slide last in the slideshow (Dalarna)
475            } // Removed from Dalarna - if we want it again, add another setting?
476            */
477            vue.totalCount = totalCount;
478            vue.busy = false;
479
480            // @TODO: create an event for these, and fire when items are created
481            // e.g:
482            // let event = new Event("cbis_product_list_loaded")
483            // document.dispatchEvent(event);
484
485            if (typeof FavouriteNode != 'undefined') {
486              setTimeout(FavouriteNode.update, 300);
487            }
488
489            if (typeof Iticket != 'undefined') {
490              let startingAfterOccasion = occasionObject && typeof occasionObject.from != 'undefined' ? occasionObject.from : null;
491              let startingUntilOccasion = occasionObject && typeof occasionObject.to != 'undefined' ? occasionObject.to : null;
492
493              let iTicketDates = {
494                StartingAfter: vue.iticketAvailabilityDates && typeof vue.iticketAvailabilityDates.from != 'undefined' ? vue.iticketAvailabilityDates.from : startingAfterOccasion,
495                StartingUntil: vue.iticketAvailabilityDates && typeof vue.iticketAvailabilityDates.to != 'undefined' ? vue.iticketAvailabilityDates.to : startingUntilOccasion,
496              };
497
498              setTimeout(function () {
499                Iticket.updateAll('cbis-product-teaser', vue.node, iTicketDates);
500              }, 300);
501            }
502          })
503            .fail(function () {
504              vue.busy = false;
505              vue.fail = true;
506            })
507            .always(function () {
508              vue.flyingXhr = null;
509            });
510        },
511        appendSlide: function () {
512          if (this.items.length === parseInt(this.maxProducts)) {
513            this.items.push(
514              '<div class="view-more-items">' +
515                ' <a href="' +
516                this.linkUrl +
517                '" rel="bookmark">' +
518                '   <div class="more-items">' +
519                this.linkTitle +
520                '     <i class="fas fa-angle-right"></i>' +
521                '   </div>' +
522                ' </a>' +
523                '</div>'
524            );
525          }
526        },
527
528        /** Camping ads */
529        appendAdItem: function () {
530          let adItemNumber = settings.adItemNumber || 'swipe1';
531          let isMobile = window.innerWidth < 980; // Bootstrap lg breakpoint
532          let divId = isMobile ? 'mobile-' + adItemNumber : 'desktop-' + adItemNumber;
533          let style = isMobile ? 'min-width: 250px; min-height: 360px;' : 'min-width: 250px; min-height: 360px;';
534
535          this.items.push(
536            '<div class="ads-teaser ads-wrapper-list-' +
537              adItemNumber +
538              '" style=\'' +
539              style +
540              "'>\n" +
541              '  <div id="' +
542              divId +
543              '" style="' +
544              style +
545              '"></div>\n' +
546              '  <strong class="ads-teaser-label">' +
547              Drupal.t('Advertisement') +
548              '</strong>\n' +
549              '</div>'
550          );
551        },
552
553        detectBrowser: function () {
554          var ua = window.navigator.userAgent;
555          var trident = ua.indexOf('Trident/');
556          if (trident > 0) {
557            // IE 11 => return version number
558            var rv = ua.indexOf('rv:');
559            return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10);
560          } else {
561            return 0;
562          }
563        },
564        reset: function () {
565          if (this.flyingXhr) {
566            this.flyingXhr.abort();
567            this.flyingXhr = null;
568          }
569          this.busy = false;
570          this.fail = false;
571          this.page = -1;
572          this.items = [];
573          this.allProductsLoaded = false;
574          this.adItemAdded = false; // Reset ad item flag when resetting
575        },
576        loadFilter: function () {
577          var vue = this;
578          var key = vue.cookieKey();
579          var value = Cookies.get(key) || '';
580          if (0 === value.length) {
581            return;
582          }
583          var filter = JSON.parse(value);
584          vue.filter = {
585            categories: filter.categories || [],
586            geos: filter.geos || [],
587            arenas: filter.arenas || [],
588            facilities: filter.facilities || [],
589          };
590
591          if (oneValuePerCustomFacilititesFilter) {
592            this.loadFilterOneValuePerCustomFacility();
593          }
594        },
595        loadFilterOneValuePerCustomFacility: function () {
596          var vue = this;
597          var filteredFacilityGroupkey = vue.cookieFilteredFacilityKey();
598          var filteredFacilityGroupValue = Cookies.get(filteredFacilityGroupkey) || '';
599          if (0 === filteredFacilityGroupValue.length) {
600            return;
601          }
602          vue.filteredFacilitySelection = JSON.parse(filteredFacilityGroupValue);
603        },
604        saveFilter: function () {
605          var vue = this;
606          var key = vue.cookieKey();
607          var value = JSON.stringify(vue.filter);
608          Cookies.set(key, value);
609        },
610        handleWindowResize: function (event) {
611          // whenever the document is resized, re-set the 'fullHeight' variable
612          if (document.documentElement.clientWidth > 1024) {
613            this.isDesktop = true;
614          } else {
615            this.isDesktop = false;
616          }
617        },
618        clearFilters: function () {
619          this.filter = {
620            categories: [],
621            geos: [],
622            arenas: [],
623            facilities: [],
624            search: '',
625          };
626          this.occasions = null;
627          this.occasionCount = null;
628          this.showFilter = {
629            all: false,
630            categories: false,
631            geos: false,
632            arenas: false,
633            facilities: false,
634            facilityMonths: false,
635            occasions: false,
636            extraFilter1: false,
637            extraFilter2: false,
638            extraFilter3: false,
639            extraFilter4: false,
640            extraFilter5: false,
641            extraFilter6: false,
642            extraFilter7: false,
643          };
644        },
645        clearFilter: function (type) {
646          switch (type) {
647            case 'facilities':
648              this.filter.facilities = {};
649              break;
650            case 'categories':
651              this.filter.categories = [];
652              break;
653            case 'geos':
654              this.filter.geos = [];
655              break;
656            case 'arenas':
657              this.filter.arenas = [];
658              break;
659            case 'informationFields':
660              this.filter.informationFields = [];
661              break;
662            default:
663              return;
664          }
665        },
666        toggleFilter: function (filterType) {
667          if (filterType == 'categories') {
668            this.showFilter = {
669              all: false,
670              categories: !this.showFilter.categories,
671              geos: false,
672              arenas: false,
673              facilities: false,
674              facilityMonths: false,
675              occasions: false,
676              extraFilter1: false,
677              extraFilter2: false,
678              extraFilter3: false,
679              extraFilter4: false,
680              extraFilter5: false,
681              extraFilter6: false,
682              extraFilter7: false,
683            };
684          } else if (filterType == 'facilities') {
685            this.showFilter = {
686              all: false,
687              categories: false,
688              geos: false,
689              arenas: false,
690              facilities: !this.showFilter.facilities,
691              facilityMonths: false,
692              occasions: false,
693              extraFilter1: false,
694              extraFilter2: false,
695              extraFilter3: false,
696              extraFilter4: false,
697              extraFilter5: false,
698              extraFilter6: false,
699              extraFilter7: false,
700            };
701          } else if (filterType == 'facilityMonths') {
702            this.showFilter = {
703              all: false,
704              categories: false,
705              geos: false,
706              arenas: false,
707              facilities: false,
708              facilityMonths: !this.showFilter.facilityMonths,
709              occasions: false,
710              extraFilter1: false,
711              extraFilter2: false,
712              extraFilter3: false,
713              extraFilter4: false,
714              extraFilter5: false,
715              extraFilter6: false,
716              extraFilter7: false,
717            };
718          } else if (filterType == 'extraFilter1') {
719            this.showFilter = {
720              all: false,
721              categories: false,
722              geos: false,
723              arenas: false,
724              facilities: false,
725              facilityMonths: false,
726              occasions: false,
727              extraFilter1: !this.showFilter.extraFilter1,
728              extraFilter2: false,
729              extraFilter3: false,
730              extraFilter4: false,
731              extraFilter5: false,
732              extraFilter6: false,
733              extraFilter7: false,
734            };
735          } else if (filterType == 'extraFilter2') {
736            this.showFilter = {
737              all: false,
738              categories: false,
739              geos: false,
740              arenas: false,
741              facilities: false,
742              facilityMonths: false,
743              occasions: false,
744              extraFilter1: false,
745              extraFilter2: !this.showFilter.extraFilter2,
746              extraFilter3: false,
747              extraFilter4: false,
748              extraFilter5: false,
749              extraFilter6: false,
750              extraFilter7: false,
751            };
752          } else if (filterType == 'extraFilter3') {
753            this.showFilter = {
754              all: false,
755              categories: false,
756              geos: false,
757              arenas: false,
758              facilities: false,
759              facilityMonths: false,
760              occasions: false,
761              extraFilter1: false,
762              extraFilter2: false,
763              extraFilter3: !this.showFilter.extraFilter3,
764              extraFilter4: false,
765              extraFilter5: false,
766              extraFilter6: false,
767              extraFilter7: false,
768            };
769          } else if (filterType == 'extraFilter4') {
770            this.showFilter = {
771              all: false,
772              categories: false,
773              geos: false,
774              arenas: false,
775              facilities: false,
776              facilityMonths: false,
777              occasions: false,
778              extraFilter1: false,
779              extraFilter2: false,
780              extraFilter3: false,
781              extraFilter4: !this.showFilter.extraFilter4,
782              extraFilter5: false,
783              extraFilter6: false,
784              extraFilter7: false,
785            };
786          } else if (filterType == 'extraFilter5') {
787            this.showFilter = {
788              all: false,
789              categories: false,
790              geos: false,
791              arenas: false,
792              facilities: false,
793              facilityMonths: false,
794              occasions: false,
795              extraFilter1: false,
796              extraFilter2: false,
797              extraFilter3: false,
798              extraFilter4: false,
799              extraFilter5: !this.showFilter.extraFilter5,
800              extraFilter6: false,
801              extraFilter7: false,
802            };
803          } else if (filterType == 'extraFilter6') {
804            this.showFilter = {
805              all: false,
806              categories: false,
807              geos: false,
808              arenas: false,
809              facilities: false,
810              facilityMonths: false,
811              occasions: false,
812              extraFilter1: false,
813              extraFilter2: false,
814              extraFilter3: false,
815              extraFilter4: false,
816              extraFilter5: false,
817              extraFilter6: !this.showFilter.extraFilter6,
818              extraFilter7: false,
819            };
820          } else if (filterType == 'extraFilter7') {
821            this.showFilter = {
822              all: false,
823              categories: false,
824              geos: false,
825              arenas: false,
826              facilities: false,
827              facilityMonths: false,
828              occasions: false,
829              extraFilter1: false,
830              extraFilter2: false,
831              extraFilter3: false,
832              extraFilter4: false,
833              extraFilter5: false,
834              extraFilter6: false,
835              extraFilter7: !this.showFilter.extraFilter7,
836            };
837          } else if (filterType == 'geos') {
838            this.showFilter = {
839              all: false,
840              categories: false,
841              geos: !this.showFilter.geos,
842              facilities: false,
843              facilityMonths: false,
844              occasions: false,
845              extraFilter1: false,
846              extraFilter2: false,
847              extraFilter3: false,
848              extraFilter4: false,
849              extraFilter5: false,
850              extraFilter6: false,
851              extraFilter7: false,
852            };
853          } else if (filterType == 'arenas') {
854            this.showFilter = {
855              all: false,
856              categories: false,
857              geos: false,
858              arenas: !this.showFilter.arenas,
859              facilities: false,
860              facilityMonths: false,
861              occasions: false,
862              extraFilter1: false,
863              extraFilter2: false,
864              extraFilter3: false,
865              extraFilter4: false,
866              extraFilter5: false,
867              extraFilter6: false,
868              extraFilter7: false,
869            };
870          } else if (filterType == 'all') {
871            this.showFilter = {
872              all: !this.showFilter.all,
873              categories: !!(this.categoryTree && Object.keys(this.categoryTree.children).length > 0),
874              geos: !!(this.categoryTree && Object.keys(this.categoryTree.children).length == 0) && this.geoTree && Object.keys(this.geoTree.children).length > 0,
875              arenas: !!this.arenas,
876              facilities: !!(this.categoryTree && Object.keys(this.categoryTree.children).length == 0) && this.geoTree && Object.keys(this.geoTree.children).length == 0 && this.facilities,
877              facilityMonths: false,
878              occasions: !!this.occasions,
879              extraFilter1: false,
880              extraFilter2: false,
881              extraFilter3: false,
882              extraFilter4: false,
883              extraFilter5: false,
884              extraFilter6: false,
885              extraFilter7: false,
886            };
887          }
888        },
889        toggleMobileFilter: function (filterType) {
890          if (filterType == 'categories') {
891            this.showFilter = {
892              all: true,
893              categories: true,
894              geos: false,
895              arenas: false,
896              facilities: false,
897              facilityMonths: false,
898              occasions: false,
899              extraFilter1: false,
900              extraFilter2: false,
901              extraFilter3: false,
902              extraFilter4: false,
903              extraFilter5: false,
904              extraFilter6: false,
905              extraFilter7: false,
906            };
907          } else if (filterType == 'facilities') {
908            this.showFilter = {
909              all: true,
910              categories: false,
911              geos: false,
912              arenas: false,
913              facilities: true,
914              facilityMonths: false,
915              occasions: false,
916              extraFilter1: false,
917              extraFilter2: false,
918              extraFilter3: false,
919              extraFilter4: false,
920              extraFilter5: false,
921              extraFilter6: false,
922              extraFilter7: false,
923            };
924          } else if (filterType == 'geos') {
925            //this.showFilter.all = false;
926            this.showFilter = {
927              all: true,
928              categories: false,
929              geos: true,
930              arenas: false,
931              facilities: false,
932              facilityMonths: false,
933              occasions: false,
934              extraFilter1: false,
935              extraFilter2: false,
936              extraFilter3: false,
937              extraFilter4: false,
938              extraFilter5: false,
939              extraFilter6: false,
940              extraFilter7: false,
941            };
942          } else if (filterType == 'arenas') {
943            //this.showFilter.all = false;
944            this.showFilter = {
945              all: true,
946              categories: false,
947              geos: false,
948              arenas: true,
949              facilities: false,
950              facilityMonths: false,
951              occasions: false,
952              extraFilter1: false,
953              extraFilter2: false,
954              extraFilter3: false,
955              extraFilter4: false,
956              extraFilter5: false,
957              extraFilter6: false,
958              extraFilter7: false,
959            };
960          } else if (filterType == 'extraFilter1') {
961            //this.showFilter.all = false;
962            this.showFilter = {
963              all: true,
964              categories: false,
965              geos: false,
966              arenas: false,
967              facilities: false,
968              facilityMonths: false,
969              occasions: false,
970              extraFilter1: true,
971              extraFilter2: false,
972              extraFilter3: false,
973              extraFilter4: false,
974              extraFilter5: false,
975              extraFilter6: false,
976              extraFilter7: false,
977            };
978          } else if (filterType == 'extraFilter2') {
979            //this.showFilter.all = false;
980            this.showFilter = {
981              all: true,
982              categories: false,
983              geos: false,
984              arenas: false,
985              facilities: false,
986              facilityMonths: false,
987              occasions: false,
988              extraFilter1: false,
989              extraFilter2: true,
990              extraFilter3: false,
991              extraFilter4: false,
992              extraFilter5: false,
993              extraFilter6: false,
994              extraFilter7: false,
995            };
996          } else if (filterType == 'extraFilter3') {
997            //this.showFilter.all = false;
998            this.showFilter = {
999              all: true,
1000              categories: false,
1001              geos: false,
1002              arenas: false,
1003              facilities: false,
1004              facilityMonths: false,
1005              occasions: false,
1006              extraFilter1: false,
1007              extraFilter2: false,
1008              extraFilter3: true,
1009              extraFilter4: false,
1010              extraFilter5: false,
1011              extraFilter6: false,
1012              extraFilter7: false,
1013            };
1014          } else if (filterType == 'extraFilter4') {
1015            //this.showFilter.all = false;
1016            this.showFilter = {
1017              all: true,
1018              categories: false,
1019              geos: false,
1020              arenas: false,
1021              facilities: false,
1022              facilityMonths: false,
1023              occasions: false,
1024              extraFilter1: false,
1025              extraFilter2: false,
1026              extraFilter3: false,
1027              extraFilter4: true,
1028              extraFilter5: false,
1029              extraFilter6: false,
1030              extraFilter7: false,
1031            };
1032          } else if (filterType == 'extraFilter5') {
1033            //this.showFilter.all = false;
1034            this.showFilter = {
1035              all: true,
1036              categories: false,
1037              geos: false,
1038              arenas: false,
1039              facilities: false,
1040              facilityMonths: false,
1041              occasions: false,
1042              extraFilter1: false,
1043              extraFilter2: false,
1044              extraFilter3: false,
1045              extraFilter4: false,
1046              extraFilter5: true,
1047              extraFilter6: false,
1048              extraFilter7: false,
1049            };
1050          } else if (filterType == 'extraFilter6') {
1051            //this.showFilter.all = false;
1052            this.showFilter = {
1053              all: true,
1054              categories: false,
1055              geos: false,
1056              arenas: false,
1057              facilities: false,
1058              facilityMonths: false,
1059              occasions: false,
1060              extraFilter1: false,
1061              extraFilter2: false,
1062              extraFilter3: false,
1063              extraFilter4: false,
1064              extraFilter5: false,
1065              extraFilter6: true,
1066              extraFilter7: false,
1067            };
1068          } else if (filterType == 'extraFilter7') {
1069            //this.showFilter.all = false;
1070            this.showFilter = {
1071              all: true,
1072              categories: false,
1073              geos: false,
1074              arenas: false,
1075              facilities: false,
1076              facilityMonths: false,
1077              occasions: false,
1078              extraFilter1: false,
1079              extraFilter2: false,
1080              extraFilter3: false,
1081              extraFilter4: false,
1082              extraFilter5: false,
1083              extraFilter6: false,
1084              extraFilter7: true,
1085            };
1086          } else if (filterType == 'apply') {
1087            this.showFilter = {
1088              all: false,
1089              categories: false,
1090              geos: false,
1091              arenas: false,
1092              facilities: false,
1093              facilityMonths: false,
1094              occasions: false,
1095              extraFilter1: false,
1096              extraFilter2: false,
1097              extraFilter3: false,
1098              extraFilter4: false,
1099              extraFilter5: false,
1100              extraFilter6: false,
1101              extraFilter7: false,
1102            };
1103          } else if (filterType == 'occasions') {
1104            // this.showFilter.all = false;
1105            this.showFilter = {
1106              all: true,
1107              categories: false,
1108              geos: false,
1109              arenas: false,
1110              facilities: false,
1111              facilityMonths: false,
1112              occasions: true,
1113              extraFilter1: false,
1114              extraFilter2: false,
1115              extraFilter3: false,
1116              extraFilter4: false,
1117              extraFilter5: false,
1118              extraFilter6: false,
1119              extraFilter7: false,
1120            };
1121          }
1122        },
1123        clearDate: function () {
1124          this.occasions = null;
1125          this.occasionCount = null;
1126        },
1127
1128        clearSearch: function () {
1129          this.filter.search = '';
1130        },
1131
1132        formatOccasionDate: function (d) {
1133          if (!d) {
1134            return '';
1135          }
1136          var month = '' + (d.getMonth() + 1),
1137            day = '' + d.getDate(),
1138            year = d.getFullYear();
1139          if (month.length < 2) {
1140            month = '0' + month;
1141          }
1142          if (day.length < 2) {
1143            day = '0' + day;
1144          }
1145          return [year, month, day].join('-');
1146        },
1147        getDaySpan: function (range) {
1148          if (!range) return 0;
1149          return Math.round((range.end - range.start) / msInDay + 1);
1150        },
1151        categoryById: function (id) {
1152          id = parseInt(id);
1153          var found = this.categoryTree.children.find(function (c) { return parseInt(c.id) === id; })
1154            || this.unfilteredCategoryTree.children.find(function (c) { return parseInt(c.id) === id; });
1155          return found || { id: id, text: '' };
1156        },
1157        geoById: function (id) {
1158          var found = null;
1159          id = parseInt(id);
1160          this.geoTree.children.forEach(function (geo) {
1161            if (parseInt(geo.id) === id) {
1162              found = geo;
1163            }
1164          });
1165          return found;
1166        },
1167        arenaById: function (id) {
1168          var found = null;
1169          id = parseInt(id);
1170          this.arenas.forEach(function (arena) {
1171            if (parseInt(arena.id) === id) {
1172              found = arena;
1173            }
1174          });
1175          return found;
1176        },
1177        facilityById: function (id) {
1178          var found = null;
1179          id = parseInt(id);
1180          this.facilities.forEach(function (facility) {
1181            if (parseInt(facility.id) === id) {
1182              found = facility;
1183            }
1184          });
1185          return found;
1186        },
1187        facilityIdExists: function (values) {
1188          var found = false;
1189          this.facilities.forEach(function (facility) {
1190            if (values.indexOf(parseInt(facility.id)) !== -1) {
1191              found = true;
1192            }
1193          });
1194          return found;
1195        },
1196        removeFilter: function (type, index) {
1197          switch (type) {
1198            case 'facilities':
1199              this.filter.facilities.splice(index, 1);
1200              break;
1201            case 'categories':
1202              this.filter.categories.splice(index, 1);
1203              break;
1204            case 'geos':
1205              this.filter.geos.splice(index, 1);
1206              break;
1207            case 'arenas':
1208              this.filter.arenas.splice(index, 1);
1209              break;
1210            default:
1211              return;
1212          }
1213        },
1214
1215        /**
1216         * Following fve functions are used together with the functionality for oneValuePerCustomFacilititesFilter,
1217         * which makes the custom facilities filters act like radio buttons.
1218         * If not passing a value for group and group = 'default', multiple custom facilities groups will not work properly,
1219         * Please pass a unique group value to make multiple custom facilities filters work.
1220         */
1221        selectOneFacilityPerGroup: function (facility, group = 'default') {
1222          if (!this.filteredFacilitySelection.some((item) => item.groupKey === group)) {
1223            this.filteredFacilitySelection.push({ id: facility.id, groupKey: group, label: facility.label });
1224          } else {
1225            var existingItem = this.filteredFacilitySelection.find((item) => item.groupKey === group);
1226            if (existingItem && existingItem.id === facility.id) {
1227              this.clearOneFacilityFilterGroup(group);
1228            } else if (existingItem) {
1229              existingItem.id = facility.id;
1230              existingItem.label = facility.label;
1231            }
1232          }
1233          this.filter.facilities = this.filteredFacilitySelection.map((item) => item.id);
1234          this.storefilteredFacilitySelection();
1235        },
1236        isFilterGroupSelected: function (groupKey = 'default') {
1237          var existingItem = this.filteredFacilitySelection.find((item) => item.groupKey === groupKey);
1238          return typeof existingItem !== 'undefined';
1239        },
1240        clearOneFacilityFilterGroup: function (group = 'default') {
1241          this.filteredFacilitySelection = this.filteredFacilitySelection.filter((item) => item.groupKey !== group);
1242          this.filter.facilities = this.filteredFacilitySelection.map((item) => item.id);
1243        },
1244        storefilteredFacilitySelection: function () {
1245          var vue = this;
1246          var key = vue.cookieFilteredFacilityKey();
1247          var value = JSON.stringify(vue.filteredFacilitySelection);
1248          Cookies.set(key, value);
1249        },
1250        cookieFilteredFacilityKey: function () {
1251          return 'cbis-product-list-selected-filter-' + (drupalSettings.cssJsQueryString || '') + '-' + nodeId;
1252        },
1253
1254        cookieKey: function () {
1255          return 'cbis-product-list-filter-' + (drupalSettings.cssJsQueryString || '') + '-' + nodeId;
1256        },
1257        outsideCategories: function (e) {
1258          this.showFilter.categories = false;
1259        },
1260        outsideFacilities: function (e) {
1261          this.showFilter.facilities = false;
1262        },
1263        outsideGeo: function (e) {
1264          this.showFilter.geos = false;
1265        },
1266        outsideArena: function (e) {
1267          this.showFilter.arenas = false;
1268        },
1269        outsideExtraFilter1: function (e) {
1270          this.showFilter.extraFilter1 = false;
1271        },
1272        outsideExtraFilter2: function (e) {
1273          this.showFilter.extraFilter2 = false;
1274        },
1275        outsideExtraFilter3: function () {
1276          this.showFilter.extraFilter3 = false;
1277        },
1278        outsideExtraFilter4: function () {
1279          this.showFilter.extraFilter4 = false;
1280        },
1281        outsideExtraFilter5: function () {
1282          this.showFilter.extraFilter5 = false;
1283        },
1284        outsideExtraFilter6: function () {
1285          this.showFilter.extraFilter6 = false;
1286        },
1287        outsideExtraFilter7: function () {
1288          this.showFilter.extraFilter7 = false;
1289        },
1290      },
1291      directives: {
1292        'click-outside': {
1293          bind: function (el, binding, vNode) {
1294            // Provided expression must evaluate to a function.
1295            if (typeof binding.value !== 'function') {
1296              const compName = vNode.context.name;
1297              /*let warn = `[Vue-click-outside:] provided expression '${binding.expression}' is not a function, but has to be`
1298                            if (compName) { warn += `Found in component '${compName}'` }*/
1299              console.warn(warn);
1300            }
1301            // Define Handler and cache it on the element
1302            const bubble = binding.modifiers.bubble;
1303            const handler = function (e) {
1304              if (bubble || (!el.contains(e.target) && el !== e.target)) {
1305                binding.value(e);
1306              }
1307            };
1308            el.__vueClickOutside__ = handler;
1309            // add Event Listeners
1310            document.addEventListener('click', handler);
1311          },
1312          unbind: function (el, binding) {
1313            // Remove Event Listeners
1314            document.removeEventListener('click', el.__vueClickOutside__);
1315            el.__vueClickOutside__ = null;
1316          },
1317        },
1318      },
1319    });
1320  });
1321})(jQuery, drupalSettings, Vue);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.