PageSourceSearch

https://fstec.ru/media/com_minitekwall/js/minitekwall.js?02c71e

js fstec.ru collected 2026-10-02 03:46:12 UTC 176,765 bytes, 3,968 lines download raw bytes

1((document, Joomla) => {
2    "use strict";
3
4    class Mwall {
5        /*
6         * Constructor
7         */
8        constructor(options, id, count, source, path, elements, itemid) {
9            this.options = options;
10            this.widgetId = parseInt(id, 10);
11            this.totalCount = parseInt(count, 10);
12            this.sourceId = source;
13            this.path = path;
14            this.elements = elements;
15            this.itemid = itemid;
16
17            this.urlHash =
18                typeof this.options.mas_url_hash === "undefined" ||
19                this.options.mas_url_hash == 0
20                    ? false
21                    : true;
22            this.filtersMode = this.options.mas_filters_mode;
23            var wallSortings =
24                this.options.mas_title_sorting != 0 ||
25                this.options.mas_date_sorting != 0 ||
26                this.options.mas_hits_sorting != 0 ||
27                this.options.mas_sorting_direction != 0
28                    ? true
29                    : false;
30            this.filtersEnabled =
31                this.options.mas_category_filters != 0 ||
32                this.options.mas_tag_filters != 0 ||
33                this.options.mas_date_filters != 0 ||
34                wallSortings
35                    ? true
36                    : false;
37            this.multipleFilters =
38                typeof this.options.mas_multiple_filters === "undefined" ||
39                this.options.mas_multiple_filters == 0
40                    ? false
41                    : true;
42            this.tagsLogicalOperator =
43                typeof this.options.mas_tags_logical_operator === "undefined"
44                    ? "OR"
45                    : this.options.mas_tags_logical_operator;
46            this.pagination = parseInt(this.options.mas_pagination, 10);
47            this.hoverBox = this.options.mas_hb != 0 ? true : false;
48            this.dateFiltersFormat =
49                typeof this.options.mas_date_filters_format === "undefined"
50                    ? "Y-m"
51                    : this.options.mas_date_filters_format;
52            this.timer;
53            this.ignoreVideos = true;
54            this.fluidHeight = false;
55            this.videoSource =
56                typeof this.options.videoSource === "undefined"
57                    ? false
58                    : this.options.videoSource;
59
60            // Hash filters
61            if (this.urlHash) this.hash_filters = this.getHashFilters();
62
63            // Initialize wall
64            this.initializeWall();
65
66            // Initialize filters
67            this.filters = {
68                category: [],
69                tag: [],
70                date: [],
71                ordering: "",
72                direction: "",
73                search: "",
74            };
75
76            // Dynamic filters
77            if (
78                this.container &&
79                this.filtersEnabled &&
80                this.filtersMode == "dynamic"
81            )
82                this.dynamicFilters();
83
84            // Trigger reset buttons
85            if (
86                this.container &&
87                this.filtersMode == "dynamic" &&
88                (this.filtersEnabled || this.options.mas_search_filter)
89            )
90                this.triggerResetButtons();
91
92            // Static filters
93            if (
94                this.container &&
95                this.filtersEnabled &&
96                this.filtersMode == "static"
97            )
98                this.staticFilters();
99
100            // Pagination
101            if (this.container && this.pagination != 0)
102                this.initializePagination();
103
104            // Pagination - Append
105            if (this.container && this.pagination === 1)
106                this.appendPagination();
107
108            // Pagination - Infinite
109            if (this.container && this.pagination === 4) {
110                this.infScroll = false;
111                this.infinitePagination();
112            }
113
114            // Pagination - Pages
115            if (this.container && this.pagination === 3) this.pagesPagination();
116
117            // Pagination - Arrows
118            if (this.container && this.pagination === 2)
119                this.arrowsPagination();
120
121            if (this.container && this.hoverBox) {
122                // Modal images
123                if (parseInt(this.options.mas_hb_zoom, 10))
124                    this.initModalMessages();
125            }
126
127            // Check if we are inside an iframe
128            this.isIframe = window.frameElement ? true : false;
129
130            if (this.isIframe) {
131                if (document.querySelector(".mwall-description"))
132                    document.querySelector(".mwall-description").style.padding =
133                        "20px";
134
135                if (document.querySelector(".mwall-results-empty-results"))
136                    document.querySelector(
137                        ".mwall-results-empty-results"
138                    ).style.padding = "20px";
139                else if (this.container) this.container.style.padding = "20px";
140            }
141        }
142
143        initializeWall() {
144            const self = this;
145
146            this.pageLimit = parseInt(this.options.mas_page_limit, 10);
147            this.closeFilters =
148                this.options.mas_close_filters != 0 ? true : false;
149            this.scrollToTop =
150                this.options.mas_pag_scroll_to_top != 0 ? true : false;
151            this.container = document.querySelector(
152                "#mwall_container_" + this.widgetId
153            );
154
155            if (this.container == null) return;
156
157            this.gridType = parseInt(this.options.mas_grid, 10);
158            if (this.gridType == 999) this.gridType = self.elements.length;
159
160            switch (this.gridType) {
161                case 98:
162                    this.layoutType = "columns";
163                    break;
164                case 99:
165                    this.layoutType = "list";
166                    break;
167                default:
168                    this.layoutType = "masonry";
169                    break;
170            }
171
172            this.fluidHeight =
173                this.layoutType == "list" ||
174                (this.layoutType == "columns" &&
175                    (this.options.mas_preserve_aspect_ratio ||
176                        this.options.videoSource));
177
178            this.layoutMode = this.options.mas_layout_mode;
179            this.dbPosition = this.options.mas_db_position_columns;
180            this.equalHeight =
181                this.options.mas_force_equal_height != 0 ? true : false;
182            this.sortBy = this.container.getAttribute("data-order");
183            this.sortDirection =
184                this.container.getAttribute("data-direction") == null
185                    ? ""
186                    : this.container
187                          .getAttribute("data-direction")
188                          .toLowerCase();
189            this.sortAscending = this.sortDirection == "asc" ? true : false;
190
191            if (
192                this.sortBy == "RAND()" ||
193                this.sortBy == "rand" ||
194                this.sortBy == "random" ||
195                this.sourceId == "rss"
196            ) {
197                this.sortBy = ["index"];
198                this.sortAscending = true;
199            } else this.sortBy = [this.sortBy, "id", "title"];
200
201            this.createSpinner(
202                document.querySelector("#mwall_loader_" + this.widgetId)
203            );
204            document.querySelector(
205                "#mwall_loader_" + this.widgetId
206            ).style.display = "block";
207            this.transitionDuration = parseInt(
208                this.options.mas_transition_duration,
209                10
210            );
211            this.transitionStagger = parseInt(
212                this.options.mas_transition_stagger,
213                10
214            );
215            this.scrollThreshold = 100;
216            this.iso_container = document.querySelector(
217                "#mwall_items_" + this.widgetId
218            );
219            this.wall;
220            var effects = this.options.mas_effects
221                ? this.options.mas_effects
222                : ["fade"];
223            var hiddenOpacity = 1;
224            var hiddenTransform = "scale(1)";
225
226            if (effects.includes("fade")) hiddenOpacity = 0;
227            if (effects.includes("scale")) hiddenTransform = "scale(0.001)";
228
229            var imgLoad = imagesLoaded(self.iso_container, {
230                background: ".mwall-photo-link",
231            });
232
233            imgLoad.on("done", function () {
234    let update_wall = function () {
235        self.wall = new Isotope(self.iso_container, {
236            itemSelector: ".mwall-item",
237            layoutMode: self.layoutMode,
238            vertical: {
239                horizontalAlignment: 0,
240            },
241            initLayout: false,
242            stagger: self.transitionStagger,
243            transitionDuration: self.transitionDuration,
244            hiddenStyle: {
245                opacity: hiddenOpacity,
246                transform: hiddenTransform,
247            },
248            visibleStyle: {
249                opacity: 1,
250                transform: "scale(1)",
251            },
252            getSortData: {
253                ordering: "[data-ordering] parseInt",
254                fordering: "[data-fordering] parseInt",
255                hits: "[data-hits] parseInt",
256                title: function (itemElem) {
257                    if (itemElem.querySelector(".mwall-title")) {
258                        let title =
259                            itemElem.querySelector(
260                                ".mwall-title"
261                            ).textContent;
262
263                        return self.removeAccents(title);
264                    }
265                },
266                id: "[data-id] parseInt",
267                alias: "[data-alias]",
268                date: "[data-date]",
269                modified: "[data-modified]",
270                start: "[data-start]",
271                finish: "[data-finish]",
272                index: "[data-index] parseInt",
273            },
274        });
275
276        self.container.style.display = "block";
277
278        if (self.filtersEnabled && self.filtersMode == "static") {
279            self.wall.arrange({
280                sortBy: ["index"],
281                sortAscending: { index: true },
282            });
283        } else {
284            self.wall.arrange({
285                sortBy: self.sortBy,
286                sortAscending: self.sortAscending,
287            });
288        }
289
290        self.fixEqualHeights("all");
291        self.container.style.opacity = 1;
292        document.querySelector(
293            "#mwall_loader_" + self.widgetId
294        ).style.display = "none";
295
296        // FIXED: Force re-layout after images are fully loaded to fix height issues
297        setTimeout(function() {
298            if (self.wall) {
299                self.wall.arrange();
300            }
301        }, 100);
302
303        // Setup search after wall is created
304        if (self.container && self.options.mas_search_filter && self.filtersMode == "dynamic") {
305            self.setupSearchInput();
306        }
307
308        // Hash filters
309        if (self.urlHash && self.filtersEnabled) self.hashFilters();
310    };
311
312    if (self.videoSource) self.videosReady(update_wall);
313
314    if (self.ignoreVideos) update_wall();
315});
316
317            // Handle broken images
318            imgLoad.on("progress", function (instance, image) {
319                var result = image.isLoaded ? "loaded" : "broken";
320                if (result == "broken") {
321                    console.log("Image not found: " + image.img.src);
322
323                    let div = document.createElement("div");
324                    div.innerHTML =
325                        "Image not found: <b>" + image.img.src + "</b>";
326                    let targetDiv = self.container;
327                    let parentDiv = targetDiv.parentNode;
328                    parentDiv.insertBefore(div, targetDiv);
329
330                    document.querySelector(
331                        "#mwall_loader_" + self.widgetId
332                    ).style.display = "none";
333                }
334            });
335
336            // Handle resize
337            var _resize;
338
339            window.addEventListener("resize", function () {
340                clearTimeout(_resize);
341
342                _resize = setTimeout(function () {
343                    self.doneBrowserResizing();
344                }, 500);
345            });
346        }
347
348        // FIXED: Общий метод для применения всех фильтров
349        applyFilters() {
350            const self = this;
351
352            // Get search value
353            var searchValue = self.filters["search"] || '';
354            var search_regex = searchValue ? new RegExp(searchValue, "gi") : null;
355
356            // Get filter value from active filters
357            var filterValue = "";
358
359            // Multiple filters
360            if (self.multipleFilters) {
361                var permutations = self.combineArrays(self.filters);
362                filterValue = permutations.join(", ");
363            }
364            // Single filters
365            else {
366                for (var prop in self.filters) {
367                    if (prop == "search") continue;
368                    for (var filter in prop) {
369                        if (self.filters[prop][filter])
370                            filterValue += self.filters[prop][filter];
371                    }
372                }
373            }
374
375            // Manual filtering through CSS
376            var allItems = self.wall.getItemElements();
377            
378            var visibleItems = [];
379            
380            for (var i = 0; i < allItems.length; i++) {
381                var item = allItems[i];
382                var shouldShow = true;
383                
384                // Check search filter
385                if (search_regex) {
386                    var titleElement = item.querySelector(".mwall-title");
387                    if (titleElement) {
388                        var title = titleElement.textContent || '';
389                        if (!search_regex.test(title)) {
390                            shouldShow = false;
391                        }
392                    } else {
393                        shouldShow = false;
394                    }
395                }
396                
397                // Check category/tag/date filters
398                if (shouldShow && filterValue) {
399                    if (!item.matches(filterValue)) {
400                        shouldShow = false;
401                    }
402                }
403                
404                if (shouldShow) {
405                    visibleItems.push(item);
406                }
407            }
408            
409            // Hide all items first
410            allItems.forEach(function(item) {
411                item.style.display = 'none';
412            });
413            
414            // Show only visible items
415            visibleItems.forEach(function(item) {
416                item.style.display = '';
417            });
418            
419            // Force Isotope to re-layout
420            self.wall.layout();
421            
422            // Update results message
423            setTimeout(function() {
424                self.resultsMessage(self, visibleItems);
425            }, 100);
426
427            self.resizeItems();
428
429            // Hide reset button in pagination if no filters active
430            var hasActiveFilters = false;
431            for (var prop in self.filters) {
432                if (prop === 'search' && self.filters[prop]) {
433                    hasActiveFilters = true;
434                    break;
435                }
436                if (prop !== 'search' && self.filters[prop] && self.filters[prop].length > 0) {
437                    hasActiveFilters = true;
438                    break;
439                }
440            }
441            
442            if (!hasActiveFilters && self.container.querySelector(".mwall-reset-btn")) {
443                self.container.querySelector(".mwall-reset-btn").style.display = "none";
444            }
445
446            // Update url hash
447            if (self.urlHash) {
448                // Update hash for all filter groups
449                for (var group in self.filters) {
450                    if (group === 'search') {
451                        if (self.filters[group]) {
452                            self.hash_filters.set(group, self.filters[group]);
453                        } else {
454                            self.hash_filters.delete(group);
455                        }
456                    } else if (self.filters[group].length) {
457                        self.hash_filters.set(group, self.filters[group].join());
458                    } else {
459                        self.hash_filters.delete(group);
460                    }
461                }
462                self.updateHash();
463            }
464        }
465
466        setupSearchInput() {
467            const self = this;
468
469            if (!self.container.querySelector(".mwall-search-input")) {
470                return;
471            }
472
473            var searchInput = self.container.querySelector(".mwall-search-input");
474
475            // Remove any existing listeners to prevent duplicates
476            if (searchInput._searchListenerAttached) {
477                return;
478            }
479            searchInput._searchListenerAttached = true;
480
481            // Helper function to check if Isotope is fully ready
482            function isIsotopeReady() {
483                if (!self.wall) return false;
484                
485                var items = self.wall.getFilteredItemElements();
486                if (!items || items.length === 0) return false;
487                
488                for (var i = 0; i < Math.min(items.length, 5); i++) {
489                    if (items[i] && typeof items[i].querySelector === 'function') {
490                        if (items[i].querySelector(".mwall-title")) {
491                            return true;
492                        }
493                    }
494                }
495                return false;
496            }
497
498            searchInput.addEventListener("input", function (e) {
499                e.preventDefault();
500                let _this = e.target;
501
502                // Wait for 800ms before searching
503                window.clearTimeout(self.timer);
504
505                self.timer = window.setTimeout(function () {
506                    // Check if wall is ready
507                    if (!isIsotopeReady()) {
508                        // Try again after 500ms
509                        setTimeout(function() {
510                            if (isIsotopeReady()) {
511                                self.filters["search"] = _this.value;
512                                self.applyFilters();
513                            } else {
514                                // Store the value and try again on next input
515                                _this._pendingSearch = _this.value;
516                            }
517                        }, 500);
518                        return;
519                    }
520                    
521                    // Check if there's a pending search from previous attempt
522                    if (_this._pendingSearch) {
523                        var pendingValue = _this._pendingSearch;
524                        _this._pendingSearch = null;
525                        self.filters["search"] = pendingValue;
526                        self.applyFilters();
527                        return;
528                    }
529                    
530                    self.filters["search"] = _this.value;
531                    self.applyFilters();
532                }, 800);
533            });
534        }
535
536        removeAccents(string) {
537            return string
538                .toLowerCase()
539                .replace(/[áàãâä]/gi, "a")
540                .replace(/[éèëê]/gi, "e")
541                .replace(/[íìïî]/gi, "i")
542                .replace(/[óòöôõø]/gi, "o")
543                .replace(/[úùüû]/gi, "u")
544                .replace(/[ç]/gi, "c")
545                .replace(/[ñ]/gi, "n");
546        }
547
548        videosReady(callback) {
549            const self = this;
550            self.ignoreVideos = true;
551            const _videos = self.iso_container.querySelectorAll("video");
552
553            if (_videos.length) {
554                let videos = [];
555
556                _videos.forEach((a) => {
557                    if (a.readyState == 0) videos.push(a);
558                });
559
560                if (videos.length) {
561                    self.ignoreVideos = false;
562                    let states = [];
563
564                    for (let i = 0; i < videos.length; i++) {
565                        states.push(0);
566                    }
567
568                    let promise = new Promise(function (resolve) {
569                        Object.keys(videos).forEach((key) => {
570                            videos[key].addEventListener("loadeddata", () => {
571                                states[key] = videos[key].readyState;
572
573                                // If all videos ready (readyState >=3), resolve promise
574                                if (states.every((v) => v >= 3))
575                                    resolve(states);
576                            });
577                        });
578                    });
579
580                    promise.then(function (value) {
581                        callback();
582                    });
583                }
584            }
585        }
586
587        hashFilters() {
588            const self = this;
589
590            let hash_category = self.hash_filters.get("category");
591            let hash_tag = self.hash_filters.get("tag");
592            let hash_date = self.hash_filters.get("date");
593            let hash_ordering = self.hash_filters.get("ordering");
594            let hash_direction = self.hash_filters.get("direction");
595            let hash_search = self.hash_filters.get("search");
596            let hash_filters =
597                hash_category ||
598                hash_tag ||
599                hash_date ||
600                hash_ordering ||
601                hash_direction ||
602                hash_search;
603
604            if (self.filtersMode == "dynamic") {
605                if (hash_category)
606                    self.filters["category"] = hash_category.split(",");
607                if (hash_tag) self.filters["tag"] = hash_tag.split(",");
608
609                var data_attr = "data-filter";
610            } else if (self.filtersMode == "static") {
611                if (hash_category)
612                    self.filters["category"] = hash_category
613                        .split(",")
614                        .map(Number);
615                if (hash_tag)
616                    self.filters["tag"] = hash_tag.split(",").map(Number);
617                if (hash_ordering) self.filters["ordering"] = hash_ordering;
618                if (hash_direction) self.filters["direction"] = hash_direction;
619
620                var data_attr = "data-id";
621            }
622
623            if (hash_date) self.filters["date"] = hash_date.split(",");
624            
625            // FIXED: Восстанавливаем поиск из hash
626            if (hash_search) {
627                self.filters["search"] = hash_search;
628                // Заполняем поле поиска
629                var searchInput = self.container.querySelector(".mwall-search-input");
630                if (searchInput) {
631                    searchInput.value = hash_search;
632                }
633            }
634
635            if (hash_filters) {
636                if (self.filtersMode == "static") {
637                    // Show loader
638                    document.querySelector(
639                        "#mwall_loader_" + self.widgetId
640                    ).style.display = "block";
641
642                    // Hide container
643                    self.container.style.display = "none";
644                    self.container.style.opacity = 0;
645                }
646
647                // Hide results message
648                self.container.querySelector(".mwall-no-items").style.display =
649                    "none";
650
651                // Show reset button in pagination
652                if (
653                    self.filters["category"].length ||
654                    self.filters["tag"].length ||
655                    self.filters["date"].length ||
656                    self.filters["search"]
657                ) {
658                    if (self.container.querySelector(".mwall-reset-btn")) {
659                        self.container.querySelector(
660                            ".mwall-reset-btn"
661                        ).style.display = "inline-block";
662
663                        if (self.filtersMode == "static") {
664                            self.container
665                                .querySelector(".mwall-reset-btn")
666                                .addEventListener("click", function (e) {
667                                    e.preventDefault();
668
669                                    self.resetStaticFilters();
670                                });
671                        }
672                    }
673                }
674
675                // Set active categories
676                if (
677                    self.filters["category"].length &&
678                    self.container.querySelector(".button-group-category")
679                ) {
680                    self.container
681                        .querySelector(".button-group-category")
682                        .querySelector(".mwall-filter[data-filter='']")
683                        .classList.remove("mwall-filter-active");
684
685                    self.filters["category"].forEach(function (a) {
686                        if (
687                            self.container
688                                .querySelector(".button-group-category")
689                                .querySelector(
690                                    ".mwall-filter[" +
691                                        data_attr +
692                                        "='" +
693                                        a +
694                                        "']"
695                                )
696                        )
697                            self.container
698                                .querySelector(".button-group-category")
699                                .querySelector(
700                                    ".mwall-filter[" +
701                                        data_attr +
702                                        "='" +
703                                        a +
704                                        "']"
705                                )
706                                .classList.add("mwall-filter-active");
707                    });
708
709                    // Show name in dropdown
710                    if (
711                        self.container
712                            .querySelector(".button-group-category")
713                            .closest(".mwall-dropdown")
714                    ) {
715                        let cat_text = self.container
716                            .querySelector(".button-group-category")
717                            .querySelector(".mwall-filter-active").textContent;
718                        self.container
719                            .querySelector(".button-group-category")
720                            .closest(".mwall-dropdown")
721                            .querySelector(
722                                ".dropdown-label span span"
723                            ).textContent = cat_text;
724                    }
725                }
726
727                // Set active tags
728                if (
729                    self.filters["tag"].length &&
730                    self.container.querySelector(".button-group-tag")
731                ) {
732                    self.container
733                        .querySelector(".button-group-tag")
734                        .querySelector(".mwall-filter[data-filter='']")
735                        .classList.remove("mwall-filter-active");
736
737                    self.filters["tag"].forEach(function (a) {
738                        if (
739                            self.container
740                                .querySelector(".button-group-tag")
741                                .querySelector(
742                                    ".mwall-filter[" +
743                                        data_attr +
744                                        "='" +
745                                        a +
746                                        "']"
747                                )
748                        )
749                            self.container
750                                .querySelector(".button-group-tag")
751                                .querySelector(
752                                    ".mwall-filter[" +
753                                        data_attr +
754                                        "='" +
755                                        a +
756                                        "']"
757                                )
758                                .classList.add("mwall-filter-active");
759                    });
760
761                    // Show name in dropdown
762                    if (
763                        self.container
764                            .querySelector(".button-group-tag")
765                            .closest(".mwall-dropdown")
766                    ) {
767                        let tag_text = self.container
768                            .querySelector(".button-group-tag")
769                            .querySelector(".mwall-filter-active").textContent;
770                        self.container
771                            .querySelector(".button-group-tag")
772                            .closest(".mwall-dropdown")
773                            .querySelector(
774                                ".dropdown-label span span"
775                            ).textContent = tag_text;
776                    }
777                }
778
779                // Set active dates
780                if (
781                    self.filters["date"].length &&
782                    self.container.querySelector(".button-group-date")
783                ) {
784                    self.container
785                        .querySelector(".button-group-date")
786                        .querySelector(".mwall-filter[data-filter='']")
787                        .classList.remove("mwall-filter-active");
788
789                    self.filters["date"].forEach(function (a) {
790                        if (
791                            self.container
792                                .querySelector(".button-group-date")
793                                .querySelector(
794                                    ".mwall-filter[" +
795                                        data_attr +
796                                        "='" +
797                                        a +
798                                        "']"
799                                )
800                        )
801                            self.container
802                                .querySelector(".button-group-date")
803                                .querySelector(
804                                    ".mwall-filter[" +
805                                        data_attr +
806                                        "='" +
807                                        a +
808                                        "']"
809                                )
810                                .classList.add("mwall-filter-active");
811                    });
812
813                    // Show name in dropdown
814                    if (
815                        self.container
816                            .querySelector(".button-group-date")
817                            .closest(".mwall-dropdown")
818                    ) {
819                        let date_text = self.container
820                            .querySelector(".button-group-date")
821                            .querySelector(".mwall-filter-active").textContent;
822                        self.container
823                            .querySelector(".button-group-date")
824                            .closest(".mwall-dropdown")
825                            .querySelector(
826                                ".dropdown-label span span"
827                            ).textContent = date_text;
828                    }
829                }
830
831                // Ordering
832                if (
833                    self.container.querySelector(".sorting-group-filters") &&
834                    (hash_ordering == "title" ||
835                        hash_ordering == "date" ||
836                        hash_ordering == "hits")
837                ) {
838                    if (self.filtersMode == "dynamic") {
839                        // Add second ordering: id
840                        let sort_Ordering = [hash_ordering, "id"];
841
842                        // Update Isotope
843                        self.wall.arrange({
844                            sortBy: sort_Ordering,
845                        });
846                    }
847
848                    // Change active class
849                    self.container
850                        .querySelector(".sorting-group-filters")
851                        .querySelectorAll(".mwall-filter")
852                        .forEach(function (a) {
853                            a.classList.remove("mwall-filter-active");
854                        });
855                    self.container
856                        .querySelector(".sorting-group-filters")
857                        .querySelector(
858                            ".mwall-filter[data-sort-value='" +
859                                hash_ordering +
860                                "']"
861                        )
862                        .classList.add("mwall-filter-active");
863
864                    // Show name in dropdown
865                    if (
866                        self.container
867                            .querySelector(".sorting-group-filters")
868                            .closest(".mwall-dropdown")
869                    ) {
870                        let sorting_text = self.container
871                            .querySelector(".sorting-group-filters")
872                            .querySelector(".mwall-filter-active").textContent;
873                        self.container
874                            .querySelector(".sorting-group-filters")
875                            .closest(".mwall-dropdown")
876                            .querySelector(
877                                ".dropdown-label span span"
878                            ).textContent = sorting_text;
879                    }
880                }
881
882                // Direction
883                if (
884                    self.container.querySelector(".sorting-group-direction") &&
885                    (hash_direction == "asc" || hash_direction == "de
885sc")
886                ) {
887                    if (self.filtersMode == "dynamic") {
888                        let sort_Direction;
889
890                        if (hash_direction == "asc") sort_Direction = true;
891                        else sort_Direction = false;
892
893                        // Update Isotope
894                        self.wall.arrange({
895                            sortAscending: sort_Direction,
896                        });
897                    }
898
899                    // Change active class
900                    self.container
901                        .querySelector(".sorting-group-direction")
902                        .querySelectorAll(".mwall-filter")
903                        .forEach(function (a) {
904                            a.classList.remove("mwall-filter-active");
905                        });
906                    self.container
907                        .querySelector(".sorting-group-direction")
908                        .querySelector(
909                            ".mwall-filter[data-sort-value='" +
910                                hash_direction +
911                                "']"
912                        )
913                        .classList.add("mwall-filter-active");
914
915                    // Show name in dropdown
916                    if (
917                        self.container
918                            .querySelector(".sorting-group-direction")
919                            .closest(".mwall-dropdown")
920                    ) {
921                        let sorting_text = self.container
922                            .querySelector(".sorting-group-direction")
923                            .querySelector(".mwall-filter-active").textContent;
924                        self.container
925                            .querySelector(".sorting-group-direction")
926                            .closest(".mwall-dropdown")
927                            .querySelector(
928                                ".dropdown-label span span"
929                            ).textContent = sorting_text;
930                    }
931                }
932
933                // FIXED: Применяем все фильтры (включая поиск) через общий метод
934                if (self.filtersMode == "dynamic") {
935                    // Применяем фильтры через общий метод
936                    self.applyFilters();
937                } else if (self.filtersMode == "static") {
938                    // Filters data
939                    let data = {
940                        category: self.filters["category"],
941                        tag: self.filters["tag"],
942                        date: self.filters["date"],
943                        ordering: self.filters["ordering"],
944                        direction: self.filters["direction"],
945                        search: self.filters["search"],
946                    };
947
948                    // Remove current items
949                    var elems = self.wall.getItemElements();
950                    self.wall.remove(elems);
951
952                    // Ajax request
953                    Joomla.request({
954                        url:
955                            self.path +
956                            "index.php?option=com_minitekwall&task=masonry.getContent&widget_id=" +
957                            self.widgetId +
958                            "&page=1" +
959                            "&tag_operator=" +
960                            self.tagsLogicalOperator +
961                            "&date_format=" +
962                            self.dateFiltersFormat +
963                            "&grid=" +
964                            self.layoutType +
965                            "&Itemid=" +
966                            self.itemid,
967                        method: "POST",
968                        data: JSON.stringify(data),
969                        onSuccess: (response, xhr) => {
970                            if (response.length > 3) {
971                                // Show container
972                                self.container.style.display = "block";
973
974                                var newItems = self.htmlToElements(
975                                    response,
976                                    ".mwall-item"
977                                );
978
979                                newItems.forEach(function (a) {
980                                    a.style.visibility = "hidden";
981                                    if (self.fluidHeight)
982                                        self.iso_container.appendChild(a);
983                                });
984
985                                self.wall.once(
986                                    "layoutComplete",
987                                    function (items) {
988                                        self.resultsMessage(self, items);
989                                    }
990                                );
991
992                                var imgLoad = imagesLoaded(self.iso_container, {
993                                    background: ".mwall-photo-link",
994                                });
995
996                                imgLoad.on("done", function () {
997                                    let update_wall = function () {
998                                        if (self.fluidHeight)
999                                            self.wall.appended(newItems);
1000                                        else self.wall.insert(newItems);
1001                                        self.wall.arrange();
1002                                        self.wall.updateSortData();
1003                                        self.fixEqualHeights(newItems);
1004
1005                                        newItems.forEach(function (a) {
1006                                            a.style.visibility = "visible";
1007                                        });
1008
1009                                        // Hide loader
1010                                        document.querySelector(
1011                                            "#mwall_loader_" + self.widgetId
1012                                        ).style.display = "none";
1013
1014                                        // Show container
1015                                        self.container.style.opacity = 1;
1016
1017                                        if (self.pagination != 0)
1018                                            self.updatePagination(data);
1019                                    };
1020
1021                                    if (self.videoSource)
1022                                        self.videosReady(update_wall);
1023
1024                                    if (self.ignoreVideos) update_wall();
1025                                });
1026                            }
1027                        },
1028                        onError: function onError(xhr) {
1029                            if (xhr.status > 0) {
1030                                Joomla.renderMessages(
1031                                    Joomla.ajaxErrorsMessages(xhr)
1032                                );
1033                            }
1034                        },
1035                    });
1036                }
1037            }
1038        }
1039
1040        resultsMessage(self, items) {
1041            if (items.length == 0) {
1042                self.container.querySelector(".mwall-no-items").style.display =
1043                    "block";
1044            } else {
1045                self.container.querySelector(".mwall-no-items").style.display =
1046                    "none";
1047            }
1048        }
1049
1050        reindexItem(grid, index) {
1051            const self = this;
1052
1053            if (index > grid) {
1054                index = index - grid;
1055                index = self.reindexItem(grid, index);
1056            }
1057
1058            return index;
1059        }
1060
1061        resizeItem(grid, index) {
1062            const self = this;
1063            let size;
1064
1065            switch (grid) {
1066                // Custom grids
1067                case "999c":
1068                    let elements = self.elements;
1069
1070                    switch (elements[index - 1].size) {
1071                        case "S":
1072                            size = "mwall-small";
1073                            break;
1074                        case "L":
1075                            size = "mwall-horizontal";
1076                            break;
1077                        case "P":
1078                            size = "mwall-vertical";
1079                            break;
1080                        case "B":
1081                            size = "mwall-big";
1082                            break;
1083                    }
1084                    break;
1085
1086                // Preset grids
1087                case "1":
1088                    size = "mwall-big";
1089                    break;
1090
1091                case "3a":
1092                    if (index == "1") {
1093                        size = "mwall-big";
1094                    } else {
1095                        size = "mwall-horizontal";
1096                    }
1097                    break;
1098
1099                case "3b":
1100                    if (index == "2") {
1101                        size = "mwall-big";
1102                    } else {
1103                        size = "mwall-horizontal";
1104                    }
1105                    break;
1106
1107                case "3c":
1108                    if (index == "1") {
1109                        size = "mwall-big";
1110                    } else {
1111                        size = "mwall-vertical";
1112                    }
1113                    break;
1114
1115                case "4":
1116                    if (index == "1") {
1117                        size = "mwall-big";
1118                    } else if (index == "2") {
1119                        size = "mwall-horizontal";
1120                    } else {
1121                        size = "mwall-small";
1122                    }
1123                    break;
1124
1125                case "5":
1126                    if (index == "1" || index == "5") {
1127                        size = "mwall-horizontal";
1128                    } else if (index == "2" || index == "4") {
1129                        size = "mwall-small";
1130                    } else {
1131                        size = "mwall-big";
1132                    }
1133                    break;
1134
1135                case "5b":
1136                    if (index == "3") {
1137                        size = "mwall-big";
1138                    } else {
1139                        size = "mwall-small";
1140                    }
1141                    break;
1142
1143                case "6":
1144                    if (index == "1") {
1145                        size = "mwall-big";
1146                    } else if (index == "3") {
1147                        size = "mwall-horizontal";
1148                    } else {
1149                        size = "mwall-small";
1150                    }
1151                    break;
1152
1153                case "7":
1154                    if (index == "1") {
1155                        size = "mwall-big";
1156                    } else if (index == "2") {
1157                        size = "mwall-horizontal";
1158                    } else if (index == "4") {
1159                        size = "mwall-vertical";
1160                    } else {
1161                        size = "mwall-small";
1162                    }
1163                    break;
1164
1165                case "8":
1166                    if (index == "1" || index == "7" || index == "8") {
1167                        size = "mwall-horizontal";
1168                    } else if (index == "2") {
1169                        size = "mwall-big";
1170                    } else if (index == "6") {
1171                        size = "mwall-vertical";
1172                    } else {
1173                        size = "mwall-small";
1174                    }
1175                    break;
1176
1177                case "9":
1178                    if (index == "1") {
1179                        size = "mwall-big";
1180                    } else if (index == "2") {
1181                        size = "mwall-horizontal";
1182                    } else if (index == "4" || index == "5" || index == "6") {
1183                        size = "mwall-vertical";
1184                    } else {
1185                        size = "mwall-small";
1186                    }
1187                    break;
1188
1189                case "9r":
1190                    if (index == "1" || index == "2" || index == "3") {
1191                        size = "mwall-horizontal";
1192                    } else if (index == "4" || index == "5") {
1193                        size = "mwall-big";
1194                    } else {
1195                        size = "mwall-small";
1196                    }
1197                    break;
1198
1199                case "12r":
1200                    if (
1201                        index == "1" ||
1202                        index == "2" ||
1203                        index == "3" ||
1204                        index == "4"
1205                    ) {
1206                        size = "mwall-horizontal";
1207                    } else if (
1208                        index == "10" ||
1209                        index == "11" ||
1210                        index == "12"
1211                    ) {
1212                        size = "mwall-big";
1213                    } else {
1214                        size = "mwall-small";
1215                    }
1216                    break;
1217
1218                case "16r":
1219                    if (
1220                        index == "1" ||
1221                        index == "5" ||
1222                        index == "7" ||
1223                        index == "15"
1224                    ) {
1225                        size = "mwall-horizontal";
1226                    } else {
1227                        size = "mwall-small";
1228                    }
1229                    break;
1230            }
1231
1232            return size;
1233        }
1234
1235        resizeItems() {
1236            const self = this;
1237            let items = self.wall.getFilteredItemElements();
1238
1239            // Resize items
1240            if (self.layoutType == "masonry") {
1241                items.forEach((item, i) => {
1242                    // Remove classes
1243                    item.classList.remove(
1244                        "mwall-small",
1245                        "mwall-horizontal",
1246                        "mwall-vertical",
1247                        "mwall-big",
1248                        "mwall-item1",
1249                        "mwall-item2",
1250                        "mwall-item3",
1251                        "mwall-item4",
1252                        "mwall-item5",
1253                        "mwall-item6",
1254                        "mwall-item7",
1255                        "mwall-item8",
1256                        "mwall-item9",
1257                        "mwall-item10",
1258                        "mwall-item11",
1259                        "mwall-item12",
1260                        "mwall-item13",
1261                        "mwall-item14",
1262                        "mwall-item15",
1263                        "mwall-item16"
1264                    );
1265
1266                    // Re-index
1267                    let index = i + 1;
1268                    item.setAttribute("data-index", index);
1269                    index = self.reindexItem(self.gridType, index);
1270
1271                    // Resize
1272                    let size = self.resizeItem(self.options.mas_grid, index);
1273
1274                    // Add new classes
1275                    item.classList.add(size, "mwall-item" + index);
1276                });
1277            }
1278
1279            self.wall.arrange();
1280        }
1281
1282        arrowsPagination() {
1283            const self = this;
1284            let wrapper = self.container.querySelector(
1285                ".mwall-pagination-wrapper"
1286            );
1287
1288            wrapper.addEventListener("click", function (e) {
1289                e.preventDefault();
1290
1291                if (e.target.classList.contains("mwall-arrow"))
1292                    var _this = e.target;
1293                else if (e.target.closest(".mwall-arrow"))
1294                    var _this = e.target.closest(".mwall-arrow");
1295                else return false;
1296
1297                if (
1298                    _this.classList.contains("disabled") ||
1299                    self.container.classList.contains("mwall-loading")
1300                )
1301                    return false;
1302
1303                // Find page
1304                var page = _this.getAttribute("data-page");
1305                page = parseInt(page, 10);
1306
1307                var prev_page = page - 1;
1308                var next_page = page + 1;
1309
1310                // Check if there is a pending ajax request
1311                if (typeof ajax_request !== "undefined") {
1312                    ajax_request.abort();
1313                    self.container.classList.remove("mwall-loading");
1314                    self.container.querySelector(
1315                        ".mwall-more-results"
1316                    ).style.display = "block";
1317                    self.container.querySelector(
1318                        ".mwall-arrow-loader"
1319                    ).style.display = "none";
1320                }
1321
1322                // Show loader
1323                self.container.classList.add("mwall-loading");
1324                _this.classList.add("arrow-loading");
1325                _this.querySelector(".mwall-more-results").style.display =
1326                    "none";
1327                _this.querySelector(".mwall-arrow-loader").style.display =
1328                    "block";
1329
1330                // Filters data
1331                var data = {};
1332
1333                if (self.filtersMode == "static") {
1334                    data = {
1335                        category: self.filters["category"],
1336                        tag: self.filters["tag"],
1337                        date: self.filters["date"],
1338                        ordering: self.filters["ordering"],
1339                        direction: self.filters["direction"],
1340                        search: self.filters["search"],
1341                    };
1342                }
1343
1344                // Remove current items
1345                var elems = self.wall.getItemElements();
1346                self.wall.remove(elems);
1347
1348                // Ajax request
1349                var ajax_request = Joomla.request({
1350                    url:
1351                        self.path +
1352                        "index.php?option=com_minitekwall&task=masonry.getContent&widget_id=" +
1353                        self.widgetId +
1354                        "&page=" +
1355                        page +
1356                        "&tag_operator=" +
1357                        self.tagsLogicalOperator +
1358                        "&date_format=" +
1359                        self.dateFiltersFormat +
1360                        "&grid=" +
1361                        self.layoutType +
1362                        "&Itemid=" +
1363                        self.itemid,
1364                    method: "POST",
1365                    data: JSON.stringify(data),
1366                    onSuccess: (response, xhr) => {
1367                        if (response.length > 3) {
1368                            // Increment/decrement page
1369                            self.container
1370                                .querySelector(".mwall-arrow-prev")
1371                                .setAttribute("data-page", prev_page);
1372                            self.container
1373                                .querySelector(".mwall-arrow-next")
1374                                .setAttribute("data-page", next_page);
1375
1376                            // Reset filters
1377                            if (
1378                                self.filtersMode == "dynamic" &&
1379                                (self.filtersEnabled ||
1380                                    self.options.mas_search_filter)
1381                            )
1382                                self.resetFilters();
1383
1384                            var newItems = self.htmlToElements(
1385                                response,
1386                                ".mwall-item"
1387                            );
1388
1389                            newItems.forEach(function (a) {
1390                                a.style.visibility = "hidden";
1391                                if (self.fluidHeight)
1392                                    self.iso_container.appendChild(a);
1393                            });
1394
1395                            var imgLoad = imagesLoaded(self.iso_container, {
1396                                background: ".mwall-photo-link",
1397                            });
1398
1399                            imgLoad.on("done", function () {
1400                                let update_wall = function () {
1401                                    if (self.fluidHeight)
1402                                        self.wall.appended(newItems);
1403                                    else self.wall.insert(newItems);
1404                                    self.wall.arrange();
1405                                    self.wall.updateSortData();
1406                                    self.fixEqualHeights(newItems);
1407
1408                                    newItems.forEach(function (a) {
1409                                        a.style.visibility = "visible";
1410                                    });
1411
1412                                    // Update filters
1413                                    if (
1414                                        self.filtersEnabled &&
1415                                        self.filtersMode == "dynamic"
1416                                    ) {
1417                                        Joomla.request({
1418                                            url:
1419                                                self.path +
1420                                                "index.php?option=com_minitekwall&task=masonry.getFilters&widget_id=" +
1421                                                self.widgetId +
1422                                                "&page=" +
1423                                                page +
1424                                                "&pagination=" +
1425                                                self.pagination +
1426                                                "&Itemid=" +
1427                                                self.itemid,
1428                                            method: "GET",
1429                                            onSuccess: (response, xhr) => {
1430                                                if (response.length > 3) {
1431                                                    // Add new filters
1432                                                    self.container.querySelector(
1433                                                        ".mwall-filters"
1434                                                    ).innerHTML = response;
1435                                                }
1436
1437                                                self.activeFilters();
1438                                                self.dropdownFilters();
1439                                            },
1440                                            onError: function onError(xhr) {
1441                                                if (xhr.status > 0) {
1442                                                    Joomla.renderMessages(
1443                                                        Joomla.ajaxErrorsMessages(
1444                                                            xhr
1445                                                        )
1446                                                    );
1447                                                }
1448                                            },
1449                                        });
1450                                    }
1451
1452                                    // Hide loader
1453                                    self.container.classList.remove(
1454                                        "mwall-loading"
1455                                    );
1456                                    _this.classList.remove("arrow-loading");
1457                                    _this.querySelector(
1458                                        ".mwall-more-results"
1459                                    ).style.display = "block";
1460                                    _this.querySelector(
1461                                        ".mwall-arrow-loader"
1462                                    ).style.display = "none";
1463
1464                                    // Enable buttons
1465                                    self.container
1466                                        .querySelectorAll(".mwall-arrow")
1467                                        .forEach((a) => {
1468                                            a.classList.remove("disabled");
1469                                        });
1470
1471                                    // First page
1472                                    if (prev_page <= 0) {
1473                                        if (prev_page < 0) {
1474                                            self.container
1475                                                .querySelector(
1476                                                    ".mwall-arrow-prev"
1477                                                )
1478                                                .setAttribute("data-page", 0);
1479                                            _this.setAttribute("data-page", 2);
1480                                        }
1481
1482                                        self.container
1483                                            .querySelector(".mwall-arrow-prev")
1484                                            .classList.add("disabled");
1485                                    }
1486
1487                                    // Last page
1488                                    var lastPage = parseInt(
1489                                        _this
1490                                            .closest(".mwall-arrows")
1491                                            .getAttribute("data-last-page"),
1492                                        10
1493                                    );
1494
1495                                    if (next_page > lastPage)
1496                                        self.container
1497                                            .querySelector(".mwall-arrow-next")
1498                                            .classList.add("disabled");
1499
1500                                    // Scroll to top
1501                                    if (self.scrollToTop) {
1502                                        setTimeout(function () {
1503                                            self.container.firstChild.scrollIntoView(
1504                                                true
1505                                            );
1506                                        }, self.transitionDuration);
1507                                    }
1508                                };
1509
1510                                if (self.videoSource)
1511                                    self.videosReady(update_wall);
1512
1513                                if (self.ignoreVideos) update_wall();
1514                            });
1515                        } else {
1516                            // Disable button / Hide loader
1517                            _this.classList.add("disabled");
1518                            self.container.querySelector(
1519                                ".mwall-arrow-loader"
1520                            ).style.display = "none";
1521                        }
1522                    },
1523                    onError: function onError(xhr) {
1524                        if (xhr.status > 0) {
1525                            Joomla.renderMessages(
1526                                Joomla.ajaxErrorsMessages(xhr)
1527                            );
1528                        }
1529                    },
1530                });
1531            });
1532        }
1533
1534        pagesPagination() {
1535            const self = this;
1536            let wrapper = self.container.querySelector(
1537                ".mwall-pagination-wrapper"
1538            );
1539
1540            wrapper.addEventListener("click", function (e) {
1541                e.preventDefault();
1542
1543                if (e.target.classList.contains("mwall-page"))
1544                    var _this = e.target;
1545                else if (e.target.closest(".mwall-page"))
1546                    var _this = e.target.closest(".mwall-page");
1547                else return false;
1548
1549                if (self.container.classList.contains("mwall-loading"))
1550                    return false;
1551
1552                self.container
1553                    .querySelectorAll(".mwall-page")
1554                    .forEach(function (a) {
1555                        a.classList.remove("mwall-active");
1556                    });
1557
1558                // Find page
1559                var page = _this.getAttribute("data-page");
1560                page = parseInt(page, 10);
1561
1562                // Check if there is a pending ajax request
1563                if (typeof ajax_request !== "undefined") {
1564                    ajax_request.abort();
1565                    self.container.classList.remove("mwall-loading");
1566                    self.container.querySelector(".page-number").style.display =
1567                        "inline-block";
1568                    self.container.querySelector(
1569                        ".mwall-page-loader"
1570                    ).style.display = "none";
1571                }
1572
1573                // Show loader
1574                self.container.classList.add("mwall-loading");
1575                _this.querySelector(".page-number").style.display = "none";
1576                _this.querySelector(".mwall-page-loader").style.display =
1577                    "block";
1578
1579                // Filters data
1580                var data = {};
1581
1582                if (self.filtersMode == "static") {
1583                    data = {
1584                        category: self.filters["category"],
1585                        tag: self.filters["tag"],
1586                        date: self.filters["date"],
1587                        ordering: self.filters["ordering"],
1588                        direction: self.filters["direction"],
1589                        search: self.filters["search"],
1590                    };
1591                }
1592
1593                // Remove current items
1594                var elems = self.wall.getItemElements();
1595                self.wall.remove(elems);
1596
1597                // Ajax request
1598                var ajax_request = Joomla.request({
1599                    url:
1600                        self.path +
1601                        "index.php?option=com_minitekwall&task=masonry.getContent&widget_id=" +
1602                        self.widgetId +
1603                        "&page=" +
1604                        page +
1605                        "&tag_operator=" +
1606                        self.tagsLogicalOperator +
1607                        "&date_format=" +
1608                        self.dateFiltersFormat +
1609                        "&grid=" +
1610                        self.layoutType +
1611                        "&Itemid=" +
1612                        self.itemid,
1613                    method: "POST",
1614                    data: JSON.stringify(data),
1615                    onSuccess: (response, xhr) => {
1616                        if (response.length > 3) {
1617                            // Reset filters
1618                            if (
1619                                self.filtersMode == "dynamic" &&
1620                                (self.filtersEnabled ||
1621                                    self.options.mas_search_filter)
1622                            )
1623                                self.resetFilters();
1624
1625                            var newItems = self.htmlToElements(
1626                                response,
1627                                ".mwall-item"
1628                            );
1629
1630                            newItems.forEach(function (a) {
1631                                a.style.visibility = "hidden";
1632                                if (self.fluidHeight)
1633                                    self.iso_container.appendChild(a);
1634                            });
1635
1636                            var imgLoad = imagesLoaded(self.iso_container, {
1637                                background: ".mwall-photo-link",
1638                            });
1639
1640                            imgLoad.on("done", function () {
1641                                let update_wall = function () {
1642                                    if (self.fluidHeight)
1643                                        self.wall.appended(newItems);
1644                                    else self.wall.insert(newItems);
1645                                    self.wall.arrange();
1646                                    self.wall.updateSortData();
1647                                    self.fixEqualHeights(newItems);
1648
1649                                    newItems.forEach(function (a) {
1650                                        a.style.visibility = "visible";
1651                                    });
1652
1653                                    if (
1654                                        self.filtersEnabled &&
1655                                        self.filtersMode == "dynamic"
1656                                    ) {
1657                                        // Update filters
1658                                        Joomla.request({
1659                                            url:
1660                                                self.path +
1661                                                "index.php?option=com_minitekwall&task=masonry.getFilters&widget_id=" +
1662                                                self.widgetId +
1663                                                "&page=" +
1664                                                page +
1665                                                "&pagination=" +
1666                                                self.pagination +
1667                                                "&Itemid=" +
1668                                                self.itemid,
1669                                            method: "GET",
1670                                            onSuccess: (response, xhr) => {
1671                                                if (response.length > 3) {
1672                                                    // Add new filters
1673                                                    self.container.querySelector(
1674                                                        ".mwall-filters"
1675                                                    ).innerHTML = response;
1676                                                }
1677
1678                                                self.activeFilters();
1679                                                self.dropdownFilters();
1680                                            },
1681                                            onError: function onError(xhr) {
1682                                                if (xhr.status > 0) {
1683                                                    Joomla.renderMessages(
1684                                                        Joomla.ajaxErrorsMessages(
1685                                                            xhr
1686                                                        )
1687                                                    );
1688                                                }
1689                                            },
1690                                        });
1691                                    }
1692
1693                                    // Hide loader
1694                                    self.container.classList.remove(
1695                                        "mwall-loading"
1696                                    );
1697                                    _this.querySelector(
1698                                        ".page-number"
1699                                    ).style.display = "inline-block";
1700                                    _this.querySelector(
1701                                        ".mwall-page-loader"
1702                                    ).style.display = "none";
1703
1704                                    // Remove active class
1705                                    if (
1706                                        !_this.classList.contains(
1707                                            "mwall-active"
1708                                        )
1709                                    )
1710                                        _this.classList.add("mwall-active");
1711
1712                                    // Scroll to top
1713                                    if (self.scrollToTop) {
1714                                        setTimeout(function () {
1715                                            self.container.firstChild.scrollIntoView(
1716                                                true
1717                                            );
1718                                        }, self.transitionDuration);
1719                                    }
1720                                };
1721
1722                                if (self.videoSource)
1723                                    self.videosReady(update_wall);
1724
1725                                if (self.ignoreVideos) update_wall();
1726                            });
1727                        } else {
1728                            // Hide loader
1729                            self.container.classList.remove("mwall-loading");
1730                            self.container.querySelector(
1731                                ".mwall-page-loader"
1732                            ).style.display = "none";
1733                        }
1734                    },
1735                    onError: function onError(xhr) {
1736                        if (xhr.status > 0) {
1737                            Joomla.renderMessages(
1738                                Joomla.ajaxErrorsMessages(xhr)
1739                            );
1740                        }
1741                    },
1742                });
1743            });
1744        }
1745
1746        infinitePagination(prefill = false) {
1747            const self = this;
1748
1749            let parent = self.container.querySelector(".mwall-more-results");
1750            var lastPage = parseInt(
1751                self.container
1752                    .querySelector(".mwall-infinite")
1753                    .getAttribute("data-last-page"),
1754                10
1755            );
1756            var page;
1757            var data = {};
1758
1759            self.infScroll = new InfiniteScroll(self.iso_container, {
1760                path: function () {
1761                    page = parent.getAttribute("data-page");
1762                    page = parseInt(page, 10);
1763
1764                    if (page <= lastPage)
1765                        return (
1766                            self.path +
1767                            "index.php?option=com_minitekwall&task=masonry.getContent&widget_id=" +
1768                            self.widgetId +
1769                            "&page=" +
1770                            page +
1771                            "&grid=" +
1772                            self.layoutType
1773                        );
1774                },
1775                checkLastPage: true,
1776                prefill: prefill,
1777                domParseResponse: true,
1778                fetchOptions: function () {
1779                    // Filters data
1780                    if (self.filtersMode == "static") {
1781                        data = {
1782                            category: self.filters["category"],
1783                            tag: self.filters["tag"],
1784                            date: self.filters["date"],
1785                            ordering: self.filters["ordering"],
1786                            direction: self.filters["direction"],
1787                            search: self.filters["search"],
1788                        };
1789                    }
1790
1791                    return {
1792                        method: "POST",
1793                        body: JSON.stringify(data),
1794                    };
1795                },
1796                scrollThreshold: self.scrollThreshold,
1797                loadOnScroll: true,
1798                outlayer: self.wall,
1799                history: false,
1800            });
1801
1802            self.infScroll.on("load", function (body) {
1803                onLoad(body);
1804            });
1805
1806            // Triggered after infinite scroll has appended items
1807            function onLoad(body) {
1808                if (page > lastPage) return;
1809                if (self.container.classList.contains("mwall-loading"))
1810                    return false;
1811
1812                // Show loader
1813                parent.style.display = "block";
1814                self.container.classList.add("mwall-loading");
1815                self.container.querySelector(
1816                    ".mwall-append-loader"
1817                ).style.display = "block";
1818
1819                let newItems = body.querySelectorAll(".mwall-item");
1820
1821                if (newItems) {
1822                    newItems.forEach(function (a) {
1823                        a.style.visibility = "hidden";
1824                        self.iso_container.appendChild(a);
1825                    });
1826
1827                    // Increment page
1828                    parent.setAttribute("data-page", page + 1);
1829
1830                    var imgLoad = imagesLoaded(self.iso_container, {
1831                        background: ".mwall-photo-link",
1832                    });
1833
1834                    imgLoad.on("done", function () {
1835                        let update_wall = function () {
1836                            // Reset filters
1837                            if (
1838                                self.filtersMode == "dynamic" &&
1839                                (self.filtersEnabled ||
1840                                    self.options.mas_search_filter)
1841                            )
1842                                self.resetFilters();
1843
1844                            self.wall.appended(newItems);
1845                            self.wall.arrange();
1846                            self.wall.updateSortData();
1847                            self.fixEqualHeights("all");
1848
1849                            newItems.forEach(function (a) {
1850                                a.style.visibility = "visible";
1851                            });
1852
1853                            if (
1854                                self.filtersEnabled &&
1855                                self.filtersMode == "dynamic"
1856                            ) {
1857                                // Update filters
1858                                Joomla.request({
1859                                    url:
1860                                        self.path +
1861                                        "index.php?option=com_minitekwall&task=masonry.getFilters&widget_id=" +
1862                                        self.widgetId +
1863                                        "&page=" +
1864                                        page +
1865                                        "&pagination=" +
1866                                        self.pagination +
1867                                        "&Itemid=" +
1868                                        self.itemid,
1869                                    method: "GET",
1870                                    onSuccess: (response, xhr) => {
1871                                        if (response.length > 3) {
1872                                            // Add new filters
1873                                            self.container.querySelector(
1874                                                ".mwall-filters"
1875                                            ).innerHTML = response;
1876                                        }
1877
1878                                        self.activeFilters();
1879                                        self.dropdownFilters();
1880                                    },
1881                                    onError: function onError(xhr) {
1882                                        if (xhr.status > 0) {
1883                                            Joomla.renderMessages(
1884                                                Joomla.ajaxErrorsMessages(xhr)
1885                                            );
1886                                        }
1887                                    },
1888                                });
1889                            }
1890
1891                            // Hide loader
1892                            self.container.classList.remove("mwall-loading");
1893                            parent.style.display = "none";
1894                            self.container.querySelector(
1895                                ".mwall-append-loader"
1896                            ).style.display = "none";
1897                        };
1898
1899                        if (self.videoSource) self.videosReady(update_wall);
1900
1901                        if (self.ignoreVideos) update_wall();
1902                    });
1903                }
1904            }
1905        }
1906
1907        appendPagination() {
1908            const self = this;
1909            let wrapper = self.container.querySelector(
1910                ".mwall-pagination-wrapper"
1911            );
1912
1913            wrapper.addEventListener("click", function (e) {
1914                e.preventDefault();
1915
1916                if (e.target && e.target.closest(".mwall-button")) {
1917                    var _this = self.container.querySelector(".mwall-button");
1918
1919                    if (
1920                        _this.classList.contains("disabled") ||
1921                        self.container.classList.contains("mwall-loading")
1922                    )
1923                        return false;
1924
1925                    var page = _this.getAttribute("data-page");
1926                    page = parseInt(page, 10);
1927
1928                    // Increment page
1929                    var new_page = page + 1;
1930                    _this.setAttribute("data-page", new_page);
1931
1932                    // Check if there is a pending ajax request
1933                    if (typeof ajax_request !== "undefined") {
1934                        ajax_request.abort();
1935                        self.container.classList.remove("mwall-loading");
1936                        self.container.querySelector(
1937                            ".mwall-more-results"
1938                        ).style.display = "block";
1939                        self.container.querySelector(
1940                            ".mwall-append-loader"
1941                        ).style.display = "none";
1942                    }
1943
1944                    // Show loader
1945                    self.container.classList.add("mwall-loading");
1946                    self.container.querySelector(
1947                        ".mwall-more-results"
1948                    ).style.display = "none";
1949                    self.container.querySelector(
1950                        ".mwall-append-loader"
1951                    ).style.display = "block";
1952
1953                    // Filters data
1954                    var data = {};
1955
1956                    if (self.filtersMode == "static") {
1957                        var data = {
1958                            category: self.filters["category"],
1959                            tag: self.filters["tag"],
1960                            date: self.filters["date"],
1961                            ordering: self.filters["ordering"],
1962                            direction: self.filters["direction"],
1963                            search: self.filters["search"],
1964                        };
1965                    }
1966
1967                    // Ajax request
1968                    var ajax_request = Joomla.request({
1969                        url:
1970                            self.path +
1971                            "index.php?option=com_minitekwall&task=masonry.getContent&widget_id=" +
1972                            self.widgetId +
1973                            "&page=" +
1974                            page +
1975                            "&tag_operator=" +
1976                            self.tagsLogicalOperator +
1977                            "&date_format=" +
1978                            self.dateFiltersFormat +
1979                            "&grid=" +
1980                            self.layoutType +
1981                            "&Itemid=" +
1982                            self.itemid,
1983                        method: "POST",
1984                        data: JSON.stringify(data),
1985                        onSuccess: (response, xhr) => {
1986                            if (response.length > 3) {
1987                                // Reset filters
1988                                if (
1989                                    self.filtersMode == "dynamic" &&
1990                                    (self.filtersEnabled ||
1991                                        self.options.mas_search_filter)
1992                                )
1993                                    self.resetFilters();
1994
1995                                var newItems = self.htmlToElements(
1996                                    response,
1997                                    ".mwall-item"
1998                                );
1999
2000                                newItems.forEach(function (a) {
2001                                    a.style.visibility = "hidden";
2002                                    self.iso_container.appendChild(a);
2003                                });
2004
2005                                var imgLoad = imagesLoaded(self.iso_container, {
2006                                    background: ".mwall-photo-link",
2007                                });
2008
2009                                imgLoad.on("done", function () {
2010                                    let update_wall = function () {
2011                                        self.wall.appended(newItems);
2012                                        self.wall.arrange();
2013                                        self.wall.updateSortData();
2014                                        self.fixEqualHeights("all");
2015
2016                                        newItems.forEach(function (a) {
2017                                            a.style.visibility = "visible";
2018                                        });
2019
2020                                        // Update filters
2021                                        if (
2022                                            self.filtersEnabled &&
2023                                            self.filtersMode == "dynamic"
2024                                        ) {
2025                                            Joomla.request({
2026                                                url:
2027                                                    self.path +
2028                                                    "index.php?option=com_minitekwall&task=masonry.getFilters&widget_id=" +
2029                                                    self.widgetId +
2030                                                    "&page=" +
2031                                                    page +
2032                                                    "&pagination=" +
2033                                                    self.pagination +
2034                                                    "&Itemid=" +
2035                                                    self.itemid,
2036                                                method: "GET",
2037                                                onSuccess: (response, xhr) => {
2038                                                    if (response.length > 3) {
2039                                                        self.container.querySelector(
2040                                                            ".mwall-filters"
2041                                                        ).innerHTML = response;
2042                                                    }
2043
2044                                                    self.activeFilters();
2045                                                    self.dropdownFilters();
2046                                                },
2047                                                onError: function onError(xhr) {
2048                                                    if (xhr.status > 0) {
2049                                                        Joomla.renderMessages(
2050                                                            Joomla.ajaxErrorsMessages(
2051                                                                xhr
2052                                                            )
2053                                                        );
2054                                                    }
2055                                                },
2056                                            });
2057                                        }
2058
2059                                        // Hide loader
2060                                        self.container.classList.remove(
2061                                            "mwall-loading"
2062                                        );
2063                                        self.container.querySelector(
2064                                            ".mwall-more-results"
2065                                        ).style.display = "block";
2066                                        self.container.querySelector(
2067                                            ".mwall-append-loader"
2068                                        ).style.display = "none";
2069                                        self.container
2070                                            .querySelector(".mwall-button")
2071                                            .blur();
2072
2073                                        // Deduct remaining items number in button
2074                                        var _remaining =
2075                                            self.container.querySelector(
2076                                                ".mwall-total-items"
2077                                            ).textContent;
2078                                        var remaining =
2079                                            parseInt(_remaining, 10) -
2080                                            self.pageLimit;
2081                                        self.container.querySelector(
2082                                            ".mwall-total-items"
2083                                        ).innerHTML = remaining;
2084
2085                                        // Remove button if no items left
2086                                        if (remaining <= 0) {
2087                                            self.container
2088                                                .querySelector(".mwall-button")
2089                                                .remove();
2090                                        }
2091                                    };
2092
2093                                    if (self.videoSource)
2094                                        self.videosReady(update_wall);
2095
2096                                    if (self.ignoreVideos) update_wall();
2097                                });
2098                            }
2099                        },
2100                        onError: function onError(xhr) {
2101                            if (xhr.status > 0) {
2102                                Joomla.renderMessages(
2103                                    Joomla.ajaxErrorsMessages(xhr)
2104                                );
2105                            }
2106                        },
2107                    });
2108                }
2109            });
2110        }
2111
2112        initializePagination() {
2113            const self = this;
2114
2115            self.container
2116                .querySelectorAll(".mwall-loader")
2117                .forEach(function (a) {
2118                    self.createSpinner(a);
2119                });
2120        }
2121
2122        // Get filters permutations
2123        combineArrays(filters) {
2124            const self = this;
2125
2126            if (!filters) {
2127                return [];
2128            }
2129
2130            if (typeof filters !== "object") {
2131                return [];
2132            }
2133
2134            if (Object.keys(filters).length == 0) {
2135                return [];
2136            }
2137
2138            let _filters = {};
2139
2140            for (var group in filters) {
2141                if (
2142                    !Array.isArray(filters[group]) ||
2143                    filters[group].length == 0
2144                )
2145                    continue;
2146                else {
2147                    if (group == "tag" && self.tagsLogicalOperator == "AND")
2148                        _filters[group] = [filters[group].join("")];
2149                    else _filters[group] = filters[group];
2150                }
2151            }
2152
2153            // Start "odometer" with a 0 for each array in filters.
2154            let odometer = new Array(Object.keys(_filters).length);
2155            odometer.fill(0);
2156
2157            let output = [];
2158
2159            let newCombination = self.formCombination(odometer, _filters);
2160
2161            output.push(newCombination);
2162
2163            while (self.odometer_increment(odometer, _filters)) {
2164                newCombination = self.formCombination(odometer, _filters);
2165                output.push(newCombination);
2166            }
2167
2168            return output;
2169        }
2170
2171        // Create a new combination
2172        formCombination(odometer, filters) {
2173            let s_output = "";
2174
2175            for (let i = 0; i < odometer.length; i++) {
2176                if (Object.values(filters)[i][odometer[i]])
2177                    s_output += "" + Object.values(filters)[i][odometer[i]];
2178            }
2179
2180            return s_output;
2181        }
2182
2183        odometer_increment(odometer, filters) {
2184            for (
2185                let i_odometer_digit = odometer.length - 1;
2186                i_odometer_digit >= 0;
2187                i_odometer_digit--
2188            ) {
2189                let maxee = Object.values(filters)[i_odometer_digit].length - 1;
2190
2191                if (odometer[i_odometer_digit] + 1 <= maxee) {
2192                    odometer[i_odometer_digit]++;
2193                    return true;
2194                } else {
2195                    if (i_odometer_digit - 1 < 0) {
2196                        return false;
2197                    } else {
2198                        odometer[i_odometer_digit] = 0;
2199                        continue;
2200                    }
2201                }
2202            }
2203        }
2204
2205        // Set active filters
2206        activeFilters() {
2207            const self = this;
2208
2209            self.container
2210                .querySelectorAll(".button-group")
2211                .forEach(function (buttonGroup) {
2212                    buttonGroup
2213                        .querySelectorAll(".mwall-filter")
2214                        .forEach(function (a) {
2215                            a.addEventListener("click", function (e) {
2216                                e.preventDefault();
2217
2218                                var filter = this.getAttribute("data-filter");
2219                                var filterGroup =
2220                                    buttonGroup.getAttribute(
2221                                        "data-filter-group"
2222                                    );
2223
2224                                // Single filter
2225                                if (!self.multipleFilters) {
2226                                    if (
2227                                        buttonGroup.querySelector(
2228                                            ".mwall-filter-active"
2229                                        )
2230                                    )
2231                                        buttonGroup
2232                                            .querySelector(
2233                                                ".mwall-filter-active"
2234                                            )
2235                                            .classList.remove(
2236                                                "mwall-filter-active"
2237                                            );
2238                                }
2239                                // Multiple filters
2240                                else {
2241                                    if (!filter) {
2242                                        buttonGroup
2243                                            .querySelectorAll(
2244                                                ".mwall-filter-active"
2245                                            )
2246                                            .forEach(function (a) {
2247                                                a.classList.remove(
2248                                                    "mwall-filter-active"
2249                                                );
2250                                            });
2251
2252                                        a.classList.add("mwall-filter-active");
2253                                    } else {
2254                                        buttonGroup
2255                                            .querySelector(
2256                                                ".mwall-filter[data-filter='']"
2257                                            )
2258                                            .classList.remove(
2259                                                "mwall-filter-active"
2260                                            );
2261                                    }
2262                                }
2263
2264                                // Toggle active filter
2265                                if (self.filters[filterGroup].includes(filter))
2266                                    a.classList.remove("mwall-filter-active");
2267                                else a.classList.add("mwall-filter-active");
2268
2269                                if (
2270                                    !buttonGroup.querySelectorAll(
2271                                        ".mwall-filter-active"
2272                                    ).length
2273                                )
2274                                    buttonGroup
2275                                        .querySelector(
2276                                            ".mwall-filter[data-filter='']"
2277                                        )
2278                                        .classList.add("mwall-filter-active");
2279                            });
2280                        });
2281                });
2282        }
2283
2284        // Activate dropdown filters actions
2285        dropdownFilters() {
2286            const self = this;
2287
2288            if (self.container.querySelector(".mwall-filters-container")) {
2289                self.container
2290                    .querySelector(".mwall-filters-container")
2291                    .querySelectorAll(".mwall-dropdown")
2292                    .forEach(function (dropdownGroup) {
2293                        dropdownGroup
2294                            .querySelector(".dropdown-label")
2295                            .addEventListener("click", function (e) {
2296                                e.preventDefault();
2297                                var filter_open;
2298
2299                                if (
2300                                    this.closest(
2301                                        ".mwall-dropdown"
2302                                    ).classList.contains("expanded")
2303                                )
2304                                    filter_open = true;
2305                                else filter_open = false;
2306
2307                                self.container
2308                                    .querySelectorAll(".mwall-dropdown")
2309                                    .forEach(function (a) {
2310                                        a.classList.remove("expanded");
2311                                    });
2312
2313                                if (!filter_open)
2314                                    this.closest(
2315                                        ".mwall-dropdown"
2316                                    ).classList.add("expanded");
2317                            });
2318                    });
2319            }
2320
2321            // Close dropdowns
2322            document.addEventListener("mouseup", function (e) {
2323                var _target = e.target;
2324                var dropdowncontainers =
2325                    self.container.querySelectorAll(".mwall-dropdown");
2326
2327                if (!dropdowncontainers) return;
2328
2329                if (!this.closeFilters) {
2330                    // Close when click outside
2331                    if (!_target.closest(".mwall-dropdown")) {
2332                        dropdowncontainers.forEach(function (a) {
2333                            a.classList.remove("expanded");
2334                        });
2335                    }
2336                } else {
2337                    // Close when click inside
2338                    if (
2339                        _target.closest(".mwall-dropdown") &&
2340                        !_target.closest(".dropdown-label")
2341                    ) {
2342                        dropdowncontainers.forEach(function (a) {
2343                            a.classList.remove("expanded");
2344                        });
2345                    }
2346                }
2347            });
2348        }
2349
2350        // Activate dropdown sortings actions
2351        dropdownSortings() {
2352            const self = this;
2353
2354            if (self.container.querySelector(".mwall-sortings")) {
2355                self.container
2356                    .querySelector(".mwall-sortings")
2357                    .querySelectorAll(".mwall-dropdown")
2358                    .forEach(function (dropdownSorting) {
2359                        dropdownSorting
2360                            .querySelector(".dropdown-label")
2361                            .addEventListener("click", function (e) {
2362                                e.preventDefault();
2363                                var sorting_open;
2364
2365                                if (
2366                                    this.closest(
2367                                        ".mwall-dropdown"
2368                                    ).classList.contains("expanded")
2369                                )
2370                                    sorting_open = true;
2371                                else sorting_open = false;
2372
2373                                self.container
2374                                    .querySelectorAll(".mwall-dropdown")
2375                                    .forEach(function (a) {
2376                                        a.classList.remove("expanded");
2377                                    });
2378
2379                                if (!sorting_open)
2380                                    this.closest(
2381                                        ".mwall-dropdown"
2382                                    ).classList.add("expanded");
2383                            });
2384                    });
2385            }
2386        }
2387
2388        updatePagination(data) {
2389            const self = this;
2390
2391            self.container.querySelector(
2392                ".mwall-pagination-wrapper"
2393            ).style.display = "none";
2394
2395            if (
2396                (data["category"].length &&
2397                    data["category"][0] &&
2398                    data["category"][0] > 0) ||
2399                (data["tag"].length && data["tag"][0] && data["tag"][0] > 0) ||
2400                (data["date"] && data["date"] != "0") ||
2401                (data["search"] && data["search"].length)
2402            ) {
2403                var filters_active = true;
2404            } else var filters_active = false;
2405
2406            Joomla.request({
2407                url:
2408                    self.path +
2409                    "index.php?option=com_minitekwall&task=masonry.getPagination&widget_id=" +
2410                    self.widgetId +
2411                    "&page=1" +
2412                    "&tag_operator=" +
2413                    self.tagsLogicalOperator +
2414                    "&date_format=" +
2415                    self.dateFiltersFormat +
2416                    "&pagination=" +
2417                    self.pagination +
2418                    "&Itemid=" +
2419                    self.itemid,
2420                method: "POST",
2421                data: JSON.stringify(data),
2422                onSuccess: (response, xhr) => {
2423                    if (response.length > 3) {
2424                        self.container.querySelector(
2425                            ".mwall-pagination-wrapper"
2426                        ).innerHTML = response;
2427
2428                        self.container.querySelector(
2429                            ".mwall-pagination-wrapper"
2430                        ).style.display = "block";
2431
2432                        self.container
2433                            .querySelectorAll(".mwall-loader")
2434                            .forEach(function (a) {
2435                                self.createSpinner(a);
2436                            });
2437
2438                        // Show reset button in pagination
2439                        if (
2440                            self.container.querySelector(".mwall-reset-btn") &&
2441                            filters_active
2442                        ) {
2443                            self.container.querySelector(
2444                                ".mwall-reset-btn"
2445                            ).style.display = "inline-block";
2446
2447                            self.container
2448                                .querySelector(".mwall-reset-btn")
2449                                .addEventListener("click", function (e) {
2450                                    e.preventDefault();
2451
2452                                    self.resetStaticFilters();
2453                                });
2454                        }
2455
2456                        // Re-initialize infinite pagination
2457                        if (self.pagination === 4) {
2458                            var wrapper = self.container.querySelector(
2459                                ".mwall-more-results"
2460                            );
2461                            wrapper.setAttribute("data-page", "2");
2462                            self.infScroll.destroy();
2463                            self.infinitePagination();
2464                        }
2465                    }
2466                },
2467                onError: function onError(xhr) {
2468                    if (xhr.status > 0) {
2469                        Joomla.renderMessages(Joomla.ajaxErrorsMessages(xhr));
2470                    }
2471                },
2472            });
2473        }
2474
2475        // Reset static filters and sortings
2476        resetStaticFilters() {
2477            const self = this;
2478
2479            if (self.container.classList.contains("mwall-loading"))
2480                return false;
2481
2482            self.container.querySelector(".mwall-no-items").style.display =
2483                "none";
2484
2485            // Reset filters
2486            self.filters["category"] = [];
2487            self.filters["tag"] = [];
2488            self.filters["date"] = [];
2489            self.filters["ordering"] = "";
2490            self.filters["direction"] = "";
2491            self.filters["search"] = "";
2492
2493            // Check if there is a pending ajax request
2494            if (typeof ajax_request !== "undefined") ajax_request.abort();
2495
2496            // Show loader
2497            self.container.classList.add("mwall-loading");
2498            if (self.container.querySelector(".mwall-reset-container"))
2499                self.container
2500                    .querySelector(".mwall-reset-container")
2501                    .querySelector(".mwall-filters-loader").style.display =
2502                    "inline-block";
2503
2504            // Hide pagination
2505            if (self.container.querySelector(".mwall-pagination-wrapper"))
2506                self.container.querySelector(
2507                    ".mwall-pagination-wrapper"
2508                ).style.display = "none";
2509
2510            // Filters data
2511            var data = {
2512                category: self.filters["category"],
2513                tag: self.filters["tag"],
2514                date: self.filters["date"],
2515                ordering: self.filters["ordering"],
2516                direction: self.filters["direction"],
2517                search: self.filters["search"],
2518            };
2519
2520            // Remove current items
2521            var elems = self.wall.getItemElements();
2522            self.wall.remove(elems);
2523
2524            // Ajax request
2525            var ajax_request = Joomla.request({
2526                url:
2527                    self.path +
2528                    "index.php?option=com_minitekwall&task=masonry.getContent&widget_id=" +
2529                    self.widgetId +
2530                    "&page=1" +
2531                    "&tag_operator=" +
2532                    self.tagsLogicalOperator +
2533                    "&date_format=" +
2534                    self.dateFiltersFormat +
2535                    "&grid=" +
2536                    self.layoutType +
2537                    "&Itemid=" +
2538                    self.itemid,
2539                method: "POST",
2540                data: JSON.stringify(data),
2541                onSuccess: (response, xhr) => {
2542                    if (response.length > 3) {
2543                        var newItems = self.htmlToElements(
2544                            response,
2545                            ".mwall-item"
2546                        );
2547
2548                        newItems.forEach(function (a) {
2549                            a.style.visibility = "hidden";
2550                            if (self.fluidHeight)
2551                                self.iso_container.appendChild(a);
2552                        });
2553
2554                        var imgLoad = imagesLoaded(self.iso_container, {
2555                            background: ".mwall-photo-link",
2556                        });
2557
2558                        imgLoad.on("done", function () {
2559                            let update_wall = function () {
2560                                if (self.fluidHeight)
2561                                    self.wall.appended(newItems);
2562                                else self.wall.insert(newItems);
2563                                self.wall.arrange();
2564                                self.wall.updateSortData();
2565                                self.fixEqualHeights(newItems);
2566
2567                                newItems.forEach(function (a) {
2568                                    a.style.visibility = "visible";
2569                                });
2570
2571                                // Reset active buttons
2572                                self.container
2573                                    .querySelectorAll(".button-group")
2574                                    .forEach(function (buttonGroup) {
2575                                        if (
2576                                            buttonGroup.querySelector(
2577                                                ".mwall-filter-active"
2578                                            )
2579                                        )
2580                                            buttonGroup
2581                                                .querySelectorAll(
2582                                                    ".mwall-filter-active"
2583                                                )
2584                                                .forEach(function (a) {
2585                                                    a.classList.remove(
2586                                                        "mwall-filter-active"
2587                                                    );
2588                                                });
2589
2590                                        buttonGroup
2591                                            .querySelector("li:first-child a")
2592                                            .classList.add(
2593                                                "mwall-filter-active"
2594                                            );
2595
2596                                        // Hide reset button in pagination
2597                                        if (
2598                                            self.container.querySelector(
2599                                                ".mwall-reset-btn"
2600                                            )
2601                                        )
2602                                            self.container.querySelector(
2603                                                ".mwall-reset-btn"
2604                                            ).style.display = "none";
2605                                    });
2606
2607                                // Reset dropdown filters text
2608                                self.container
2609                                    .querySelectorAll(".mwall-dropdown")
2610                                    .forEach(function (dropdownGroup) {
2611                                        var filter_text = dropdownGroup
2612                                            .querySelector(
2613                                                ".dropdown-label span"
2614                                            )
2615                                            .getAttribute("data-label");
2616                                        dropdownGroup.querySelector(
2617                                            ".dropdown-label span span"
2618                                        ).textContent = filter_text;
2619                                    });
2620
2621                                // Reset search filter
2622                                if (
2623                                    self.container.querySelector(
2624                                        ".mwall-search-input"
2625                                    )
2626                                ) {
2627                                    self.container.querySelector(
2628                                        ".mwall-search-input"
2629                                    ).value = "";
2630                                    self.filters["search"] = "";
2631                                }
2632
2633                                // Reset sortings
2634                                self.container
2635                                    .querySelectorAll(".sorting-group-filters")
2636                                    .forEach(function (sortingGroup) {
2637                                        sortingGroup
2638                                            .querySelectorAll(".mwall-filter")
2639                                            .forEach(function (a) {
2640                                                a.classList.remove(
2641                                                    "mwall-filter-active"
2642                                                );
2643                                            });
2644                                        if (
2645                                            sortingGroup.querySelector(
2646                                                'li a[data-sort-value="' +
2647                                                    self.sortBy[0] +
2648                                                    '"]'
2649                                            )
2650                                        ) {
2651                                            sortingGroup
2652                                                .querySelector(
2653                                                    'li a[data-sort-value="' +
2654                                                        self.sortBy[0] +
2655                                                        '"]'
2656                                                )
2657                                                .classList.add(
2658                                                    "mwall-filter-active"
2659                                                );
2660                                        }
2661                                    });
2662
2663                                self.container
2664                                    .querySelectorAll(
2665                                        ".sorting-group-direction"
2666                                    )
2667                                    .forEach(function (sortingGroupDirection) {
2668                                        sortingGroupDirection
2669                                            .querySelector(
2670                                                ".mwall-filter-active"
2671                                            )
2672                                            .classList.remove(
2673                                                "mwall-filter-active"
2674                                            );
2675                                        sortingGroupDirection
2676                                            .querySelector(
2677                                                'li a[data-sort-value="' +
2678                                                    self.sortDirection +
2679                                                    '"]'
2680                                            )
2681                                            .classList.add(
2682                                                "mwall-filter-active"
2683                                            );
2684                                    });
2685
2686                                // Hide loader
2687                                self.container.classList.remove(
2688                                    "mwall-loading"
2689                                );
2690                                if (
2691                                    self.container.querySelector(
2692                                        ".mwall-reset-container"
2693                                    )
2694                                )
2695                                    self.container
2696                                        .querySelector(".mwall-reset-container")
2697                                        .querySelector(
2698                                            ".mwall-filters-loader"
2699                                        ).style.display = "none";
2700
2701                                if (self.pagination != 0)
2702                                    self.updatePagination(data);
2703                            };
2704
2705                            if (self.videoSource) self.videosReady(update_wall);
2706
2707                            if (self.ignoreVideos) update_wall();
2708                        });
2709
2710                        if (self.urlHash) self.removeHash();
2711                    }
2712                },
2713                onError: function onError(xhr) {
2714                    if (xhr.status > 0) {
2715                        Joomla.renderMessages(Joomla.ajaxErrorsMessages(xhr));
2716                    }
2717                },
2718            });
2719        }
2720
2721        staticFilters() {
2722            const self = this;
2723
2724            // Create loader
2725            self.container
2726                .querySelectorAll(".mwall-filters-loader")
2727                .forEach(function (a) {
2728                    self.createSpinner(a);
2729                });
2730
2731            // Search filter
2732            if (self.container.querySelector(".mwall-search-input")) {
2733                self.container
2734                    .querySelector(".mwall-search-input")
2735                    .addEventListener("input", function (e) {
2736                        e.preventDefault();
2737
2738                        if (self.container.classList.contains("mwall-loading"))
2739                            return false;
2740
2741                        let _this = e.target;
2742
2743                        // Wait for 800ms before searching
2744                        window.clearTimeout(self.timer);
2745
2746                        self.timer = window.setTimeout(function () {
2747                            // Sanitize value
2748                            let value = self.escapeRegex(_this.value);
2749                            self.filters["search"] = value;
2750
2751                            // Check if there is a pending ajax request
2752                            if (typeof ajax_request !== "undefined")
2753                                ajax_request.abort();
2754
2755                            // Show loader
2756                            self.container.classList.add("mwall-loading");
2757                            _this
2758                                .closest(".mwall-filters-group")
2759                                .querySelector(
2760                                    ".mwall-filters-loader"
2761                                ).style.display = "inline-block";
2762
2763                            // Hide pagination
2764                            if (
2765                                self.container.querySelector(
2766                                    ".mwall-pagination-wrapper"
2767                                )
2768                            )
2769                                self.container.querySelector(
2770                                    ".mwall-pagination-wrapper"
2771                                ).style.display = "none";
2772
2773                            // Filters data
2774                            var data = {
2775                                category: self.filters["category"],
2776                                tag: self.filters["tag"],
2777                                date: self.filters["date"],
2778                                ordering: self.filters["ordering"],
2779                                direction: self.filters["direction"],
2780                                search: self.filters["search"],
2781                            };
2782
2783                            // Remove current items
2784                            var elems = self.wall.getItemElements();
2785                            self.wall.remove(elems);
2786
2787                            // Ajax request
2788                            var ajax_request = Joomla.request({
2789                                url:
2790                                    self.path +
2791                                    "index.php?option=com_minitekwall&task=masonry.getContent&widget_id=" +
2792                                    self.widgetId +
2793                                    "&page=1" +
2794                                    "&tag_operator=" +
2795                                    self.tagsLogicalOperator +
2796                                    "&date_format=" +
2797                                    self.dateFiltersFormat +
2798                                    "&grid=" +
2799                                    self.layoutType +
2800                                    "&Itemid=" +
2801                                    self.itemid,
2802                                method: "POST",
2803                                data: JSON.stringify(data),
2804                                onSuccess: (response, xhr) => {
2805                                    if (response.length > 3) {
2806                                        var newItems = self.htmlToElements(
2807                                            response,
2808                                            ".mwall-item"
2809                                        );
2810
2811                                        newItems.forEach(function (a) {
2812                                            a.style.visibility = "hidden";
2813                                            if (self.fluidHeight)
2814                                                self.iso_container.appendChild(
2815                                                    a
2816                                                );
2817                                        });
2818
2819                                        self.wall.once(
2820                                            "layoutComplete",
2821                                            function (items) {
2822                                                self.resultsMessage(
2823                                                    self,
2824                                                    items
2825                                                );
2826                                            }
2827                                        );
2828
2829                                        var imgLoad = imagesLoaded(
2830                                            self.iso_container,
2831                                            {
2832                                                background: ".mwall-photo-link",
2833                                            }
2834                                        );
2835
2836                                        imgLoad.on("done", function () {
2837                                            let update_wall = function () {
2838                                                if (self.fluidHeight)
2839                                                    self.wall.appended(
2840                                                        newItems
2841                                                    );
2842                                                else self.wall.insert(newItems);
2843                                                self.wall.arrange();
2844                                                self.wall.updateSortData();
2845                                                self.fixEqualHeights(newItems);
2846
2847                                                newItems.forEach(function (a) {
2848                                                    a.style.visibility =
2849                                                        "visible";
2850                                                });
2851
2852                                                // Hide loader
2853                                                self.container.classList.remove(
2854                                                    "mwall-loading"
2855                                                );
2856                                                _this
2857                                                    .closest(
2858                                                        ".mwall-filters-group"
2859                                                    )
2860                                                    .querySelector(
2861                                                        ".mwall-filters-loader"
2862                                                    ).style.display = "none";
2863
2864                                                if (self.pagination != 0)
2865                                                    self.updatePagination(data);
2866                                            };
2867
2868                                            if (self.videoSource)
2869                                                self.videosReady(update_wall);
2870
2871                                            if (self.ignoreVideos)
2872                                                update_wall();
2873                                        });
2874                                    }
2875                                },
2876                                onError: function onError(xhr) {
2877                                    if (xhr.status > 0) {
2878                                        Joomla.renderMessages(
2879                                            Joomla.ajaxErrorsMessages(xhr)
2880                                        );
2881                                    }
2882                                },
2883                            });
2884                        }, 800);
2885                    });
2886            }
2887
2888            // Filters
2889            self.container
2890                .querySelectorAll(".mwall-filters-group")
2891                .forEach(function (group) {
2892                    group
2893                        .querySelectorAll(".mwall-filter")
2894                        .forEach(function (a) {
2895                            a.addEventListener("click", function (e) {
2896                                e.preventDefault();
2897
2898                                if (
2899                                    self.container.classList.contains(
2900                                        "mwall-loading"
2901                                    )
2902                                )
2903                                    return false;
2904
2905                                var filterGroup = a
2906                                    .closest(".button-group")
2907                                    .getAttribute("data-filter-group");
2908                                var data_id = a.getAttribute("data-id");
2909
2910                                // Check whether filter exists
2911                                let index =
2912                                    self.filters[filterGroup].indexOf(data_id);
2913
2914                                // Store filter
2915                                if (
2916                                    filterGroup == "category" ||
2917                                    filterGroup == "tag" ||
2918                                    filterGroup == "date"
2919                                ) {
2920                                    if (parseInt(data_id, 10)) {
2921                                        // Multiple filters
2922                                        if (self.multipleFilters) {
2923                                            if (
2924                                                !self.filters[
2925                                                    filterGroup
2926                                                ].includes(data_id)
2927                                            )
2928                                                self.filters[filterGroup].push(
2929                                                    data_id
2930                                                );
2931                                            else
2932                                                self.filters[
2933                                                    filterGroup
2934                                                ].splice(index, 1);
2935                                        }
2936                                        // Single filter
2937                                        else {
2938                                            if (
2939                                                !self.filters[
2940                                                    filterGroup
2941                                                ].includes(data_id)
2942                                            )
2943                                                self.filters[filterGroup] = [
2944                                                    data_id,
2945                                                ];
2946                                            else self.filters[filterGroup] = [];
2947                                        }
2948                                    } else self.filters[filterGroup] = [];
2949                                } else self.filters[filterGroup] = data_id;
2950
2951                                var data_filter = a.getAttribute("data-filter");
2952
2953                                // Single filter
2954                                if (!self.multipleFilters) {
2955                                    if (
2956                                        group.querySelector(
2957                                            ".mwall-filter-active"
2958                                        )
2959                                    )
2960                                        group
2961                                            .querySelector(
2962                                                ".mwall-filter-active"
2963                                            )
2964                                            .classList.remove(
2965                                                "mwall-filter-active"
2966                                            );
2967                                }
2968                                // Multiple filters
2969                                else {
2970                                    if (!data_filter) {
2971                                        group
2972                                            .querySelectorAll(
2973                                                ".mwall-filter-active"
2974                                            )
2975                                            .forEach(function (a) {
2976                                                a.classList.remove(
2977                                                    "mwall-filter-active"
2978                                                );
2979                                            });
2980
2981                                        a.classList.add("mwall-filter-active");
2982                                    } else {
2983                                        group
2984                                            .querySelector(
2985                                                ".mwall-filter[data-filter='']"
2986                                            )
2987                                            .classList.remove(
2988                                                "mwall-filter-active"
2989                                            );
2990                                    }
2991                                }
2992
2993                                // Toggle active filter
2994                                if (self.filters[filterGroup].includes(data_id))
2995                                    a.classList.add("mwall-filter-active");
2996                                else a.classList.remove("mwall-filter-active");
2997
2998                                if (
2999                                    !group.querySelectorAll(
3000                                        ".mwall-filter-active"
3001                                    ).length
3002                                )
3003                                    group
3004                                        .querySelector(
3005                                            ".mwall-filter[data-filter='']"
3006                                        )
3007                                        .classList.add("mwall-filter-active");
3008
3009                                // Show filter name in dropdown
3010                                if (a.closest(".mwall-dropdown")) {
3011                                    if (
3012                                        typeof data_filter !==
3013                                            typeof undefined &&
3014                                        data_filter !== false
3015                                    ) {
3016                                        var filter_text;
3017
3018                                        if (data_filter.length) {
3019                                            if (index === -1)
3020                                                filter_text = a.textContent;
3021                                            // Deselect filter
3022                                            else if (index >= 0) {
3023                                                filter_text = a
3024                                                    .closest(".mwall-dropdown")
3025                                                    .querySelector(
3026                                                        ".dropdown-label span"
3027                                                    )
3028                                                    .getAttribute("data-label");
3029                                            }
3030                                        } else
3031                                            filter_text = a
3032                                                .closest(".mwall-dropdown")
3033                                                .querySelector(
3034                                                    ".dropdown-label span"
3035                                                )
3036                                                .getAttribute("data-label");
3037
3038                                        a
3039                                            .closest(".mwall-dropdown")
3040                                            .querySelector(
3041                                                ".dropdown-label span span"
3042                                            ).textContent = filter_text;
3043                                    }
3044                                }
3045
3046                                // Check if there is a pending ajax request
3047                                if (typeof ajax_request !== "undefined")
3048                                    ajax_request.abort();
3049
3050                                // Show loader
3051                                self.container.classList.add("mwall-loading");
3052                                a
3053                                    .closest(".mwall-filters-group")
3054                                    .querySelector(
3055                                        ".mwall-filters-loader"
3056                                    ).style.display = "inline-block";
3057
3058                                // Hide pagination
3059                                if (
3060                                    self.container.querySelector(
3061                                        ".mwall-pagination-wrapper"
3062                                    )
3063                                )
3064                                    self.container.querySelector(
3065                                        ".mwall-pagination-wrapper"
3066                                    ).style.display = "none";
3067
3068                                // Update url hash
3069                                if (self.urlHash) {
3070                                    if (self.filters[filterGroup].length)
3071                                        self.hash_filters.set(
3072                                            filterGroup,
3073                                            self.filters[filterGroup].join()
3074                                        );
3075                                    else self.hash_filters.delete(filterGroup);
3076
3077                                    self.updateHash();
3078                                }
3079
3080                                // Filters data
3081                                var data = {
3082                                    category: self.filters["category"],
3083                                    tag: self.filters["tag"],
3084                                    date: self.filters["date"],
3085                                    ordering: self.filters["ordering"],
3086                                    direction: self.filters["direction"],
3087                                    search: self.filters["search"],
3088                                };
3089
3090                                // Remove current items
3091                                var elems = self.wall.getItemElements();
3092                                self.wall.remove(elems);
3093
3094                                // Ajax request
3095                                var ajax_request = Joomla.request({
3096                                    url:
3097                                        self.path +
3098                                        "index.php?option=com_minitekwall&task=masonry.getContent&widget_id=" +
3099                                        self.widgetId +
3100                                        "&page=1" +
3101                                        "&tag_operator=" +
3102                                        self.tagsLogicalOperator +
3103                                        "&date_format=" +
3104                                        self.dateFiltersFormat +
3105                                        "&grid=" +
3106                                        self.layoutType +
3107                                        "&Itemid=" +
3108                                        self.itemid,
3109                                    method: "POST",
3110                                    data: JSON.stringify(data),
3111                                    onSuccess: (response, xhr) => {
3112                                        if (response.length > 3) {
3113                                            var newItems = self.htmlToElements(
3114                                                response,
3115                                                ".mwall-item"
3116                                            );
3117
3118                                            newItems.forEach(function (a) {
3119                                                a.style.visibility = "hidden";
3120                                                if (self.fluidHeight)
3121                                                    self.iso_container.appendChild(
3122                                                        a
3123                                                    );
3124                                            });
3125
3126                                            self.wall.once(
3127                                                "layoutComplete",
3128                                                function (items) {
3129                                                    self.resultsMessage(
3130                                                        self,
3131                                                        items
3132                                                    );
3133                                                }
3134                                            );
3135
3136                                            var imgLoad = imagesLoaded(
3137                                                self.iso_container,
3138                                                {
3139                                                    background:
3140                                                        ".mwall-photo-link",
3141                                                }
3142                                            );
3143
3144                                            imgLoad.on("done", function () {
3145                                                let update_wall = function () {
3146                                                    if (self.fluidHeight)
3147                                                        self.wall.appended(
3148                                                            newItems
3149                                                        );
3150                                                    else
3151                                                        self.wall.insert(
3152                                                            newItems
3153                                                        );
3154                                                    self.wall.arrange();
3155                                                    self.wall.updateSortData();
3156                                                    self.fixEqualHeights(
3157                                                        newItems
3158                                                    );
3159
3160                                                    newItems.forEach(function (
3161                                                        a
3162                                                    ) {
3163                                                        a.style.visibility =
3164                                                            "visible";
3165                                                    });
3166
3167                                                    // Hide loader
3168                                                    self.container.classList.remove(
3169                                                        "mwall-loading"
3170                                                    );
3171                                                    a
3172                                                        .closest(
3173                                                            ".mwall-filters-group"
3174                                                        )
3175                                                        .querySelector(
3176                                                            ".mwall-filters-loader"
3177                                                        ).style.display =
3178                                                        "none";
3179
3180                                                    if (self.pagination != 0)
3181                                                        self.updatePagination(
3182                                                            data
3183                                                        );
3184                                                };
3185
3186                                                if (self.videoSource)
3187                                                    self.videosReady(
3188                                                        update_wall
3189                                                    );
3190
3191                                                if (self.ignoreVideos)
3192                                                    update_wall();
3193                                            });
3194                                        }
3195                                    },
3196                                    onError: function onError(xhr) {
3197                                        if (xhr.status > 0) {
3198                                            Joomla.renderMessages(
3199                                                Joomla.ajaxErrorsMessages(xhr)
3200                                            );
3201                                        }
3202                                    },
3203                                });
3204                            });
3205                        });
3206                });
3207
3208            self.dropdownFilters();
3209
3210            // Ordering / Direction
3211            if (self.container.querySelector(".mwall-sortings-group")) {
3212                self.container
3213                    .querySelectorAll(".mwall-sortings-group")
3214                    .forEach(function (group) {
3215                        group
3216                            .querySelectorAll(".mwall-filter")
3217                            .forEach(function (a) {
3218                                a.addEventListener("click", function (e) {
3219                                    e.preventDefault();
3220
3221                                    if (
3222                                        self.container.classList.contains(
3223                                            "mwall-loading"
3224                                        )
3225                                    )
3226                                        return false;
3227
3228                                    // Show sorting name in dropdown
3229                                    if (a.closest(".mwall-dropdown")) {
3230                                        var sorting_text = a.textContent;
3231                                        a
3232                                            .closest(".mwall-dropdown")
3233                                            .querySelector(
3234                                                ".dropdown-label span span"
3235                                            ).textContent = sorting_text;
3236                                    }
3237
3238                                    // Change active class on sorting filters
3239                                    a.closest(".mwall-sortings-group")
3240                                        .querySelectorAll(".mwall-filter")
3241                                        .forEach(function (a) {
3242                                            a.classList.remove(
3243                                                "mwall-filter-active"
3244                                            );
3245                                        });
3246                                    a.classList.add("mwall-filter-active");
3247
3248                                    // Store ordering
3249                                    if (a.closest(".sorting-group-filters"))
3250                                        self.filters["ordering"] =
3251                                            a.getAttribute("data-sort-value");
3252
3253                                    // Store direction
3254                                    if (a.closest(".sorting-group-direction"))
3255                                        self.filters["direction"] =
3256                                            a.getAttribute("data-sort-value");
3257
3258                                    // Check if there is a pending ajax request
3259                                    if (typeof ajax_request !== "undefined")
3260                                        ajax_request.abort();
3261
3262                                    // Show loader
3263                                    self.container.classList.add(
3264                                        "mwall-loading"
3265                                    );
3266                                    a
3267                                        .closest(".mwall-sortings-group")
3268                                        .querySelector(
3269                                            ".mwall-filters-loader"
3270                                        ).style.display = "inline-block";
3271
3272                                    // Hide pagination
3273                                    if (
3274                                        self.container.querySelector(
3275                                            ".mwall-pagination-wrapper"
3276                                        )
3277                                    )
3278                                        self.container.querySelector(
3279                                            ".mwall-pagination-wrapper"
3280                                        ).style.display = "none";
3281
3282                                    // Update url hash
3283                                    if (self.urlHash) {
3284                                        let filter_type;
3285
3286                                        if (a.closest(".sorting-group-filters"))
3287                                            filter_type = "ordering";
3288                                        else if (
3289                                            a.closest(
3290                                                ".sorting-group-direction"
3291                                            )
3292                                        )
3293                                            filter_type = "direction";
3294
3295                                        self.hash_filters.set(
3296                                            filter_type,
3297                                            self.filters[filter_type]
3298                                        );
3299                                        self.updateHash();
3300                                    }
3301
3302                                    // Filters data
3303                                    var data = {
3304                                        category: self.filters["category"],
3305                                        tag: self.filters["tag"],
3306                                        date: self.filters["date"],
3307                                        ordering: self.filters["ordering"],
3308                                        direction: self.filters["direction"],
3309                                        search: self.filters["search"],
3310                                    };
3311
3312                                    // Remove current items
3313                                    var elems = self.wall.getItemElements();
3314                                    self.wall.remove(elems);
3315
3316                                    // Ajax request
3317                                    var ajax_request = Joomla.request({
3318                                        url:
3319                                            self.path +
3320                                            "index.php?option=com_minitekwall&task=masonry.getContent&widget_id=" +
3321                                            self.widgetId +
3322                                            "&page=1" +
3323                                            "&tag_operator=" +
3324                                            self.tagsLogicalOperator +
3325                                            "&date_format=" +
3326                                            self.dateFiltersFormat +
3327                                            "&grid=" +
3328                                            self.layoutType +
3329                                            "&Itemid=" +
3330                                            self.itemid,
3331                                        method: "POST",
3332                                        data: JSON.stringify(data),
3333                                        onSuccess: (response, xhr) => {
3334                                            if (response.length > 3) {
3335                                                var newItems =
3336                                                    self.htmlToElements(
3337                                                        response,
3338                                                        ".mwall-item"
3339                                                    );
3340
3341                                                newItems.forEach(function (a) {
3342                                                    a.style.visibility =
3343                                                        "hidden";
3344                                                    if (self.fluidHeight)
3345                                                        self.iso_container.appendChild(
3346                                                            a
3347                                                        );
3348                                                });
3349
3350                                                var imgLoad = imagesLoaded(
3351                                                    self.iso_container,
3352                                                    {
3353                                                        background:
3354                                                            ".mwall-photo-link",
3355                                                    }
3356                                                );
3357
3358                                                imgLoad.on("done", function () {
3359                                                    let update_wall =
3360                                                        function () {
3361                                                            if (
3362                                                                self.fluidHeight
3363                                                            )
3364                                                                self.wall.appended(
3365                                                                    newItems
3366                                                                );
3367                                                            else
3368                                                                self.wall.insert(
3369                                                                    newItems
3370                                                                );
3371                                                            self.wall.arrange();
3372                                                            self.wall.updateSortData();
3373                                                            self.fixEqualHeights(
3374                                                                newItems
3375                                                            );
3376
3377                                                            newItems.forEach(
3378                                                                function (a) {
3379                                                                    a.style.visibility =
3380                                                                        "visible";
3381                                                                }
3382                                                            );
3383
3384                                                            // Hide loader
3385                                                            self.container.classList.remove(
3386                                                                "mwall-loading"
3387                                                            );
3388                                                            a
3389                                                                .closest(
3390                                                                    ".mwall-sortings-group"
3391                                                                )
3392                                                                .querySelector(
3393                                                                    ".mwall-filters-loader"
3394                                                                ).style.display =
3395                                                                "none";
3396
3397                                                            if (
3398                                                                self.pagination !=
3399                                                                0
3400                                                            )
3401                                                                self.updatePagination(
3402                                                                    data
3403                                                                );
3404                                                        };
3405
3406                                                    if (self.videoSource)
3407                                                        self.videosReady(
3408                                                            update_wall
3409                                                        );
3410
3411                                                    if (self.ignoreVideos)
3412                                                        update_wall();
3413                                                });
3414                                            }
3415                                        },
3416                                        onError: function onError(xhr) {
3417                                            if (xhr.status > 0) {
3418                                                Joomla.renderMessages(
3419                                                    Joomla.ajaxErrorsMessages(
3420                                                        xhr
3421                                                    )
3422                                                );
3423                                            }
3424                                        },
3425                                    });
3426                                });
3427                            });
3428                    });
3429            }
3430
3431            self.dropdownSortings();
3432
3433            // Reset button
3434            if (self.container.querySelector(".btn-reset")) {
3435                self.container
3436                    .querySelector(".btn-reset")
3437                    .addEventListener("click", function (e) {
3438                        e.preventDefault();
3439
3440                        self.resetStaticFilters();
3441                    });
3442            }
3443        }
3444
3445        getHashFilters() {
3446            const hash_filters = new URLSearchParams(
3447                window.location.hash.substring(1)
3448            );
3449
3450            return hash_filters;
3451        }
3452
3453        escapeRegex(string) {
3454            return string.replace(/[/\-\\^$*+?.()|[\]{}]/g, "\\$&");
3455        }
3456
3457        dynamicFilters() {
3458            const self = this;
3459
3460            if (self.container.querySelector(".mwall-filters-container")) {
3461                self.container
3462                    .querySelector(".mwall-filters-container")
3463                    .addEventListener("click", function (e) {
3464                        e.preventDefault();
3465
3466                        // Hide results message
3467                        self.container.querySelector(
3468                            ".mwall-no-items"
3469                        ).style.display = "none";
3470
3471                        if (
3472                            e.target &&
3473                            e.target.classList.contains("mwall-filter")
3474                        ) {
3475                            var _this = e.target;
3476                            var data_filter = _this.getAttribute("data-filter");
3477
3478                            // Show reset button in pagination
3479                            if (
3480                                self.container.querySelector(".mwall-reset-btn")
3481                            )
3482                                self.container.querySelector(
3483                                    ".mwall-reset-btn"
3484                                ).style.display = "inline-block";
3485
3486                            // Get group key
3487                            var filterGroup = _this
3488                                .closest(".button-group")
3489                                .getAttribute("data-filter-group");
3490
3491                            // Check whether filter exists
3492                            let index =
3493                                self.filters[filterGroup].indexOf(data_filter);
3494
3495                            // Multiple filters
3496                            if (self.multipleFilters) {
3497                                // Add filter to group if it does not exist
3498                                if (index === -1) {
3499                                    if (data_filter)
3500                                        self.filters[filterGroup].push(
3501                                            data_filter
3502                                        );
3503                                    else self.filters[filterGroup] = [];
3504                                } else {
3505                                    self.filters[filterGroup].splice(index, 1);
3506                                }
3507
3508                                // Create all permutations from all filters
3509                                var permutations = self.combineArrays(
3510                                    self.filters
3511                                );
3512
3513                                var filterValue = permutations.join(", ");
3514                            }
3515                            // Single filters
3516                            else {
3517                                // Add filter to group if it does not exist
3518                                if (index === -1) {
3519                                    if (data_filter)
3520                                        self.filters[filterGroup] = [
3521                                            data_filter,
3522                                        ];
3523                                    else self.filters[filterGroup] = [];
3524                                } else {
3525                                    self.filters[filterGroup] = [];
3526                                }
3527
3528                                var filterValue = "";
3529
3530                                for (var prop in self.filters) {
3531                                    if (prop == "search") continue;
3532
3533                                    for (var filter in prop) {
3534                                        if (self.filters[prop][filter])
3535                                            filterValue +=
3536                                                self.filters[prop][filter];
3537                                    }
3538                                }
3539                            }
3540
3541                            // Show filter name in dropdown
3542                            if (_this.closest(".mwall-dropdown")) {
3543                                if (
3544                                    typeof data_filter !== typeof undefined &&
3545                                    data_filter !== false
3546                                ) {
3547                                    var filter_text;
3548
3549                                    if (data_filter.length) {
3550                                        if (index === -1)
3551                                            filter_text = _this.textContent;
3552                                        // Deselect filter
3553                                        else if (index >= 0) {
3554                                            filter_text = _this
3555                                                .closest(".mwall-dropdown")
3556                                                .querySelector(
3557                                                    ".dropdown-label span"
3558                                                )
3559                                                .getAttribute("data-label");
3560                                        }
3561                                    } else
3562                                        filter_text = _this
3563                                            .closest(".mwall-dropdown")
3564                                            .querySelector(
3565                                                ".dropdown-label span"
3566                                            )
3567                                            .getAttribute("data-label");
3568
3569                                    _this
3570                                        .closest(".mwall-dropdown")
3571                                        .querySelector(
3572                                            ".dropdown-label span span"
3573                                        ).textContent = filter_text;
3574                                }
3575                            }
3576
3577                            // FIXED: Use the same manual filtering approach as in search
3578                            self.applyFilters();
3579                        }
3580                    });
3581            }
3582
3583            self.activeFilters();
3584            self.dropdownFilters();
3585
3586            // Ordering
3587            if (self.container.querySelector(".sorting-group-filters")) {
3588                self.container
3589                    .querySelector(".sorting-group-filters")
3590                    .querySelectorAll(".mwall-filter")
3591                    .forEach(function (a) {
3592                        a.addEventListener("click", function (e) {
3593                            e.preventDefault();
3594
3595                            // Show sorting name in dropdown
3596                            if (this.closest(".mwall-dropdown")) {
3597                                var sorting_text = this.textContent;
3598                                this.closest(".mwall-dropdown").querySelector(
3599                                    ".dropdown-label span span"
3600                                ).textContent = sorting_text;
3601                            }
3602
3603                            var sortValue =
3604                                this.getAttribute("data-sort-value");
3605
3606                            // Update Isotope
3607                            self.wall.arrange({
3608                                sortBy: [sortValue, "id"],
3609                            });
3610
3611                            self.resizeItems();
3612
3613                            // Change active class on sorting filters
3614                            self.container
3615                                .querySelector(".sorting-group-filters")
3616                                .querySelectorAll(".mwall-filter")
3617                                .forEach(function (a) {
3618                                    a.classList.remove("mwall-filter-active");
3619                                });
3620                            this.classList.add("mwall-filter-active");
3621
3622                            // Update url hash
3623                            if (self.urlHash) {
3624                                self.hash_filters.set("ordering", sortValue);
3625                                self.updateHash();
3626                            }
3627                        });
3628                    });
3629            }
3630
3631            // Direction
3632            if (self.container.querySelector(".sorting-group-direction")) {
3633                self.container
3634                    .querySelector(".sorting-group-direction")
3635                    .querySelectorAll(".mwall-filter")
3636                    .forEach(function (a) {
3637                        a.addEventListener("click", function (e) {
3638                            e.preventDefault();
3639
3640                            // Show sorting name in dropdown
3641                            if (this.closest(".mwall-dropdown")) {
3642                                var sorting_text = this.textContent;
3643                                this.closest(".mwall-dropdown").querySelector(
3644                                    ".dropdown-label span span"
3645                                ).textContent = sorting_text;
3646                            }
3647
3648                            var sortDirection =
3649                                this.getAttribute("data-sort-value");
3650                            var sort_Direction;
3651
3652                            if (sortDirection == "asc") sort_Direction = true;
3653                            else sort_Direction = false;
3654
3655                            // Update Isotope
3656                            self.wall.arrange({
3657                                sortAscending: sort_Direction,
3658                            });
3659
3660                            self.resizeItems();
3661
3662                            // Change active class on sorting direction
3663                            self.container
3664                                .querySelector(".sorting-group-direction")
3665                                .querySelectorAll(".mwall-filter")
3666                                .forEach(function (a) {
3667                                    a.classList.remove("mwall-filter-active");
3668                                });
3669                            this.classList.add("mwall-filter-active");
3670
3671                            // Update url hash
3672                            if (self.urlHash) {
3673                                self.hash_filters.set(
3674                                    "direction",
3675                                    sortDirection
3676                                );
3677                                self.updateHash();
3678                            }
3679                        });
3680                    });
3681            }
3682
3683            self.dropdownSortings();
3684        }
3685
3686        // Reset dynamic filters and sortings
3687        resetFilters() {
3688            const self = this;
3689
3690            self.container.querySelector(".mwall-no-items").style.display =
3691                "none";
3692
3693            // Reset active buttons
3694            self.container
3695                .querySelectorAll(".button-group")
3696                .forEach(function (buttonGroup) {
3697                    if (buttonGroup.querySelector(".mwall-filter-active"))
3698                        buttonGroup
3699                            .querySelectorAll(".mwall-filter-active")
3700                            .forEach(function (a) {
3701                                a.classList.remove("mwall-filter-active");
3702                            });
3703
3704                    buttonGroup
3705                        .querySelector("li:first-child a")
3706                        .classList.add("mwall-filter-active");
3707
3708                    // Reset filters
3709                    var filterGroup =
3710                        buttonGroup.getAttribute("data-filter-group");
3711                    self.filters[filterGroup] = [];
3712
3713                    // Hide reset button in pagination
3714                    if (self.container.querySelector(".mwall-reset-btn"))
3715                        self.container.querySelector(
3716                            ".mwall-reset-btn"
3717                        ).style.display = "none";
3718                });
3719
3720            // Reset dropdown filters text
3721            self.container
3722                .querySelectorAll(".mwall-dropdown")
3723                .forEach(function (dropdownGroup) {
3724                    var filter_text = dropdownGroup
3725                        .querySelector(".dropdown-label span")
3726                        .getAttribute("data-label");
3727                    dropdownGroup.querySelector(
3728                        ".dropdown-label span span"
3729                    ).textContent = filter_text;
3730                });
3731
3732            // Reset sortings
3733            self.container
3734                .querySelectorAll(".sorting-group-filters")
3735                .forEach(function (sortingGroup) {
3736                    sortingGroup
3737                        .querySelectorAll(".mwall-filter")
3738                        .forEach(function (a) {
3739                            a.classList.remove("mwall-filter-active");
3740                        });
3741                    if (
3742                        sortingGroup.querySelector(
3743                            'li a[data-sort-value="' + self.sortBy[0] + '"]'
3744                        )
3745                    ) {
3746                        sortingGroup
3747                            .querySelector(
3748                                'li a[data-sort-value="' + self.sortBy[0] + '"]'
3749                            )
3750                            .classList.add("mwall-filter-active");
3751                    }
3752                });
3753
3754            self.container
3755                .querySelectorAll(".sorting-group-direction")
3756                .forEach(function (sortingGroupDirection) {
3757                    sortingGroupDirection
3758                        .querySelector(".mwall-filter-active")
3759                        .classList.remove("mwall-filter-active");
3760                    sortingGroupDirection
3761                        .querySelector(
3762                            'li a[data-sort-value="' + self.sortDirection + '"]'
3763                        )
3764                        .classList.add("mwall-filter-active");
3765                });
3766
3767            // Reset search filter
3768            var searchInput = self.container.querySelector(".mwall-search-input");
3769            if (searchInput) {
3770                searchInput.value = "";
3771                self.filters["search"] = "";
3772            }
3773
3774            // Update Isotope
3775            self.wall.arrange({
3776                filter: "",
3777                sortBy: self.sortBy,
3778                sortAscending: self.sortAscending,
3779            });
3780
3781            // FIXED: Also update visibility of items manually to clear search filter
3782            var allItems = self.wall.getItemElements();
3783            allItems.forEach(function(item) {
3784                item.style.display = '';
3785            });
3786            self.wall.layout();
3787
3788            // Update results message
3789            self.resultsMessage(self, allItems);
3790
3791            if (self.urlHash) {
3792                // Clear all filters from hash
3793                for (var group in self.filters) {
3794                    self.hash_filters.delete(group);
3795                }
3796                self.updateHash();
3797            }
3798
3799            self.resizeItems();
3800        }
3801
3802        triggerResetButtons() {
3803            const self = this;
3804
3805            document
3806                .querySelectorAll(
3807                    "#mwall_reset_" +
3808                        this.widgetId +
3809                        ", #mwall_container_" +
3810                        this.widgetId +
3811                        " .mwall-reset-btn"
3812                )
3813                .forEach(function (a) {
3814                    a.addEventListener("click", function (e) {
3815                        e.preventDefault();
3816
3817                        self.resetFilters();
3818                    });
3819                });
3820        }
3821
3822        removeHash() {
3823            const self = this;
3824            self.hash_filters = new URLSearchParams();
3825
3826            history.pushState(
3827                "",
3828                document.title,
3829                window.location.pathname + window.location.search
3830            );
3831        }
3832
3833        updateHash() {
3834            const self = this;
3835
3836            // Сохраняем поиск в hash
3837            if (self.filters["search"]) {
3838                self.hash_filters.set("search", self.filters["search"]);
3839            } else {
3840                self.hash_filters.delete("search");
3841            }
3842
3843            history.pushState(
3844                "",
3845                document.title,
3846                "#" + self.hash_filters.toString()
3847            );
3848        }
3849
3850        doneBrowserResizing() {
3851            const self = this;
3852
3853            self.fixEqualHeights("all");
3854            self.wall.arrange();
3855        }
3856
3857        fixEqualHeights(items) {
3858            const self = this;
3859
3860            if (
3861                this.gridType == 98 &&
3862                this.layoutMode == "fitRows" &&
3863                this.dbPosition == "below" &&
3864                this.equalHeight
3865            ) {
3866                var max_height = 0;
3867
3868                if (items == "all") {
3869                    this.container
3870                        .querySelectorAll(".mwall-item-inner")
3871                        .forEach(function (a) {
3872                            a.style.height = "auto";
3873
3874                            if (a.offsetHeight > max_height)
3875                                max_height = a.offsetHeight;
3876                        });
3877                } else {
3878                    items.forEach(function (a) {
3879                        var _this_item_inner =
3880                            a.querySelector(".mwall-item-inner");
3881                        _this_item_inner.style.height = "auto";
3882
3883                        if (_this_item_inner.offsetHeight > max_height)
3884                            max_height = _this_item_inner.offsetHeight;
3885                    });
3886                }
3887
3888                this.container
3889                    .querySelectorAll(".mwall-item-inner")
3890                    .forEach(function (a) {
3891                        a.style.height = max_height + "px";
3892                    });
3893
3894                setTimeout(function () {
3895                    self.wall.arrange();
3896                }, 1);
3897            }
3898        }
3899
3900        createSpinner(divIdentifier) {
3901            var spinner_options = {
3902                lines: 9,
3903                length: 4,
3904                width: 3,
3905                radius: 3,
3906                corners: 1,
3907                rotate: 0,
3908                direction: 1,
3909                color: "#000",
3910                speed: 1,
3911                trail: 52,
3912                shadow: false,
3913                hwaccel: false,
3914                className: "spinner",
3915                zIndex: 2e9,
3916                top: "50%",
3917                left: "50%",
3918            };
3919
3920            var target = divIdentifier;
3921
3922            if (target) {
3923                var spinner = new Spinner(spinner_options).spin();
3924                target.innerHTML = "";
3925                target.appendChild(spinner.el);
3926            }
3927
3928            return;
3929        }
3930
3931        htmlToElements(htmlString, selector) {
3932            var div = document.createElement("div");
3933            div.innerHTML = htmlString.trim();
3934
3935            return div.querySelectorAll(selector);
3936        }
3937
3938        initModalMessages() {
3939            var zoomWall = document.querySelector("#zoomWall_" + this.widgetId);
3940
3941            if (!zoomWall) return;
3942
3943            zoomWall.addEventListener("show.bs.modal", function (e) {
3944                // Button that triggered the modal
3945                var button = e.relatedTarget;
3946
3947                // Update the title
3948                if (zoomWall.querySelector(".modal-title")) {
3949                    var title = button.getAttribute("data-mw-title");
3950                    zoomWall.querySelector(".modal-title").textContent = title;
3951                }
3952
3953                // Update the image
3954                var image = button.getAttribute("data-src");
3955                zoomWall.querySelector("img").setAttribute("src", image);
3956            });
3957
3958            zoomWall.addEventListener("hidden.bs.modal", function (e) {
3959                zoomWall.querySelector("img").setAttribute("src", "");
3960            });
3961        }
3962    }
3963
3964    window.Mwall = {
3965        initialise: (options, id, count, source, path, elements, itemid) =>
3966            new Mwall(options, id, count, source, path, elements, itemid),
3967    };
3968})(document, Joomla);

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.