PageSourceSearch

https://athinodoros.gr/wp-content/plugins/breakdance/subplugins/br…/gallery.js?bd_ver=2.8.3

js athinodoros.gr collected 2026-10-02 21:20:13 UTC 8,321 bytes, 310 lines download raw bytes

1(function () {
2  const { mergeObjects, debounce, getCurrentBreakpoint, onResize } = BreakdanceFrontend.utils;
3
4  class BreakdanceGallery {
5    defaultOptions = {
6      type: "grid",
7      mode: "single",
8      row_height: {
9        breakpoint_base: {
10          number: 300
11        }
12      },
13      columns: {
14        breakpoint_base: 3,
15        breakpoint_phone_portrait: 1,
16      },
17      slider: {
18        settings: null,
19        pagination: null,
20      },
21      defaultActiveIndex: 0
22    };
23
24    items = [];
25    filterActiveClass = "is-active";
26
27    constructor(selector, options) {
28      this.relayout = this.relayout.bind(this);
29      this.resize = this.resize.bind(this);
30      this.update = debounce(this._update, 100);
31      this.onImagesLoaded = this.onImagesLoaded.bind(this);
32      this.onFilterChange = this.onFilterChange.bind(this);
33      this.selector = selector;
34      this.options = mergeObjects(this.defaultOptions, options);
35      this.init();
36    }
37
38    checkForImagesLoaded() {
39      return this.options.type === "masonry";
40    }
41
42    getIsotopeSettings(layoutInstant = true) {
43      return {
44        layoutMode: this.getLayoutMode(),
45        layoutInstant,
46        packery: { gutter: '.ee-gallery-gutter' },
47        masonry: { gutter: '.ee-gallery-gutter' }
48      };
49    }
50
51    /*
52     * Turn DOM Elements into Isotope-ready Items
53     * This is required in order to make Isotope work in the Builder.
54     */
55    itemize(items) {
56      return items.map((elem) => new Isotope.Item(elem, this.iso));
57    }
58
59    /*
60     * Force Isotope to accept our DOM Elements.
61     * This is required due to a bug in the library.
62     * "elem instanceof HTMLCollection" always return false inside same-origin iframes
63     */
64    appendItems(elems) {
65      const items = this.itemize(elems);
66
67      if (!items.length) return;
68
69      this.iso.items = items;
70      this.iso.filteredItems = items;
71    }
72
73    relayout() {
74      if (!this.iso) return;
75      this.iso.layout();
76    }
77
78    getItemElems(elem) {
79      return [].slice.call(elem.querySelectorAll(".ee-gallery-item"));
80    }
81
82    onImagesLoaded() {
83      this.relayout();
84    }
85
86    determineFilter(category) {
87      return category === "all" ? "*" : `[data-category="${category}"]`;
88    }
89
90    // Filters
91    filterBy(node) {
92      const category = (node.value || node.id).split("-").pop();
93
94      if (this.options.type === "slider") {
95        this.filterSlider(category);
96      } else {
97        const filter = this.determineFilter(category);
98        this.iso.arrange({
99          layoutInstant: false,
100          filter,
101        });
102      }
103
104      const button = this.filterButtons.find((button) => button.id === node.id);
105
106      if (button) this.setActiveButton(button);
107
108      const customEvent = new CustomEvent("breakdance_gallery_filtered", {
109        detail: {
110          category,
111        },
112      });
113
114      this.element.dispatchEvent(customEvent);
115    }
116
117    filterSlider(category) {
118      const swiperEl = this.element.querySelector(".swiper");
119
120      const itemsToShow = category === "all" ? this.items : this.items.filter((item) => {
121        return item.dataset.category === category
122      });
123      const itemsToHide = this.items.filter(x => !itemsToShow.includes(x));
124
125      itemsToShow.forEach(item => item.style.display = null);
126      itemsToHide.forEach(item => item.style.display = "none");
127
128      swiperEl.swiper.update();
129      swiperEl.swiper.slideTo(0, 0);
130    }
131
132    setActiveButton(activeButton) {
133      this.filterButtons.forEach((button) => {
134        button.classList.remove(this.filterActiveClass);
135      });
136
137      activeButton.classList.add(this.filterActiveClass);
138    }
139
140    onFilterChange(event) {
141      event.preventDefault();
142
143      const target = event.currentTarget;
144      this.filterBy(target);
145      this.maybeJustifyItems();
146    }
147
148    getAll(selector) {
149      return [].slice.call(this.element.querySelectorAll(selector));
150    }
151
152    // The filter bar is only available when the gallery type is "multiple".
153    initFilters() {
154      const mobileFilter = this.element.querySelector(".js-tab-select");
155
156      this.filterButtons = this.getAll(".js-tab");
157
158      this.filterButtons.forEach((button, index) => {
159        if (index === this.options.defaultActiveIndex) {
160          this.filterBy(button);
161        }
162
163        button.addEventListener("click", this.onFilterChange);
164      });
165
166      if (mobileFilter) {
167        mobileFilter.addEventListener("change", this.onFilterChange);
168      }
169    }
170
171    maybeJustifyItems() {
172      if (this.options.type !== "justified") {
173        return this.unjustifyItems();
174      }
175
176      const justifiedLayout = require("justified-layout"); // TODO: Remove dependency on browserify.
177
178      const items = this.iso.filteredItems;
179
180      const geometry = items.map((item) => {
181        const [width, height] = item.element.dataset.lgSize.split("-");
182        return { width, height };
183      });
184
185      const config = {
186        containerWidth: this.galleryEl.clientWidth,
187        containerPadding: 0,
188        boxSpacing: this.getResponsiveUnit("gap"),
189        targetRowHeight: this.getResponsiveUnit("row_height"),
190      };
191
192      console.log(config);
193
194      const output = justifiedLayout(geometry, config);
195
196      items.forEach((item, index) => {
197        const box = output.boxes[index];
198        item.element.style.width = `${box.width}px`;
199        item.element.style.height = `${box.height}px`;
200      });
201
202      this.relayout();
203    }
204
205    unjustifyItems() {
206      if (!this.iso) return;
207
208      const items = this.iso.filteredItems;
209      items.forEach((item, index) => {
210        item.element.style.removeProperty("width");
211        item.element.style.removeProperty("height");
212      });
213    }
214
215    getResponsiveUnit(path) {
216      if (this.options[path] === undefined) return 0;
217
218      const availableBreakpoints = Object.keys(this.options[path]);
219      const currBreakpoint = getCurrentBreakpoint(availableBreakpoints);
220
221      // version >= 1.1 - backwards compatibility for non-breakpoint values.
222      const value = this.options[path][currBreakpoint.id]?.number || this.options[path].number || 0;
223
224      return Math.max(value, 0);
225    }
226
227    getLayoutMode() {
228      const type = this.options.type || "grid";
229
230      const layoutModes = {
231        grid: "masonry",
232        masonry: "masonry",
233        justified: "packery",
234      };
235
236      return layoutModes[type];
237    }
238
239    refresh(options = {}) {
240      this.options = mergeObjects(this.defaultOptions, options);
241      this.maybeJustifyItems();
242
243      const config = this.getIsotopeSettings();
244      this.iso.arrange(config);
245      this.init();
246    }
247
248    _update(options = {}) {
249      this.options = mergeObjects(this.defaultOptions, options);
250      this.destroy();
251      this.init();
252    }
253
254    // Fires on resize and when the element becomes visible after removing display: none
255    resize() {
256      this.maybeJustifyItems();
257      this.relayout();
258    }
259
260    destroy() {
261      this.destroyIsotope();
262      this.disconnect();
263    }
264
265    destroyIsotope() {
266      if (!this.iso) return;
267
268      this.iso.destroy();
269      this.iso = null;
270
271      if (this.checkForImagesLoaded()) {
272        imagesLoaded(this.element).off("progress", this.onImagesLoaded);
273      }
274    }
275
276    initIsotope(layoutInstant) {
277      const config = this.getIsotopeSettings(layoutInstant);
278
279      this.iso = new Isotope(this.galleryEl, config);
280      this.appendItems(this.items);
281
282      this.relayout();
283      this.maybeJustifyItems();
284
285      if (this.checkForImagesLoaded()) {
286        imagesLoaded(this.element).on("progress", this.onImagesLoaded);
287      }
288    }
289
290    init(layoutInstant) {
291      this.element = document.querySelector(this.selector);
292      this.galleryEl = this.element.querySelector(".ee-gallery");
293      this.items = this.getItemElems(this.element);
294
295      // For performance purposes, the combination of "single" mode and "grid" type is css-only and does not rely on Isotope.
296      const cssOnlyMode = this.options.mode === "single" && this.options.type === "grid";
297      const isSlider = this.options.type === "slider";
298
299     if (!isSlider && !cssOnlyMode) {
300        this.initIsotope(layoutInstant);
301      }
302
303      this.initFilters();
304
305      this.disconnect = onResize(this.resize);
306    }
307  }
308
309  window.BreakdanceGallery = BreakdanceGallery;
310})();

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.