PageSourceSearch

https://vipcrossing.com/assets/calendar-v2/calendar-collection-4-23-3.js

js vipcrossing.com collected 2026-10-01 16:32:49 UTC 10,435 bytes, 282 lines download raw bytes

1(function () {
2    'use strict';
3
4    function initCollectionCalendar() {
5        var root = document.getElementById('vpc-collection-calendar');
6        if (!root) { return; }
7        if (root.getAttribute('data-vpc-calendar-version') === '4.23.2') { return; }
8
9        var memberId = parseInt(root.getAttribute('data-member-id'), 10);
10        var locale = root.getAttribute('data-locale') || 'fr';
11        var apiBase = root.getAttribute('data-api-base') || '/api/v2/calendar/member';
12        var calendarBase = root.getAttribute('data-calendar-base') || ('/' + locale + '/calendrier-v2');
13
14        var list = document.getElementById('vpc-collection-calendar-list');
15        var loading = document.getElementById('vpc-collection-calendar-loading');
16        var empty = document.getElementById('vpc-collection-calendar-empty');
17        var error = document.getElementById('vpc-collection-calendar-error');
18        var monthLabel = document.getElementById('vpc-collection-calendar-month');
19        var prevButton = document.getElementById('vpc-collection-calendar-prev');
20        var nextButton = document.getElementById('vpc-collection-calendar-next');
21        var todayButton = document.getElementById('vpc-collection-calendar-today');
22
23		if (!memberId) {
24			if (loading) {
25				loading.textContent = 'Calendrier indisponible : membre invalide.';
26			}
27			return;
28		}
29
30		/*
31		 * V4.23.3
32		 * Le composant complète automatiquement les éléments manquants.
33		 */
34		if (!monthLabel) {
35			monthLabel = document.createElement('strong');
36			monthLabel.id = 'vpc-collection-calendar-month';
37
38			var nav = root.querySelector('.vpc-collection-calendar-nav');
39
40			if (nav) {
41				if (nextButton) {
42					nav.insertBefore(monthLabel, nextButton);
43				} else {
44					nav.appendChild(monthLabel);
45				}
46			} else {
47				root.insertBefore(monthLabel, root.firstChild);
48			}
49		}
50
51		if (!loading) {
52			loading = document.createElement('div');
53			loading.id = 'vpc-collection-calendar-loading';
54			loading.className = 'vpc-collection-calendar-state';
55			loading.textContent = 'Chargement du calendrier…';
56			root.appendChild(loading);
57		}
58
59		if (!error) {
60			error = document.createElement('div');
61			error.id = 'vpc-collection-calendar-error';
62			error.className = 'vpc-collection-calendar-state vpc-collection-calendar-error';
63			error.hidden = true;
64			root.appendChild(error);
65		}
66
67		if (!empty) {
68			empty = document.createElement('div');
69			empty.id = 'vpc-collection-calendar-empty';
70			empty.className = 'vpc-collection-calendar-state';
71			empty.textContent = 'Aucun événement visible pour cette période.';
72			empty.hidden = true;
73			root.appendChild(empty);
74		}
75
76		if (!list) {
77			list = document.createElement('div');
78			list.id = 'vpc-collection-calendar-list';
79			list.className = 'vpc-collection-calendar-list';
80			root.appendChild(list);
81		}
82
83        root.setAttribute('data-vpc-calendar-ready', '1');
84        root.setAttribute('data-vpc-calendar-version', '4.23.3');
85
86        var cursor = new Date();
87        cursor = new Date(cursor.getFullYear(), cursor.getMonth(), 1);
88
89        function pad2(v) { return v < 10 ? '0' + v : String(v); }
90        function isoDate(d) { return d.getFullYear() + '-' + pad2(d.getMonth() + 1) + '-' + pad2(d.getDate()); }
91        function monthStart(d) { return new Date(d.getFullYear(), d.getMonth(), 1); }
92        function monthEnd(d) { return new Date(d.getFullYear(), d.getMonth() + 1, 0); }
93
94        function esc(v) {
95            return String(v == null ? '' : v)
96                .replace(/&/g, '&amp;')
97                .replace(/</g, '&lt;')
98                .replace(/>/g, '&gt;')
99                .replace(/"/g, '&quot;')
100                .replace(/'/g, '&#039;');
101        }
102
103        function parseDate(v) {
104            if (!v) { return null; }
105            var d = new Date(v);
106            return isNaN(d.getTime()) ? null : d;
107        }
108
109        function formatMonth(d) {
110            try {
111                return new Intl.DateTimeFormat(locale, { month: 'long', year: 'numeric' }).format(d);
112            } catch (e) {
113                return pad2(d.getMonth() + 1) + '/' + d.getFullYear();
114            }
115        }
116
117        function formatSmallMonth(d) {
118            try {
119                return new Intl.DateTimeFormat(locale, { month: 'short' }).format(d).replace('.', '');
120            } catch (e) {
121                return pad2(d.getMonth() + 1);
122            }
123        }
124
125        function formatTime(d) {
126            if (!d) { return ''; }
127            try {
128                return new Intl.DateTimeFormat(locale, { hour: '2-digit', minute: '2-digit' }).format(d);
129            } catch (e) {
130                return pad2(d.getHours()) + ':' + pad2(d.getMinutes());
131            }
132        }
133
134        function statusLabel(s) {
135            if (s === 'IN_PROGRESS') { return 'En cours'; }
136            if (s === 'FINISHED') { return 'Terminé'; }
137            if (s === 'CANCELLED') { return 'Annulé'; }
138            if (s === 'POSTPONED') { return 'Reporté'; }
139            return 'Planifié';
140        }
141
142        function visibilityLabel(v) {
143            if (v === 'PRIVATE') { return 'Privé'; }
144            if (v === 'FOLLOWERS') { return 'Abonnés'; }
145            return 'Public';
146        }
147
148        function setState(s) {
149            loading.hidden = s !== 'loading';
150            error.hidden = s !== 'error';
151            if (s === 'loading') {
152                empty.hidden = true;
153                list.innerHTML = '';
154            }
155        }
156
157        function render(items) {
158            list.innerHTML = '';
159            if (!items || !items.length) {
160                empty.hidden = false;
161                return;
162            }
163
164            empty.hidden = true;
165            var now = new Date();
166            var html = '';
167
168            items.forEach(function (item) {
169                var start = parseDate(item.start_at);
170                var end = parseDate(item.end_at);
171                if (!start) { return; }
172
173                var isPast = end ? end < now : start < now;
174                var location = '';
175
176                if (item.location) {
177                    location = item.location.venue_name || item.location.address || '';
178                }
179
180                var whenText = item.all_day ? 'Toute la journée' : formatTime(start);
181
182                if (!item.all_day && end) {
183                    whenText += ' – ' + formatTime(end);
184                }
185
186                var statusClass = '';
187                if (item.status === 'POSTPONED') { statusClass = ' is-postponed'; }
188                if (item.status === 'CANCELLED') { statusClass = ' is-cancelled'; }
189
190                html +=
191                    '<article class="vpc-collection-calendar-item' + (isPast ? ' is-past' : '') + '">' +
192                        '<div class="vpc-collection-calendar-date">' +
193                            '<span class="vpc-collection-calendar-day">' + esc(pad2(start.getDate())) + '</span>' +
194                            '<span class="vpc-collection-calendar-month-small">' + esc(formatSmallMonth(start)) + '</span>' +
195                        '</div>' +
196                        '<div class="vpc-collection-calendar-content">' +
197                            '<h4><a href="' + esc(calendarBase + '/evenement/' + item.event_id) + '">' +
198                                esc(item.title || 'Événement') +
199                            '</a></h4>' +
200                            '<div class="vpc-collection-calendar-meta">' +
201                                esc(whenText) + (location ? ' · ' + esc(location) : '') +
202                            '</div>' +
203                            '<div class="vpc-collection-calendar-badges">' +
204                                '<span class="vpc-collection-calendar-badge' + statusClass + '">' +
205                                    esc(statusLabel(item.status)) +
206                                '</span>' +
207                                '<span class="vpc-collection-calendar-badge">' +
208                                    esc(visibilityLabel(item.visibility)) +
209                                '</span>' +
210                            '</div>' +
211                        '</div>' +
212                    '</article>';
213            });
214
215            list.innerHTML = html;
216            if (!html) { empty.hidden = false; }
217        }
218
219        function loadMonth() {
220            var from = isoDate(monthStart(cursor));
221            var to = isoDate(monthEnd(cursor));
222
223            monthLabel.textContent = formatMonth(cursor);
224            setState('loading');
225
226            fetch(apiBase + '/' + memberId + '/' + from + '/' + to, {
227                method: 'GET',
228                credentials: 'same-origin',
229                headers: { 'Accept': 'application/json' }
230            })
231            .then(function (response) {
232                if (!response.ok) { throw new Error('HTTP ' + response.status); }
233                return response.json();
234            })
235            .then(function (payload) {
236                if (!payload || payload.success !== true) {
237                    throw new Error('Réponse calendrier invalide');
238                }
239
240                setState('ready');
241                render(payload.data || []);
242            })
243            .catch(function (err) {
244                setState('error');
245                error.textContent = 'Impossible de charger le calendrier.';
246                if (window.console && console.error) {
247                    console.error('Calendrier collection V4.23.2 :', err);
248                }
249            });
250        }
251
252        if (prevButton) {
253            prevButton.addEventListener('click', function () {
254                cursor = new Date(cursor.getFullYear(), cursor.getMonth() - 1, 1);
255                loadMonth();
256            });
257        }
258
259        if (nextButton) {
260            nextButton.addEventListener('click', function () {
261                cursor = new Date(cursor.getFullYear(), cursor.getMonth() + 1, 1);
262                loadMonth();
263            });
264        }
265
266        if (todayButton) {
267            todayButton.addEventListener('click', function () {
268                var today = new Date();
269                cursor = new Date(today.getFullYear(), today.getMonth(), 1);
270                loadMonth();
271            });
272        }
273
274        loadMonth();
275    }
276
277    if (document.readyState === 'loading') {
278        document.addEventListener('DOMContentLoaded', initCollectionCalendar);
279    } else {
280        initCollectionCalendar();
281    }
282})();

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.