PageSourceSearch

https://app.emailkampane.cz/js/loginpage-carousel.js

js emailkampane.cz collected 2026-09-25 21:48:30 UTC 8,610 bytes, 234 lines download raw bytes

1(function ($) {
2    "use strict";
3
4    // GLOBAL VARIABLE DECLARATION
5    const 	releaseNotes = $('.release-notes'),
6            introAnimationTime = 1000,
7            carouselTimer = (window.CAROUSEL_TIMER_VALUE ?? 5) * 1000;
8    let     autoAdvance = true;
9
10    // INTRO ANIMATION
11    $(function () {
12        const   loginScreen = $('.loginscreen'),
13                rnChildren = releaseNotes.children();
14
15        loginScreen.addClass('slide-in');
16
17        setTimeout(() => {
18            requestAnimationFrame(() => {
19                releaseNotes.css('transform', 'scale(1)');
20            });
21        }, 650);
22
23        setTimeout(() => {
24            rnChildren.css('opacity', 1);
25        }, introAnimationTime);
26    });
27
28    // GLOBAL RELEASE NOTES STORE
29    window.ReleaseNotes = {
30        data: [],
31        get() { return this.data.slice(); }
32    };
33
34    // LANGUAGE AND DATE
35    const APP_LANG = window.APP_LANG.toLowerCase().slice(0, 2);
36
37    const FEED_URLS = {
38        cs: 'https://www.emailcampaigns.eu/action/function/feeds/releasenotes/cz.xml',
39        sk: 'https://www.emailcampaigns.eu/action/function/feeds/releasenotes/sk.xml',
40        en: 'https://www.emailcampaigns.eu/action/function/feeds/releasenotes/en.xml',
41        hu: 'https://www.emailcampaigns.eu/action/function/feeds/releasenotes/hu.xml'
42    };
43
44    const feedUrl = FEED_URLS[APP_LANG];
45
46    function formatRssDate(pubDateStr) {
47        if (!pubDateStr) return '';
48        let d = new Date(pubDateStr);
49        if (isNaN(d)) return '';
50        let y = d.getFullYear();
51        let m = ('0' + (d.getMonth() + 1)).slice(-2);
52        let dd = ('0' + d.getDate()).slice(-2);
53        return dd + '.' + m + '.' + y;
54    }
55
56    // FETCH
57    async function fetchReleaseNotes() {
58        try {
59            const xml = await $.ajax({
60                url: feedUrl,
61                type: 'GET',
62                dataType: 'xml'
63            });
64
65            const data = [];
66            $('channel > item', xml).each(function () {
67                const getText = (el, selector) => el.find(selector).first().text();
68                const 	icon        = getText($(this), 'ec\\:icon'),
69                        iconColor   = getText($(this), 'ec\\:iconColor'),
70                        iconBgColor = getText($(this), 'ec\\:iconBgColor'),
71                        borderColor = getText($(this), 'ec\\:borderColor'),
72                        releaseDate = formatRssDate(getText($(this), 'pubDate')),
73                        title       = getText($(this), 'title'),
74                        text        = getText($(this), 'description, text'),
75                        buttonText  = getText($(this), 'ec\\:buttonText'),
76                        buttonUrl   = getText($(this), 'link');
77
78                data.push({
79                    icon: icon,
80                    iconColor: iconColor,
81                    iconBgColor: iconBgColor,
82                    borderColor: borderColor,
83                    releaseDate: releaseDate,
84                    title: title,
85                    text: text,
86                    buttonText: buttonText,
87                    buttonUrl: buttonUrl
88                });
89            });
90
91            window.ReleaseNotes.data = data;
92            $(document).trigger('releaseNotes:loaded', [ data ]);
93            return data;
94        } catch (err) {
95            autoAdvance = false;
96            $('#release-notes-carousel').css('visibility', 'hidden');
97            $('#release-notes-fallback').css('visibility', 'visible');
98            return [];
99        }
100    }
101
102    // CAROUSEL
103    async function releaseNotesCarousel () {
104
105        window.ReleaseNotes.data = await fetchReleaseNotes();
106        const 	content = window.ReleaseNotes.data,
107                $rnIconWrapper = $('.rn-main-icon'),
108                $rnIcon = $('.rn-main-icon i'),
109                $releaseDateWrapper = $('.release-date-wrapper'),
110                $releaseDate = $('.rn-release-date'),
111                $title = $('.release-notes article h2'),
112                $text = $('.release-notes article p'),
113                $button = $('.release-notes article a'),
114                $carousel = $('.carousel');
115        let     currentIndex = 0,
116                timeoutId;
117
118        if (!content.length) {
119            autoAdvance = false;
120            $('#release-notes-carousel').css('visibility', 'hidden');
121            $('#release-notes-fallback').css('visibility', 'visible');
122            return;
123        } else if (content.length === 1) {
124            autoAdvance = false;
125            $('#release-notes-carousel').css('visibility', 'visible');
126            $('#release-notes-fallback').css('visibility', 'hidden');
127            $carousel.css('visibility', 'hidden');
128        } else {
129            $('#release-notes-carousel').css('visibility', 'visible');
130            $('#release-notes-fallback').css('visibility', 'hidden');
131            $carousel.empty();
132            content.forEach(() => $carousel.append($('<span class="carousel-button"></span>')));
133        }
134
135        const $carouselButtons = $('.carousel-button');
136        
137        function changeContent(index) {
138            $rnIcon.add($releaseDateWrapper).add($title).add($text).add($button).css({
139                "transition": "opacity 0.25s ease",
140                "opacity": 0
141            });
142            $carouselButtons.removeClass('opacity-1');
143            $carouselButtons.eq(index).addClass('opacity-1');
144
145            setTimeout(() => {
146                releaseNotes.css({"borderColor": content[index].borderColor || "#ffffff"});
147                $rnIconWrapper.css({"color": content[index].iconColor, "backgroundColor": content[index].iconBgColor});
148                $rnIcon.removeClass().addClass('fa-light fa-' + content[index].icon);
149                $releaseDate.text(content[index].releaseDate);
150                $title.html(content[index].title);
151                $text.html(content[index].text);
152                $button.text(content[index].buttonText).attr('href', content[index].buttonUrl);
153                $rnIcon.add($title).add($text).css('opacity', 1);
154
155                let     rd = $releaseDate.text().trim(),
156                        hasValidDate = rd !== '' && rd !== '0000-00-00' && rd !== '00.00.0000';
157
158                if (hasValidDate) {
159                    const   parts = rd.split('.'),
160                            year = parseInt(parts[2], 10);
161                    if (!isNaN(year) && year < 2025) hasValidDate = false;
162                }
163
164                $releaseDateWrapper.css('opacity', hasValidDate ? 1 : 0);
165
166                let bt = $button.text().trim();
167                if (bt === '') {
168                    $button.css({
169                        "opacity": 0,
170                        "pointer-events": "none"
171                    }).attr("aria-hidden", "true");
172                } else {
173                    $button.css({
174                        "opacity": 1,
175                        "pointer-events": ""
176                    }).removeAttr("aria-hidden");
177                }
178            }, 250);
179            // 250 ms = trvanie zmeny release note (fade-in/out)
180        }
181
182        function startCarousel() {
183            timeoutId = setTimeout(function cycle() {
184                if (!autoAdvance) return;
185
186                currentIndex = (currentIndex + 1) % content.length;
187                changeContent(currentIndex);
188
189                timeoutId = setTimeout(cycle, carouselTimer);
190            }, carouselTimer + introAnimationTime); 
191        }
192
193        changeContent(currentIndex);
194        if (autoAdvance) {
195            startCarousel();
196        }
197
198
199        function throttle(func, limit) {
200            let inThrottle = false;
201            return function () {
202                if (!inThrottle) {
203                    func.apply(this, arguments);
204                    inThrottle = true;
205                    setTimeout(() => inThrottle = false, limit);
206                }
207            };
208        }
209
210        const throttledClick = throttle(function (index) {
211            const prevIndex = currentIndex;
212            clearTimeout(timeoutId);
213            autoAdvance = false;
214            currentIndex = index;
215            if (index !== prevIndex) {
216                changeContent(currentIndex);
217            }
218        }, 500);
219        // umožňuje manuálnu zmenu vykonávať iba raz za 0,5s aby sa animácie neprekrývali
220
221        $carouselButtons.off('click');
222        $carouselButtons.each(function (index) {
223            $(this).on('click', function () {
224                throttledClick(index);
225            });
226        });
227
228    }
229
230    $(function(){ 
231        releaseNotesCarousel();
232    });
233
234})(jQuery);

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.