PageSourceSearch

https://www.thionville.fr/_assets/53b3d70c8f30479a83ed3eb0614b88db…/Javascript/SocialwallWidget.js?1773051381

js thionville.fr collected 2026-10-02 08:06:31 UTC 14,772 bytes, 390 lines download raw bytes

1(function (global) {
2
3    function SocialwallWidget(args) {
4        this.args = args;
5        // arguments
6        this.displayType = (args.displayType !== undefined) ? args.displayType : 'classic';
7        this.orderBy = (args.orderBy !== undefined) ? args.orderBy : 'dateDesc';
8        this.debug = args.debug || false;
9        this.defaultFilter = 'all';
10        this.activeFilter = args.defaultFilter || this.defaultFilter;
11        this.hiddenClass = args.hiddenClass || 'hide is-hidden';
12        this.unfilteredClass = args.unfilteredClass || 'unfiltered';
13        this.animationInterval = args.animationInterval || 100;
14
15        // variables
16        this.$widget = $(this.args.selector);
17        this.$container = $(this.args.containerSelector || '#sw_flux');
18        this.posts = [];
19        this.theseNetworksHasPosts = [];
20        this.isFiltering = false;
21        this.interval_SW = undefined;
22        this.$filters = $('#sw_filters li > button, #sw_filters li > a');
23        this.macy = undefined;
24        this.macyConfig = this.args.macyConfig || {};
25        this.activeFilterClass = this.args.activeFilterClass || 'filter_act iso-active';
26
27        if (this.debug) this.log('Debug mode is active');
28
29        this.bind();
30        this.init();
31
32        return this;
33    }
34
35    SocialwallWidget.prototype.setDebug = function (active) {
36        this.debug = active;
37    };
38
39    SocialwallWidget.prototype.init = function () {
40        let $this = this;
41
42        for (let i = 0; i < $this.args.ajaxUriList.length; i++) {
43            $.ajax({
44                method: 'POST',
45                url: $this.args.ajaxUriList[i],
46                dataType: 'json',
47                cache: false,
48                success: function (response) {
49                    $this.injectPosts(response);
50                    $this.updateFilterButtons();
51                },
52                error: function (jqXHR, textStatus, errorThrow) {
53                    $this.log('ajax error', jqXHR, textStatus, errorThrow);
54                }
55            });
56        }
57
58        if (
59            $($this.args.containerSelector).length &&
60            $this.displayType === 'masonry' &&
61            typeof window.Macy !== 'undefined'
62        ) {
63            $this.macy = Macy($.extend({
64                container: $this.args.containerSelector,
65            }, $this.macyConfig));
66        }
67    };
68
69    SocialwallWidget.prototype.bind = function () {
70        let $this = this;
71
72        $(document).on('click', '#sw_filters li > button, #sw_filters li > a', function () {
73            let network = $(this).attr('data-network') || $this.defaultFilter;
74            $this.onFilterClicked(network);
75        });
76    };
77
78    SocialwallWidget.prototype.injectPosts = function (result) {
79        let $this = this;
80        if (result.posts) {
81            // add returned posts to global posts array
82            result.posts.forEach(function (post, index) {
83                post.page = result.page;
84                $this.posts.push(post);
85            });
86
87            if (result.posts.length > 0) {
88                $this.theseNetworksHasPosts[result.page.network] = result.posts.length;
89            }
90
91            // sort items
92            if ($this.orderBy === 'dateDesc') { // DATE DESC
93
94                $this.posts.sort(sortByDateDesc);
95
96            } else if ($this.orderBy === 'random') { // RANDOM
97                // since this shuffle method only invert the position with neighbours, we have to do it multiple times
98                // FAUDRA QUE JE TROUVE UNE AUTRE METHODE, PARCE QUE C'EST UN PEU DEGUEULASSE QUAND MEME
99                $this.posts.sort(shuffle);
100                $this.posts.sort(shuffle);
101                $this.posts.sort(shuffle);
102                $this.posts.sort(shuffle);
103                $this.posts.sort(shuffle);
104                $this.posts.sort(shuffle);
105                $this.posts.sort(shuffle);
106                $this.posts.sort(shuffle);
107                $this.posts.sort(shuffle);
108                $this.posts.sort(shuffle);
109            }
110
111            function sortByDateDesc(a, b) {
112                return (b.post.date.localeCompare(a.post.date)); // simple shuffle
113            }
114
115            function shuffle(a, b) {
116                return (0.5 - Math.random()); // simple shuffle
117            }
118
119            // remove all items
120            $this.$container.find('.sw_item').remove();
121
122            let metroIndices = [
123                {name: 'facebook', index: 0},
124                {name: 'twitter', index: 0},
125                {name: 'youtube', index: 0},
126                {name: 'instagram', index: 0},
127            ];
128
129            function getIndiceIdByNetwork(network) {
130                for (let i = 0; i < metroIndices.length; i++) {
131                    if (metroIndices[i].name === network)
132                        return i;
133                }
134            }
135
136            function getPostByNetworkAndIndex(targetNetwork, targetIndex) {
137                let currentIndex = 0;
138                for (let i = 0; i < $this.posts.length; i++) {
139                    let post = $this.posts[i];
140                    if (post.page.network === targetNetwork) {
141                        if (currentIndex >= targetIndex) {
142                            return post;
143                        }
144                        currentIndex++;
145                    }
146                }
147                return undefined;
148            }
149
150            // display the posts according to the metro config
151            if ($this.displayType === 'metro') {
152                if ($this.args.metroConfig.length > 0) {
153                    for (let networkIndex = 0; networkIndex < $this.args.metroConfig.length; networkIndex++) {
154                        let network = $this.args.metroConfig[networkIndex].network;
155                        let metroIndicesIndex = getIndiceIdByNetwork(network);
156
157                        let post = getPostByNetworkAndIndex(network, metroIndices[metroIndicesIndex].index);
158
159                        if (post !== undefined) {
160                            $(post.html).appendTo($this.$container);
161                            metroIndices[metroIndicesIndex].index++;
162                        }
163                    }
164                }
165            }
166
167            // enqueue the posts array
168            let networkCounter = {
169                'facebook': 0,
170                'twitter': 0,
171                'youtube': 0,
172                'instagram': 0,
173            };
174            let $posts = [];
175            for (let i = 0; i < $this.posts.length; i++) {
176                let post = $this.posts[i];
177                let metroIndicesIndex = getIndiceIdByNetwork(post.page.network);
178
179                if (networkCounter[post.page.network] >= metroIndices[metroIndicesIndex].index) {
180                    let $post = $(post.html);
181                    $posts.push($post);
182                    $post.appendTo($this.$container);
183                }
184                networkCounter[post.page.network]++;
185            }
186
187            // update masonry
188            if (typeof $this.$container.masonry !== 'undefined') {
189                $this.$container.masonry('appended', $posts);
190                $this.$container.masonry('layout');
191            }
192
193            // Set additional classes
194            if ($this.displayType === 'metro') {
195                if ($this.args.metroConfig.length > 0) {
196                    let $items = $($this.args.selector + " .sw_item");
197                    for (let networkIndex = 0; networkIndex < $this.args.metroConfig.length; networkIndex++) {
198                        let classesUnfiltered = $this.args.metroConfig[networkIndex].classesUnfiltered,
199                            classesFiltered = $this.args.metroConfig[networkIndex].classesFiltered;
200
201                        $items.eq(networkIndex)
202                            .addClass(classesUnfiltered)
203                            .attr('data-class-unfiltered', classesUnfiltered)
204                            .attr('data-class-filtered', classesFiltered);
205                    }
206                }
207            }
208
209            // set 'first' class
210            $this.onFilterClicked($this.activeFilter);
211
212            // lazy load for images
213            if (typeof window.Hunt !== 'undefined') {
214                let $images = document.querySelectorAll($this.args.selector + " img.lazy");
215                new Hunt($images, {
216                    enter: function (e) {
217                        e.src = e.dataset.src;
218                    }
219                });
220            }
221
222            // filter posts + appear animation
223            $this.isFiltering = ($this.activeFilter !== "all");
224            $this.filterPosts($this.defaultFilter);
225
226        }
227    };
228
229    SocialwallWidget.prototype.updateFilterButtons = function () {
230        let $this = this;
231
232        // update the 'unfiltered' class of the container
233        if ($this.activeFilter === $this.defaultFilter) {
234            $this.$container.addClass($this.unfilteredClass);
235        } else {
236            $this.$container.removeClass($this.unfilteredClass);
237        }
238
239        if (Object.keys($this.theseNetworksHasPosts).length > 1 && $(this)) {
240
241            let atLeastOneNetwork = false;
242
243            $this.$filters.each(function () {
244
245                let $button = $(this);
246                let $parent = $button.parents('li');
247                let network = $button.attr("data-network").toLowerCase();
248
249                if (!$this.$filters.hasClass($this.defaultFilter)) {
250
251                    let countPost = $this.theseNetworksHasPosts[network];
252
253
254                    if (countPost > 0) atLeastOneNetwork = true;
255
256                    if (countPost > 0) {
257                        $parent.removeClass($this.hiddenClass);
258                        $this.log('updateFilterButtons', network + ' is visible');
259                    } else {
260                        // $parent.addClass($this.hiddenClass);
261                        $this.log('updateFilterButtons', network + ' is hidden');
262                    }
263
264                }
265
266                // update the title
267                if (network === $this.activeFilter) {
268                    $button.attr('title', $button.attr('data-title-active'));
269                    $button.attr('aria-pressed', true);
270                } else {
271                    $button.attr('title', $button.attr('data-title'));
272                    $button.attr('aria-pressed', false);
273                }
274
275            });
276
277            if (atLeastOneNetwork) {
278                $this.$filters.eq(0).parents('li').removeClass($this.hiddenClass);
279            }
280
281        } else {
282
283            // hide all filters
284            $this.$filters.parents('li').addClass($this.hiddenClass);
285            $this.log('updateFilterButtons', 'all filters are hidden');
286
287        }
288    };
289
290    SocialwallWidget.prototype.onFilterClicked = function (network, $button) {
291        let $this = this;
292
293        let $allItems = $this.$container.find('.sw_item');
294
295        // remove first class
296        $allItems.removeClass('first');
297
298        // select only the posts to show
299        let $itemsToShow = (network === 'all')
300            ? $allItems
301            : $this.$container.find('.sw_item.item_' + network);
302
303        // add class 'first' on the first item of selected network
304        let $firstItem = $itemsToShow.eq(0);
305        $firstItem.addClass('first');
306
307        // set active filter
308        $this.activeFilter = network;
309
310        $this.log('onFilterClicked', 'The active filter is ' + network);
311
312        $this.updateFilterButtons();
313        $this.filterPosts(network);
314
315    };
316
317    SocialwallWidget.prototype.filterPosts = function () {
318        let $this = this,
319            metroCount = $this.$widget.attr('data-metro-count'),
320            $itemsToShow, $itemsToHide,
321            index = 0;
322
323        // get the posts to show / hide depending on the current filter
324        if ($this.activeFilter === $this.defaultFilter) {
325            $itemsToShow = $this.$widget.find(".sw_item:lt(" + (metroCount) + ")");
326            $itemsToHide = $this.$widget.find(".sw_item:gt(" + (metroCount - 1) + ")");
327        } else {
328            $itemsToShow = $this.$widget.find(".sw_item.item_" + $this.activeFilter);
329            $itemsToHide = $this.$widget.find(".sw_item:not(.item_" + $this.activeFilter + ")");
330        }
331
332        // update the hidden state (by class)
333        $this.$container.find('.sw_item')
334            .addClass($this.hiddenClass)
335            .removeClass('mui-enter-active');
336        $itemsToShow.removeClass($this.hiddenClass);
337
338        if ($this.isFiltering === false) {
339            $itemsToHide.addClass($this.hiddenClass);
340        }
341
342        // update the active filter
343        $this.$widget.find('#sw_filters li, #sw_filters li > button, #sw_filters li > a').removeClass($this.activeFilterClass);
344        $this.$widget.find('#sw_filters li.' + $this.activeFilter + ', #sw_filters li.' + $this.activeFilter + ' > button, #sw_filters li.' + $this.activeFilter + ' > a').addClass($this.activeFilterClass);
345
346        clearInterval($this.interval_SW);
347        $this.interval_SW = setInterval(function () {
348            let $item = $itemsToShow.eq(index);
349
350            if (index < metroCount) {
351                $item.addClass('mui-enter-active');
352
353                let classUnfiltered = $item.attr('data-class-unfiltered'),
354                    classFiltered = $item.attr('data-class-filtered');
355
356                if ($this.activeFilter !== $this.defaultFilter) {
357                    $item.removeClass(classUnfiltered).addClass(classFiltered);
358                } else {
359                    $item.removeClass(classFiltered).addClass(classUnfiltered);
360                }
361
362            } else {
363                clearInterval($this.interval_SW);
364                $this.interval_SW = undefined;
365            }
366            index++;
367        }, $this.animationInterval);
368
369        if (
370            $($this.args.containerSelector).length &&
371            $this.displayType === 'masonry' &&
372            typeof window.Macy !== 'undefined'
373        ) {
374            setTimeout(function () {
375                $this.macy.reInit();
376            }, 100);
377        }
378    };
379
380    SocialwallWidget.prototype.log = function (...args) {
381        if (this.debug) console.log('SocialWall', ...args);
382    };
383
384    let socialwallWidget = function (args) {
385        return new SocialwallWidget(args);
386    };
387
388    global.SocialwallWidget = socialwallWidget;
389
390})(this);

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.