PageSourceSearch

https://kutaisi.travel/wp-content/plugins/advanced-calendar/view.js?ver=1770106164

js kutaisi.travel collected 2026-10-02 22:51:10 UTC 11,663 bytes, 278 lines download raw bytes

1document.addEventListener('DOMContentLoaded', function() {
2    // Cache frequently accessed elements
3    const calendarDaysContainer = document.getElementById('calendar-days');
4    const calendarWeekDaysContainer = document.getElementById('calendar-week-days');
5
6    const rotatingContainer = document.getElementById('rotating-container');
7    const staticContainer = document.querySelector('.static-container');
8    const calendarPosterHead = document.getElementById('calendar-poster-head');
9    const calendarPosterBody = document.getElementById('calendar-poster-body');
10    const monthTitle = document.getElementById('month-title');
11
12    // Used to store day -> array of events
13    const daysAndEvents = new Map();
14
15    // Prepare data for AJAX
16    const data = {
17        action: 'get_calendar_events',
18        nonce: advancedCalendarData.nonce,
19        locale: advancedCalendarData.locale 
20    };
21
22    // Fetch events data
23    jQuery.post(advancedCalendarData.ajaxurl, data, (response) => {
24        if (response.success) {
25            const eventsData = response.data;
26            if (!eventsData) {
27                console.error('No event data returned.');
28                return;
29            }
30
31            const {
32                weekDays = [],
33                calendarPosterHeadSrc = '',
34                months = [],
35                events = [],
36                eventMonth = 1,
37                eventYear = 1970,
38            } = eventsData;
39
40            const monthIndex = parseInt(eventMonth, 10) - 1;
41            const yearNum = parseInt(eventYear, 10);
42
43            if (calendarPosterHeadSrc) {
44                calendarPosterHead.setAttribute('src', calendarPosterHeadSrc);
45            }
46
47            events.forEach(evt => {
48                const { day, header, location, link, time } = evt;
49                const formatted = formatTime(time);
50                if (!daysAndEvents.has(day)) {
51                    daysAndEvents.set(day, []);
52                }
53                daysAndEvents.get(day).push({
54                    header,
55                    location,
56                    link,
57                    time: formatted
58                });
59            });
60
61            daysAndEvents.forEach((evtArray) => {
62                evtArray.sort((a, b) => {
63                    const timeA = new Date(`1970-01-01T${a.time}Z`);
64                    const timeB = new Date(`1970-01-01T${b.time}Z`);
65                    return timeA - timeB;
66                });
67            });
68
69            generateCalendar(monthIndex, yearNum, weekDays, months);
70
71            const blockElement = document.querySelector('.wp-block-create-block-advanced-calendar');
72            if (blockElement) {
73                blockElement.style.visibility = 'visible';
74            }
75        } else {
76            console.error('Failed to load calendar events.');
77        }
78    });
79
80    // ------------------------------------
81    // Helper Functions
82    // ------------------------------------
83
84    function formatTime(time = '') {
85        const timePattern = /^([01]\d|2[0-3]):([0-5]\d)$/;
86        if (timePattern.test(time)) {
87            return time;
88        }
89        let [hours = '00', minutes = '00'] = time.split(':');
90        hours = hours.padStart(2, '0');
91        minutes = minutes.padStart(2, '0');
92        return `${hours}:${minutes}`;
93    }
94
95    function generateCalendar(eventMonth, eventYear, weekDays, monthsArray) {
96        monthTitle.innerHTML = monthsArray[eventMonth] || '';
97
98        const firstDayOfMonth = new Date(eventYear, eventMonth, 1);
99        const daysInMonth = new Date(eventYear, eventMonth + 1, 0).getDate();
100
101        const dayOfWeek = firstDayOfMonth.getDay();
102        const adjustedDayOfWeek = (dayOfWeek === 0) ? 6 : dayOfWeek - 1;
103
104        calendarDaysContainer.innerHTML = '';
105        calendarWeekDaysContainer.innerHTML = '';
106
107        for (let i = 0; i < 7; i++) {
108            const li = document.createElement('li');
109            li.textContent = weekDays[i] || '';
110            calendarWeekDaysContainer.appendChild(li);
111        }
112
113        for (let i = 0; i < adjustedDayOfWeek; i++) {
114            const emptyLi = document.createElement('li');
115            calendarDaysContainer.appendChild(emptyLi);
116        }
117
118        const today = new Date();
119        for (let day = 1; day <= daysInMonth; day++) {
120            const li = document.createElement('li');
121            li.textContent = day;
122
123            // Universal SVG: Every day gets a circle path
124            const svg = createDaySVG();
125            svg.style.visibility = 'hidden';
126            li.appendChild(svg);
127
128            const isToday = (
129                today.getDate() === day &&
130                today.getMonth() === eventMonth &&
131                today.getFullYear() === eventYear
132            );
133
134            if (isToday) {
135                changeBanner(day, true);
136                changeBanner(day, false);
137                if (svg) {
138                    svg.style.visibility = 'visible';
139                    svg.classList.add('active-date');
140                }
141            }
142
143            // Universal Hover: Draw animation on every date
144            li.addEventListener('mouseover', () => {
145                if (svg && !svg.classList.contains('active-date')) {
146                    svg.style.visibility = 'visible';
147                    li.myVivus = new Vivus(svg);
148                }
149            });
150
151            li.addEventListener('mouseout', () => {
152                if (li.myVivus && svg && !svg.classList.contains('active-date')) {
153                    li.myVivus.destroy();
154                    svg.style.visibility = 'hidden';
155                }
156            });
157
158            // Universal Click: Circle every date on click
159            li.addEventListener('click', () => {
160                changeBanner(day, true);
161                
162                // Hide and reset all other circles
163                document.querySelectorAll('.animation-svg').forEach((svgEl) => {
164                    svgEl.style.visibility = 'hidden';
165                    svgEl.classList.remove('active-date');
166                });
167
168                // Show, animate, and lock THIS day's circle
169                if (svg) {
170                    svg.style.visibility = 'visible';
171                    svg.classList.add('active-date');
172                    // Force a fresh draw on click
173                    new Vivus(svg);
174                }
175
176                // Page turn animation
177                calendarPosterBody.classList.add('page-turn');
178                rotatingContainer.style.overflowY = 'unset';
179                calendarPosterBody.addEventListener('animationend', function onAnimEnd() {
180                    calendarPosterBody.classList.remove('page-turn');
181                    rotatingContainer.style.overflowY = 'auto';
182                    changeBanner(day, false);
183                    calendarPosterBody.removeEventListener('animationend', onAnimEnd);
184                });
185            });
186
187            calendarDaysContainer.appendChild(li);
188        }
189    }
190
191    function createDaySVG() {
192        const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
193        svg.classList.add('animation-svg');
194        svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
195        svg.setAttribute('viewBox', '0 0 87.86 73.04');
196
197        const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
198        path.classList.add('animatedPath');
199        path.setAttribute(
200            'd',
201            'M34.79,5.45c-10.68,1.22-19.11,9.85-21.58,20.1-2.8,11.66,1.2,24.49,8.79,33.55,3.74,4.47,8.52,7.84,13.97,9.9s11.75,2.96,17.7,2.89c5.41-.07,10.97-1.05,15.74-3.71,5.21-2.9,8.59-7.72,11.04-13.03,2.6-5.63,5.04-11.79,4.63-18.11s-3.29-12.03-6.7-17.18-7.1-9.46-11.93-12.88S55.32,1.34,49.21,.49c-11.97-1.68-24.58,.95-34.27,8.36C5.89,15.77-.93,27.02,.1,38.74s9.79,20.77,20.21,25.15c11.26,4.74,24.34,5.05,36.1,2.13,5.88-1.46,11.6-3.78,16.79-6.93,4.71-2.85,9.14-6.56,11.86-11.42,6.19-11.06,1.28-24.06-6.91-32.54C69.99,6.69,58.72,1.44,47.04,.44c-6.3-.54-12.75,.18-18.78,2.07-5.57,1.74-11.07,4.41-15.36,8.44C4.62,18.71,2.91,31.14,5.58,41.76s9.08,19.24,17.83,24.97c9.27,6.08,20.95,7.79,31.66,5.04,11.47-2.95,20.21-11.05,25.97-21.18,3.01-5.29,4.55-10.95,3.05-16.99-1.42-5.72-4.96-10.8-9.02-14.98-8.12-8.37-19.04-14.5-30.9-14.79-5.79-.14-11.56,1.14-16.66,3.91-1.7,.92-.18,3.51,1.51,2.59,9.86-5.35,21.85-4.16,31.52,.98,4.73,2.51,8.99,5.86,12.68,9.73s6.85,8.5,8.06,13.75c1.29,5.66-.69,10.77-3.6,15.57-2.83,4.68-6.34,9.03-10.69,12.38-9.65,5.69-20.95,8.45-32.13,8.02-10.88-.42-22.37-3.84-29.75-12.26-3.27-3.73-5.61-8.43-6.16-13.39-.62-5.64,.86-11.37,3.55-16.32C11.71,13.61,20.72,7.08,30.82,4.42c10.82-2.85,23.53-1.75,33.05,4.43,4.64,3.02,8.36,7.28,11.44,11.82,3.15,4.64,6.06,9.84,6.68,15.51s-1.55,11.76-3.97,17.07c-2.18,4.8-5,9.31-9.65,12.05-4.31,2.54-9.38,3.47-14.32,3.57-5.47,.11-11.07-.62-16.25-2.4-10.24-3.52-17.52-12.37-20.73-22.52s-2.11-21.84,5.78-29.56c3.23-3.16,7.43-5.42,11.95-5.94,1.9-.22,1.92-3.22,0-3h0Z'
202        );
203        svg.appendChild(path);
204        return svg;
205    }
206
207    function changeBanner(day, isStatic) {
208        const currentDayEvents = daysAndEvents.get(day);
209        cleanBanner(isStatic);
210        if (!currentDayEvents) return;
211
212        const container = isStatic ? staticContainer : calendarPosterBody;
213        const prefix = isStatic ? 'static' : 'dynamic';
214
215        currentDayEvents.forEach((evt, i) => {
216            const index = i + 1;
217            if (index > 1) {
218                const divider = document.createElement('div');
219                divider.id = `${prefix}-divider-${index}`;
220                divider.classList.add('class-divider');
221                container.appendChild(divider);
222            }
223            const wrapper = document.createElement('div');
224            wrapper.id = `${prefix}-wrapper-${index}`;
225
226            const headingDiv = document.createElement('div');
227            headingDiv.className = 'section-heading';
228            headingDiv.id = `section-heading-id-${prefix}-${index}`;
229            headingDiv.textContent = evt.header || '';
230
231            if (evt.link) {
232                headingDiv.style.cursor = 'pointer';
233                headingDiv.addEventListener('click', () => {
234                    window.open(evt.link, '_blank');
235                });
236            }
237
238            const metaDiv = document.createElement('div');
239            metaDiv.className = 'meta-group';
240
241            const locDiv = document.createElement('div');
242            locDiv.className = 'section-location';
243            locDiv.id = `section-location-id-${prefix}-${index}`;
244            locDiv.textContent = evt.location || '';
245
246            const timeP = document.createElement('p');
247            timeP.id = `section-time-id-${prefix}-${index}`;
248            timeP.className = 'section-time';
249            timeP.textContent = evt.time || '';
250
251            metaDiv.appendChild(locDiv);
252            metaDiv.appendChild(timeP);
253
254            wrapper.appendChild(headingDiv);
255            wrapper.appendChild(metaDiv);
256            container.appendChild(wrapper);
257        });
258    }
259
260    function cleanBanner(isStatic) {
261        const prefix = isStatic ? 'static' : 'dynamic';
262        const container = isStatic ? staticContainer : calendarPosterBody;
263        let i = 1;
264        while (true) {
265            const wrapper = document.getElementById(`${prefix}-wrapper-${i}`);
266            if (!wrapper) break;
267            container.removeChild(wrapper);
268
269            if (i > 1) {
270                const divider = document.getElementById(`${prefix}-divider-${i}`);
271                if (divider) {
272                    container.removeChild(divider);
273                }
274            }
275            i++;
276        }
277    }
278});

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.